gdk-toogle 0.9.3 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,6 @@ body {
12
12
  gap: 1rem;
13
13
 
14
14
  padding: 1rem;
15
- z-index: 2;
16
15
 
17
16
  a,
18
17
  span {
@@ -25,15 +24,29 @@ body {
25
24
 
26
25
  > main {
27
26
  display: flex;
28
- flex-direction: column-reverse;
29
- align-items: stretch;
30
- justify-content: start;
31
- width: 100ch;
32
- max-width: 95%;
33
- margin: auto;
27
+ flex-direction: column;
28
+ align-items: center;
34
29
  gap: 3rem;
35
- padding: 2rem 0;
30
+
31
+ padding: 0 1rem;
36
32
  flex-grow: 1;
33
+
34
+ &.with-sticky-search {
35
+ margin-top: 2rem;
36
+
37
+ .sticky-search {
38
+ align-self: center;
39
+ position: sticky;
40
+ width: min(100%, 80ch);
41
+ top: 0;
42
+ background-image: linear-gradient(
43
+ var(--color-page-bg) 90%,
44
+ transparent 100%
45
+ );
46
+ padding-bottom: 0.5rem;
47
+ z-index: 2;
48
+ }
49
+ }
37
50
  }
38
51
 
39
52
  > footer {
@@ -46,6 +59,50 @@ body {
46
59
  }
47
60
  }
48
61
 
62
+ .flags {
63
+ width: min(100%, 80ch);
64
+
65
+ section {
66
+ margin-top: 3rem;
67
+
68
+ h3 {
69
+ font-size: 0.875rem;
70
+ font-weight: bold;
71
+ text-transform: uppercase;
72
+ letter-spacing: 0.08em;
73
+ color: var(--color-text-muted);
74
+ }
75
+
76
+ ul {
77
+ margin-top: 1rem;
78
+
79
+ > p {
80
+ color: var(--color-text-muted);
81
+ }
82
+ }
83
+ }
84
+
85
+ li.shine {
86
+ animation: shine-fade 1.2s ease-out;
87
+ border-radius: 2px;
88
+ }
89
+ }
90
+
91
+ @keyframes shine-fade {
92
+ from {
93
+ background-color: hsl(var(--hue-primary), 10%, 50%, 0.25);
94
+ }
95
+ to {
96
+ background-color: transparent;
97
+ }
98
+ }
99
+
100
+ .metadata {
101
+ display: grid;
102
+ grid-template-columns: auto 1fr;
103
+ gap: 0.5rem;
104
+ }
105
+
49
106
  li.feature-toggle {
50
107
  display: flex;
51
108
  flex-direction: column;
@@ -55,29 +112,15 @@ li.feature-toggle {
55
112
  .row {
56
113
  align-items: center;
57
114
  flex-grow: 1;
115
+ gap: 0.25rem;
58
116
 
59
117
  button {
60
118
  opacity: 0;
61
- transition: 0.2s;
62
119
  }
63
120
  }
64
121
 
65
- > .col {
66
- padding: 0.5rem;
67
- }
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
-
79
122
  &:hover {
80
- background-color: rgba(153, 153, 153, 0.1);
123
+ background-color: hsl(var(--hue-primary), 10%, 50%, 0.07);
81
124
 
82
125
  button {
83
126
  opacity: 1;
@@ -24,10 +24,6 @@
24
24
  flex-grow: 1;
25
25
  }
26
26
 
27
- .stretch {
28
- align-self: stretch;
29
- }
30
-
31
27
  .gap {
32
28
  gap: 1em;
33
29
  }
@@ -35,3 +31,8 @@
35
31
  .w-100 {
36
32
  width: 100%;
37
33
  }
34
+
35
+ .ellipsis {
36
+ overflow-x: hidden;
37
+ text-overflow: ellipsis;
38
+ }
@@ -1,23 +1,59 @@
1
1
  html {
2
+ color-scheme: light;
3
+
2
4
  --hue-primary: 35;
3
5
  --saturation-bg: 5%;
4
- --lightness-bg0: 80%;
5
- --lightness-bg1: 88%;
6
- --lightness-bg2: 96%;
6
+ --lightness-bg0: 92%; /* page */
7
+ --lightness-bg2: 97%; /* raised surfaces: inputs, badges */
8
+ --lightness-track: 84%; /* toggle tracks, slightly sunken */
9
+ --lightness-thumb: 99%; /* toggle thumbs (off) */
10
+ --lightness-disabled: 88%; /* disabled toggles, washed out into the page */
7
11
  --lightness-fg: 10%;
8
- --lightness-shadow: 50%;
12
+ --lightness-muted: 42%;
13
+ --lightness-shadow: 65%;
9
14
 
10
15
  --color-primary: hsl(var(--hue-primary), 90%, 50%);
11
16
  --color-text: hsl(var(--hue-primary), 0%, var(--lightness-fg));
17
+ --color-text-muted: hsl(var(--hue-primary), 5%, var(--lightness-muted));
12
18
  --color-shadow: hsl(0, var(--saturation-bg), var(--lightness-shadow));
19
+ --color-page-bg: hsl(
20
+ var(--hue-primary),
21
+ var(--saturation-bg),
22
+ var(--lightness-bg0)
23
+ );
24
+ --color-surface: hsl(
25
+ var(--hue-primary),
26
+ var(--saturation-bg),
27
+ var(--lightness-bg2)
28
+ );
29
+ --color-track: hsl(
30
+ var(--hue-primary),
31
+ var(--saturation-bg),
32
+ var(--lightness-track)
33
+ );
34
+ --color-thumb: hsl(
35
+ var(--hue-primary),
36
+ var(--saturation-bg),
37
+ var(--lightness-thumb)
38
+ );
39
+ --color-disabled: hsl(
40
+ var(--hue-primary),
41
+ var(--saturation-bg),
42
+ var(--lightness-disabled)
43
+ );
13
44
  }
14
45
 
15
46
  @media (prefers-color-scheme: dark) {
16
47
  html:not(.light-mode) {
48
+ color-scheme: dark;
49
+
17
50
  --lightness-bg0: 8%;
18
- --lightness-bg1: 16%;
19
- --lightness-bg2: 24%;
51
+ --lightness-bg2: 16%;
52
+ --lightness-track: 22%;
53
+ --lightness-thumb: 70%;
54
+ --lightness-disabled: 12%;
20
55
  --lightness-fg: 90%;
21
- --lightness-shadow: 4%;
56
+ --lightness-muted: 60%;
57
+ --lightness-shadow: 3%;
22
58
  }
23
59
  }
@@ -5,16 +5,13 @@ module Toogle
5
5
  # content security policy.
6
6
  content_security_policy false, if: -> { Rails.env.development? }
7
7
 
8
- # Prevent all browser caching. Otherwise a cached version of a page might show the wrong toggle state.
9
- # Also, it really doesn't matter on localhost :)
8
+ # Never cache: a stale page could show the wrong toggle state.
10
9
  before_action :set_cache_headers
11
10
 
12
11
  private
13
12
 
14
13
  def set_cache_headers
15
- response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
16
- response.headers["Pragma"] = "no-cache"
17
- response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
14
+ response.headers["Cache-Control"] = "no-store"
18
15
  end
19
16
  end
20
17
  end
@@ -1,10 +1,7 @@
1
1
  module Toogle
2
2
  class DefinitionsController < ApplicationController
3
- # This controller is only used to fetch the long list of feature definitions async.
4
- layout false
5
-
6
3
  def index
7
- @definitions = Toogle::Definition.unchanged
4
+ render json: Toogle::Definition.all
8
5
  end
9
6
  end
10
7
  end
@@ -1,7 +1,7 @@
1
1
  module Toogle
2
2
  class FeaturesController < ApplicationController
3
3
  def index
4
- @features = Toogle::Feature.all
4
+ load_features
5
5
 
6
6
  respond_to do |format|
7
7
  format.html
@@ -12,10 +12,14 @@ module Toogle
12
12
  def show
13
13
  @definition = Toogle::Definition.find(params[:id])
14
14
  if @definition.nil?
15
- flash[:notice] = "No feature defintion with name \"#{params[:id]}\" found."
15
+ flash.now[:notice] = "No feature definition with name \"#{params[:id]}\" found."
16
+ end
17
+ load_features
18
+
19
+ respond_to do |format|
20
+ format.html { render "index" }
21
+ format.json { render json: @features }
16
22
  end
17
- index
18
- render "index"
19
23
  end
20
24
 
21
25
  def update
@@ -51,5 +55,11 @@ module Toogle
51
55
  end
52
56
  end
53
57
  end
58
+
59
+ private
60
+
61
+ def load_features
62
+ @features = Toogle::Feature.all
63
+ end
54
64
  end
55
65
  end
@@ -2,7 +2,8 @@
2
2
 
3
3
  module Toogle
4
4
  class Definition
5
- attr_accessor :name, :default_enabled
5
+ attr_reader :name, :default_enabled, :milestone, :type,
6
+ :feature_issue_url, :introduced_by_url, :rollout_issue_url
6
7
 
7
8
  def self.all
8
9
  ::Feature::Definition.definitions.map do |definition|
@@ -10,25 +11,25 @@ module Toogle
10
11
  name: definition[0].to_s,
11
12
  default_enabled: definition[1].default_enabled,
12
13
  milestone: definition[1].milestone,
14
+ type: definition[1].type,
15
+ feature_issue_url: definition[1].feature_issue_url,
13
16
  introduced_by_url: definition[1].introduced_by_url,
14
- rollout_issue_url: definition[1].rollout_issue_url,
17
+ rollout_issue_url: definition[1].rollout_issue_url
15
18
  )
16
19
  end
17
20
  end
18
21
 
19
- def self.unchanged
20
- changed_features = Toogle::Feature.all.map(&:name)
21
- all.reject { |definition| changed_features.include?(definition.name) }
22
- end
23
-
24
22
  def self.find(name)
25
23
  all.find { |definition| definition.name == name }
26
24
  end
27
25
 
28
- def initialize(name:, default_enabled:, milestone: nil, introduced_by_url: nil, rollout_issue_url: nil)
26
+ def initialize(name:, default_enabled:, milestone: nil, type: nil,
27
+ feature_issue_url: nil, introduced_by_url: nil, rollout_issue_url: nil)
29
28
  @name = name
30
29
  @default_enabled = default_enabled
31
30
  @milestone = milestone
31
+ @type = type
32
+ @feature_issue_url = feature_issue_url
32
33
  @introduced_by_url = introduced_by_url
33
34
  @rollout_issue_url = rollout_issue_url
34
35
  end
@@ -2,18 +2,18 @@
2
2
 
3
3
  module Toogle
4
4
  class Feature
5
- attr_accessor :name, :state, :definition
5
+ attr_reader :name, :state, :definition
6
6
 
7
7
  def self.all
8
- definitions = Definition.all
8
+ definitions_by_name = Definition.all.index_by(&:name)
9
9
 
10
10
  Flipper::Adapters::ActiveRecord.new(
11
11
  feature_class: ::Feature::FlipperFeature,
12
12
  gate_class: ::Feature::FlipperGate
13
13
  ).get_all.map do |feature_name, feature_values|
14
- feature_definition = Definition.find(feature_name)
14
+ feature_definition = definitions_by_name[feature_name]
15
15
  feature_state = if feature_definition
16
- feature_values[:boolean] ? :enabled: :disabled
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.
@@ -3,12 +3,15 @@
3
3
  %head
4
4
  %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
5
5
  %meta(name="viewport" content="width=device-width, initial-scale=1.0")
6
+ -# GitLab's masked_referrer_url helper (Snowplow) crashes on referrers
7
+ -# pointing into this engine, because it cannot regenerate engine routes
8
+ -# with the main app's URL helpers. So never send a referrer.
9
+ %meta(name="referrer" content="no-referrer")
6
10
  %title Feature flags
7
11
  = csrf_meta_tags
8
12
  = csp_meta_tag
9
13
  = stylesheet_link_tag "toogle/application", media: "all"
10
14
  = javascript_include_tag 'toogle/application'
11
- %script(defer src="https://cdn.jsdelivr.net/npm/@alpinejs/anchor@3.x.x/dist/cdn.min.js")
12
15
  %script(defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js")
13
16
 
14
17
  %body
@@ -16,12 +19,6 @@
16
19
  %nav.d-flex.gap
17
20
  = link_to main_app.root_path do
18
21
  = render partial: "shared/logo", formats: :svg
19
- %span ›
20
- = link_to_unless_current "Feature flags", features_path do
21
- %span Feature flags
22
- - if @feature
23
- %span ›
24
- %span= @feature.name
25
22
 
26
23
  %button(x-data="darkModeSwitcher" x-bind="button")
27
24
  %svg(x-show="isDark" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round")
@@ -39,15 +36,23 @@
39
36
  -# 🌙
40
37
  %path(d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z")
41
38
 
42
- %main
43
- = yield
39
+ %main.with-sticky-search
44
40
  - if notice.present?
45
- #notice.d-flex.row.center.gap
41
+ .notice.d-flex.row.center.gap
46
42
  %svg(width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round")
47
43
  %circle(cx="12" cy="12" r="10")
48
44
  %line(x1="12" y1="16" x2="12" y2="12")
49
45
  %line(x1="12" y1="8" x2="12.01" y2="8")
50
46
  %span.grow= notice
47
+ -# Client-side errors, e.g. fetch failures when the server is gone.
48
+ .notice.d-flex.row.center.gap(x-data x-show="$store.flash.message" x-cloak)
49
+ %svg(width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round")
50
+ %circle(cx="12" cy="12" r="10")
51
+ %line(x1="12" y1="16" x2="12" y2="12")
52
+ %line(x1="12" y1="8" x2="12.01" y2="8")
53
+ %span.grow(x-text="$store.flash.message")
54
+
55
+ = yield
51
56
 
52
57
  %footer
53
58
  %a(href="https://gitlab.com/thutterer/toogle" target="_blank")
@@ -0,0 +1,7 @@
1
+ -# The ⋯ button opening the details dialog. `subject` is the Alpine
2
+ -# expression for the flag's name, e.g. "feature.name".
3
+ %button(title="Show details" x-on:click="openDetails(#{subject})")
4
+ %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")
5
+ %circle(cx="12" cy="12" r="1")
6
+ %circle(cx="12" cy="5" r="1")
7
+ %circle(cx="12" cy="19" r="1")
@@ -1,76 +1,103 @@
1
- .card
2
- %h3 My feature flags
3
- %small These features already use custom settings in this GDK.
1
+ .flags(x-data="flags('#{features_url}', '#{definitions_path}', '#{@definition&.name}')")
2
+ .sticky-search
3
+ %input.large.w-100#search{
4
+ "type": "search",
5
+ "placeholder": "Search feature flags",
6
+ "x-model.debounce.400ms": "query"}
7
+
8
+ %section
9
+ %h3 Customized in this GDK
10
+
11
+ %ul.pinned
12
+ %template(x-for="feature in filteredFeatures()" :key="feature.name")
13
+ %li.feature-toggle{":style": "feature.name === moving ? `view-transition-name: flag-${feature.name}` : ''", ":class": "{shine: feature.name === lastMoved}"}
14
+ .d-flex.row.nowrap
15
+ %template(x-if="feature.state === 'unknown'")
16
+ %label.toggle(title="This feature does not exist on the current branch.")
17
+ %input(type="checkbox" disabled :name="feature.name")
18
+ %span.handle.round
19
+ %template(x-if="feature.state !== 'unknown'")
20
+ %label.toggle
21
+ %input(type="checkbox" x-on:change="toggleFeature(feature)" :checked="feature.state === 'enabled'" :name="feature.name")
22
+ %span.handle.round
23
+
24
+ %code.grow.ellipsis(x-text="feature.name")
25
+
26
+ = render "details_button", subject: "feature.name"
27
+
28
+ %button(title="Forget this setting and use default" x-on:click="deleteFeature(feature.name)")
29
+ %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")
30
+ %line(x1="18" y1="6" x2="6" y2="18")
31
+ %line(x1="6" y1="6" x2="18" y2="18")
32
+ %p(x-show="!features.length") Nothing custom yet. Toggle any flag below.
33
+ %p(x-show="features.length && !filteredFeatures().length") No matches.
4
34
 
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'")
35
+ %section
36
+ %h3 Defaults from the code
37
+
38
+ %ul.defaults
39
+ %template(x-for="definition in filteredDefinitions()" :key="definition.name")
40
+ %li.feature-toggle{":style": "definition.name === moving ? `view-transition-name: flag-${definition.name}` : ''", ":class": "{shine: definition.name === lastMoved}"}
41
+ .d-flex.row.nowrap
14
42
  %label.toggle
15
- %input(type="checkbox" x-on:change="toggleFeature(feature)" :checked="feature.state === 'enabled'" :name="feature.name")
16
- %span.handle.round
43
+ %input(type="checkbox" x-on:change="toggleDefault(definition)" :checked="definition.default_enabled" :name="definition.name")
44
+ %span.handle.round(:title="definition.default_enabled ? 'Enabled by default. Click to disable.' : 'Disabled by default. Click to enable.'")
45
+
46
+ %code.grow.ellipsis(x-text="definition.name")
17
47
 
18
- %code.grow(x-text="feature.name")
48
+ = render "details_button", subject: "definition.name"
49
+ %p(x-show="definitions.length && !matchingDefinitions().length")
50
+ No matches. Are you on the right branch?
51
+ %p(x-show="defaultsCapped()" x-text="`Showing first ${max} of ${matchingDefinitions().length}. Type to narrow down.`")
19
52
 
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")
53
+ %dialog{"x-ref": "dialog", "@close": "closeDetails()", "@click.self": "$refs.dialog.close()"}
54
+ %template(x-if="selected()")
55
+ .details
56
+ %header
57
+ %h2
58
+ %template(x-if="selected().state === 'unknown'")
59
+ %label.toggle(title="This feature does not exist on the current branch.")
60
+ %input(type="checkbox" disabled)
61
+ %span.handle.round
62
+ %template(x-if="selected().state !== 'unknown'")
63
+ %label.toggle
64
+ %input(type="checkbox" x-on:change="toggleSelected()" :checked="selected().state === 'enabled'")
65
+ %span.handle.round
25
66
 
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")
67
+ %code(x-text="selectedName")
30
68
 
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") -
69
+ .d-flex.row.badges(x-show="selected().definition")
70
+ %span.badge.type{"x-show": "selected().definition?.type",
71
+ "x-text": "selected().definition?.type"}
72
+ %span.badge{"x-show": "selected().definition?.milestone",
73
+ "x-text": "`since ${selected().definition?.milestone}`"}
74
+
75
+ %main.d-flex.col
76
+ %template(x-if="selected().definition")
77
+ .metadata
78
+ %strong Feature issue
79
+ %a{"x-show": "selected().definition.feature_issue_url",
80
+ "x-text": "`#${selected().definition.feature_issue_url?.split('/').at(-1)}`",
81
+ ":href": "selected().definition.feature_issue_url",
82
+ "target": "_blank"}
83
+ %span(x-show="!selected().definition.feature_issue_url") -
84
+ %strong Introduced by
85
+ %a{"x-show": "selected().definition.introduced_by_url",
86
+ "x-text": "`!${selected().definition.introduced_by_url?.split('/').at(-1)}`",
87
+ ":href": "selected().definition.introduced_by_url",
88
+ "target": "_blank"}
89
+ %span(x-show="!selected().definition.introduced_by_url") -
90
+ %strong Rollout issue
91
+ %a{"x-show": "selected().definition.rollout_issue_url",
92
+ "x-text": "`#${selected().definition.rollout_issue_url?.split('/').at(-1)}`",
93
+ ":href": "selected().definition.rollout_issue_url",
94
+ "target": "_blank"}
95
+ %span(x-show="!selected().definition.rollout_issue_url") -
96
+ %template(x-if="!selected().definition")
97
+ %p This feature does not exist on the current branch.
47
98
 
48
99
  %hr
49
100
  %small Share this URL with MR reviewers.
50
101
  .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")
68
- .d-flex.col.stretch{
69
- "x-anchor.bottom-start.offset.5" => "$refs.search",
70
- "x-transition": nil}
71
- .grow{
72
- "data-url": definitions_path,
73
- "x-data": "{}",
74
- "x-init": "$el.innerHTML = await (await fetch($el.dataset.url)).text()"}
75
-
76
- = render "dialog"
102
+ %input.grow{":value": "`${featuresUrl}/${selectedName}`", "type": "text", "readonly": "readonly"}
103
+ %button(x-on:click="navigator.clipboard.writeText(`${featuresUrl}/${selectedName}`)") Copy
@@ -1,3 +1,3 @@
1
1
  module Toogle
2
- VERSION = "0.9.3"
2
+ VERSION = "1.0.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gdk-toogle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Hutterer
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-03-15 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rails
@@ -94,8 +93,6 @@ files:
94
93
  - app/assets/config/toogle_manifest.js
95
94
  - app/assets/javascript/toogle/application.js
96
95
  - app/assets/stylesheets/toogle/application.css
97
- - app/assets/stylesheets/toogle/components/card.css
98
- - app/assets/stylesheets/toogle/components/scrollbox.css
99
96
  - app/assets/stylesheets/toogle/components/toggle.css
100
97
  - app/assets/stylesheets/toogle/elements.css
101
98
  - app/assets/stylesheets/toogle/layout.css
@@ -107,9 +104,7 @@ files:
107
104
  - app/models/toogle/definition.rb
108
105
  - app/models/toogle/feature.rb
109
106
  - app/views/layouts/toogle/application.html.haml
110
- - app/views/toogle/definitions/index.html.haml
111
- - app/views/toogle/features/_dialog.html.haml
112
- - app/views/toogle/features/_toggle.html.haml
107
+ - app/views/toogle/features/_details_button.html.haml
113
108
  - app/views/toogle/features/index.html.haml
114
109
  - config/routes.rb
115
110
  - lib/toogle.rb
@@ -123,7 +118,6 @@ metadata:
123
118
  homepage_uri: https://gitlab.com/thutterer/toogle
124
119
  source_code_uri: https://gitlab.com/thutterer/toogle
125
120
  changelog_uri: https://gitlab.com/thutterer/toogle
126
- post_install_message:
127
121
  rdoc_options: []
128
122
  require_paths:
129
123
  - lib
@@ -138,8 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
132
  - !ruby/object:Gem::Version
139
133
  version: '0'
140
134
  requirements: []
141
- rubygems_version: 3.4.10
142
- signing_key:
135
+ rubygems_version: 4.0.12
143
136
  specification_version: 4
144
137
  summary: Toogle toggles feature flags
145
138
  test_files: []
@@ -1,10 +0,0 @@
1
- .card {
2
- background-color: hsl(
3
- var(--hue-primary),
4
- var(--saturation-bg),
5
- var(--lightness-bg1)
6
- );
7
- border-radius: 5px;
8
- padding: 2rem;
9
- box-shadow: 0 10px 16px var(--color-shadow);
10
- }