flipper-ui 0.2.0.beta2 → 0.2.0.beta3

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.
Files changed (218) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +12 -11
  3. data/README.md +5 -7
  4. data/examples/basic.ru +27 -26
  5. data/flipper-ui.gemspec +5 -3
  6. data/lib/flipper-ui.rb +1 -0
  7. data/lib/flipper/ui.rb +11 -2
  8. data/lib/flipper/ui/action.rb +45 -4
  9. data/lib/flipper/ui/actions/actors_gate.rb +48 -0
  10. data/lib/flipper/ui/actions/add_feature.rb +20 -0
  11. data/lib/flipper/ui/actions/boolean_gate.rb +26 -0
  12. data/lib/flipper/ui/actions/feature.rb +32 -0
  13. data/lib/flipper/ui/actions/features.rb +23 -3
  14. data/lib/flipper/ui/actions/file.rb +1 -1
  15. data/lib/flipper/ui/actions/gate.rb +11 -117
  16. data/lib/flipper/ui/actions/groups_gate.rb +43 -0
  17. data/lib/flipper/ui/actions/{index.rb → home.rb} +3 -3
  18. data/lib/flipper/ui/actions/percentage_of_actors_gate.rb +27 -0
  19. data/lib/flipper/ui/actions/percentage_of_time_gate.rb +27 -0
  20. data/lib/flipper/ui/actor.rb +13 -0
  21. data/lib/flipper/ui/assets/javascripts/application.coffee +0 -305
  22. data/lib/flipper/ui/assets/stylesheets/_bootstrap-compass.scss +9 -0
  23. data/lib/flipper/ui/assets/stylesheets/_bootstrap-mincer.scss +19 -0
  24. data/lib/flipper/ui/assets/stylesheets/_bootstrap-sprockets.scss +9 -0
  25. data/lib/flipper/ui/assets/stylesheets/_bootstrap.scss +50 -0
  26. data/lib/flipper/ui/assets/stylesheets/application.scss +33 -216
  27. data/lib/flipper/ui/assets/stylesheets/bootstrap/_alerts.scss +73 -0
  28. data/lib/flipper/ui/assets/stylesheets/bootstrap/_badges.scss +68 -0
  29. data/lib/flipper/ui/assets/stylesheets/bootstrap/_breadcrumbs.scss +26 -0
  30. data/lib/flipper/ui/assets/stylesheets/bootstrap/_button-groups.scss +243 -0
  31. data/lib/flipper/ui/assets/stylesheets/bootstrap/_buttons.scss +160 -0
  32. data/lib/flipper/ui/assets/stylesheets/bootstrap/_carousel.scss +269 -0
  33. data/lib/flipper/ui/assets/stylesheets/bootstrap/_close.scss +36 -0
  34. data/lib/flipper/ui/assets/stylesheets/bootstrap/_code.scss +69 -0
  35. data/lib/flipper/ui/assets/stylesheets/bootstrap/_component-animations.scss +37 -0
  36. data/lib/flipper/ui/assets/stylesheets/bootstrap/_dropdowns.scss +214 -0
  37. data/lib/flipper/ui/assets/stylesheets/bootstrap/_forms.scss +578 -0
  38. data/lib/flipper/ui/assets/stylesheets/bootstrap/_glyphicons.scss +305 -0
  39. data/lib/flipper/ui/assets/stylesheets/bootstrap/_grid.scss +84 -0
  40. data/lib/flipper/ui/assets/stylesheets/bootstrap/_input-groups.scss +166 -0
  41. data/lib/flipper/ui/assets/stylesheets/bootstrap/_jumbotron.scss +50 -0
  42. data/lib/flipper/ui/assets/stylesheets/bootstrap/_labels.scss +66 -0
  43. data/lib/flipper/ui/assets/stylesheets/bootstrap/_list-group.scss +124 -0
  44. data/lib/flipper/ui/assets/stylesheets/bootstrap/_media.scss +61 -0
  45. data/lib/flipper/ui/assets/stylesheets/bootstrap/_mixins.scss +39 -0
  46. data/lib/flipper/ui/assets/stylesheets/bootstrap/_modals.scss +150 -0
  47. data/lib/flipper/ui/assets/stylesheets/bootstrap/_navbar.scss +662 -0
  48. data/lib/flipper/ui/assets/stylesheets/bootstrap/_navs.scss +242 -0
  49. data/lib/flipper/ui/assets/stylesheets/bootstrap/_normalize.scss +427 -0
  50. data/lib/flipper/ui/assets/stylesheets/bootstrap/_pager.scss +54 -0
  51. data/lib/flipper/ui/assets/stylesheets/bootstrap/_pagination.scss +88 -0
  52. data/lib/flipper/ui/assets/stylesheets/bootstrap/_panels.scss +265 -0
  53. data/lib/flipper/ui/assets/stylesheets/bootstrap/_popovers.scss +135 -0
  54. data/lib/flipper/ui/assets/stylesheets/bootstrap/_print.scss +107 -0
  55. data/lib/flipper/ui/assets/stylesheets/bootstrap/_progress-bars.scss +87 -0
  56. data/lib/flipper/ui/assets/stylesheets/bootstrap/_responsive-embed.scss +35 -0
  57. data/lib/flipper/ui/assets/stylesheets/bootstrap/_responsive-utilities.scss +177 -0
  58. data/lib/flipper/ui/assets/stylesheets/bootstrap/_scaffolding.scss +162 -0
  59. data/lib/flipper/ui/assets/stylesheets/bootstrap/_tables.scss +234 -0
  60. data/lib/flipper/ui/assets/stylesheets/bootstrap/_theme.scss +273 -0
  61. data/lib/flipper/ui/assets/stylesheets/bootstrap/_thumbnails.scss +38 -0
  62. data/lib/flipper/ui/assets/stylesheets/bootstrap/_tooltip.scss +102 -0
  63. data/lib/flipper/ui/assets/stylesheets/bootstrap/_type.scss +298 -0
  64. data/lib/flipper/ui/assets/stylesheets/bootstrap/_utilities.scss +55 -0
  65. data/lib/flipper/ui/assets/stylesheets/bootstrap/_variables.scss +866 -0
  66. data/lib/flipper/ui/assets/stylesheets/bootstrap/_wells.scss +29 -0
  67. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_alerts.scss +14 -0
  68. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_background-variant.scss +11 -0
  69. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_border-radius.scss +18 -0
  70. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_buttons.scss +52 -0
  71. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_center-block.scss +7 -0
  72. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_clearfix.scss +22 -0
  73. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_forms.scss +88 -0
  74. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_gradients.scss +58 -0
  75. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +81 -0
  76. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_grid.scss +122 -0
  77. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_hide-text.scss +21 -0
  78. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_image.scss +33 -0
  79. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_labels.scss +12 -0
  80. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_list-group.scss +31 -0
  81. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_nav-divider.scss +10 -0
  82. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  83. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_opacity.scss +8 -0
  84. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_pagination.scss +23 -0
  85. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_panels.scss +24 -0
  86. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_progress-bar.scss +10 -0
  87. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_reset-filter.scss +8 -0
  88. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_resize.scss +6 -0
  89. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_responsive-visibility.scss +21 -0
  90. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_size.scss +10 -0
  91. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_tab-focus.scss +9 -0
  92. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_table-row.scss +28 -0
  93. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +11 -0
  94. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_text-overflow.scss +8 -0
  95. data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss +222 -0
  96. data/lib/flipper/ui/assets/stylesheets/primer/.scss-lint.yml +446 -0
  97. data/lib/flipper/ui/assets/stylesheets/primer/_alerts.scss +106 -0
  98. data/lib/flipper/ui/assets/stylesheets/primer/_avatars.scss +36 -0
  99. data/lib/flipper/ui/assets/stylesheets/primer/_base.scss +40 -0
  100. data/lib/flipper/ui/assets/stylesheets/primer/_blankslate.scss +96 -0
  101. data/lib/flipper/ui/assets/stylesheets/primer/_buttons.scss +404 -0
  102. data/lib/flipper/ui/assets/stylesheets/primer/_counter.scss +10 -0
  103. data/lib/flipper/ui/assets/stylesheets/primer/_filter-list.scss +68 -0
  104. data/lib/flipper/ui/assets/stylesheets/primer/_flex-table.scss +20 -0
  105. data/lib/flipper/ui/assets/stylesheets/primer/_forms.scss +756 -0
  106. data/lib/flipper/ui/assets/stylesheets/primer/_layout.scss +69 -0
  107. data/lib/flipper/ui/assets/stylesheets/primer/_menu.scss +113 -0
  108. data/lib/flipper/ui/assets/stylesheets/primer/_mixins.scss +53 -0
  109. data/lib/flipper/ui/assets/stylesheets/primer/_normalize.scss +425 -0
  110. data/lib/flipper/ui/assets/stylesheets/primer/_states.scss +32 -0
  111. data/lib/flipper/ui/assets/stylesheets/primer/_tabnav.scss +65 -0
  112. data/lib/flipper/ui/assets/stylesheets/primer/_tooltips.scss +255 -0
  113. data/lib/flipper/ui/assets/stylesheets/primer/_truncate.scss +27 -0
  114. data/lib/flipper/ui/assets/stylesheets/primer/_type.scss +92 -0
  115. data/lib/flipper/ui/assets/stylesheets/primer/_utility.scss +73 -0
  116. data/lib/flipper/ui/assets/stylesheets/primer/_variables.scss +34 -0
  117. data/lib/flipper/ui/assets/stylesheets/primer/primer.scss +39 -0
  118. data/lib/flipper/ui/decorators/feature.rb +37 -4
  119. data/lib/flipper/ui/middleware.rb +12 -3
  120. data/lib/flipper/ui/public/css/application.css +2563 -144
  121. data/lib/flipper/ui/public/css/primer.css +1 -0
  122. data/lib/flipper/ui/public/css/primer/primer.css +1933 -0
  123. data/lib/flipper/ui/public/css/scss/primer.css +1933 -0
  124. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  125. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.svg +288 -0
  126. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  127. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  128. data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  129. data/lib/flipper/ui/public/js/application.js +0 -539
  130. data/lib/flipper/ui/public/js/bootstrap-sprockets.js +12 -0
  131. data/lib/flipper/ui/public/js/bootstrap.js +2317 -0
  132. data/lib/flipper/ui/public/js/bootstrap.min.js +7 -0
  133. data/lib/flipper/ui/public/js/bootstrap/affix.js +162 -0
  134. data/lib/flipper/ui/public/js/bootstrap/alert.js +94 -0
  135. data/lib/flipper/ui/public/js/bootstrap/button.js +116 -0
  136. data/lib/flipper/ui/public/js/bootstrap/carousel.js +237 -0
  137. data/lib/flipper/ui/public/js/bootstrap/collapse.js +211 -0
  138. data/lib/flipper/ui/public/js/bootstrap/dropdown.js +161 -0
  139. data/lib/flipper/ui/public/js/bootstrap/modal.js +339 -0
  140. data/lib/flipper/ui/public/js/bootstrap/popover.js +108 -0
  141. data/lib/flipper/ui/public/js/bootstrap/scrollspy.js +172 -0
  142. data/lib/flipper/ui/public/js/bootstrap/tab.js +153 -0
  143. data/lib/flipper/ui/public/js/bootstrap/tooltip.js +476 -0
  144. data/lib/flipper/ui/public/js/bootstrap/transition.js +59 -0
  145. data/lib/flipper/ui/public/octicons/LICENSE.txt +9 -0
  146. data/lib/flipper/ui/public/octicons/README.md +1 -0
  147. data/lib/flipper/ui/public/octicons/octicons-local.ttf +0 -0
  148. data/lib/flipper/ui/public/octicons/octicons.css +236 -0
  149. data/lib/flipper/ui/public/octicons/octicons.eot +0 -0
  150. data/lib/flipper/ui/public/octicons/octicons.less +235 -0
  151. data/lib/flipper/ui/public/octicons/octicons.svg +200 -0
  152. data/lib/flipper/ui/public/octicons/octicons.ttf +0 -0
  153. data/lib/flipper/ui/public/octicons/octicons.woff +0 -0
  154. data/lib/flipper/ui/public/octicons/sprockets-octicons.scss +232 -0
  155. data/lib/flipper/ui/util.rb +4 -0
  156. data/lib/flipper/ui/version.rb +1 -1
  157. data/lib/flipper/ui/views/add_actor.erb +22 -0
  158. data/lib/flipper/ui/views/add_feature.erb +18 -0
  159. data/lib/flipper/ui/views/add_group.erb +31 -0
  160. data/lib/flipper/ui/views/feature.erb +209 -0
  161. data/lib/flipper/ui/views/features.erb +46 -0
  162. data/lib/flipper/ui/views/layout.erb +31 -149
  163. data/script/release +15 -0
  164. data/spec/flipper/ui/actions/actors_gate_spec.rb +68 -0
  165. data/spec/flipper/ui/actions/add_feature_spec.rb +17 -0
  166. data/spec/flipper/ui/actions/boolean_gate_spec.rb +41 -0
  167. data/spec/flipper/ui/actions/feature_spec.rb +59 -0
  168. data/spec/flipper/ui/actions/features_spec.rb +37 -0
  169. data/spec/flipper/ui/actions/file_spec.rb +43 -0
  170. data/spec/flipper/ui/actions/gate_spec.rb +24 -0
  171. data/spec/flipper/ui/actions/groups_gate_spec.rb +80 -0
  172. data/spec/flipper/ui/actions/home_spec.rb +16 -0
  173. data/spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb +40 -0
  174. data/spec/flipper/ui/actions/percentage_of_time_gate_spec.rb +39 -0
  175. data/spec/flipper/ui/decorators/feature_spec.rb +38 -1
  176. data/spec/flipper/ui/decorators/gate_spec.rb +1 -1
  177. data/spec/flipper/ui_spec.rb +18 -441
  178. data/spec/helper.rb +22 -7
  179. metadata +199 -52
  180. data/examples/flipper.html +0 -14
  181. data/examples/flipper.png +0 -0
  182. data/lib/flipper/ui/assets/javascripts/spine/ajax.coffee +0 -223
  183. data/lib/flipper/ui/assets/javascripts/spine/list.coffee +0 -43
  184. data/lib/flipper/ui/assets/javascripts/spine/local.coffee +0 -16
  185. data/lib/flipper/ui/assets/javascripts/spine/manager.coffee +0 -83
  186. data/lib/flipper/ui/assets/javascripts/spine/relation.coffee +0 -148
  187. data/lib/flipper/ui/assets/javascripts/spine/route.coffee +0 -146
  188. data/lib/flipper/ui/assets/javascripts/spine/spine.coffee +0 -542
  189. data/lib/flipper/ui/assets/javascripts/spine/version +0 -1
  190. data/lib/flipper/ui/public/css/images/animated-overlay.gif +0 -0
  191. data/lib/flipper/ui/public/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  192. data/lib/flipper/ui/public/css/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  193. data/lib/flipper/ui/public/css/images/ui-bg_flat_10_000000_40x100.png +0 -0
  194. data/lib/flipper/ui/public/css/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  195. data/lib/flipper/ui/public/css/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  196. data/lib/flipper/ui/public/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  197. data/lib/flipper/ui/public/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  198. data/lib/flipper/ui/public/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  199. data/lib/flipper/ui/public/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  200. data/lib/flipper/ui/public/css/images/ui-icons_222222_256x240.png +0 -0
  201. data/lib/flipper/ui/public/css/images/ui-icons_228ef1_256x240.png +0 -0
  202. data/lib/flipper/ui/public/css/images/ui-icons_ef8c08_256x240.png +0 -0
  203. data/lib/flipper/ui/public/css/images/ui-icons_ffd27a_256x240.png +0 -0
  204. data/lib/flipper/ui/public/css/images/ui-icons_ffffff_256x240.png +0 -0
  205. data/lib/flipper/ui/public/css/jquery-ui-1.10.3.slider.min.css +0 -5
  206. data/lib/flipper/ui/public/js/handlebars.js +0 -1992
  207. data/lib/flipper/ui/public/js/jquery-ui-1.10.3.slider.min.js +0 -6
  208. data/lib/flipper/ui/public/js/jquery.js +0 -9555
  209. data/lib/flipper/ui/public/js/jquery.min.js +0 -4
  210. data/lib/flipper/ui/public/js/jquery.min.map +0 -1
  211. data/lib/flipper/ui/public/js/spine/ajax.js +0 -320
  212. data/lib/flipper/ui/public/js/spine/list.js +0 -72
  213. data/lib/flipper/ui/public/js/spine/local.js +0 -29
  214. data/lib/flipper/ui/public/js/spine/manager.js +0 -157
  215. data/lib/flipper/ui/public/js/spine/relation.js +0 -260
  216. data/lib/flipper/ui/public/js/spine/route.js +0 -223
  217. data/lib/flipper/ui/public/js/spine/spine.js +0 -927
  218. data/lib/flipper/ui/views/index.erb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0066f600077329991959e5bba71ad6a820c1bef8
