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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 00b09ef9134ecfe7b076edae579e9ff91827964ada4053fa8d5b5167b2965992
|
|
4
|
+
data.tar.gz: 22b200ae581fd91ced63c0936bfa03ce9ee306779bf09c7ed40809ec97e9d4c6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d85919950864694f4156846ffd1cf20c758451821409c6ae7fb566b11759740842368af8393669617c5d8c5764ac5a9d11c7f91207641c51892dec0169cd09ad
|
|
7
|
+
data.tar.gz: 62b4831c0a38c4321ab627480e79ab5043140d4b57869c80a3792288d9b2d21421133f701ba1a8df72b6d5d707854df65714cce7009cb383aee039c04177718a
|
data/examples/ui/basic.ru
CHANGED
|
@@ -25,6 +25,7 @@ Flipper::UI.configure do |config|
|
|
|
25
25
|
config.feature_removal_enabled = true
|
|
26
26
|
config.cloud_recommendation = true
|
|
27
27
|
config.confirm_fully_enable = false
|
|
28
|
+
config.confirm_disable = false
|
|
28
29
|
config.read_only = false
|
|
29
30
|
# config.show_feature_description_in_list = true
|
|
30
31
|
config.descriptions_source = lambda do |_keys|
|
|
@@ -46,6 +47,8 @@ Flipper::UI.configure do |config|
|
|
|
46
47
|
'6' => '<a href="https://opensoul.org">Brandon</a>',
|
|
47
48
|
}
|
|
48
49
|
end
|
|
50
|
+
|
|
51
|
+
config.application_href = "https://example.com"
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
# You can uncomment these to get some default data:
|
|
@@ -63,5 +66,6 @@ end
|
|
|
63
66
|
use Rack::Reloader
|
|
64
67
|
|
|
65
68
|
run Flipper::UI.app { |builder|
|
|
69
|
+
builder.use Rack::Reloader, 1
|
|
66
70
|
builder.use Rack::Session::Cookie, secret: "_super_secret"
|
|
67
71
|
}
|
data/flipper-ui.gemspec
CHANGED
|
@@ -21,8 +21,9 @@ Gem::Specification.new do |gem|
|
|
|
21
21
|
gem.metadata = Flipper::METADATA
|
|
22
22
|
|
|
23
23
|
gem.add_dependency 'rack', '>= 1.4', '< 4'
|
|
24
|
-
gem.add_dependency 'rack-protection', '>= 1.5.3', '
|
|
24
|
+
gem.add_dependency 'rack-protection', '>= 1.5.3', '<5.0.0'
|
|
25
|
+
gem.add_dependency 'rack-session', '>= 1.0.2', '< 3.0.0'
|
|
25
26
|
gem.add_dependency 'flipper', "~> #{Flipper::VERSION}"
|
|
26
27
|
gem.add_dependency 'erubi', '>= 1.0.0', '< 2.0.0'
|
|
27
|
-
gem.add_dependency 'sanitize', '<
|
|
28
|
+
gem.add_dependency 'sanitize', '< 8'
|
|
28
29
|
end
|
data/lib/flipper/ui/action.rb
CHANGED
|
@@ -7,12 +7,20 @@ require 'sanitize'
|
|
|
7
7
|
|
|
8
8
|
module Flipper
|
|
9
9
|
module UI
|
|
10
|
+
# Sanitize config for descriptions in list view. Removes anchor tags to
|
|
11
|
+
# avoid nested links (the feature row is wrapped in an <a> tag).
|
|
12
|
+
# See: https://github.com/flippercloud/flipper/issues/939
|
|
13
|
+
SANITIZE_LIST = Sanitize::Config.merge(
|
|
14
|
+
Sanitize::Config::BASIC,
|
|
15
|
+
elements: Sanitize::Config::BASIC[:elements] - ['a']
|
|
16
|
+
)
|
|
17
|
+
|
|
10
18
|
class Action
|
|
11
19
|
module FeatureNameFromRoute
|
|
12
20
|
def feature_name
|
|
13
21
|
@feature_name ||= begin
|
|
14
22
|
match = request.path_info.match(self.class.route_regex)
|
|
15
|
-
match ?
|
|
23
|
+
match ? Flipper::UI::Util.unescape(match[:feature_name]) : nil
|
|
16
24
|
end
|
|
17
25
|
end
|
|
18
26
|
private :feature_name
|
|
@@ -27,24 +35,7 @@ module Flipper
|
|
|
27
35
|
'delete'.freeze,
|
|
28
36
|
]).freeze
|
|
29
37
|
|
|
30
|
-
SOURCES =
|
|
31
|
-
bootstrap_css: {
|
|
32
|
-
src: '/css/bootstrap-4.6.0.min.css'.freeze,
|
|
33
|
-
hash: 'sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l'.freeze
|
|
34
|
-
}.freeze,
|
|
35
|
-
jquery_js: {
|
|
36
|
-
src: '/js/jquery-3.6.0.slim.js'.freeze,
|
|
37
|
-
hash: 'sha256-HwWONEZrpuoh951cQD1ov2HUK5zA5DwJ1DNUXaM6FsY='.freeze
|
|
38
|
-
}.freeze,
|
|
39
|
-
popper_js: {
|
|
40
|
-
src: '/js/popper-1.12.9.min.js'.freeze,
|
|
41
|
-
hash: 'sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q'.freeze
|
|
42
|
-
}.freeze,
|
|
43
|
-
bootstrap_js: {
|
|
44
|
-
src: '/js/bootstrap-4.6.0.min.js'.freeze,
|
|
45
|
-
hash: 'sha384-+YQ4JLhjyBLPDQt//I+STsc9iw4uQqACwlvpslubQzn4u2UU2UFM80nGisd026JF'.freeze
|
|
46
|
-
}.freeze
|
|
47
|
-
}.freeze
|
|
38
|
+
SOURCES = JSON.parse(File.read(File.expand_path('sources.json', __dir__))).freeze
|
|
48
39
|
CONTENT_SECURITY_POLICY = <<-CSP.delete("\n")
|
|
49
40
|
default-src 'none';
|
|
50
41
|
img-src 'self';
|
|
@@ -110,12 +101,6 @@ module Flipper
|
|
|
110
101
|
@request = request
|
|
111
102
|
@code = 200
|
|
112
103
|
@headers = {Rack::CONTENT_TYPE => 'text/plain'}
|
|
113
|
-
@breadcrumbs =
|
|
114
|
-
if Flipper::UI.configuration.application_breadcrumb_href
|
|
115
|
-
[Breadcrumb.new('App', Flipper::UI.configuration.application_breadcrumb_href)]
|
|
116
|
-
else
|
|
117
|
-
[]
|
|
118
|
-
end
|
|
119
104
|
end
|
|
120
105
|
|
|
121
106
|
# Public: Runs the request method for the provided request.
|
|
@@ -187,7 +172,7 @@ module Flipper
|
|
|
187
172
|
# location - The String location to set the Location header to.
|
|
188
173
|
def redirect_to(location)
|
|
189
174
|
status 302
|
|
190
|
-
header 'location', "#{script_name}#{
|
|
175
|
+
header 'location', "#{script_name}#{location}"
|
|
191
176
|
halt [@code, @headers, ['']]
|
|
192
177
|
end
|
|
193
178
|
|
|
@@ -219,16 +204,6 @@ module Flipper
|
|
|
219
204
|
end
|
|
220
205
|
end
|
|
221
206
|
|
|
222
|
-
# Public: Add a breadcrumb to the trail.
|
|
223
|
-
#
|
|
224
|
-
# text - The String text for the breadcrumb.
|
|
225
|
-
# href - The String href for the anchor tag (optional). If nil, breadcrumb
|
|
226
|
-
# is assumed to be the end of the trail.
|
|
227
|
-
def breadcrumb(text, href = nil)
|
|
228
|
-
breadcrumb_href = href.nil? ? href : "#{script_name}#{href}"
|
|
229
|
-
@breadcrumbs << Breadcrumb.new(text, breadcrumb_href)
|
|
230
|
-
end
|
|
231
|
-
|
|
232
207
|
# Private
|
|
233
208
|
def view_with_layout(&block)
|
|
234
209
|
view :layout, &block
|
|
@@ -252,6 +227,16 @@ module Flipper
|
|
|
252
227
|
request.env['SCRIPT_NAME']
|
|
253
228
|
end
|
|
254
229
|
|
|
230
|
+
# Internal: Generate urls relative to the app's script name.
|
|
231
|
+
#
|
|
232
|
+
# url_for("feature") # => "http://localhost:9292/flipper/feature"
|
|
233
|
+
# url_for("/thing") # => "http://localhost:9292/thing"
|
|
234
|
+
# url_for("https://example.com") # => "https://example.com"
|
|
235
|
+
#
|
|
236
|
+
def url_for(*parts)
|
|
237
|
+
URI.join(request.base_url, script_name + '/', *parts).to_s
|
|
238
|
+
end
|
|
239
|
+
|
|
255
240
|
# Private
|
|
256
241
|
def views_path
|
|
257
242
|
self.class.views_path
|
|
@@ -279,11 +264,6 @@ module Flipper
|
|
|
279
264
|
# to inform people of that fact.
|
|
280
265
|
def render_read_only
|
|
281
266
|
status 403
|
|
282
|
-
|
|
283
|
-
breadcrumb 'Home', '/'
|
|
284
|
-
breadcrumb 'Features', '/features'
|
|
285
|
-
breadcrumb 'Noooooope'
|
|
286
|
-
|
|
287
267
|
halt view_response(:read_only)
|
|
288
268
|
end
|
|
289
269
|
|
|
@@ -296,19 +276,23 @@ module Flipper
|
|
|
296
276
|
end
|
|
297
277
|
|
|
298
278
|
def bootstrap_css
|
|
299
|
-
|
|
279
|
+
asset_hash "/css/bootstrap.min.css"
|
|
300
280
|
end
|
|
301
281
|
|
|
302
282
|
def bootstrap_js
|
|
303
|
-
|
|
283
|
+
asset_hash "/js/bootstrap.min.js"
|
|
304
284
|
end
|
|
305
285
|
|
|
306
286
|
def popper_js
|
|
307
|
-
|
|
287
|
+
asset_hash "/js/popper.min.js"
|
|
308
288
|
end
|
|
309
289
|
|
|
310
|
-
def
|
|
311
|
-
|
|
290
|
+
def asset_hash(src)
|
|
291
|
+
v = ENV["RACK_ENV"] == "development" ? Time.now.to_i : Flipper::VERSION
|
|
292
|
+
{
|
|
293
|
+
src: "#{src}?v=#{v}",
|
|
294
|
+
hash: SOURCES[src]
|
|
295
|
+
}
|
|
312
296
|
end
|
|
313
297
|
end
|
|
314
298
|
end
|
|
@@ -13,12 +13,6 @@ module Flipper
|
|
|
13
13
|
def get
|
|
14
14
|
feature = flipper[feature_name]
|
|
15
15
|
@feature = Decorators::Feature.new(feature)
|
|
16
|
-
|
|
17
|
-
breadcrumb 'Home', '/'
|
|
18
|
-
breadcrumb 'Features', '/features'
|
|
19
|
-
breadcrumb @feature.key, "/features/#{@feature.key}"
|
|
20
|
-
breadcrumb 'Add Actor'
|
|
21
|
-
|
|
22
16
|
view_response :add_actor
|
|
23
17
|
end
|
|
24
18
|
|
|
@@ -31,7 +25,7 @@ module Flipper
|
|
|
31
25
|
|
|
32
26
|
if values.empty?
|
|
33
27
|
error = "#{value.inspect} is not a valid actor value."
|
|
34
|
-
redirect_to("/features/#{feature.key}/actors?error=#{error}")
|
|
28
|
+
redirect_to("/features/#{Flipper::UI::Util.escape feature.key}/actors?error=#{Flipper::UI::Util.escape error}")
|
|
35
29
|
end
|
|
36
30
|
|
|
37
31
|
values.each do |value|
|
|
@@ -45,7 +39,7 @@ module Flipper
|
|
|
45
39
|
end
|
|
46
40
|
end
|
|
47
41
|
|
|
48
|
-
redirect_to("/features/#{feature.key}")
|
|
42
|
+
redirect_to("/features/#{Flipper::UI::Util.escape feature.key}")
|
|
49
43
|
end
|
|
50
44
|
end
|
|
51
45
|
end
|
|
@@ -12,18 +12,9 @@ module Flipper
|
|
|
12
12
|
|
|
13
13
|
unless Flipper::UI.configuration.feature_creation_enabled
|
|
14
14
|
status 403
|
|
15
|
-
|
|
16
|
-
breadcrumb 'Home', '/'
|
|
17
|
-
breadcrumb 'Features', '/features'
|
|
18
|
-
breadcrumb 'Noooooope'
|
|
19
|
-
|
|
20
15
|
halt view_response(:feature_creation_disabled)
|
|
21
16
|
end
|
|
22
17
|
|
|
23
|
-
breadcrumb 'Home', '/'
|
|
24
|
-
breadcrumb 'Features', '/features'
|
|
25
|
-
breadcrumb 'Add'
|
|
26
|
-
|
|
27
18
|
view_response :add_feature
|
|
28
19
|
end
|
|
29
20
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'flipper/ui/action'
|
|
2
|
+
require 'flipper/ui/util'
|
|
3
|
+
|
|
4
|
+
module Flipper
|
|
5
|
+
module UI
|
|
6
|
+
module Actions
|
|
7
|
+
class CloudMigrate < UI::Action
|
|
8
|
+
route %r{\A/settings\/cloud/?\Z}
|
|
9
|
+
|
|
10
|
+
def post
|
|
11
|
+
result = Flipper::Cloud.migrate(flipper)
|
|
12
|
+
|
|
13
|
+
if result.url
|
|
14
|
+
status 302
|
|
15
|
+
header 'location', result.url
|
|
16
|
+
halt [@code, @headers, ['']]
|
|
17
|
+
else
|
|
18
|
+
message = "Migration failed (HTTP #{result.code})"
|
|
19
|
+
message << ": #{result.message}" if result.message
|
|
20
|
+
redirect_to "/settings?error=#{Flipper::UI::Util.escape(message)}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -18,10 +18,6 @@ module Flipper
|
|
|
18
18
|
@page_title = "#{@feature.key} // Features"
|
|
19
19
|
@percentages = [0, 1, 5, 10, 25, 50, 100]
|
|
20
20
|
|
|
21
|
-
breadcrumb 'Home', '/'
|
|
22
|
-
breadcrumb 'Features', '/features'
|
|
23
|
-
breadcrumb @feature.key
|
|
24
|
-
|
|
25
21
|
view_response :feature
|
|
26
22
|
end
|
|
27
23
|
|
|
@@ -31,9 +27,6 @@ module Flipper
|
|
|
31
27
|
unless Flipper::UI.configuration.feature_removal_enabled
|
|
32
28
|
status 403
|
|
33
29
|
|
|
34
|
-
breadcrumb 'Home', '/'
|
|
35
|
-
breadcrumb 'Features', '/features'
|
|
36
|
-
|
|
37
30
|
halt view_response(:feature_removal_disabled)
|
|
38
31
|
end
|
|
39
32
|
|
|
@@ -29,9 +29,6 @@ module Flipper
|
|
|
29
29
|
|
|
30
30
|
@show_blank_slate = @features.empty?
|
|
31
31
|
|
|
32
|
-
breadcrumb 'Home', '/'
|
|
33
|
-
breadcrumb 'Features'
|
|
34
|
-
|
|
35
32
|
view_response :features
|
|
36
33
|
end
|
|
37
34
|
|
|
@@ -41,10 +38,6 @@ module Flipper
|
|
|
41
38
|
unless Flipper::UI.configuration.feature_creation_enabled
|
|
42
39
|
status 403
|
|
43
40
|
|
|
44
|
-
breadcrumb 'Home', '/'
|
|
45
|
-
breadcrumb 'Features', '/features'
|
|
46
|
-
breadcrumb 'Noooooope'
|
|
47
|
-
|
|
48
41
|
halt view_response(:feature_creation_disabled)
|
|
49
42
|
end
|
|
50
43
|
|
|
@@ -52,13 +45,13 @@ module Flipper
|
|
|
52
45
|
|
|
53
46
|
if Util.blank?(value)
|
|
54
47
|
error = "#{value.inspect} is not a valid feature name."
|
|
55
|
-
redirect_to("/features/new?error=#{error}")
|
|
48
|
+
redirect_to("/features/new?error=#{Flipper::UI::Util.escape error}")
|
|
56
49
|
end
|
|
57
50
|
|
|
58
51
|
feature = flipper[value]
|
|
59
52
|
feature.add
|
|
60
53
|
|
|
61
|
-
redirect_to "/features/#{value}"
|
|
54
|
+
redirect_to "/features/#{Flipper::UI::Util.escape value}"
|
|
62
55
|
end
|
|
63
56
|
end
|
|
64
57
|
end
|
|
@@ -13,11 +13,6 @@ module Flipper
|
|
|
13
13
|
feature = flipper[feature_name]
|
|
14
14
|
@feature = Decorators::Feature.new(feature)
|
|
15
15
|
|
|
16
|
-
breadcrumb 'Home', '/'
|
|
17
|
-
breadcrumb 'Features', '/features'
|
|
18
|
-
breadcrumb @feature.key, "/features/#{@feature.key}"
|
|
19
|
-
breadcrumb 'Add Group'
|
|
20
|
-
|
|
21
16
|
view_response :add_group
|
|
22
17
|
end
|
|
23
18
|
|
|
@@ -35,10 +30,10 @@ module Flipper
|
|
|
35
30
|
feature.disable_group value
|
|
36
31
|
end
|
|
37
32
|
|
|
38
|
-
redirect_to("/features/#{feature.key}")
|
|
33
|
+
redirect_to("/features/#{Flipper::UI::Util.escape feature.key}")
|
|
39
34
|
else
|
|
40
35
|
error = "The group named #{value.inspect} has not been registered."
|
|
41
|
-
redirect_to("/features/#{feature.key}/groups?error=#{error}")
|
|
36
|
+
redirect_to("/features/#{Flipper::UI::Util.escape feature.key}/groups?error=#{Flipper::UI::Util.escape error}")
|
|
42
37
|
end
|
|
43
38
|
end
|
|
44
39
|
end
|
|
@@ -19,10 +19,10 @@ module Flipper
|
|
|
19
19
|
feature.enable_percentage_of_actors params['value']
|
|
20
20
|
rescue ArgumentError => exception
|
|
21
21
|
error = "Invalid percentage of actors value: #{exception.message}"
|
|
22
|
-
redirect_to("/features/#{@feature.key}?error=#{error}")
|
|
22
|
+
redirect_to("/features/#{Flipper::UI::Util.escape @feature.key}?error=#{Flipper::UI::Util.escape error}")
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
redirect_to "/features/#{@feature.key}"
|
|
25
|
+
redirect_to "/features/#{Flipper::UI::Util.escape @feature.key}"
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
end
|
|
@@ -19,10 +19,10 @@ module Flipper
|
|
|
19
19
|
feature.enable_percentage_of_time params['value']
|
|
20
20
|
rescue ArgumentError => exception
|
|
21
21
|
error = "Invalid percentage of time value: #{exception.message}"
|
|
22
|
-
redirect_to("/features/#{@feature.key}?error=#{error}")
|
|
22
|
+
redirect_to("/features/#{Flipper::UI::Util.escape @feature.key}?error=#{Flipper::UI::Util.escape error}")
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
redirect_to "/features/#{@feature.key}"
|
|
25
|
+
redirect_to "/features/#{Flipper::UI::Util.escape @feature.key}"
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
end
|
|
@@ -5,18 +5,28 @@ module Flipper
|
|
|
5
5
|
class Configuration
|
|
6
6
|
attr_reader :delete
|
|
7
7
|
|
|
8
|
-
attr_accessor :banner_text
|
|
9
|
-
|
|
8
|
+
attr_accessor :banner_text
|
|
9
|
+
attr_reader :banner_class
|
|
10
10
|
|
|
11
11
|
# Public: Is the UI in read only mode or not. Default is false. This
|
|
12
12
|
# supersedes all other write-related options such as
|
|
13
13
|
# (feature_creation_enabled and feature_removal_enabled).
|
|
14
14
|
attr_accessor :read_only
|
|
15
15
|
|
|
16
|
-
# Public: If you set this, the UI will always have a first
|
|
16
|
+
# Public: If you set this, the UI will always have a first nav item that
|
|
17
17
|
# says "App" which points to this href. The href can be a path (ie: "/")
|
|
18
18
|
# or full url ("https://app.example.com/").
|
|
19
|
-
attr_accessor :
|
|
19
|
+
attr_accessor :application_href
|
|
20
|
+
alias_method :application_breadcrumb_href, :application_href
|
|
21
|
+
alias_method :application_breadcrumb_href=, :application_href=
|
|
22
|
+
|
|
23
|
+
# Public: An array of nav items to show. By default "Features" and
|
|
24
|
+
# "Settings" are shown, but you can add your own. Each item must have
|
|
25
|
+
# a `:title` and `:href` key:
|
|
26
|
+
#
|
|
27
|
+
# config.nav_items << { title: "Custom", href: "/custom/page" }
|
|
28
|
+
#
|
|
29
|
+
attr_accessor :nav_items
|
|
20
30
|
|
|
21
31
|
# Public: Is feature creation allowed from the UI? Defaults to true. If
|
|
22
32
|
# set to false, users of the UI cannot create features. All feature
|
|
@@ -97,6 +107,10 @@ module Flipper
|
|
|
97
107
|
@confirm_fully_enable = false
|
|
98
108
|
@confirm_disable = true
|
|
99
109
|
@read_only = false
|
|
110
|
+
@nav_items = [
|
|
111
|
+
{ title: "Features", href: "features" },
|
|
112
|
+
{ title: "Settings", href: "settings" },
|
|
113
|
+
]
|
|
100
114
|
end
|
|
101
115
|
|
|
102
116
|
def using_descriptions?
|
|
@@ -27,6 +27,7 @@ module Flipper
|
|
|
27
27
|
@action_collection.add UI::Actions::Features
|
|
28
28
|
@action_collection.add UI::Actions::Export
|
|
29
29
|
@action_collection.add UI::Actions::Import
|
|
30
|
+
@action_collection.add UI::Actions::CloudMigrate
|
|
30
31
|
@action_collection.add UI::Actions::Settings
|
|
31
32
|
|
|
32
33
|
# Static Assets/Files
|