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.
- checksums.yaml +4 -4
- data/Gemfile +12 -11
- data/README.md +5 -7
- data/examples/basic.ru +27 -26
- data/flipper-ui.gemspec +5 -3
- data/lib/flipper-ui.rb +1 -0
- data/lib/flipper/ui.rb +11 -2
- data/lib/flipper/ui/action.rb +45 -4
- data/lib/flipper/ui/actions/actors_gate.rb +48 -0
- data/lib/flipper/ui/actions/add_feature.rb +20 -0
- data/lib/flipper/ui/actions/boolean_gate.rb +26 -0
- data/lib/flipper/ui/actions/feature.rb +32 -0
- data/lib/flipper/ui/actions/features.rb +23 -3
- data/lib/flipper/ui/actions/file.rb +1 -1
- data/lib/flipper/ui/actions/gate.rb +11 -117
- data/lib/flipper/ui/actions/groups_gate.rb +43 -0
- data/lib/flipper/ui/actions/{index.rb → home.rb} +3 -3
- data/lib/flipper/ui/actions/percentage_of_actors_gate.rb +27 -0
- data/lib/flipper/ui/actions/percentage_of_time_gate.rb +27 -0
- data/lib/flipper/ui/actor.rb +13 -0
- data/lib/flipper/ui/assets/javascripts/application.coffee +0 -305
- data/lib/flipper/ui/assets/stylesheets/_bootstrap-compass.scss +9 -0
- data/lib/flipper/ui/assets/stylesheets/_bootstrap-mincer.scss +19 -0
- data/lib/flipper/ui/assets/stylesheets/_bootstrap-sprockets.scss +9 -0
- data/lib/flipper/ui/assets/stylesheets/_bootstrap.scss +50 -0
- data/lib/flipper/ui/assets/stylesheets/application.scss +33 -216
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_alerts.scss +73 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_badges.scss +68 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_breadcrumbs.scss +26 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_button-groups.scss +243 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_buttons.scss +160 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_carousel.scss +269 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_close.scss +36 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_code.scss +69 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_component-animations.scss +37 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_dropdowns.scss +214 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_forms.scss +578 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_glyphicons.scss +305 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_grid.scss +84 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_input-groups.scss +166 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_jumbotron.scss +50 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_labels.scss +66 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_list-group.scss +124 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_media.scss +61 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_mixins.scss +39 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_modals.scss +150 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_navbar.scss +662 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_navs.scss +242 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_normalize.scss +427 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_pager.scss +54 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_pagination.scss +88 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_panels.scss +265 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_popovers.scss +135 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_print.scss +107 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_progress-bars.scss +87 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_responsive-embed.scss +35 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_responsive-utilities.scss +177 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_scaffolding.scss +162 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_tables.scss +234 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_theme.scss +273 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_thumbnails.scss +38 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_tooltip.scss +102 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_type.scss +298 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_utilities.scss +55 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_variables.scss +866 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/_wells.scss +29 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_alerts.scss +14 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_background-variant.scss +11 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_border-radius.scss +18 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_buttons.scss +52 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_center-block.scss +7 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_clearfix.scss +22 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_forms.scss +88 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_gradients.scss +58 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +81 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_grid.scss +122 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_hide-text.scss +21 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_image.scss +33 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_labels.scss +12 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_list-group.scss +31 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_nav-divider.scss +10 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss +9 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_opacity.scss +8 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_pagination.scss +23 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_panels.scss +24 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_progress-bar.scss +10 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_reset-filter.scss +8 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_resize.scss +6 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_responsive-visibility.scss +21 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_size.scss +10 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_tab-focus.scss +9 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_table-row.scss +28 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +11 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_text-overflow.scss +8 -0
- data/lib/flipper/ui/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss +222 -0
- data/lib/flipper/ui/assets/stylesheets/primer/.scss-lint.yml +446 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_alerts.scss +106 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_avatars.scss +36 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_base.scss +40 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_blankslate.scss +96 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_buttons.scss +404 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_counter.scss +10 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_filter-list.scss +68 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_flex-table.scss +20 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_forms.scss +756 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_layout.scss +69 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_menu.scss +113 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_mixins.scss +53 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_normalize.scss +425 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_states.scss +32 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_tabnav.scss +65 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_tooltips.scss +255 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_truncate.scss +27 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_type.scss +92 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_utility.scss +73 -0
- data/lib/flipper/ui/assets/stylesheets/primer/_variables.scss +34 -0
- data/lib/flipper/ui/assets/stylesheets/primer/primer.scss +39 -0
- data/lib/flipper/ui/decorators/feature.rb +37 -4
- data/lib/flipper/ui/middleware.rb +12 -3
- data/lib/flipper/ui/public/css/application.css +2563 -144
- data/lib/flipper/ui/public/css/primer.css +1 -0
- data/lib/flipper/ui/public/css/primer/primer.css +1933 -0
- data/lib/flipper/ui/public/css/scss/primer.css +1933 -0
- data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
- data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.svg +288 -0
- data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
- data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
- data/lib/flipper/ui/public/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
- data/lib/flipper/ui/public/js/application.js +0 -539
- data/lib/flipper/ui/public/js/bootstrap-sprockets.js +12 -0
- data/lib/flipper/ui/public/js/bootstrap.js +2317 -0
- data/lib/flipper/ui/public/js/bootstrap.min.js +7 -0
- data/lib/flipper/ui/public/js/bootstrap/affix.js +162 -0
- data/lib/flipper/ui/public/js/bootstrap/alert.js +94 -0
- data/lib/flipper/ui/public/js/bootstrap/button.js +116 -0
- data/lib/flipper/ui/public/js/bootstrap/carousel.js +237 -0
- data/lib/flipper/ui/public/js/bootstrap/collapse.js +211 -0
- data/lib/flipper/ui/public/js/bootstrap/dropdown.js +161 -0
- data/lib/flipper/ui/public/js/bootstrap/modal.js +339 -0
- data/lib/flipper/ui/public/js/bootstrap/popover.js +108 -0
- data/lib/flipper/ui/public/js/bootstrap/scrollspy.js +172 -0
- data/lib/flipper/ui/public/js/bootstrap/tab.js +153 -0
- data/lib/flipper/ui/public/js/bootstrap/tooltip.js +476 -0
- data/lib/flipper/ui/public/js/bootstrap/transition.js +59 -0
- data/lib/flipper/ui/public/octicons/LICENSE.txt +9 -0
- data/lib/flipper/ui/public/octicons/README.md +1 -0
- data/lib/flipper/ui/public/octicons/octicons-local.ttf +0 -0
- data/lib/flipper/ui/public/octicons/octicons.css +236 -0
- data/lib/flipper/ui/public/octicons/octicons.eot +0 -0
- data/lib/flipper/ui/public/octicons/octicons.less +235 -0
- data/lib/flipper/ui/public/octicons/octicons.svg +200 -0
- data/lib/flipper/ui/public/octicons/octicons.ttf +0 -0
- data/lib/flipper/ui/public/octicons/octicons.woff +0 -0
- data/lib/flipper/ui/public/octicons/sprockets-octicons.scss +232 -0
- data/lib/flipper/ui/util.rb +4 -0
- data/lib/flipper/ui/version.rb +1 -1
- data/lib/flipper/ui/views/add_actor.erb +22 -0
- data/lib/flipper/ui/views/add_feature.erb +18 -0
- data/lib/flipper/ui/views/add_group.erb +31 -0
- data/lib/flipper/ui/views/feature.erb +209 -0
- data/lib/flipper/ui/views/features.erb +46 -0
- data/lib/flipper/ui/views/layout.erb +31 -149
- data/script/release +15 -0
- data/spec/flipper/ui/actions/actors_gate_spec.rb +68 -0
- data/spec/flipper/ui/actions/add_feature_spec.rb +17 -0
- data/spec/flipper/ui/actions/boolean_gate_spec.rb +41 -0
- data/spec/flipper/ui/actions/feature_spec.rb +59 -0
- data/spec/flipper/ui/actions/features_spec.rb +37 -0
- data/spec/flipper/ui/actions/file_spec.rb +43 -0
- data/spec/flipper/ui/actions/gate_spec.rb +24 -0
- data/spec/flipper/ui/actions/groups_gate_spec.rb +80 -0
- data/spec/flipper/ui/actions/home_spec.rb +16 -0
- data/spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb +40 -0
- data/spec/flipper/ui/actions/percentage_of_time_gate_spec.rb +39 -0
- data/spec/flipper/ui/decorators/feature_spec.rb +38 -1
- data/spec/flipper/ui/decorators/gate_spec.rb +1 -1
- data/spec/flipper/ui_spec.rb +18 -441
- data/spec/helper.rb +22 -7
- metadata +199 -52
- data/examples/flipper.html +0 -14
- data/examples/flipper.png +0 -0
- data/lib/flipper/ui/assets/javascripts/spine/ajax.coffee +0 -223
- data/lib/flipper/ui/assets/javascripts/spine/list.coffee +0 -43
- data/lib/flipper/ui/assets/javascripts/spine/local.coffee +0 -16
- data/lib/flipper/ui/assets/javascripts/spine/manager.coffee +0 -83
- data/lib/flipper/ui/assets/javascripts/spine/relation.coffee +0 -148
- data/lib/flipper/ui/assets/javascripts/spine/route.coffee +0 -146
- data/lib/flipper/ui/assets/javascripts/spine/spine.coffee +0 -542
- data/lib/flipper/ui/assets/javascripts/spine/version +0 -1
- data/lib/flipper/ui/public/css/images/animated-overlay.gif +0 -0
- data/lib/flipper/ui/public/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-icons_222222_256x240.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-icons_228ef1_256x240.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-icons_ef8c08_256x240.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-icons_ffd27a_256x240.png +0 -0
- data/lib/flipper/ui/public/css/images/ui-icons_ffffff_256x240.png +0 -0
- data/lib/flipper/ui/public/css/jquery-ui-1.10.3.slider.min.css +0 -5
- data/lib/flipper/ui/public/js/handlebars.js +0 -1992
- data/lib/flipper/ui/public/js/jquery-ui-1.10.3.slider.min.js +0 -6
- data/lib/flipper/ui/public/js/jquery.js +0 -9555
- data/lib/flipper/ui/public/js/jquery.min.js +0 -4
- data/lib/flipper/ui/public/js/jquery.min.map +0 -1
- data/lib/flipper/ui/public/js/spine/ajax.js +0 -320
- data/lib/flipper/ui/public/js/spine/list.js +0 -72
- data/lib/flipper/ui/public/js/spine/local.js +0 -29
- data/lib/flipper/ui/public/js/spine/manager.js +0 -157
- data/lib/flipper/ui/public/js/spine/relation.js +0 -260
- data/lib/flipper/ui/public/js/spine/route.js +0 -223
- data/lib/flipper/ui/public/js/spine/spine.js +0 -927
- data/lib/flipper/ui/views/index.erb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71211c26364825d2e5ba11f9669b7355f3fc8687
|
4
|
+
data.tar.gz: add561910d6cc8d6f6993ec7b3a202b567d22d5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 '
|
7
|
-
gem '
|
8
|
-
gem '
|
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.
|
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
|
data/examples/basic.ru
CHANGED
@@ -3,16 +3,16 @@
|
|
3
3
|
# bundle exec rackup examples/basic.ru
|
4
4
|
# http://localhost:9292/
|
5
5
|
#
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
6
|
+
require "pp"
|
7
|
+
require "logger"
|
8
|
+
require "pathname"
|
9
9
|
|
10
|
-
root_path = Pathname(__FILE__).dirname.join(
|
11
|
-
lib_path = root_path.join(
|
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
|
15
|
-
require
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
flipper[:
|
36
|
-
flipper[:
|
37
|
-
flipper[:
|
38
|
-
flipper[:suits].
|
39
|
-
flipper[:
|
40
|
-
flipper[:secrets].
|
41
|
-
flipper[:
|
42
|
-
flipper[:
|
43
|
-
|
44
|
-
|
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")
|
data/flipper-ui.gemspec
CHANGED
@@ -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
|
data/lib/flipper-ui.rb
CHANGED
data/lib/flipper/ui.rb
CHANGED
@@ -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 '
|
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'
|
data/lib/flipper/ui/action.rb
CHANGED
@@ -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
|
80
|
-
# # => result of running
|
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
|
-
|
13
|
+
@page_title = "Features"
|
14
|
+
@features = flipper.features.map { |feature|
|
13
15
|
Decorators::Feature.new(feature)
|
14
|
-
}.
|
16
|
+
}.sort
|
15
17
|
|
16
|
-
|
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
|