flipper-ui 0.2.0.beta2 → 0.2.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
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