flipper-ui 1.2.1 → 1.4.0
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/examples/ui/basic.ru +4 -0
- data/flipper-ui.gemspec +3 -2
- data/lib/flipper/ui/action.rb +30 -46
- data/lib/flipper/ui/actions/actors_gate.rb +2 -8
- data/lib/flipper/ui/actions/add_feature.rb +0 -9
- data/lib/flipper/ui/actions/boolean_gate.rb +1 -1
- data/lib/flipper/ui/actions/cloud_migrate.rb +26 -0
- data/lib/flipper/ui/actions/feature.rb +0 -7
- data/lib/flipper/ui/actions/features.rb +2 -9
- data/lib/flipper/ui/actions/groups_gate.rb +2 -7
- data/lib/flipper/ui/actions/percentage_of_actors_gate.rb +2 -2
- data/lib/flipper/ui/actions/percentage_of_time_gate.rb +2 -2
- data/lib/flipper/ui/actions/settings.rb +0 -3
- data/lib/flipper/ui/configuration.rb +18 -4
- data/lib/flipper/ui/middleware.rb +1 -0
- data/lib/flipper/ui/public/css/bootstrap.min.css +6 -0
- data/lib/flipper/ui/public/js/application.js +17 -33
- data/lib/flipper/ui/public/js/bootstrap.min.js +7 -0
- data/lib/flipper/ui/public/js/popper.min.js +6 -0
- data/lib/flipper/ui/sources.json +5 -0
- data/lib/flipper/ui/util.rb +10 -0
- data/lib/flipper/ui/views/add_actor.erb +8 -4
- data/lib/flipper/ui/views/add_feature.erb +3 -3
- data/lib/flipper/ui/views/add_group.erb +14 -9
- data/lib/flipper/ui/views/feature.erb +93 -80
- data/lib/flipper/ui/views/features.erb +29 -29
- data/lib/flipper/ui/views/layout.erb +28 -20
- data/lib/flipper/ui/views/settings.erb +31 -4
- data/lib/flipper/ui.rb +16 -2
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/ui/actions/actors_gate_spec.rb +6 -6
- data/spec/flipper/ui/actions/add_feature_spec.rb +1 -1
- data/spec/flipper/ui/actions/boolean_gate_spec.rb +1 -1
- data/spec/flipper/ui/actions/cloud_migrate_spec.rb +54 -0
- data/spec/flipper/ui/actions/feature_spec.rb +28 -0
- data/spec/flipper/ui/actions/features_spec.rb +60 -3
- data/spec/flipper/ui/actions/groups_gate_spec.rb +6 -6
- data/spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb +3 -3
- data/spec/flipper/ui/actions/percentage_of_time_gate_spec.rb +3 -3
- data/spec/flipper/ui/actions/settings_spec.rb +8 -0
- data/spec/flipper/ui/configuration_spec.rb +9 -4
- data/spec/flipper/ui_spec.rb +19 -31
- metadata +40 -35
- data/lib/flipper/ui/public/css/bootstrap-4.6.0.min.css +0 -7
- data/lib/flipper/ui/public/js/bootstrap-4.6.0.min.js +0 -7
- data/lib/flipper/ui/public/js/popper-1.12.9.min.js +0 -5
|
@@ -21,15 +21,20 @@
|
|
|
21
21
|
<div class="card">
|
|
22
22
|
<%# Gate State Header %>
|
|
23
23
|
<div class="card-header">
|
|
24
|
-
<
|
|
25
|
-
|
|
24
|
+
<div class="row align-items-center">
|
|
25
|
+
<h4 class="col text-truncate mb-0"><%= feature_name %></h4>
|
|
26
|
+
<div class="col-auto">
|
|
27
|
+
<span class="status <%= @feature.color_class %> me-2"></span>
|
|
28
|
+
<%= @feature.gate_state_title %>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
26
31
|
</div>
|
|
27
32
|
|
|
28
33
|
<% unless @feature.boolean_value %>
|
|
29
34
|
<%# Actors Info and Form %>
|
|
30
35
|
<div class="card-body border-bottom">
|
|
31
36
|
<div class="row align-items-center js-toggle-container">
|
|
32
|
-
<div class="col col-
|
|
37
|
+
<div class="col col-me-auto toggle-block-when-off">
|
|
33
38
|
<h6 class="m-0">
|
|
34
39
|
<strong class="<%= "text-muted" if @feature.actors_value.empty? %>">
|
|
35
40
|
<% if @feature.actors_value.count > 0 %>
|
|
@@ -42,14 +47,18 @@
|
|
|
42
47
|
</div>
|
|
43
48
|
<% if write_allowed? %>
|
|
44
49
|
<div class="col col-auto toggle-block-when-off">
|
|
45
|
-
<button class="btn btn-outline-secondary js-toggle-trigger" data-toggle="collapse" data-target="#add-actor">Add an actor</button>
|
|
50
|
+
<button class="btn btn-outline-secondary js-toggle-trigger" data-bs-toggle="collapse" data-bs-target="#add-actor">Add an actor</button>
|
|
46
51
|
</div>
|
|
47
52
|
<div class="col toggle-block-when-on">
|
|
48
|
-
<form action="<%= script_name %>/features/<%= @feature.key %>/actors" method="post" class="
|
|
53
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>/actors" method="post" class="row">
|
|
49
54
|
<%== csrf_input_tag %>
|
|
50
55
|
<input type="hidden" name="operation" value="enable">
|
|
51
|
-
<
|
|
52
|
-
|
|
56
|
+
<div class="col">
|
|
57
|
+
<input type="text" name="value" placeholder="<%= Flipper::UI.configuration.add_actor_placeholder %>" class="form-control">
|
|
58
|
+
</div>
|
|
59
|
+
<div class="col-auto">
|
|
60
|
+
<input type="submit" value="Add Actor" class="btn btn-primary">
|
|
61
|
+
</div>
|
|
53
62
|
</form>
|
|
54
63
|
</div>
|
|
55
64
|
<div class="col col-auto toggle-block-when-on">
|
|
@@ -63,7 +72,7 @@
|
|
|
63
72
|
<% @feature.actors_value.each do |item| %>
|
|
64
73
|
<div class="card-body bg-lightest border-bottom py-3">
|
|
65
74
|
<div class="row align-items-center">
|
|
66
|
-
<div class="col col-
|
|
75
|
+
<div class="col col-me-auto ps-md-5">
|
|
67
76
|
<h6 class="m-0">
|
|
68
77
|
<% if Flipper::UI::Util.present?(@feature.actor_names[item]) %>
|
|
69
78
|
<%== Sanitize.fragment("#{@feature.actor_names[item]} (#{item})", Sanitize::Config::BASIC) %>
|
|
@@ -74,11 +83,11 @@
|
|
|
74
83
|
</div>
|
|
75
84
|
<div class="col col-auto">
|
|
76
85
|
<% if write_allowed? %>
|
|
77
|
-
<form action="<%= script_name %>/features/<%= @feature.key %>/actors" method="post">
|
|
86
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>/actors" method="post">
|
|
78
87
|
<%== csrf_input_tag %>
|
|
79
88
|
<input type="hidden" name="operation" value="disable">
|
|
80
89
|
<input type="hidden" name="value" value="<%= item %>">
|
|
81
|
-
<button type="submit" value="Disable" class="btn btn-outline-danger" data-toggle="tooltip" title="Disable <%= item %>" data-placement="left">
|
|
90
|
+
<button type="submit" value="Disable" class="btn btn-outline-danger" data-bs-toggle="tooltip" title="Disable <%= item %>" data-bs-placement="left">
|
|
82
91
|
Remove
|
|
83
92
|
</button>
|
|
84
93
|
</form>
|
|
@@ -91,7 +100,7 @@
|
|
|
91
100
|
<%# Groups Info and Form %>
|
|
92
101
|
<div class="card-body border-bottom">
|
|
93
102
|
<div class="row align-items-center js-toggle-container">
|
|
94
|
-
<div class="col col-
|
|
103
|
+
<div class="col col-me-auto toggle-block-when-off">
|
|
95
104
|
<h6 class="m-0">
|
|
96
105
|
<strong class="<%= "text-muted" if @feature.groups_value.empty? %>">
|
|
97
106
|
<% if @feature.groups_value.count > 0 %>
|
|
@@ -104,22 +113,24 @@
|
|
|
104
113
|
</div>
|
|
105
114
|
<% if write_allowed? %>
|
|
106
115
|
<div class="col col-auto toggle-block-when-off">
|
|
107
|
-
<button class="btn btn-outline-secondary js-toggle-trigger" data-toggle="collapse" data-target="#add-actor">Add a group</button>
|
|
116
|
+
<button class="btn btn-outline-secondary js-toggle-trigger" data-bs-toggle="collapse" data-bs-target="#add-actor">Add a group</button>
|
|
108
117
|
</div>
|
|
109
118
|
<div class="col collapse toggle-block-when-on">
|
|
110
119
|
<% if @feature.disabled_groups.empty? %>
|
|
111
120
|
All groups enabled.
|
|
112
121
|
<% else %>
|
|
113
|
-
<form action="<%= script_name %>/features/<%= @feature.key %>/groups" method="post" class="
|
|
122
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>/groups" method="post" class="row">
|
|
114
123
|
<%== csrf_input_tag %>
|
|
115
124
|
<input type="hidden" name="operation" value="enable">
|
|
116
|
-
<
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
125
|
+
<div class="col">
|
|
126
|
+
<select name="value" class="form-select">
|
|
127
|
+
<option value="">Select a group...</option>
|
|
128
|
+
<% @feature.disabled_groups.sort_by(&:name).each do |group| %>
|
|
129
|
+
<option value="<%= group.name %>"><%= group.name %></option>
|
|
130
|
+
<% end %>
|
|
131
|
+
</select>
|
|
132
|
+
</div>
|
|
133
|
+
<div class="col-auto"><input type="submit" value="Add Group" class="btn btn-primary btn"></div>
|
|
123
134
|
</form>
|
|
124
135
|
<% end %>
|
|
125
136
|
</div>
|
|
@@ -134,16 +145,16 @@
|
|
|
134
145
|
<% @feature.groups_value.each do |item| %>
|
|
135
146
|
<div class="card-body bg-lightest border-bottom py-3">
|
|
136
147
|
<div class="row align-items-center">
|
|
137
|
-
<div class="col col-
|
|
148
|
+
<div class="col col-me-auto ps-md-5">
|
|
138
149
|
<h6 class="m-0"><%= item %></h6>
|
|
139
150
|
</div>
|
|
140
151
|
<div class="col col-auto">
|
|
141
152
|
<% if write_allowed? %>
|
|
142
|
-
<form action="<%= script_name %>/features/<%= @feature.key %>/groups" method="post">
|
|
153
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>/groups" method="post">
|
|
143
154
|
<%== csrf_input_tag %>
|
|
144
155
|
<input type="hidden" name="operation" value="disable">
|
|
145
156
|
<input type="hidden" name="value" value="<%= item %>">
|
|
146
|
-
<button type="submit" value="Disable" class="btn btn-outline-danger" data-toggle="tooltip" title="Disable <%= item %>" data-placement="left">
|
|
157
|
+
<button type="submit" value="Disable" class="btn btn-outline-danger" data-bs-toggle="tooltip" title="Disable <%= item %>" data-bs-placement="left">
|
|
147
158
|
Remove
|
|
148
159
|
</button>
|
|
149
160
|
</form>
|
|
@@ -157,7 +168,7 @@
|
|
|
157
168
|
<div class="js-toggle-container">
|
|
158
169
|
<div class="card-body border-bottom">
|
|
159
170
|
<div class="row align-items-center">
|
|
160
|
-
<div class="col col-
|
|
171
|
+
<div class="col col-me-auto">
|
|
161
172
|
<h6 class="m-0"><strong class="<%= "text-muted" unless @feature.percentage_of_actors_value > 0 %>">Enabled for <%= @feature.percentage_of_actors_value %>% of actors</strong></h6>
|
|
162
173
|
</div>
|
|
163
174
|
<% if write_allowed? %>
|
|
@@ -173,24 +184,22 @@
|
|
|
173
184
|
|
|
174
185
|
<% if write_allowed? %>
|
|
175
186
|
<div class="card-body border-bottom toggle-block-when-on bg-lightest">
|
|
176
|
-
<div class="row">
|
|
177
|
-
<
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
<% @
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
</form>
|
|
193
|
-
</div>
|
|
187
|
+
<div class="row align-items-center">
|
|
188
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>/percentage_of_actors" method="post" class="col">
|
|
189
|
+
<%== csrf_input_tag %>
|
|
190
|
+
<div class="btn-group">
|
|
191
|
+
<% @percentages.each do |number| %>
|
|
192
|
+
<input type="submit" name="value" value="<%= number %>%" class="btn btn-light" <% if number == @feature.percentage_of_actors_value %>disabled<% end %>>
|
|
193
|
+
<% end %>
|
|
194
|
+
</div>
|
|
195
|
+
</form>
|
|
196
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>/percentage_of_actors" method="post" class="col-auto row">
|
|
197
|
+
<%== csrf_input_tag %>
|
|
198
|
+
<div class="col-auto">
|
|
199
|
+
<input style="width:5em;" type="number" max="100" min="0" name="value" <% if @feature.percentage_of_actors_value > 0 %>value="<%= @feature.percentage_of_actors_value %>"<% end %> title="Custom percentage (26, 32, etc.)" placeholder="0" class="form-control">
|
|
200
|
+
</div>
|
|
201
|
+
<div class="col-auto ms-auto"><input type="submit" name="action" value="Save" class="btn btn-primary"></div>
|
|
202
|
+
</form>
|
|
194
203
|
</div>
|
|
195
204
|
</div>
|
|
196
205
|
<% end %>
|
|
@@ -200,7 +209,7 @@
|
|
|
200
209
|
<div class="js-toggle-container">
|
|
201
210
|
<div class="card-body border-bottom">
|
|
202
211
|
<div class="row align-items-center">
|
|
203
|
-
<div class="col col-
|
|
212
|
+
<div class="col col-me-auto">
|
|
204
213
|
<h6 class="m-0"><strong class="<%= "text-muted" unless @feature.percentage_of_time_value > 0 %>">Enabled for <%= @feature.percentage_of_time_value %>% of time</strong></h6>
|
|
205
214
|
</div>
|
|
206
215
|
<% if write_allowed? %>
|
|
@@ -216,24 +225,22 @@
|
|
|
216
225
|
|
|
217
226
|
<% if write_allowed? %>
|
|
218
227
|
<div class="card-body border-bottom toggle-block-when-on bg-lightest">
|
|
219
|
-
<div class="row">
|
|
220
|
-
<
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
<% @
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
</form>
|
|
236
|
-
</div>
|
|
228
|
+
<div class="row align-items-center">
|
|
229
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>/percentage_of_time" method="post" class="col">
|
|
230
|
+
<%== csrf_input_tag %>
|
|
231
|
+
<div class="btn-group">
|
|
232
|
+
<% @percentages.each do |number| %>
|
|
233
|
+
<input type="submit" name="value" value="<%= number %>%" class="btn btn-light" <% if number == @feature.percentage_of_time_value %>disabled<% end %>>
|
|
234
|
+
<% end %>
|
|
235
|
+
</div>
|
|
236
|
+
</form>
|
|
237
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>/percentage_of_time" method="post" class="col-auto row">
|
|
238
|
+
<%== csrf_input_tag %>
|
|
239
|
+
<div class="col-auto">
|
|
240
|
+
<input style="width:5em;" type="number" max="100" min="0" name="value" <% if @feature.percentage_of_time_value > 0 %>value="<%= @feature.percentage_of_time_value %>"<% end %> title="Custom percentage (26, 32, etc.)" placeholder="0" class="form-control">
|
|
241
|
+
</div>
|
|
242
|
+
<div class="col-auto ms-auto"><input type="submit" name="action" value="Save" class="btn btn-primary"></div>
|
|
243
|
+
</form>
|
|
237
244
|
</div>
|
|
238
245
|
</div>
|
|
239
246
|
<% end %>
|
|
@@ -242,19 +249,19 @@
|
|
|
242
249
|
|
|
243
250
|
<% if write_allowed? %>
|
|
244
251
|
<div class="card-body">
|
|
245
|
-
<form action="<%= script_name %>/features/<%= @feature.key %>/boolean" method="post">
|
|
252
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>/boolean" method="post">
|
|
246
253
|
<%== csrf_input_tag %>
|
|
247
254
|
|
|
248
255
|
<div class="row">
|
|
249
256
|
<% unless @feature.boolean_value %>
|
|
250
|
-
<div class="col">
|
|
251
|
-
<button type="submit" name="action" value="Enable"
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
257
|
+
<div class="col d-grid">
|
|
258
|
+
<button type="submit" name="action" value="Enable" class="btn btn-outline-success"
|
|
259
|
+
<% if Flipper::UI.configuration.confirm_fully_enable %>
|
|
260
|
+
data-confirmation-prompt="Are you sure you want to fully enable this feature for everyone? Please enter the name of the feature to confirm it: <%= feature_name %>"
|
|
261
|
+
data-confirmation-text="<%= feature_name %>"
|
|
262
|
+
<% end %>
|
|
263
|
+
>
|
|
264
|
+
<span class="d-block" data-bs-toggle="tooltip" title="Enable for everyone">
|
|
258
265
|
Fully Enable
|
|
259
266
|
</span>
|
|
260
267
|
</button>
|
|
@@ -262,14 +269,14 @@
|
|
|
262
269
|
<% end %>
|
|
263
270
|
|
|
264
271
|
<% unless @feature.off? %>
|
|
265
|
-
<div class="col">
|
|
266
|
-
<button type="submit" name="action" value="Disable"
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
272
|
+
<div class="col d-grid">
|
|
273
|
+
<button type="submit" name="action" value="Disable" class="btn btn-outline-danger"
|
|
274
|
+
<% if Flipper::UI.configuration.confirm_disable %>
|
|
275
|
+
data-confirmation-prompt="Are you sure you want to disable this feature for everyone? Please enter the name of the feature to confirm it: <%= feature_name %>"
|
|
276
|
+
data-confirmation-text="<%= feature_name %>"
|
|
277
|
+
<% end %>
|
|
278
|
+
>
|
|
279
|
+
<span class="d-block" data-bs-toggle="tooltip" title="Disable for everyone by clearing all percentages, groups and actors.">
|
|
273
280
|
Disable
|
|
274
281
|
</span>
|
|
275
282
|
</button>
|
|
@@ -292,11 +299,17 @@
|
|
|
292
299
|
<p>
|
|
293
300
|
<%= Flipper::UI.configuration.delete.description %>
|
|
294
301
|
</p>
|
|
295
|
-
<form action="<%= script_name %>/features/<%= @feature.key %>" method="post">
|
|
302
|
+
<form action="<%= script_name %>/features/<%= Flipper::UI::Util.escape @feature.key %>" method="post">
|
|
296
303
|
<%== csrf_input_tag %>
|
|
297
304
|
<input type="hidden" id="feature_name" name="_feature" value="<%= feature_name %>">
|
|
298
305
|
<input type="hidden" name="_method" value="DELETE">
|
|
299
|
-
<button type="submit" name="action" value="Delete" id="delete_feature__button"
|
|
306
|
+
<button type="submit" name="action" value="Delete" id="delete_feature__button" class="btn btn-outline-danger" data-bs-toggle="tooltip" data-bs-placement="right"
|
|
307
|
+
data-confirmation-prompt="Are you sure you want to remove this feature from the list of features and disable it for everyone? Please enter the name of the feature to confirm it: <%= feature_name%>"
|
|
308
|
+
data-confirmation-text="<%= feature_name %>"
|
|
309
|
+
title="Remove feature from list of features and disable it."
|
|
310
|
+
>
|
|
311
|
+
Delete
|
|
312
|
+
</button>
|
|
300
313
|
</form>
|
|
301
314
|
</div>
|
|
302
315
|
</div>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<% if @show_blank_slate %>
|
|
2
|
-
<div class="
|
|
2
|
+
<div class="bg-light p-5 rounded-3 text-center m-0">
|
|
3
3
|
<% if Flipper::UI.configuration.fun %>
|
|
4
4
|
<h4>But I've got a blank space baby...</h4>
|
|
5
5
|
<p>And I'll flip your features.</p>
|
|
6
6
|
<%- if write_allowed? && Flipper::UI.configuration.feature_creation_enabled -%>
|
|
7
7
|
<p>
|
|
8
|
-
<a class="btn btn-primary
|
|
8
|
+
<a class="btn btn-primary" href="<%= script_name %>/features/new">Add Feature</a>
|
|
9
9
|
</p>
|
|
10
10
|
<%- end -%>
|
|
11
11
|
<% else %>
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<p class="mb-1">You have not added any features to configure yet.</p>
|
|
14
14
|
<%- if write_allowed? && Flipper::UI.configuration.feature_creation_enabled -%>
|
|
15
15
|
<p class="mt-2">
|
|
16
|
-
<a class="btn btn-primary btn-
|
|
16
|
+
<a class="btn btn-primary btn-lg" href="<%= script_name %>/features/new">Add Feature</a>
|
|
17
17
|
</p>
|
|
18
18
|
<% else %>
|
|
19
19
|
<p>
|
|
@@ -24,36 +24,36 @@
|
|
|
24
24
|
<% end %>
|
|
25
25
|
</div>
|
|
26
26
|
<% else %>
|
|
27
|
-
<div class="
|
|
28
|
-
<div class="
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
<div class="list-group">
|
|
28
|
+
<div class="list-group-item bg-light">
|
|
29
|
+
<div class="row align-items-center">
|
|
30
|
+
<h4 class="col m-0">Features</h4>
|
|
31
|
+
<%- if write_allowed? && Flipper::UI.configuration.feature_creation_enabled -%>
|
|
32
|
+
<div class="col-auto">
|
|
33
|
+
<a class="btn btn-primary btn-sm" href="<%= script_name %>/features/new">Add Feature</a>
|
|
34
|
+
</div>
|
|
35
|
+
<%- end -%>
|
|
36
|
+
</div>
|
|
35
37
|
</div>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<div class="
|
|
39
|
-
<div class="col-1
|
|
40
|
-
<span class="status <%= feature.color_class %>" data-toggle="tooltip" title=<%= feature.state.to_s.capitalize %>></span>
|
|
38
|
+
<% @features.each do |feature| %>
|
|
39
|
+
<a href="<%= "#{script_name}/features/#{Flipper::UI::Util.escape(feature.key)}" %>" class="list-group-item list-group-item-action">
|
|
40
|
+
<div class="row align-items-center">
|
|
41
|
+
<div class="col-1 text-center">
|
|
42
|
+
<span class="status <%= feature.color_class %>" data-bs-toggle="tooltip" title=<%= feature.state.to_s.capitalize %>></span>
|
|
41
43
|
</div>
|
|
42
|
-
<div class="col-
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<%== Sanitize.fragment(feature.description, Sanitize::Config::BASIC) %>
|
|
48
|
-
</div>
|
|
49
|
-
<% end %>
|
|
50
|
-
<div class="text-muted text-truncate">
|
|
51
|
-
<%== feature.gates_in_words %>
|
|
44
|
+
<div class="col-11">
|
|
45
|
+
<div class="text-truncate" style="font-weight: 500"><%= feature.key %></div>
|
|
46
|
+
<% if Flipper::UI.configuration.show_feature_description_in_list? && Flipper::UI::Util.present?(feature.description) %>
|
|
47
|
+
<div class="text-muted fw-light" style="line-height: 1.4; white-space: initial; padding: 8px 0">
|
|
48
|
+
<%== Sanitize.fragment(feature.description, Flipper::UI::SANITIZE_LIST) %>
|
|
52
49
|
</div>
|
|
53
|
-
|
|
50
|
+
<% end %>
|
|
51
|
+
<div class="text-muted text-truncate">
|
|
52
|
+
<%== feature.gates_in_words %>
|
|
53
|
+
</div>
|
|
54
54
|
</div>
|
|
55
55
|
</div>
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
</a>
|
|
57
|
+
<% end %>
|
|
58
58
|
</div>
|
|
59
59
|
<% end %>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
|
-
<title><%= @page_title ? "#{@page_title} // " : "" %>Flipper</title>
|
|
4
|
+
<title><%= defined?(@page_title) ? "#{@page_title} // " : "" %>Flipper</title>
|
|
5
5
|
<meta charset="utf-8">
|
|
6
6
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
@@ -12,43 +12,52 @@
|
|
|
12
12
|
<body class="py-4">
|
|
13
13
|
<div class="container mw-600">
|
|
14
14
|
<%- unless Flipper::UI.configuration.banner_text.nil? -%>
|
|
15
|
-
<div class="alert alert-<%= Flipper::UI.configuration.banner_class %> text-center
|
|
15
|
+
<div class="alert alert-<%= Flipper::UI.configuration.banner_class %> text-center fw-bold">
|
|
16
16
|
<%== Sanitize.fragment(Flipper::UI.configuration.banner_text, Sanitize::Config::BASIC) %>
|
|
17
17
|
</div>
|
|
18
18
|
<%- end -%>
|
|
19
19
|
|
|
20
|
-
<div class="
|
|
21
|
-
<a href="
|
|
22
|
-
<a href="<%= script_name %>/settings">Settings</a> •
|
|
23
|
-
Version: <%= Flipper::VERSION %>
|
|
24
|
-
<a href="#" class="badge badge-warning ml-2 d-none" style="font-size:100%" id="new-version-badge" data-version="<%= Flipper::VERSION %>">
|
|
20
|
+
<div class="text-muted small text-end">
|
|
21
|
+
<a href="#" class="badge text-bg-warning ms-2 d-none" style="font-size:100%" id="new-version-badge" data-version="<%= Flipper::VERSION %>">
|
|
25
22
|
</a>
|
|
26
23
|
|
|
27
24
|
<% if Flipper.deprecated_ruby_version? %>
|
|
28
|
-
<a href="https://github.com/flippercloud/flipper/pull/776" class="badge
|
|
25
|
+
<a href="https://github.com/flippercloud/flipper/pull/776" class="badge text-bg-danger ms-2" style="font-size:100%">
|
|
29
26
|
Ruby <%= RUBY_VERSION %> deprecated
|
|
30
27
|
</a>
|
|
31
28
|
<% end %>
|
|
32
29
|
|
|
33
30
|
<% if defined?(Rails) && Flipper::Engine.deprecated_rails_version? %>
|
|
34
|
-
<a href="https://github.com/flippercloud/flipper/pull/776" class="badge
|
|
31
|
+
<a href="https://github.com/flippercloud/flipper/pull/776" class="badge text-bg-danger ms-2" style="font-size:100%">
|
|
35
32
|
Rails <%= Rails.version %> deprecated
|
|
36
33
|
</a>
|
|
37
34
|
<% end %>
|
|
38
35
|
</div>
|
|
36
|
+
<nav>
|
|
37
|
+
<ul class="nav nav-underline mb-3 align-items-center">
|
|
38
|
+
<% if Flipper::UI.configuration.application_href %>
|
|
39
|
+
<li class="nav-item">
|
|
40
|
+
<a class="nav-link" href="<%= Flipper::UI.configuration.application_href %>">
|
|
41
|
+
‹ App
|
|
42
|
+
</a>
|
|
43
|
+
</li>
|
|
44
|
+
<% end %>
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<% else %>
|
|
47
|
-
<a href="<%= breadcrumb.href %>"><%= breadcrumb.text %></a>
|
|
48
|
-
<% end %>
|
|
46
|
+
|
|
47
|
+
<% Flipper::UI.configuration.nav_items.each do |item| %>
|
|
48
|
+
<li class="nav-item">
|
|
49
|
+
<a href="<%= url_for(item[:href]) %>" class="nav-link<%= " active" if request.url.start_with?(url_for(item[:href])) %>">
|
|
50
|
+
<%= item[:title] %>
|
|
51
|
+
</a>
|
|
49
52
|
</li>
|
|
50
53
|
<% end %>
|
|
51
|
-
|
|
54
|
+
|
|
55
|
+
<li class="nav-item ms-auto text-muted small">
|
|
56
|
+
<a href="https://www.flippercloud.io/docs/ui?utm_source=oss&utm_medium=ui&utm_campaign=docs">Docs</a>
|
|
57
|
+
•
|
|
58
|
+
Version: <%= Flipper::VERSION %>
|
|
59
|
+
</li>
|
|
60
|
+
</ul>
|
|
52
61
|
</nav>
|
|
53
62
|
|
|
54
63
|
<div>
|
|
@@ -71,7 +80,6 @@
|
|
|
71
80
|
<% end %>
|
|
72
81
|
</div>
|
|
73
82
|
|
|
74
|
-
<script src="<%= script_name + jquery_js[:src] %>" integrity="<%= jquery_js[:hash] %>" crossorigin="anonymous"></script>
|
|
75
83
|
<script src="<%= script_name + popper_js[:src] %>" integrity="<%= popper_js[:hash] %>" crossorigin="anonymous"></script>
|
|
76
84
|
<script src="<%= script_name + bootstrap_js[:src] %>" integrity="<%= bootstrap_js[:hash] %>" crossorigin="anonymous"></script>
|
|
77
85
|
<script src="<%= script_name %>/js/application.js?v=<%= Flipper::VERSION %>"></script>
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
<% if params.key?("error") %>
|
|
2
|
+
<div class="alert alert-danger"><%= params["error"] %></div>
|
|
3
|
+
<% end %>
|
|
4
|
+
|
|
5
|
+
<div class="card mb-4">
|
|
6
|
+
<div class="card-header">
|
|
7
|
+
<h4 class="m-0">Migrate to Flipper Cloud</h4>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="card-body">
|
|
10
|
+
<p>Flipper Cloud gives you audit history, rollback, finer-grained permissions, and multi-environment sync. We even have a free tier!</p>
|
|
11
|
+
|
|
12
|
+
<ul class="mb-3">
|
|
13
|
+
<li>Audit log of every feature change</li>
|
|
14
|
+
<li>Instant rollback to any previous state</li>
|
|
15
|
+
<li>Team permissions and approval workflows</li>
|
|
16
|
+
<li>Sync flags across environments</li>
|
|
17
|
+
</ul>
|
|
18
|
+
|
|
19
|
+
<p>You have <strong><%= flipper.features.count %></strong> <%= flipper.features.count == 1 ? 'feature' : 'features' %> ready to migrate.</p>
|
|
20
|
+
|
|
21
|
+
<form action="<%= script_name %>/settings/cloud" method="post">
|
|
22
|
+
<%== csrf_input_tag %>
|
|
23
|
+
<input type="submit" value="Migrate to Flipper Cloud" class="btn btn-primary">
|
|
24
|
+
</form>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
1
28
|
<div class="card mb-4 ">
|
|
2
29
|
<div class="card-header">
|
|
3
30
|
<h4 class="m-0">Export</h4>
|
|
@@ -6,7 +33,7 @@
|
|
|
6
33
|
<form action="<%= script_name %>/settings/export" method="post">
|
|
7
34
|
<%== csrf_input_tag %>
|
|
8
35
|
<p>Download all your feature data in a single file.</p>
|
|
9
|
-
<input type="submit" value="Download" class="btn btn-
|
|
36
|
+
<input type="submit" value="Download" class="btn btn-light">
|
|
10
37
|
</form>
|
|
11
38
|
</div>
|
|
12
39
|
</div>
|
|
@@ -17,10 +44,10 @@
|
|
|
17
44
|
</div>
|
|
18
45
|
<div class="card-body">
|
|
19
46
|
<p>Import a backup file to restore your feature data. This will overwrite any of your existing feature data so be sure you are uploading the correct export.</p>
|
|
20
|
-
<form action="<%= script_name %>/settings/import" method="post" class="
|
|
47
|
+
<form action="<%= script_name %>/settings/import" method="post" class="row" enctype="multipart/form-data">
|
|
21
48
|
<%== csrf_input_tag %>
|
|
22
|
-
<input type="file" name="file" class="form-control
|
|
23
|
-
<input type="submit" value="Import" class="btn btn-
|
|
49
|
+
<div class="col-auto"><input type="file" name="file" class="form-control"></div>
|
|
50
|
+
<div class="col-auto"><input type="submit" value="Import" class="btn btn-light"></div>
|
|
24
51
|
</form>
|
|
25
52
|
</div>
|
|
26
53
|
</div>
|
data/lib/flipper/ui.rb
CHANGED
|
@@ -20,12 +20,26 @@ module Flipper
|
|
|
20
20
|
|
|
21
21
|
def self.app(flipper = nil, options = {})
|
|
22
22
|
env_key = options.fetch(:env_key, 'flipper')
|
|
23
|
-
rack_protection_options = options.
|
|
23
|
+
rack_protection_options = if options.key?(:rack_protection)
|
|
24
|
+
options[:rack_protection]
|
|
25
|
+
else
|
|
26
|
+
{}
|
|
27
|
+
end
|
|
24
28
|
|
|
25
29
|
app = ->(_) { [200, { Rack::CONTENT_TYPE => 'text/html' }, ['']] }
|
|
26
30
|
builder = Rack::Builder.new
|
|
27
31
|
yield builder if block_given?
|
|
28
|
-
|
|
32
|
+
|
|
33
|
+
# Only use Rack::Protection::AuthenticityToken if no other options are
|
|
34
|
+
# provided. Should avoid some pain for some people. If any options are
|
|
35
|
+
# provided then go whole hog and include all of Rack::Protection for
|
|
36
|
+
# backwards compatibility.
|
|
37
|
+
if rack_protection_options.empty?
|
|
38
|
+
builder.use Rack::Protection::AuthenticityToken
|
|
39
|
+
else
|
|
40
|
+
builder.use Rack::Protection, rack_protection_options
|
|
41
|
+
end
|
|
42
|
+
|
|
29
43
|
builder.use Rack::MethodOverride
|
|
30
44
|
builder.use Flipper::Middleware::SetupEnv, flipper, env_key: env_key
|
|
31
45
|
builder.use Flipper::UI::Middleware, flipper: flipper, env_key: env_key
|
data/lib/flipper/version.rb
CHANGED