4
- data.tar.gz: 372ff7bd0108faa1eeff9edcdb0f64f8b685c4f1
3
+ metadata.gz: 71211c26364825d2e5ba11f9669b7355f3fc8687
4
+ data.tar.gz: add561910d6cc8d6f6993ec7b3a202b567d22d5b
5
5
  SHA512:
6
- metadata.gz: 7c8a4c2ab207262a94f3d9c88b9ff0f3bc1852085bbccb586f244e59c5c6558bf7c8b19a0642cca79e3f81ea8bcc974cee83d637339b124ae0e2e8b14b3c3235
7
- data.tar.gz: 276d8e236e9ee6ab4b984c7e68f4abc16f4235c203631860ade07f694cf15e3749acca051d0e69ab1c1bb2b6a6511190728285319e8235d580ac7b22fdb18103
6
+ metadata.gz: 7bc66dd6dc92a57168d0260563fceecc003003a6030467566307f7fcc31b310bc20c38f5039778c5dfb78e3f2995018f21ac42d348a0b4f3fa7e881c7e4388fa
7
+ data.tar.gz: 655a47804905a1edf3f172915617e3056c6842dac461d65cd63b876b5773c3b3d5d62338dc48f8811e35b99428114e09804b7786582a2f9e352e988d2631b6f9
data/Gemfile CHANGED
@@ -1,17 +1,18 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem 'rake'
5
- gem 'shotgun'
6
- gem 'rspec'
7
- gem 'rack-test'
8
- gem 'activesupport'
4
+ gem 'rake', '~> 10.0.3'
5
+ gem 'shotgun', '~> 0.9'
6
+ gem 'flipper-redis', '~> 0.7.0.beta1'
7
+ gem 'rspec', '~> 2.12'
8
+ gem 'rack-test', '~> 0.6.1'
9
+ gem 'activesupport', '~> 3.2.13', '< 4.3'
9
10
 
