gdk-toogle 0.7.0 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc23503c85ec958b0051f3dd65ae20430ef7260df40441c6bc887b5caa1b3502
4
- data.tar.gz: f88f8017af1429e311e216cab810197c4d4b5d9feafa327633dda26e84a70739
3
+ metadata.gz: b41975a3c2a35c12eecaad91aa7bfd949d68d0132576d1f68ecca48987abf641
4
+ data.tar.gz: ad9ede84ae8f37f9286699d33163f360a04854a00abb3fbfb4ec6b07e3ec386f
5
5
  SHA512:
6
- metadata.gz: b99d1e496643408bfaee5ff88409e5136fb89fa895b36b8f94ee08210a4d9ae03fe578d4699e5552672fceb345bb9d83c82ee557147348057d712b73e7803ce5
7
- data.tar.gz: d24eaa1a2864ab9734d242843f7fc5cda999946fe361fc13d3a023d7c312d9dded7fa78c51a02094a231c171a5e4f92bb972bb1474e254fe24e5c62cd3e70c27
6
+ metadata.gz: 20a49dff67060c27ab608f9851570494726856f34e0deb11ad3c60266b72a3af13260384c63ddf3afe3284449e9984e03f3fd345a9302c6e132760a515c124eb
7
+ data.tar.gz: 1d372ec1b321404ad287154a027aef0a1732116ffedd449602bcd57f57e4d4d77b0a0e5ea11f2e5ed5e7c5caf3901ae99569485f3db8c0e50c7bc5f581ba5957
@@ -1 +1,2 @@
1
1
  //= link toogle/application.css
2
+ //= link toogle/application.js
@@ -0,0 +1,117 @@
1
+ document.addEventListener("alpine:init", () => {
2
+ Alpine.data("features", (indexUrl) => ({
3
+ features: [],
4
+ indexUrl,
5
+
6
+ init() {
7
+ fetch(this.indexUrl, {
8
+ method: "GET",
9
+ headers: {
10
+ Accept: "application/json",
11
+ },
12
+ })
13
+ .then((response) => response.json())
14
+ .then((data) => {
15
+ this.features = data;
16
+ })
17
+ .catch((error) => console.error("Error fetching data:", error));
18
+ },
19
+
20
+ toggleFeature(feature) {
21
+ const newState = feature.state === "enabled" ? "disabled" : "enabled";
22
+ fetch(`${this.indexUrl}/${feature.name}`, {
23
+ method: "PUT",
24
+ headers: {
25
+ Accept: "application/json",
26
+ "Content-Type": "application/json",
27
+ },
28
+ body: JSON.stringify({
29
+ state: newState,
30
+ }),
31
+ }).then(() => {
32
+ this.features = this.features.map((f) => {
33
+ return f === feature ? { ...f, state: newState } : f;
34
+ });
35
+ });
36
+ },
37
+
38
+ deleteFeature(featureName) {
39
+ const csrfToken = document.head.querySelector(
40
+ "meta[name=csrf-token]"
41
+ )?.content;
42
+
43
+ fetch(`${this.indexUrl}/${featureName}`, {
44
+ method: "DELETE",
45
+ headers: {
46
+ Accept: "application/json",
47
+ "X-CSRF-Token": csrfToken,
48
+ },
49
+ }).then(() => {
50
+ this.features = this.features.filter((f) => f.name !== featureName);
51
+ });
52
+ },
53
+ }));
54
+
55
+ Alpine.data("toggle", (featureName, isChecked, indexUrl) => ({
56
+ name: featureName,
57
+ checked: isChecked,
58
+ indexUrl,
59
+
60
+ input: {
61
+ ["@change"]() {
62
+ const csrfToken = document.head.querySelector(
63
+ "meta[name=csrf-token]"
64
+ )?.content;
65
+
66
+ fetch(`${this.indexUrl}/${this.name}`, {
67
+ method: "PUT",
68
+ headers: {
69
+ "Content-Type": "application/json",
70
+ "X-CSRF-Token": csrfToken,
71
+ },
72
+ body: JSON.stringify({
73
+ state: this.checked ? "disabled" : "enabled",
74
+ }),
75
+ }).then(() => {
76
+ window.location = this.indexUrl;
77
+ });
78
+ },
79
+ },
80
+ }));
81
+
82
+ Alpine.data("darkModeSwitcher", () => ({
83
+ isDark: undefined,
84
+
85
+ init() {
86
+ const cookieValue = this.getCookieValue();
87
+ if (cookieValue) {
88
+ this.isDark = cookieValue === "true";
89
+ } else {
90
+ this.isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
91
+ }
92
+ },
93
+
94
+ getCookieValue() {
95
+ return (
96
+ document.cookie
97
+ .match("(^|;)\\s*" + "toogle-dark" + "\\s*=\\s*([^;]+)")
98
+ ?.pop() || ""
99
+ );
100
+ },
101
+
102
+ button: {
103
+ ["@click"]() {
104
+ this.isDark = !this.isDark;
105
+ document.cookie = `toogle-dark=${this.isDark}; SameSite=Strict`;
106
+ if (this.isDark) {
107
+ document.documentElement.classList.remove("light-mode");
108
+ } else {
109
+ document.documentElement.classList.add("light-mode");
110
+ }
111
+ },
112
+ ["x-bind:title"]() {
113
+ return `Switch to ${this.isDark ? "Light Mode" : "Dark Mode"}`;
114
+ },
115
+ },
116
+ }));
117
+ });
@@ -8,8 +8,6 @@
8
8
  @import "components/scrollbox";
