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.
- checksums.yaml +4 -4
- data/README.md +76 -13
- data/Rakefile +4 -1
- data/app/assets/javascript/toogle/application.js +184 -49
- data/app/assets/stylesheets/toogle/application.css +1 -3
- data/app/assets/stylesheets/toogle/components/toggle.css +37 -22
- data/app/assets/stylesheets/toogle/elements.css +92 -23
- data/app/assets/stylesheets/toogle/layout.css +67 -24
- data/app/assets/stylesheets/toogle/utilities.css +5 -4
- data/app/assets/stylesheets/toogle/variables.css +43 -7
- data/app/controllers/toogle/application_controller.rb +2 -5
- data/app/controllers/toogle/definitions_controller.rb +1 -4
- data/app/controllers/toogle/features_controller.rb +14 -4
- data/app/models/toogle/definition.rb +9 -8
- data/app/models/toogle/feature.rb +4 -4
- data/app/views/layouts/toogle/application.html.haml +15 -10
- data/app/views/toogle/features/_details_button.html.haml +7 -0
- data/app/views/toogle/features/index.html.haml +93 -66
- data/lib/toogle/version.rb +1 -1
- metadata +4 -11
- data/app/assets/stylesheets/toogle/components/card.css +0 -10
- data/app/assets/stylesheets/toogle/components/scrollbox.css +0 -26
- data/app/views/toogle/definitions/index.html.haml +0 -9
- data/app/views/toogle/features/_dialog.html.haml +0 -18
- data/app/views/toogle/features/_toggle.html.haml +0 -8
|
@@ -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
|
|
29
|
-
align-items:
|
|
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
|
-
|
|
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:
|
|
123
|
+
background-color: hsl(var(--hue-primary), 10%, 50%, 0.07);
|
|
81
124
|
|
|
82
125
|
button {
|
|
83
126
|
opacity: 1;
|
|
@@ -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:
|
|
5
|
-
--lightness-
|
|
6
|
-
--lightness-
|
|
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-
|
|
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-
|
|
19
|
-
--lightness-
|
|
51
|
+
--lightness-bg2: 16%;
|
|
52
|
+
--lightness-track: 22%;
|
|
53
|
+
--lightness-thumb: 70%;
|
|
54
|
+
--lightness-disabled: 12%;
|
|
20
55
|
--lightness-fg: 90%;
|
|
21
|
-
--lightness-
|
|
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
|
-
#
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
5
|
+
attr_reader :name, :state, :definition
|
|
6
6
|
|
|
7
7
|
def self.all
|
|
8
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
.
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
%
|
|
6
|
-
%
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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="
|
|
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
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
%span
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
52
|
-
%button(x-on:click="
|
|
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
|
data/lib/toogle/version.rb
CHANGED
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.
|
|
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:
|
|
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/
|
|
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:
|
|
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: []
|