10
11
  group(:guard) do
11
- gem 'guard'
12
- gem 'guard-rspec'
13
- gem 'guard-bundler'
14
- gem 'guard-coffeescript'
15
- gem 'guard-sass'
16
- gem 'rb-fsevent'
12
+ gem 'guard', '~> 1.6.2'
13
+ gem 'guard-rspec', '~> 2.4.0'
14
+ gem 'guard-bundler', '~> 1.0.0'
15
+ gem 'guard-coffeescript', '~> 1.2.1'
16
+ gem 'guard-sass', '~> 1.0.2'
17
+ gem 'rb-fsevent', '~> 0.9.3'
17
18
  end
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Flipper::UI
2
2
 
3
- UI for the [Flipper](https://github.com/jnunemaker/flipper) gem. __Note__: This is not fully functional yet. The end product will look like this:
4
-
5
- ![flipper web](./examples/flipper.png)
3
+ UI for the [Flipper](https://github.com/jnunemaker/flipper) gem.
6
4
 
7
5
  ## Installation
8
6
 
@@ -34,7 +32,7 @@ you can mount `Flipper::UI` to a route of your choice:
34
32
  # config/routes.rb
35
33
 
36
34
  YourRailsApp::Application.routes.draw do
37
- mount Flipper::UI.app($flipper) => '/flipper'
35
+ mount Flipper::UI.app($flipper, secret: "_your_session_secret") => '/flipper'
38
36
  end
39
37
  ```
40
38
 
@@ -47,7 +45,7 @@ You almost certainly want to limit access when using Flipper::UI in production.
47
45
 
48
46
  flipper_constraint = lambda { |request| request.remote_ip == '127.0.0.1' }
49
47
  constraints flipper_constraint do
50
- mount Flipper::UI.app($flipper) => '/flipper'
48
+ mount Flipper::UI.app($flipper, secret: "_your_session_secret") => '/flipper'
51
49
  end
52
50
  ```
53
51
 
@@ -67,7 +65,7 @@ end
67
65
  # config/routes.rb
68
66
 
69
67
  constraints CanAccessFlipperUI do
70
- mount Flipper::UI.app($flipper) => '/flipper'
68
+ mount Flipper::UI.app($flipper, secret: "_your_session_secret") => '/flipper'
71
69
  end
72
70
  ```
73
71
 
@@ -85,7 +83,7 @@ require 'flipper/adapters/memory'
85
83
  adapter = Flipper::Adapters::Memory.new
86
84
  flipper = Flipper.new(adapter)
87
85
 
88
- run Flipper::UI.app(flipper)
86
+ run Flipper::UI.app(flipper, secret: "_your_session_secret")
89
87
  ```
90
88
 
91
89
  See [examples/basic.ru](https://github.com/jnunemaker/flipper-ui/blob/master/examples/basic.ru) for a more full example
@@ -3,16 +3,16 @@
3
3
  # bundle exec rackup examples/basic.ru
4
4
  # http://localhost:9292/
5
5
  #
6
- require 'pp'
7
- require 'logger'
8
- require 'pathname'
6
+ require "pp"
7
+ require "logger"
8
+ require "pathname"
9
9
 
10
- root_path = Pathname(__FILE__).dirname.join('..').expand_path
11
- lib_path = root_path.join('lib')
10
+ root_path = Pathname(__FILE__).dirname.join("..").expand_path
11
+ lib_path = root_path.join("lib")
12
12
  $:.unshift(lib_path)
13
13
 
14
- require 'flipper-ui'
15
- require 'flipper/adapters/memory'
14
+ require "flipper-ui"
15
+ require "flipper-redis"
16
16
 
17
17
  Flipper.register(:admins) { |actor|
18
18
  actor.respond_to?(:admin?) && actor.admin?
@@ -23,22 +23,23 @@ Flipper.register(:early_access) { |actor|
23
23
  }
24
24
 
25
25
  # Setup logging of flipper calls.
26
- require 'flipper/instrumentation/log_subscriber'
27
- Flipper::Instrumentation::LogSubscriber.logger = Logger.new(STDOUT)
28
-
29
- adapter = Flipper::Adapters::Memory.new({})
30
- flipper = Flipper.new(adapter, :instrumenter => ActiveSupport::Notifications)
31
-
32
- Actor = Struct.new(:flipper_id)
33
-
34
- flipper[:search_performance_another_long_thing].enable
35
- flipper[:gauges_tracking].enable
36
- flipper[:unused].disable
37
- flipper[:suits].enable Actor.new('1')
38
- flipper[:suits].enable Actor.new('6')
39
- flipper[:secrets].enable flipper.group(:admins)
40
- flipper[:secrets].enable flipper.group(:early_access)
41
- flipper[:logging].enable flipper.time(5)
42
- flipper[:new_cache].enable flipper.actors(15)
43
-
44
- run Flipper::UI.app(flipper)
26
+ $logger = Logger.new(STDOUT)
27
+ require "active_support/notifications"
28
+ require "flipper/instrumentation/log_subscriber"
29
+ Flipper::Instrumentation::LogSubscriber.logger = $logger
30
+
31
+ adapter = Flipper::Adapters::Redis.new(Redis.new(port: ENV["GH_REDIS_PORT"]))
32
+ flipper = Flipper.new(adapter, instrumenter: ActiveSupport::Notifications)
33
+
34
+ # You can uncomment these to get some default data:
35
+ # flipper[:search_performance_another_long_thing].enable
36
+ # flipper[:gauges_tracking].enable
37
+ # flipper[:unused].disable
38
+ # flipper[:suits].enable_actor Flipper::UI::Actor.new('1')
39
+ # flipper[:suits].enable_actor Flipper::UI::Actor.new('6')
40
+ # flipper[:secrets].enable_group :admins
41
+ # flipper[:secrets].enable_group :early_access
42
+ # flipper[:logging].enable_percentage_of_time 5
43
+ # flipper[:new_cache].enable_percentage_of_actors 15
44
+
45
+ run Flipper::UI.app(flipper, secret: "example_secret_dont_use_this")
@@ -4,8 +4,9 @@ require File.expand_path('../lib/flipper/ui/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["John Nunemaker"]
6
6
  gem.email = ["nunemaker@gmail.com"]
7
- gem.description = %q{UI for the Flipper gem}
8
7
  gem.summary = %q{UI for the Flipper gem}
8
+ gem.description = %q{Rack middleware that provides a fully featured web interface for the flipper gem.}
9
+ gem.license = "MIT"
9
10
  gem.homepage = "https://github.com/jnunemaker/flipper-ui"
10
11
 
11
12
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -15,7 +16,8 @@ Gem::Specification.new do |gem|
15
16
  gem.require_paths = ["lib"]
16
17
  gem.version = Flipper::UI::VERSION
17
18
 
18
- gem.add_dependency 'rack'
19
+ gem.add_dependency 'rack', '~> 1.5', '< 1.7'
20
+ gem.add_dependency 'rack-protection', '~> 1.5.3'
19
21
  gem.add_dependency 'flipper', '~> 0.7.0.beta1'
20
- gem.add_dependency 'erubis'
22
+ gem.add_dependency 'erubis', '~> 2.7.0'
21
23
  end
@@ -1 +1,2 @@
1
+ require 'flipper'
1
2
  require 'flipper/ui'
@@ -1,7 +1,9 @@
1
1
  require 'pathname'
2
2
  require 'rack'
3
+ require 'rack/methodoverride'
4
+ require 'rack/protection'
3
5
  require 'flipper'
4
- require 'multi_json'
6
+ require 'flipper/middleware/memoizer'
5
7
 
6
8
  module Flipper
7
9
  module UI
@@ -9,10 +11,16 @@ module Flipper
9
11
  @root ||= Pathname(__FILE__).dirname.expand_path.join('ui')
10
12
  end
11
13
 
12
- def self.app(flipper)
14
+ def self.app(flipper, options = {})
13
15
  app = lambda { |env| [200, {'Content-Type' => 'text/html'}, ['']] }
14
16
  builder = Rack::Builder.new
15
17
  yield builder if block_given?
18
+ secret = options[:secret] || raise(ArgumentError, "Flipper::UI.app missing required option: secret")
19
+ builder.use Rack::Session::Cookie, secret: secret
20
+ builder.use Rack::Protection
21
+ builder.use Rack::Protection::AuthenticityToken
22
+ builder.use Rack::MethodOverride
23
+ builder.use Flipper::Middleware::Memoizer, flipper
16
24
  builder.use Middleware, flipper
17
25
  builder.run app
18
26
  builder
@@ -21,3 +29,4 @@ module Flipper
21
29
  end
22
30
 
23
31
  require 'flipper/ui/middleware'
32
+ require 'flipper/ui/actor'
@@ -56,6 +56,7 @@ module Flipper
56
56
  @flipper, @request = flipper, request
57
57
  @code = 200
58
58
  @headers = {}
59
+ @breadcrumbs = []
59
60
  end
60
61
 
61
62
  # Public: Runs the request method for the provided request.
@@ -76,8 +77,8 @@ module Flipper
76
77
  #
77
78
  # Examples
78
79
  #
79
- # run_other_action Index
80
- # # => result of running Index action
80
+ # run_other_action Home
81
+ # # => result of running Home action
81
82
  #
82
83
  # Returns result of other action.
83
84
  def run_other_action(action_class)
@@ -100,7 +101,7 @@ module Flipper
100
101
  def view_response(name)
101
102
  header 'Content-Type', 'text/html'
102
103
  body = view_with_layout { view_without_layout name }
103
- [@code, @headers, [body]]
104
+ halt [@code, @headers, [body]]
104
105
  end
105
106
 
106
107
  # Public: Dumps an object as json and returns rack response with that as
@@ -112,7 +113,16 @@ module Flipper
112
113
  def json_response(object)
113
114
  header 'Content-Type', 'application/json'
114
115
  body = JSON.dump(object)
115
- [@code, @headers, [body]]
116
+ halt [@code, @headers, [body]]
117
+ end
118
+
119
+ # Public: Redirect to a new location.
120
+ #
121
+ # location - The String location to set the Location header to.
122
+ def redirect_to(location)
123
+ status 302
124
+ header "Location", location
125
+ halt [@code, @headers, [""]]
116
126
  end
117
127
 
118
128
  # Public: Set the status code for the response.
@@ -130,6 +140,28 @@ module Flipper
130
140
  @headers[name] = value
131
141
  end
132
142
 
143
+ class Breadcrumb
144
+ attr_reader :text, :href
145
+
146
+ def initialize(text, href = nil)
147
+ @text = text
148
+ @href = href
149
+ end
150
+
151
+ def active?
152
+ @href.nil?
153
+ end
154
+ end
155
+
156
+ # Public: Add a breadcrumb to the trail.
157
+ #
158
+ # text - The String text for the breadcrumb.
159
+ # href - The String href for the anchor tag (optional). If nil, breadcrumb
160
+ # is assumed to be the end of the trail.
161
+ def breadcrumb(text, href = nil)
162
+ @breadcrumbs << Breadcrumb.new(text, href)
163
+ end
164
+
133
165
  # Private
134
166
  def view_with_layout(&block)
135
167
  view :layout, &block
@@ -143,6 +175,11 @@ module Flipper
143
175
  # Private
144
176
  def view(name)
145
177
  path = views_path.join("#{name}.erb")
178
+
179
+ unless path.exist?
180
+ raise "Template does not exist: #{path}"
181
+ end
182
+
146
183
  contents = path.read
147
184
  compiled = Eruby.new(contents)
148
185
  compiled.result Proc.new {}.binding
@@ -167,6 +204,10 @@ module Flipper
167
204
  def request_method_name
168
205
  @request_method_name ||= @request.request_method.downcase
169
206
  end
207
+
208
+ def csrf_input_tag
209
+ %Q(<input type="hidden" name="authenticity_token" value="#{@request.session[:csrf]}">)
210
+ end
170
211
  end
171
212
  end
172
213
  end
@@ -0,0 +1,48 @@
1
+ require 'flipper/ui/action'
2
+ require 'flipper/ui/decorators/feature'
3
+ require 'flipper/ui/util'
4
+
5
+ module Flipper
6
+ module UI
7
+ module Actions
8
+ class ActorsGate < UI::Action
9
+ route %r{features/[^/]*/actors/?\Z}
10
+
11
+ def get
12
+ feature_name = Rack::Utils.unescape(request.path.split('/')[-2])
13
+ feature = flipper[feature_name.to_sym]
14
+ @feature = Decorators::Feature.new(feature)
15
+
16
+ breadcrumb "Home", "/"
17
+ breadcrumb "Features", "/features"
18
+ breadcrumb @feature.key, "/features/#{@feature.key}"
19
+ breadcrumb "Add Actor"
20
+
21
+ view_response :add_actor
22
+ end
23
+
24
+ def post
25
+ feature_name = Rack::Utils.unescape(request.path.split('/')[-2])
26
+ feature = flipper[feature_name.to_sym]
27
+ value = params["value"]
28
+
29
+ if Util.blank?(value)
30
+ error = Rack::Utils.escape("#{value.inspect} is not a valid actor value.")
31
+ redirect_to("/features/#{feature.key}/actors?error=#{error}")
32
+ end
33
+
34
+ actor = Flipper::UI::Actor.new(value)
35
+
36
+ case params["operation"]
37
+ when "enable"
38
+ feature.enable_actor actor
39
+ when "disable"
40
+ feature.disable_actor actor
41
+ end
42
+
43
+ redirect_to("/features/#{feature.key}")
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,20 @@
1
+ require 'flipper/ui/action'
2
+ require 'flipper/ui/decorators/feature'
3
+
4
+ module Flipper
5
+ module UI
6
+ module Actions
7
+ class AddFeature < UI::Action
8
+ route %r{features/new/?\Z}
9
+
10
+ def get
11
+ breadcrumb "Home", "/"
12
+ breadcrumb "Features", "/features"
13
+ breadcrumb "Add"
14
+
15
+ view_response :add_feature
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ require 'flipper/ui/action'
2
+ require 'flipper/ui/decorators/feature'
3
+
4
+ module Flipper
5
+ module UI
6
+ module Actions
7
+ class BooleanGate < UI::Action
8
+ route %r{features/[^/]*/boolean/?\Z}
9
+
10
+ def post
11
+ feature_name = Rack::Utils.unescape(request.path.split("/")[-2])
12
+ feature = flipper[feature_name.to_sym]
13
+ @feature = Decorators::Feature.new(feature)
14
+
15
+ if params["action"] == "Enable"
16
+ feature.enable
17
+ else
18
+ feature.disable
19
+ end
20
+
21
+ redirect_to "/features/#{@feature.key}"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ require 'flipper/ui/action'
2
+ require 'flipper/ui/decorators/feature'
3
+
4
+ module Flipper
5
+ module UI
6
+ module Actions
7
+ class Feature < UI::Action
8
+
9
+ route %r{features/[^/]*/?\Z}
10
+
11
+ def get
12
+ feature_name = Rack::Utils.unescape(request.path.split("/").last)
13
+ @feature = Decorators::Feature.new(flipper[feature_name])
14
+ @page_title = "#{@feature.key} // Features"
15
+ @percentages = [0, 1, 5, 10, 15, 25, 50, 75, 100]
16
+
17
+ breadcrumb "Features", "/features"
18
+ breadcrumb @feature.key
19
+
20
+ view_response :feature
21
+ end
22
+
23
+ def delete
24
+ feature_name = Rack::Utils.unescape(request.path.split("/").last)
25
+ feature = flipper[feature_name]
26
+ flipper.adapter.remove(feature)
27
+ redirect_to "/features"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,6 @@
1
1
  require 'flipper/ui/action'
2
2
  require 'flipper/ui/decorators/feature'
3
+ require 'flipper/ui/util'
3
4
 
4
5
  module Flipper
5
6
  module UI
@@ -9,11 +10,30 @@ module Flipper
9
10
  route %r{features/?\Z}
10
11
 
11
12
  def get
12
- features = flipper.features.map { |feature|
13
+ @page_title = "Features"
14
+ @features = flipper.features.map { |feature|
13
15
  Decorators::Feature.new(feature)
14
- }.sort_by(&:pretty_name)
16
+ }.sort
15
17
 
16
- json_response features.map(&:as_json)
18
+ @show_blank_slate = @features.empty?
19
+
20
+ breadcrumb "Home", "/"
21
+ breadcrumb "Features"
22
+
23
+ view_response :features
24
+ end
25
+
26
+ def post
27
+ value = params["value"]
28
+
29
+ if Util.blank?(value)
30
+ error = Rack::Utils.escape("#{value.inspect} is not a valid feature name.")
31
+ redirect_to("/features/new?error=#{error}")
32
+ end
33
+
34
+ flipper.adapter.add(flipper[value])
35
+
36
+ redirect_to "/features"
17
37
  end
18
38
  end
19
39
  end