9
9
  @import "components/toggle";
10
10
 
11
- @import "dark-mode";
12
-
13
11
  [x-cloak] {
14
12
  display: none !important;
15
13
  }
@@ -1,6 +1,10 @@
1
1
  .card {
2
- background-color: #f0f0f0;
2
+ background-color: hsl(
3
+ var(--hue-primary),
4
+ var(--saturation-bg),
5
+ var(--lightness-bg1)
6
+ );
3
7
  border-radius: 5px;
4
8
  padding: 2rem;
5
- box-shadow: 0 0.5rem 1rem #888;
9
+ box-shadow: 0 10px 16px var(--color-shadow);
6
10
  }
@@ -1,13 +1,26 @@
1
1
  .scrollbox {
2
2
  max-height: 20ch;
3
3
  overflow: auto;
4
- padding: 1em 0;
4
+ padding: 1rem 0;
5
5
  word-break: break-all;
6
6
 
7
- background-color: white;
8
- border: 2px solid #444;
7
+ background-color: hsl(
8
+ var(--hue-primary),
9
+ var(--saturation-bg),
10
+ var(--lightness-bg2)
11
+ );
12
+ border: 2px solid
13
+ hsl(var(--hue-primary), var(--saturation-bg), var(--lightness-bg1));
9
14
 
10
- li:hover {
11
- background-color: rgba(153, 153, 153, 0.1);
15
+ border-style: ridge;
16
+
17
+ box-shadow: 0 5px 10px var(--color-shadow);
18
+
19
+ li {
20
+ padding: 0 1rem;
21
+
22
+ &:hover {
23
+ background-color: hsl(var(--hue-primary), 60%, var(--lightness-bg1));
24
+ }
12
25
  }
13
26
  }
@@ -1,8 +1,11 @@
1
1
  html {
2
- --page-bg: #ddd;
3
-
4
- background-color: var(--page-bg);
2
+ color: var(--color-text);
5
3
  transition: 0.2s;
4
+ background-image: radial-gradient(
5
+ circle at 10vh 10vw,
6
+ hsl(var(--hue-primary), var(--saturation-bg), var(--lightness-bg1)),
7
+ hsl(var(--hue-primary), var(--saturation-bg), var(--lightness-bg0))
8
+ );
6
9
  }
7
10
 
8
11
  body {
@@ -11,7 +14,6 @@ body {
11
14
  > header {
12
15
  position: sticky;
13
16
  top: 0;
14
- background-color: var(--page-bg);
15
17
  transition: 0.2s;
16
18
  }
17
19
  }
@@ -27,34 +29,58 @@ p {
27
29
  }
28
30
 
29
31
  a {
30
- color: #222;
32
+ color: var(--color-primary);
31
33
  font-weight: bold;
32
34
  text-decoration: none;
33
- padding: 2px;
34
35
  border-radius: 2px;
35
36
  transition: outline 0.2s;
36
37
 
37
38
  &:focus {
38
- outline: 4px solid var(--color-primary);
39
+ outline: 2px solid var(--color-primary);
39
40
  }
40
41
  }
41
42
 
43
+ footer a {
44
+ color: var(--color-text);
45
+ }
46
+
42
47
  input[type="submit"]:not(.small) {
43
48
  font-size: large;
44
49
  padding: 0.25rem;
45
50
  }
46
51
 
47
- input[type="search"] {
52
+ input[type="search"],
53
+ input[type="text"] {
48
54
  margin: 0.25rem 0;
49
55
  padding: 0.75rem;
50
56
  font-family: monospace;
51
57
  border-radius: 0.5rem;
52
58
 
59
+ &:not(:read-only):focus {
60
+ outline: 2px solid var(--color-primary);
61
+ }
62
+
63
+ &:read-only:focus {
64
+ outline: none;
65
+ }
66
+
53
67
  &.large {
54
68
  font-size: large;
55
69
  }
56
70
  }
57
71
 
72
+ input[type="search"],
73
+ input[type="text"] {
74
+ color: hsl(var(--hue-primary), var(--saturation-bg), var(--lightness-fg));
75
+ background-color: hsl(
76
+ var(--hue-primary),
77
+ var(--saturation-bg),
78
+ var(--lightness-bg2)
79
+ );
80
+ border: none;
81
+ box-shadow: inset 1px 1px 2px var(--color-shadow);
82
+ }
83
+
58
84
  hr {
59
85
  margin: 1.5rem 0;
60
86
  }
@@ -64,6 +90,7 @@ code {
64
90
  }
65
91
 
66
92
  button {
93
+ color: var(--color-text);
67
94
  cursor: pointer;
68
95
  background-color: transparent;
69
96
  border: none;
@@ -84,13 +111,9 @@ button {
84
111
  }
85
112
 
86
113
  &:focus {
87
- outline: 4px solid var(--color-primary);
114
+ outline: 2px solid var(--color-primary);
88
115
  opacity: 1 !important;
89
116
  }
90
-
91
- > svg + span {
92
- margin-left: 0.25em;
93
- }
94
117
  }
95
118
 
96
119
  ul {
@@ -108,6 +131,7 @@ ul {
108
131
 
109
132
  dialog {
110
133
  background-color: transparent;
134
+ color: var(--color-text);
111
135
  border: none;
112
136
  outline: none;
113
137
 
@@ -26,6 +26,8 @@ body {
26
26
  > main {
27
27
  display: flex;
28
28
  flex-direction: column-reverse;
29
+ align-items: stretch;
30
+ justify-content: start;
29
31
  width: 100ch;
30
32
  max-width: 95%;
31
33
  margin: auto;
@@ -64,6 +66,16 @@ li.feature-toggle {
64
66
  padding: 0.5rem;
65
67
  }
66
68
 
69
+ .more-info {
70
+ padding-left: 68px; /* toggle width */
71
+ }
72
+
73
+ .metadata {
74
+ display: grid;
75
+ grid-template-columns: auto 1fr;
76
+ gap: 0.5rem;
77
+ }
78
+
67
79
  &:hover {
68
80
  background-color: rgba(153, 153, 153, 0.1);
69
81
 
@@ -1,3 +1,23 @@
1
- :root {
2
- --color-primary: #fca326;
1
+ html {
2
+ --hue-primary: 35;
3
+ --saturation-bg: 5%;
4
+ --lightness-bg0: 80%;
5
+ --lightness-bg1: 88%;
6
+ --lightness-bg2: 96%;
7
+ --lightness-fg: 10%;
8
+ --lightness-shadow: 50%;
9
+
10
+ --color-primary: hsl(var(--hue-primary), 90%, 50%);
11
+ --color-text: hsl(var(--hue-primary), 0%, var(--lightness-fg));
12
+ --color-shadow: hsl(0, var(--saturation-bg), var(--lightness-shadow));
13
+ }
14
+
15
+ @media (prefers-color-scheme: dark) {
16
+ html:not(.light-mode) {
17
+ --lightness-bg0: 8%;
18
+ --lightness-bg1: 16%;
19
+ --lightness-bg2: 24%;
20
+ --lightness-fg: 90%;
21
+ --lightness-shadow: 4%;
22
+ }
3
23
  }
@@ -2,6 +2,11 @@ module Toogle
2
2
  class FeaturesController < ApplicationController
3
3
  def index
4
4
  @features = Toogle::Feature.all
5
+
6
+ respond_to do |format|
7
+ format.html
8
+ format.json { render json: @features }
9
+ end
5
10
  end
6
11
 
7
12
  def show
@@ -35,7 +40,16 @@ module Toogle
35
40
 
36
41
  def destroy
37
42
  ::Feature.remove(params[:id])
38
- redirect_to features_url, status: :see_other
43
+
44
+ respond_to do |format|
45
+ format.html do
46
+ redirect_to features_url, status: :see_other
47
+ end
48
+
49
+ format.json do
50
+ head :ok
51
+ end
52
+ end
39
53
  end
40
54
  end
41
55
  end
@@ -6,7 +6,13 @@ module Toogle
6
6
 
7
7
  def self.all
8
8
  ::Feature::Definition.definitions.map do |definition|
9
- new(name: definition[0].to_s, default_enabled: definition[1].default_enabled)
9
+ new(
10
+ name: definition[0].to_s,
11
+ default_enabled: definition[1].default_enabled,
12
+ milestone: definition[1].milestone,
13
+ introduced_by_url: definition[1].introduced_by_url,
14
+ rollout_issue_url: definition[1].rollout_issue_url,
15
+ )
10
16
  end
11
17
  end
12
18
 
@@ -19,9 +25,12 @@ module Toogle
19
25
  all.find { |definition| definition.name == name }
20
26
  end
21
27
 
22
- def initialize(name:, default_enabled:)
28
+ def initialize(name:, default_enabled:, milestone: nil, introduced_by_url: nil, rollout_issue_url: nil)
23
29
  @name = name
24
30
  @default_enabled = default_enabled
31
+ @milestone = milestone
32
+ @introduced_by_url = introduced_by_url
33
+ @rollout_issue_url = rollout_issue_url
25
34
  end
26
35
  end
27
36
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Toogle
4
4
  class Feature
5
- attr_accessor :name, :state
5
+ attr_accessor :name, :state, :definition
6
6
 
7
7
  def self.all
8
8
  definitions = Definition.all
@@ -11,21 +11,22 @@ module Toogle
11
11
  feature_class: ::Feature::FlipperFeature,
12
12
  gate_class: ::Feature::FlipperGate
13
13
  ).get_all.map do |feature_name, feature_values|
14
- feature_exists_on_current_branch = definitions.any?{ |d| d.name == feature_name }
15
- feature_state = if feature_exists_on_current_branch
14
+ feature_definition = Definition.find(feature_name)
15
+ feature_state = if feature_definition
16
16
  feature_values[:boolean] ? :enabled: :disabled
17
17
  else
18
18
  # This usually happens when switching back from an unmerged feature
19
19
  # branch that introduces a new flag, or when a flag got deleted.
20
20
  :unknown
21
21
  end
22
- new(name: feature_name, state: feature_state)
22
+ new(name: feature_name, state: feature_state, definition: feature_definition)
23
23
  end
24
24
  end
25
25
 
26
- def initialize(name:, state:)
26
+ def initialize(name:, state:, definition:)
27
27
  @name = name
28
28
  @state = state
29
+ @definition = definition
29
30
  end
30
31
  end
31
32
  end
@@ -7,8 +7,10 @@
7
7
  = csrf_meta_tags
8
8
  = csp_meta_tag
9
9
  = stylesheet_link_tag "toogle/application", media: "all"
10
+ = javascript_include_tag 'toogle/application'
10
11
  %script(defer src="https://cdn.jsdelivr.net/npm/@alpinejs/anchor@3.x.x/dist/cdn.min.js")
11
12
  %script(defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js")
13
+
12
14
  %body
13
15
  %header
14
16
  %nav.d-flex.gap
@@ -38,6 +40,7 @@
38
40
  %path(d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z")
39
41
 
40
42
  %main
43
+ = yield
41
44
  - if notice.present?
42
45
  #notice.d-flex.row.center.gap
43
46
  %svg(width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round")
@@ -45,9 +48,7 @@
45
48
  %line(x1="12" y1="16" x2="12" y2="12")
46
49
  %line(x1="12" y1="8" x2="12.01" y2="8")
47
50
  %span.grow= notice
48
- = yield
51
+
49
52
  %footer
50
53
  %a(href="https://gitlab.com/thutterer/toogle" target="_blank")
51
54
  = Toogle::VERSION
52
-
53
- = render "alpine_components"
@@ -3,7 +3,7 @@
3
3
  - name = definition.name
4
4
  - enabled = definition.default_enabled
5
5
  %li.d-flex.center.row.nowrap(x-show="$el.textContent.includes(query) || query == ''")
6
- %label.toggle(x-data="toggle('#{name}', #{enabled})")
6
+ %label.toggle(x-data="toggle('#{name}', #{enabled}, '#{features_url}')")
7
7
  %input(type="checkbox" x-bind="input" x-model="checked"){checked: enabled}
8
8
  %span.handle.round(:title="checked ? 'Enabled by default. Click to disable.' : 'Disabled by default. Click to enable.'")
9
9
  %code.grow= name
@@ -2,7 +2,7 @@
2
2
  .card{"x-on:click.outside": "$refs.dialog.close()"}
3
3
  %header
4
4
  %h2
5
- %label.toggle(x-data="toggle(feature, isAlreadyEnabled)")
5
+ %label.toggle(x-data="toggle(feature, isAlreadyEnabled, '#{features_url}')")
6
6
  %input(type="checkbox" x-bind="input" x-model="checked")
7
7
  %span.handle.round
8
8
 
@@ -1,46 +1,71 @@
1
- .grow
2
- .card
3
- %h3 My feature flags
4
- %small These features already use custom settings in this GDK.
5
-
6
- - if @features.any?
7
- %ul
8
- - @features.each do |feature|
9
- %li.feature-toggle(x-data="{ showMore: false }")
10
- .d-flex.row
11
- = render "toggle", feature: feature
12
-
13
- %code.grow= feature.name
14
-
15
- %button(title="Show Share URL" x-on:click="showMore = !showMore")
16
- %svg(xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round")
17
- %path(d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8")
18
- %polyline(points="16 6 12 2 8 6")
19
- %line(x1="12" y1="2" x2="12" y2="15")
20
-
21
- = render "remove", feature: feature
22
-
23
- .d-flex.col(x-show="showMore" x-data="{text: '#{request.url}#{feature.name}'}"){'@click.outside' => 'showMore = false'}
24
- %small Share this URL with MR reviewers.
25
- .d-flex.row
26
- %input.grow(x-ref="copyText" x-model="text" type="text" readonly="readonly")
27
- %button(x-on:click="$refs.copyText.select(); document.execCommand('copy');") Copy
28
- - else
29
- %p No active feature flags in this GDK yet.
30
-
31
- .grow.d-flex
32
- .card.grow(style="align-self: center;")
33
- %h3 Search and toggle feature flags
34
- .d-flex.col{
35
- "x-data": "{query: '', show: false}",
36
- "@click.outside": 'show = false'}
37
- %input.large.w-100#search{
38
- "type": "search",
39
- "x-model.debounce.400ms": "query",
40
- "x-ref": "search",
41
- "x-on:focus": "show = true"}
1
+ .card
2
+ %h3 My feature flags
3
+ %small These features already use custom settings in this GDK.
4
+
5
+ %ul(x-data="features('#{features_url}')")
6
+ %template(x-for="feature in features" :key="feature.name")
7
+ %li.feature-toggle(x-data="{ showMore: false }"){"@click.outside": "showMore = false"}
8
+ .d-flex.row
9
+ %template(x-if="feature.state === 'unknown'")
10
+ %label.toggle(title="This feature does not exist on the current branch.")
11
+ %input(type="checkbox" disabled :name="feature.name")
12
+ %span.handle.round
13
+ %template(x-if="feature.state !== 'unknown'")
14
+ %label.toggle
15
+ %input(type="checkbox" x-on:change="toggleFeature(feature)" :checked="feature.state === 'enabled'" :name="feature.name")
16
+ %span.handle.round
17
+
18
+ %code.grow(x-text="feature.name")
19
+
20
+ %button(title="Show more" x-on:click="showMore = !showMore")
21
+ %svg(xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round")
22
+ %circle(cx="12" cy="12" r="1")
23
+ %circle(cx="12" cy="5" r="1")
24
+ %circle(cx="12" cy="19" r="1")
25
+
26
+ %button(title="Forget this setting and use default" x-on:click="deleteFeature(feature.name)")
27
+ %svg(xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round")
28
+ %line(x1="18" y1="6" x2="6" y2="18")
29
+ %line(x1="6" y1="6" x2="18" y2="18")
30
+
31
+ .d-flex.col.more-info{ "x-show": "showMore" }
32
+ .metadata
33
+ %strong Milestone
34
+ %span(x-text="feature.definition.milestone || '-'")
35
+ %strong Introduced by
36
+ %a(x-show="feature.definition.introduced_by_url"
37
+ x-text="`!${feature.definition.introduced_by_url?.split('/').at(-1)}`"
38
+ :href="feature.definition.introduced_by_url"
39
+ target="_blank")
40
+ %span(x-show="!feature.definition.introduced_by_url") -
41
+ %strong Rollout issue
42
+ %a(x-show="feature.definition.rollout_issue_url"
43
+ x-text="`#${feature.definition.rollout_issue_url?.split('/').at(-1)}`"
44
+ :href="feature.definition.rollout_issue_url"
45
+ target="_blank")
46
+ %span(x-show="!feature.definition.rollout_issue_url") -
47
+
48
+ %hr
49
+ %small Share this URL with MR reviewers.
50
+ .d-flex.row
51
+ %input.grow(x-ref="copyText" :value="`${indexUrl}${feature.name}`" type="text" readonly="readonly")
52
+ %button(x-on:click="$refs.copyText.select(); document.execCommand('copy');") Copy
53
+ %p(x-show="!features.length") No active feature flags in this GDK yet.
54
+
55
+ .card(style="margin: 8vh 0 5vh;")
56
+ %h3 Search and toggle feature flags
57
+ .d-flex.col{
58
+ "x-data": "{query: '', show: false}",
59
+ "@click.outside": "show = false",
60
+ "@keyup.esc": "show = false"}
61
+ %input.large.w-100#search{
62
+ "type": "search",
63
+ "x-model.debounce.400ms": "query",
64
+ "x-ref": "search",
65
+ "x-on:input": "show = true",
66
+ "x-on:focus": "show = true"}
67
+ %template(x-if="show")
42
68
  .d-flex.col.stretch{
43
- "x-show": "show",
44
69
  "x-anchor.bottom-start.offset.5" => "$refs.search",
45
70
  "x-transition": nil}
46
71
  .grow{
@@ -1,3 +1,3 @@
1
1
  module Toogle
2
- VERSION = "0.7.0"
2
+ VERSION = "0.9.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gdk-toogle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Hutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-13 00:00:00.000000000 Z
11
+ date: 2024-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -92,11 +92,11 @@ files:
92
92
  - README.md
93
93
  - Rakefile
94
94
  - app/assets/config/toogle_manifest.js
95
+ - app/assets/javascript/toogle/application.js
95
96
  - app/assets/stylesheets/toogle/application.css
96
97
  - app/assets/stylesheets/toogle/components/card.css
97
98
  - app/assets/stylesheets/toogle/components/scrollbox.css
98
99
  - app/assets/stylesheets/toogle/components/toggle.css
99
- - app/assets/stylesheets/toogle/dark-mode.css
100
100
  - app/assets/stylesheets/toogle/elements.css
101
101
  - app/assets/stylesheets/toogle/layout.css
102
102
  - app/assets/stylesheets/toogle/utilities.css
@@ -107,10 +107,8 @@ files:
107
107
  - app/models/toogle/definition.rb
108
108
  - app/models/toogle/feature.rb
109
109
  - app/views/layouts/toogle/application.html.haml
110
- - app/views/toogle/application/_alpine_components.html.haml
111
110
  - app/views/toogle/definitions/index.html.haml
112
111
  - app/views/toogle/features/_dialog.html.haml
113
- - app/views/toogle/features/_remove.html.haml
114
112
  - app/views/toogle/features/_toggle.html.haml
115
113
  - app/views/toogle/features/index.html.haml
116
114
  - config/routes.rb
@@ -1,25 +0,0 @@
1
- @media (prefers-color-scheme: dark) {
2
- html:not(.light-mode) {
3
- --page-bg: #181822;
4
-
5
- color: #eee;
6
-
7
- a {
8
- color: #ddd;
9
- }
10
-
11
- button,
12
- dialog {
13
- color: #eee;
14
- }
15
-
16
- .card {
17
- background-color: #282833;
18
- box-shadow: 0 0.5rem 1rem #111;
19
- }
20
-
21
- .scrollbox {
22
- background-color: #444;
23
- }
24
- }
25
- }
@@ -1,56 +0,0 @@
1
- :javascript
2
- document.addEventListener("alpine:init", () => {
3
- Alpine.data("toggle", (featureName, isChecked) => ({
4
- name: featureName,
5
- checked: isChecked,
6
-
7
- input: {
8
- ['@change']() {
9
- fetch(`./${this.name}.json`, {
10
- method: "PUT",
11
- headers: {
12
- 'Content-Type': 'application/json'
13
- },
14
- body: JSON.stringify({state: this.checked ? 'disabled' : 'enabled'})
15
- }).then(() => {
16
- // Always reload the page after change as a lazy way to move newly
17
- // enabled feature flags into the top section.
18
- // TODO: Either make this a classic form element or go full Alpine.
19
- window.location = '#{features_url}'
20
- })
21
- },
22
- },
23
- }));
24
-
25
- Alpine.data("darkModeSwitcher", () => ({
26
- isDark: undefined,
27
-
28
- init() {
29
- const cookieValue = this.getCookieValue()
30
- if (cookieValue) {
31
- this.isDark = cookieValue === "true"
32
- } else {
33
- this.isDark = window.matchMedia("(prefers-color-scheme: dark)").matches
34
- }
35
- },
36
-
37
- getCookieValue() {
38
- return document.cookie.match('(^|;)\\s*' + 'toogle-dark' + '\\s*=\\s*([^;]+)')?.pop() || ''
39
- },
40
-
41
- button: {
42
- ['@click']() {
43
- this.isDark = !this.isDark
44
- document.cookie = `toogle-dark=${this.isDark}; SameSite=Strict`
45
- if(this.isDark) {
46
- document.documentElement.classList.remove('light-mode');
47
- } else {
48
- document.documentElement.classList.add('light-mode');
49
- }
50
- },
51
- ['x-bind:title']() {
52
- return `Switch to ${this.isDark ? 'Light Mode' : 'Dark Mode'}`
53
- }
54
- },
55
- }));
56
- });
@@ -1,4 +0,0 @@
1
- = button_to feature_path(feature.name), method: :delete, title: "Forget this setting and use default" do
2
- %svg(xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round")
3
- %line(x1="18" y1="6" x2="6" y2="18")
4
- %line(x1="6" y1="6" x2="18" y2="18")