flipper-ui 0.16.2 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +5 -5
  2. data/docs/ui/README.md +34 -24
  3. data/docs/ui/images/banner.png +0 -0
  4. data/docs/ui/images/description.png +0 -0
  5. data/docs/ui/images/feature.png +0 -0
  6. data/docs/ui/images/features.png +0 -0
  7. data/examples/ui/basic.ru +20 -0
  8. data/flipper-ui.gemspec +2 -3
  9. data/lib/flipper/ui/action.rb +3 -6
  10. data/lib/flipper/ui/actions/feature.rb +5 -2
  11. data/lib/flipper/ui/actions/features.rb +14 -1
  12. data/lib/flipper/ui/actions/file.rb +1 -1
  13. data/lib/flipper/ui/assets/javascripts/application.coffee +5 -3
  14. data/lib/flipper/ui/configuration.rb +34 -10
  15. data/lib/flipper/ui/decorators/feature.rb +39 -13
  16. data/lib/flipper/ui/public/css/application.css +20 -6493
  17. data/lib/flipper/ui/public/js/application.js +5 -5
  18. data/lib/flipper/ui/util.rb +40 -0
  19. data/lib/flipper/ui/views/add_actor.erb +2 -2
  20. data/lib/flipper/ui/views/add_feature.erb +2 -2
  21. data/lib/flipper/ui/views/add_group.erb +1 -1
  22. data/lib/flipper/ui/views/feature.erb +199 -180
  23. data/lib/flipper/ui/views/features.erb +55 -36
  24. data/lib/flipper/ui/views/layout.erb +4 -14
  25. data/lib/flipper/ui.rb +4 -7
  26. data/lib/flipper/version.rb +1 -1
  27. data/spec/flipper/ui/actions/actors_gate_spec.rb +9 -13
  28. data/spec/flipper/ui/actions/feature_spec.rb +14 -16
  29. data/spec/flipper/ui/actions/features_spec.rb +49 -14
  30. data/spec/flipper/ui/actions/file_spec.rb +0 -10
  31. data/spec/flipper/ui/actions/groups_gate_spec.rb +0 -6
  32. data/spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb +0 -2
  33. data/spec/flipper/ui/actions/percentage_of_time_gate_spec.rb +0 -2
  34. data/spec/flipper/ui/configuration_spec.rb +69 -34
  35. data/spec/flipper/ui/decorators/feature_spec.rb +2 -32
  36. data/spec/flipper/ui_spec.rb +1 -1
  37. metadata +21 -133
  38. data/docs/ui/images/configured-ui.png +0 -0
  39. data/docs/ui/images/environment-banner.png +0 -0
  40. data/lib/flipper/ui/assets/stylesheets/.DS_Store +0 -0
  41. data/lib/flipper/ui/assets/stylesheets/application.scss +0 -19
  42. data/lib/flipper/ui/assets/stylesheets/bootstrap/_alert.scss +0 -51
  43. data/lib/flipper/ui/assets/stylesheets/bootstrap/_badge.scss +0 -47
  44. data/lib/flipper/ui/assets/stylesheets/bootstrap/_breadcrumb.scss +0 -38
  45. data/lib/flipper/ui/assets/stylesheets/bootstrap/_button-group.scss +0 -166
  46. data/lib/flipper/ui/assets/stylesheets/bootstrap/_buttons.scss +0 -143
  47. data/lib/flipper/ui/assets/stylesheets/bootstrap/_card.scss +0 -270
  48. data/lib/flipper/ui/assets/stylesheets/bootstrap/_carousel.scss +0 -191
  49. data/lib/flipper/ui/assets/stylesheets/bootstrap/_close.scss +0 -34
  50. data/lib/flipper/ui/assets/stylesheets/bootstrap/_code.scss +0 -56
  51. data/lib/flipper/ui/assets/stylesheets/bootstrap/_custom-forms.scss +0 -297
  52. data/lib/flipper/ui/assets/stylesheets/bootstrap/_dropdown.scss +0 -131
  53. data/lib/flipper/ui/assets/stylesheets/bootstrap/_forms.scss +0 -333
  54. data/lib/flipper/ui/assets/stylesheets/bootstrap/_functions.scss +0 -86
  55. data/lib/flipper/ui/assets/stylesheets/bootstrap/_grid.scss +0 -52
  56. data/lib/flipper/ui/assets/stylesheets/bootstrap/_images.scss +0 -42
  57. data/lib/flipper/ui/assets/stylesheets/bootstrap/_input-group.scss +0 -159
  58. data/lib/flipper/ui/assets/stylesheets/bootstrap/_jumbotron.scss +0 -16
  59. data/lib/flipper/ui/assets/stylesheets/bootstrap/_list-group.scss +0 -115
  60. data/lib/flipper/ui/assets/stylesheets/bootstrap/_media.scss +0 -8
  61. data/lib/flipper/ui/assets/stylesheets/bootstrap/_mixins.scss +0 -42
  62. data/lib/flipper/ui/assets/stylesheets/bootstrap/_modal.scss +0 -168
  63. data/lib/flipper/ui/assets/stylesheets/bootstrap/_nav.scss +0 -118
  64. data/lib/flipper/ui/assets/stylesheets/bootstrap/_navbar.scss +0 -311
  65. data/lib/flipper/ui/assets/stylesheets/bootstrap/_pagination.scss +0 -77
  66. data/lib/flipper/ui/assets/stylesheets/bootstrap/_popover.scss +0 -183
  67. data/lib/flipper/ui/assets/stylesheets/bootstrap/_print.scss +0 -124
  68. data/lib/flipper/ui/assets/stylesheets/bootstrap/_progress.scss +0 -33
  69. data/lib/flipper/ui/assets/stylesheets/bootstrap/_reboot.scss +0 -482
  70. data/lib/flipper/ui/assets/stylesheets/bootstrap/_root.scss +0 -19
  71. data/lib/flipper/ui/assets/stylesheets/bootstrap/_tables.scss +0 -180
  72. data/lib/flipper/ui/assets/stylesheets/bootstrap/_tooltip.scss +0 -115
  73. data/lib/flipper/ui/assets/stylesheets/bootstrap/_transitions.scss +0 -36
  74. data/lib/flipper/ui/assets/stylesheets/bootstrap/_type.scss +0 -125
  75. data/lib/flipper/ui/assets/stylesheets/bootstrap/_utilities.scss +0 -14
  76. data/lib/flipper/ui/assets/stylesheets/bootstrap/_variables.scss +0 -894
  77. data/lib/flipper/ui/assets/stylesheets/bootstrap/bootstrap-grid.scss +0 -32
  78. data/lib/flipper/ui/assets/stylesheets/bootstrap/bootstrap-reboot.scss +0 -12
  79. data/lib/flipper/ui/assets/stylesheets/bootstrap/bootstrap.scss +0 -42
  80. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_alert.scss +0 -13
  81. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_background-variant.scss +0 -21
  82. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_badge.scss +0 -12
  83. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_border-radius.scss +0 -35
  84. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_box-shadow.scss +0 -5
  85. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_breakpoints.scss +0 -123
  86. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_buttons.scss +0 -109
  87. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_caret.scss +0 -65
  88. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_clearfix.scss +0 -7
  89. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_float.scss +0 -11
  90. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_forms.scss +0 -137
  91. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_gradients.scss +0 -45
  92. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +0 -67
  93. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_grid.scss +0 -52
  94. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_hover.scss +0 -39
  95. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_image.scss +0 -36
  96. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_list-group.scss +0 -21
  97. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_lists.scss +0 -7
  98. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_nav-divider.scss +0 -10
  99. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_navbar-align.scss +0 -10
  100. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_pagination.scss +0 -22
  101. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_reset-text.scss +0 -17
  102. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_resize.scss +0 -6
  103. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_screen-reader.scss +0 -35
  104. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_size.scss +0 -6
  105. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_table-row.scss +0 -30
  106. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +0 -14
  107. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_text-hide.scss +0 -9
  108. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_text-truncate.scss +0 -8
  109. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_transition.scss +0 -9
  110. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_visibility.scss +0 -7
  111. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_align.scss +0 -8
  112. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_background.scss +0 -19
  113. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_borders.scss +0 -59
  114. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_clearfix.scss +0 -3
  115. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_display.scss +0 -38
  116. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_embed.scss +0 -52
  117. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_flex.scss +0 -46
  118. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_float.scss +0 -9
  119. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_position.scss +0 -36
  120. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_screenreaders.scss +0 -11
  121. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_sizing.scss +0 -12
  122. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_spacing.scss +0 -51
  123. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_text.scss +0 -52
  124. data/lib/flipper/ui/assets/stylesheets/bootstrap/utilities/_visibility.scss +0 -11
  125. data/lib/flipper/ui/assets/stylesheets/primer/.scss-lint.yml +0 -446
  126. data/lib/flipper/ui/assets/stylesheets/primer/_alerts.scss +0 -106
  127. data/lib/flipper/ui/assets/stylesheets/primer/_avatars.scss +0 -36
  128. data/lib/flipper/ui/assets/stylesheets/primer/_base.scss +0 -40
  129. data/lib/flipper/ui/assets/stylesheets/primer/_blankslate.scss +0 -96
  130. data/lib/flipper/ui/assets/stylesheets/primer/_buttons.scss +0 -404
  131. data/lib/flipper/ui/assets/stylesheets/primer/_counter.scss +0 -10
  132. data/lib/flipper/ui/assets/stylesheets/primer/_filter-list.scss +0 -68
  133. data/lib/flipper/ui/assets/stylesheets/primer/_flex-table.scss +0 -20
  134. data/lib/flipper/ui/assets/stylesheets/primer/_forms.scss +0 -756
  135. data/lib/flipper/ui/assets/stylesheets/primer/_layout.scss +0 -69
  136. data/lib/flipper/ui/assets/stylesheets/primer/_menu.scss +0 -113
  137. data/lib/flipper/ui/assets/stylesheets/primer/_mixins.scss +0 -53
  138. data/lib/flipper/ui/assets/stylesheets/primer/_normalize.scss +0 -425
  139. data/lib/flipper/ui/assets/stylesheets/primer/_states.scss +0 -32
  140. data/lib/flipper/ui/assets/stylesheets/primer/_tabnav.scss +0 -65
  141. data/lib/flipper/ui/assets/stylesheets/primer/_tooltips.scss +0 -255
  142. data/lib/flipper/ui/assets/stylesheets/primer/_truncate.scss +0 -27
  143. data/lib/flipper/ui/assets/stylesheets/primer/_type.scss +0 -92
  144. data/lib/flipper/ui/assets/stylesheets/primer/_utility.scss +0 -73
  145. data/lib/flipper/ui/assets/stylesheets/primer/_variables.scss +0 -34
  146. data/lib/flipper/ui/assets/stylesheets/primer/primer.scss +0 -39
  147. data/lib/flipper/ui/eruby.rb +0 -11
  148. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  149. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.svg +0 -288
  150. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  151. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  152. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  153. data/lib/flipper/ui/public/images/remove.png +0 -0
  154. data/lib/flipper/ui/public/octicons/octicons.less +0 -235
  155. data/lib/flipper/ui/public/octicons/sprockets-octicons.scss +0 -232
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 71eccacf760968860d08a08de30d86c435314c3a
4
- data.tar.gz: 9e6a0d87e9158c108dbf7c80fbf663576899fcf3
2
+ SHA256:
3
+ metadata.gz: bfa566d9ce94dadf56643f0f8effcd75795dc478e8098a91374fa20b612d772c
4
+ data.tar.gz: 0423fa89225c97f21cfe5bc851b43c8d13dbe930764989a8255cd61ab23bdada
5
5
  SHA512:
6
- metadata.gz: 5790f438fba84b3a34301fc004fab83f6609c249026438639395781b474848e2c57f38aa612a5864e6365b5e2e853b00a7c72c96c69e6b9074e37fd5e55da44b
7
- data.tar.gz: ed1011c894f34b0ebd3ff87a06ed5687428c7ba8d76466d8e18a49ccfc595716eae65afdb6f2b54786ebde372f8ad367b6bea079773da00977d155d06d9b2d64
6
+ metadata.gz: b65bcd93a19db4a5807f6ef4900d99ec9e8bf3232e569d0e5c27d4ad54b294657055448d5b45ee68bc66b9bf03a5810c090b210adf1de7501ea3bd61cdbd4c39
7
+ data.tar.gz: 52c3fbade80bc667eed46f94059d65f84c1e46330a456dda768c6cbc5e807b0681bb5d8952e88fde8b4dae992009ac559c5073073987bfdc581b55ca75482790
data/docs/ui/README.md CHANGED
@@ -5,9 +5,11 @@ UI for the [Flipper](https://github.com/jnunemaker/flipper) gem.
5
5
  ## Screenshots
6
6
 
7
7
  Viewing list of features:
8
+
8
9
  ![features](images/features.png)
9
10
 
10
11
  Viewing an individual feature:
12
+
11
13
  ![feature](images/feature.png)
12
14
 
13
15
  ## Installation
@@ -37,14 +39,15 @@ YourRailsApp::Application.routes.draw do
37
39
  end
38
40
  ```
39
41
 
40
- If you'd like to lazy load flipper, you can pass a block instead:
42
+ If you'd like to lazy load flipper, you can instead pass a block to initialize it:
41
43
 
42
44
  ```ruby
43
45
  # config/routes.rb
44
46
  YourRailsApp::Application.routes.draw do
45
47
  flipper_block = lambda {
46
48
  # some flipper initialization here, for example:
47
- # YourRailsApp.flipper
49
+ adapter = Flipper::Adapters::Memory.new
50
+ Flipper.new(adapter)
48
51
  }
49
52
  mount Flipper::UI.app(flipper_block) => '/flipper'
50
53
  end
@@ -95,7 +98,7 @@ end
95
98
  # config/routes.rb
96
99
 
97
100
  constraints CanAccessFlipperUI do
98
- mount Flipper::UI.app(flipper) => '/flipper'
101
+ mount Flipper::UI.app(Flipper) => '/flipper'
99
102
  end
100
103
  ```
101
104
 
@@ -126,32 +129,30 @@ See [examples/ui/basic.ru](https://github.com/jnunemaker/flipper/blob/master/exa
126
129
 
127
130
  ### Configuration
128
131
 
129
- Flipper UI can be customized via `configure`, which yields a configuration instance for setting the text on the five main sections of the UI feature view.
132
+ Flipper UI can be customized via `configure`, which yields a configuration instance.
130
133
 
131
- * `config.actors`
132
- * `config.groups`
133
- * `config.percentage_of_actors`
134
- * `config.percentage_of_time`
135
- * `config.delete`
134
+ #### Description
136
135
 
137
- Each of these methods returns a [Flipper::UI::Option](https://github.com/jnunemaker/flipper/blob/master/lib/flipper/ui/configuration/option.rb) that responds to `title=`, `description=` as seen below.
136
+ We can associate a `description` for each `feature` by providing a descriptions source:
138
137
 
139
- *e.g. customzing the percentage_of_actors and delete sections' titles and descriptions*
140
138
  ```ruby
141
139
  Flipper::UI.configure do |config|
142
- config.percentage_of_actors.title = "My Custom Title"
143
- config.percentage_of_actors.description = "My custom description"
140
+ config.descriptions_source = ->(keys) do
141
+ # descriptions loaded from YAML file or database (postgres, mysql, etc)
142
+ # return has to be hash of {String key => String description}
143
+ end
144
144
 
145
- config.delete.title = "BE VERY CAREFUL!"
146
- config.delete.description = "YOU'VE BEEN WARNED!"
145
+ # Defaults to false. Set to true to show feature descriptions on the list
146
+ # page as well as the view page.
147
+ # config.show_feature_description_in_list = true
147
148
  end
148
149
  ```
149
150
 
150
- results in:
151
+ Descriptions show up in the UI like so:
151
152
 
152
- ![configure](images/configured-ui.png)
153
+ ![description](images/description.png)
153
154
 
154
- ### Banner
155
+ #### Banner
155
156
 
156
157
  Flipper UI can display a banner across the top of the page. The `banner_text` and `banner_class` can be configured by using the `Flipper::UI.configure` block as seen below.
157
158
 
@@ -166,15 +167,24 @@ By default the `environment` is set to an empty string so no banner will show. I
166
167
 
167
168
  The above configuration results in:
168
169
 
169
- ![configure](images/environment-banner.png)
170
+ ![banner](images/banner.png)
171
+
172
+ #### Fun mode
173
+
174
+ By default, Flipper UI displays a videoclip when there are no flags. The `fun` mode can be configured by using the `Flipper::UI.configure` block as seen below.
175
+
176
+ ```ruby
177
+ Flipper::UI.configure do |config|
178
+ config.fun = false
179
+ end
180
+ ```
170
181
 
171
182
  ## Contributing
172
183
 
173
184
  1. Fork it
174
185
  2. Create your feature branch (`git checkout -b my-new-feature`)
175
186
  3. **Fire up the app** (`script/server`)
176
- 4. **Start up guard** (`bundle exec guard` for automatic coffeescript/sass compilation and such).
177
- 5. Run the tests `bundle exec rake`
178
- 6. Commit your changes (`git commit -am 'Added some feature'`)
179
- 7. Push to the branch (`git push origin my-new-feature`)
180
- 8. Create new Pull Request
187
+ 4. Run the tests `bundle exec rake`
188
+ 5. Commit your changes (`git commit -am 'Added some feature'`)
189
+ 6. Push to the branch (`git push origin my-new-feature`)
190
+ 7. Create new Pull Request
Binary file
Binary file
Binary file
Binary file
data/examples/ui/basic.ru CHANGED
@@ -34,6 +34,26 @@ end
34
34
  adapter = Flipper::Adapters::PStore.new
35
35
  flipper = Flipper.new(adapter, instrumenter: ActiveSupport::Notifications)
36
36
 
37
+ Flipper::UI.configure do |config|
38
+ # config.banner_text = 'Production Environment'
39
+ # config.banner_class = 'danger'
40
+ config.feature_creation_enabled = true
41
+ config.feature_removal_enabled = true
42
+ # config.show_feature_description_in_list = true
43
+ config.descriptions_source = lambda do |_keys|
44
+ {
45
+ "search_performance_another_long_thing" => "Just to test feature name length.",
46
+ "gauges_tracking" => "Should we track page views with gaug.es.",
47
+ "unused" => "Not used.",
48
+ "suits" => "Are suits necessary in business?",
49
+ "secrets" => "Secrets are lies.",
50
+ "logging" => "Log all the things.",
51
+ "new_cache" => "Like the old cache but newer.",
52
+ "a/b" => "Why would someone use a slash? I don't know but someone did. Let's make this really long so they regret using slashes. Please don't use slashes.",
53
+ }
54
+ end
55
+ end
56
+
37
57
  # You can uncomment these to get some default data:
38
58
  # flipper[:search_performance_another_long_thing].enable
39
59
  # flipper[:gauges_tracking].enable
data/flipper-ui.gemspec CHANGED
@@ -10,7 +10,6 @@ Gem::Specification.new do |gem|
10
10
  gem.authors = ['John Nunemaker']
11
11
  gem.email = ['nunemaker@gmail.com']
12
12
  gem.summary = 'UI for the Flipper gem'
13
- gem.description = 'Rack middleware that provides a fully featured web interface for the flipper gem.'
14
13
  gem.license = 'MIT'
15
14
  gem.homepage = 'https://github.com/jnunemaker/flipper'
16
15
 
@@ -22,7 +21,7 @@ Gem::Specification.new do |gem|
22
21
  gem.metadata = Flipper::METADATA
23
22
 
24
23
  gem.add_dependency 'rack', '>= 1.4', '< 3'
25
- gem.add_dependency 'rack-protection', '>= 1.5.3', '< 2.1.0'
24
+ gem.add_dependency 'rack-protection', '>= 1.5.3', '< 2.2.0'
26
25
  gem.add_dependency 'flipper', "~> #{Flipper::VERSION}"
27
- gem.add_dependency 'erubis', '~> 2.7.0'
26
+ gem.add_dependency 'erubi', '>= 1.0.0', '< 2.0.0'
28
27
  end
@@ -1,6 +1,7 @@
1
1
  require 'forwardable'
2
+ require 'flipper/ui/configuration'
2
3
  require 'flipper/ui/error'
3
- require 'flipper/ui/eruby'
4
+ require 'erubi'
4
5
  require 'json'
5
6
 
6
7
  module Flipper
@@ -205,12 +206,8 @@ module Flipper
205
206
  # Private
206
207
  def view(name)
207
208
  path = views_path.join("#{name}.erb")
208
-
209
209
  raise "Template does not exist: #{path}" unless path.exist?
210
-
211
- contents = path.read
212
- compiled = Eruby.new(contents)
213
- compiled.result proc {}.binding
210
+ eval(Erubi::Engine.new(path.read, escape: true).src)
214
211
  end
215
212
 
216
213
  # Internal: The path the app is mounted at.
@@ -10,9 +10,12 @@ module Flipper
10
10
  route %r{\A/features/(?<feature_name>.*)\Z}
11
11
 
12
12
  def get
13
- @feature = Decorators::Feature.new(flipper[feature_name])
13
+ flipper_feature = flipper[feature_name]
14
+ @feature = Decorators::Feature.new(flipper_feature)
15
+ descriptions = Flipper::UI.configuration.descriptions_source.call([flipper_feature.key])
16
+ @feature.description = descriptions[@feature.key]
14
17
  @page_title = "#{@feature.key} // Features"
15
- @percentages = [0, 1, 5, 10, 15, 25, 50, 75, 100]
18
+ @percentages = [0, 1, 5, 10, 25, 50, 100]
16
19
 
17
20
  breadcrumb 'Home', '/'
18
21
  breadcrumb 'Features', '/features'
@@ -10,8 +10,21 @@ module Flipper
10
10
 
11
11
  def get
12
12
  @page_title = 'Features'
13
+ keys = flipper.features.map(&:key)
14
+ descriptions = if Flipper::UI.configuration.show_feature_description_in_list?
15
+ Flipper::UI.configuration.descriptions_source.call(keys)
16
+ else
17
+ {}
18
+ end
19
+
13
20
  @features = flipper.features.map do |feature|
14
- Decorators::Feature.new(feature)
21
+ decorated_feature = Decorators::Feature.new(feature)
22
+
23
+ if Flipper::UI.configuration.show_feature_description_in_list?
24
+ decorated_feature.description = descriptions[feature.key]
25
+ end
26
+
27
+ decorated_feature
15
28
  end.sort
16
29
 
17
30
  @show_blank_slate = @features.empty?
@@ -5,7 +5,7 @@ module Flipper
5
5
  module UI
6
6
  module Actions
7
7
  class File < UI::Action
8
- route %r{(images|css|js|octicons|fonts)/.*\Z}
8
+ route %r{(images|css|js|octicons)/.*\Z}
9
9
 
10
10
  def get
11
11
  Rack::File.new(public_path).call(request.env)
@@ -1,3 +1,5 @@
1
- $(() ->
2
- $('[data-toggle="tooltip"]').tooltip();
3
- );
1
+ $ ->
2
+ $(document).on('click', '.js-toggle-trigger', ->
3
+ $container = $(this).closest('.js-toggle-container')
4
+ $container.toggleClass('toggle-on')
5
+ )
@@ -3,11 +3,7 @@ require 'flipper/ui/configuration/option'
3
3
  module Flipper
4
4
  module UI
5
5
  class Configuration
6
- attr_reader :actors,
7
- :delete,
8
- :groups,
9
- :percentage_of_actors,
10
- :percentage_of_time
6
+ attr_reader :delete
11
7
 
12
8
  attr_accessor :banner_text,
13
9
  :banner_class
@@ -26,6 +22,24 @@ module Flipper
26
22
  # set to false, users won't be able to delete features from the UI.
27
23
  attr_accessor :feature_removal_enabled
28
24
 
25
+ # Public: Are you feeling lucky? Defaults to true. If set to false, users
26
+ # won't see a videoclip of Taylor Swift when there aren't any features
27
+ attr_accessor :fun
28
+
29
+ # Public: What should show up in the form to add actors. This can be
30
+ # different per application since flipper_id's can be whatever an
31
+ # application needs. Defaults to "a flipper id".
32
+ attr_accessor :add_actor_placeholder
33
+
34
+ # Public: If you set this, Flipper::UI will fetch descriptions
35
+ # from your external source. Descriptions for `features` will be shown on `feature`
36
+ # page, and optionally the `features` pages. Defaults to empty block.
37
+ attr_accessor :descriptions_source
38
+
39
+ # Public: Should feature descriptions be show on the `features` list page.
40
+ # Default false. Only works when using descriptions.
41
+ attr_accessor :show_feature_description_in_list
42
+
29
43
  VALID_BANNER_CLASS_VALUES = %w(
30
44
  danger
31
45
  dark
@@ -37,16 +51,26 @@ module Flipper
37
51
  warning
38
52
  ).freeze
39
53
 
54
+ DEFAULT_DESCRIPTIONS_SOURCE = ->(_keys) { {} }
55
+
40
56
  def initialize
41
- @actors = Option.new("Actors", "Enable actors using the form above.")
42
- @groups = Option.new("Groups", "Enable groups using the form above.")
43
- @percentage_of_actors = Option.new("Percentage of Actors", "Percentage of actors functions independently of percentage of time. If you enable 50% of Actors and 25% of Time then the feature will always be enabled for 50% of users and occasionally enabled 25% of the time for everyone.") # rubocop:disable Metrics/LineLength
44
- @percentage_of_time = Option.new("Percentage of Time", "Percentage of actors functions independently of percentage of time. If you enable 50% of Actors and 25% of Time then the feature will always be enabled for 50% of users and occasionally enabled 25% of the time for everyone.") # rubocop:disable Metrics/LineLength
45
- @delete = Option.new("Danger Zone", "Deleting a feature removes it from the list of features and disables it for everyone.") # rubocop:disable Metrics/LineLength
57
+ @delete = Option.new("Danger Zone", "Deleting a feature removes it from the list of features and disables it for everyone.")
46
58
  @banner_text = nil
47
59
  @banner_class = 'danger'
48
60
  @feature_creation_enabled = true
49
61
  @feature_removal_enabled = true
62
+ @fun = true
63
+ @add_actor_placeholder = "a flipper id"
64
+ @descriptions_source = DEFAULT_DESCRIPTIONS_SOURCE
65
+ @show_feature_description_in_list = false
66
+ end
67
+
68
+ def using_descriptions?
69
+ @descriptions_source != DEFAULT_DESCRIPTIONS_SOURCE
70
+ end
71
+
72
+ def show_feature_description_in_list?
73
+ using_descriptions? && @show_feature_description_in_list
50
74
  end
51
75
 
52
76
  def banner_class=(value)
@@ -11,24 +11,15 @@ module Flipper
11
11
  # Public: The feature being decorated.
12
12
  alias_method :feature, :__getobj__
13
13
 
14
+ # Internal: Used to preload description if descriptions_source is
15
+ # configured for Flipper::UI.
16
+ attr_accessor :description
17
+
14
18
  # Public: Returns name titleized.
15
19
  def pretty_name
16
20
  @pretty_name ||= Util.titleize(name)
17
21
  end
18
22
 
19
- # Public: Returns instance as hash that is ready to be json dumped.
20
- def as_json
21
- gate_values = feature.gate_values
22
- {
23
- 'id' => name.to_s,
24
- 'name' => pretty_name,
25
- 'state' => state.to_s,
26
- 'gates' => gates.map do |gate|
27
- Decorators::Gate.new(gate, gate_values[gate.key]).as_json
28
- end,
29
- }
30
- end
31
-
32
23
  def color_class
33
24
  case feature.state
34
25
  when :on
@@ -40,6 +31,41 @@ module Flipper
40
31
  end
41
32
  end
42
33
 
34
+ def gates_in_words
35
+ return "Fully Enabled" if feature.boolean_value
36
+
37
+ statuses = []
38
+
39
+ if feature.actors_value.count > 0
40
+ statuses << %Q(<span data-toggle="tooltip" data-placement="bottom" title="#{Util.to_sentence(feature.actors_value.to_a)}">) + Util.pluralize(feature.actors_value.count, 'actor', 'actors') + "</span>"
41
+ end
42
+
43
+ if feature.groups_value.count > 0
44
+ statuses << %Q(<span data-toggle="tooltip" data-placement="bottom" title="#{Util.to_sentence(feature.groups_value.to_a)}">) + Util.pluralize(feature.groups_value.count, 'group', 'groups') + "</span>"
45
+ end
46
+
47
+ if feature.percentage_of_actors_value > 0
48
+ statuses << "#{feature.percentage_of_actors_value}% of actors"
49
+ end
50
+
51
+ if feature.percentage_of_time_value > 0
52
+ statuses << "#{feature.percentage_of_time_value}% of time"
53
+ end
54
+
55
+ Util.to_sentence(statuses)
56
+ end
57
+
58
+ def gate_state_title
59
+ case feature.state
60
+ when :on
61
+ "Fully enabled"
62
+ when :conditional
63
+ "Conditionally enabled"
64
+ else
65
+ "Disabled"
66
+ end
67
+ end
68
+
43
69
  def pretty_enabled_gate_names
44
70
  enabled_gates.map { |gate| Util.titleize(gate.key) }.sort.join(', ')
45
71
  end