flipper-ui 0.22.2 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/flipper-ui.gemspec +1 -0
- data/lib/flipper/ui/action.rb +10 -8
- data/lib/flipper/ui/views/feature.erb +1 -1
- data/lib/flipper/ui/views/features.erb +1 -1
- data/lib/flipper/ui/views/layout.erb +1 -1
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/ui/action_spec.rb +0 -2
- data/spec/flipper/ui/actions/actors_gate_spec.rb +0 -2
- data/spec/flipper/ui/actions/add_feature_spec.rb +0 -2
- data/spec/flipper/ui/actions/boolean_gate_spec.rb +0 -2
- data/spec/flipper/ui/actions/feature_spec.rb +0 -2
- data/spec/flipper/ui/actions/features_spec.rb +0 -2
- data/spec/flipper/ui/actions/file_spec.rb +0 -2
- data/spec/flipper/ui/actions/groups_gate_spec.rb +0 -2
- data/spec/flipper/ui/actions/home_spec.rb +0 -2
- data/spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb +0 -2
- data/spec/flipper/ui/actions/percentage_of_time_gate_spec.rb +0 -2
- data/spec/flipper/ui/configuration_spec.rb +0 -2
- data/spec/flipper/ui/decorators/feature_spec.rb +0 -2
- data/spec/flipper/ui/decorators/gate_spec.rb +0 -1
- data/spec/flipper/ui/util_spec.rb +0 -1
- data/spec/flipper/ui_spec.rb +0 -2
- metadata +19 -10
- data/docs/ui/README.md +0 -190
- data/docs/ui/images/banner.png +0 -0
- data/docs/ui/images/description.png +0 -0
- data/docs/ui/images/feature.png +0 -0
- data/docs/ui/images/features.png +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a6e8757e6a2726e4cf55323286a04caf186af13c6841a4e8b82b813b3c69f2f
|
4
|
+
data.tar.gz: 9ea49e24c52b723f7385da8c90dcae9daf96bef269f0b0e6066df1bc11065411
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7e435cc10e1b05c2282c022d977666479de870dc14cad3914e19e17acb6eacaf644fe37bf751f2931fb26525079a07b00b374f4815afdd10ab0e4192448ad27
|
7
|
+
data.tar.gz: a3a8fa7a1be586667573b98ee311a157f23591ee4f7bad15b1638aa25a1ec6444f75c909f90cd331d9cd17d8ba8869367755c299a9798e6eedef8583c2833dc7
|
data/flipper-ui.gemspec
CHANGED
data/lib/flipper/ui/action.rb
CHANGED
@@ -3,6 +3,7 @@ require 'flipper/ui/configuration'
|
|
3
3
|
require 'flipper/ui/error'
|
4
4
|
require 'erubi'
|
5
5
|
require 'json'
|
6
|
+
require 'sanitize'
|
6
7
|
|
7
8
|
module Flipper
|
8
9
|
module UI
|
@@ -28,20 +29,20 @@ module Flipper
|
|
28
29
|
|
29
30
|
SOURCES = {
|
30
31
|
bootstrap_css: {
|
31
|
-
src:
|
32
|
-
hash:
|
32
|
+
src: 'https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css'.freeze,
|
33
|
+
hash: 'sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l'.freeze
|
33
34
|
}.freeze,
|
34
35
|
jquery_js: {
|
35
|
-
src:
|
36
|
-
hash:
|
36
|
+
src: 'https://code.jquery.com/jquery-3.6.0.slim.js'.freeze,
|
37
|
+
hash: 'sha256-HwWONEZrpuoh951cQD1ov2HUK5zA5DwJ1DNUXaM6FsY='.freeze
|
37
38
|
}.freeze,
|
38
39
|
popper_js: {
|
39
|
-
src:
|
40
|
-
hash:
|
40
|
+
src: 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js'.freeze,
|
41
|
+
hash: 'sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q'.freeze
|
41
42
|
}.freeze,
|
42
43
|
bootstrap_js: {
|
43
|
-
src:
|
44
|
-
hash:
|
44
|
+
src: 'https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js'.freeze,
|
45
|
+
hash: 'sha384-+YQ4JLhjyBLPDQt//I+STsc9iw4uQqACwlvpslubQzn4u2UU2UFM80nGisd026JF'.freeze
|
45
46
|
}.freeze
|
46
47
|
}.freeze
|
47
48
|
SCRIPT_SRCS = SOURCES.values_at(:jquery_js, :popper_js, :bootstrap_js).map { |s| s[:src] }
|
@@ -238,6 +239,7 @@ module Flipper
|
|
238
239
|
def view(name)
|
239
240
|
path = views_path.join("#{name}.erb")
|
240
241
|
raise "Template does not exist: #{path}" unless path.exist?
|
242
|
+
|
241
243
|
eval(Erubi::Engine.new(path.read, escape: true).src)
|
242
244
|
end
|
243
245
|
|
@@ -47,7 +47,7 @@
|
|
47
47
|
<div class="text-truncate" style="font-weight: 500"><%= feature.key %></div>
|
48
48
|
<% if Flipper::UI.configuration.show_feature_description_in_list? && Flipper::UI::Util.present?(feature.description) %>
|
49
49
|
<div class="text-muted font-weight-light" style="line-height: 1.4; white-space: initial; padding: 8px 0">
|
50
|
-
|
50
|
+
<%== Sanitize.fragment(feature.description, Sanitize::Config::BASIC) %>
|
51
51
|
</div>
|
52
52
|
<% end %>
|
53
53
|
<div class="text-muted text-truncate">
|
@@ -13,7 +13,7 @@
|
|
13
13
|
<div class="container mw-600">
|
14
14
|
<%- unless Flipper::UI.configuration.banner_text.nil? -%>
|
15
15
|
<div class="alert alert-<%= Flipper::UI.configuration.banner_class %> text-center font-weight-bold">
|
16
|
-
|
16
|
+
<%== Sanitize.fragment(Flipper::UI.configuration.banner_text, Sanitize::Config::BASIC) %>
|
17
17
|
</div>
|
18
18
|
<%- end -%>
|
19
19
|
|
data/lib/flipper/version.rb
CHANGED
data/spec/flipper/ui_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper-ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.23.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -56,14 +56,14 @@ dependencies:
|
|
56
56
|
requirements:
|
57
57
|
- - "~>"
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: 0.
|
59
|
+
version: 0.23.0
|
60
60
|
type: :runtime
|
61
61
|
prerelease: false
|
62
62
|
version_requirements: !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
64
64
|
- - "~>"
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
version: 0.
|
66
|
+
version: 0.23.0
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: erubi
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,6 +84,20 @@ dependencies:
|
|
84
84
|
- - "<"
|
85
85
|
- !ruby/object:Gem::Version
|
86
86
|
version: 2.0.0
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: sanitize
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - "<"
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '7'
|
94
|
+
type: :runtime
|
95
|
+
prerelease: false
|
96
|
+
version_requirements: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - "<"
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '7'
|
87
101
|
description:
|
88
102
|
email:
|
89
103
|
- nunemaker@gmail.com
|
@@ -91,11 +105,6 @@ executables: []
|
|
91
105
|
extensions: []
|
92
106
|
extra_rdoc_files: []
|
93
107
|
files:
|
94
|
-
- docs/ui/README.md
|
95
|
-
- docs/ui/images/banner.png
|
96
|
-
- docs/ui/images/description.png
|
97
|
-
- docs/ui/images/feature.png
|
98
|
-
- docs/ui/images/features.png
|
99
108
|
- examples/ui/authorization.ru
|
100
109
|
- examples/ui/basic.ru
|
101
110
|
- flipper-ui.gemspec
|
@@ -169,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
169
178
|
- !ruby/object:Gem::Version
|
170
179
|
version: '0'
|
171
180
|
requirements: []
|
172
|
-
rubygems_version: 3.
|
181
|
+
rubygems_version: 3.1.2
|
173
182
|
signing_key:
|
174
183
|
specification_version: 4
|
175
184
|
summary: UI for the Flipper gem
|
data/docs/ui/README.md
DELETED
@@ -1,190 +0,0 @@
|
|
1
|
-
# Flipper::UI
|
2
|
-
|
3
|
-
UI for the [Flipper](https://github.com/jnunemaker/flipper) gem.
|
4
|
-
|
5
|
-
## Screenshots
|
6
|
-
|
7
|
-
Viewing list of features:
|
8
|
-
|
9
|
-
![features](images/features.png)
|
10
|
-
|
11
|
-
Viewing an individual feature:
|
12
|
-
|
13
|
-
![feature](images/feature.png)
|
14
|
-
|
15
|
-
## Installation
|
16
|
-
|
17
|
-
Add this line to your application's Gemfile:
|
18
|
-
|
19
|
-
gem 'flipper-ui'
|
20
|
-
|
21
|
-
And then execute:
|
22
|
-
|
23
|
-
$ bundle
|
24
|
-
|
25
|
-
Or install it yourself as:
|
26
|
-
|
27
|
-
$ gem install flipper-ui
|
28
|
-
|
29
|
-
## Usage
|
30
|
-
|
31
|
-
### Rails
|
32
|
-
|
33
|
-
Given that you've already initialized `Flipper` as per the [flipper](https://github.com/jnunemaker/flipper) readme, you can mount `Flipper::UI` to a route of your choice:
|
34
|
-
|
35
|
-
```ruby
|
36
|
-
# config/routes.rb
|
37
|
-
YourRailsApp::Application.routes.draw do
|
38
|
-
mount Flipper::UI.app(Flipper) => '/flipper'
|
39
|
-
end
|
40
|
-
```
|
41
|
-
|
42
|
-
If you'd like to lazy load flipper, you can instead pass a block to initialize it:
|
43
|
-
|
44
|
-
```ruby
|
45
|
-
# config/routes.rb
|
46
|
-
YourRailsApp::Application.routes.draw do
|
47
|
-
flipper_block = lambda {
|
48
|
-
# some flipper initialization here, for example:
|
49
|
-
adapter = Flipper::Adapters::Memory.new
|
50
|
-
Flipper.new(adapter)
|
51
|
-
}
|
52
|
-
mount Flipper::UI.app(flipper_block) => '/flipper'
|
53
|
-
end
|
54
|
-
```
|
55
|
-
|
56
|
-
#### Security
|
57
|
-
|
58
|
-
You almost certainly want to limit access when using Flipper::UI in production.
|
59
|
-
|
60
|
-
##### Basic Authentication via Rack
|
61
|
-
The `Flipper::UI.app` method yields a builder instance prior to any predefined middleware. You can insert the `Rack::Auth::Basic` middleware, that'll prompt for a username and password when visiting the defined (i.e., `/flipper`) route.
|
62
|
-
|
63
|
-
```ruby
|
64
|
-
# config/routes.rb
|
65
|
-
|
66
|
-
flipper_app = Flipper::UI.app(Flipper.instance) do |builder|
|
67
|
-
builder.use Rack::Auth::Basic do |username, password|
|
68
|
-
# Verify credentials
|
69
|
-
end
|
70
|
-
end
|
71
|
-
mount flipper_app, at: '/flipper'
|
72
|
-
```
|
73
|
-
|
74
|
-
##### Route Constraints
|
75
|
-
It is possible to use [routes constraints](http://guides.rubyonrails.org/routing.html#request-based-constraints) to limit access to routes:
|
76
|
-
|
77
|
-
```ruby
|
78
|
-
# config/routes.rb
|
79
|
-
|
80
|
-
flipper_constraint = lambda { |request| request.remote_ip == '127.0.0.1' }
|
81
|
-
constraints flipper_constraint do
|
82
|
-
mount Flipper::UI.app(flipper) => '/flipper'
|
83
|
-
end
|
84
|
-
```
|
85
|
-
|
86
|
-
Another example is to use the `current_user` when using a gem-based authentication system (i.e., [warden](https://github.com/hassox/warden) or [devise](https://github.com/plataformatec/devise)):
|
87
|
-
|
88
|
-
```ruby
|
89
|
-
# initializers/admin_access.rb
|
90
|
-
|
91
|
-
class CanAccessFlipperUI
|
92
|
-
def self.matches?(request)
|
93
|
-
current_user = request.env['warden'].user
|
94
|
-
current_user.present? && current_user.respond_to?(:admin?) && current_user.admin?
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# config/routes.rb
|
99
|
-
|
100
|
-
constraints CanAccessFlipperUI do
|
101
|
-
mount Flipper::UI.app(Flipper) => '/flipper'
|
102
|
-
end
|
103
|
-
```
|
104
|
-
|
105
|
-
### Standalone
|
106
|
-
|
107
|
-
Minimal example for Rack:
|
108
|
-
|
109
|
-
```ruby
|
110
|
-
# config.ru
|
111
|
-
|
112
|
-
require 'flipper/ui'
|
113
|
-
|
114
|
-
adapter = Flipper::Adapters::Memory.new
|
115
|
-
flipper = Flipper.new(adapter)
|
116
|
-
|
117
|
-
run Flipper::UI.app(flipper) { |builder|
|
118
|
-
builder.use Rack::Session::Cookie, secret: "something long and random"
|
119
|
-
}
|
120
|
-
```
|
121
|
-
|
122
|
-
The key is that you need to have sessions setup. Rails does this for you, so this step isn't necessary, but for standalone rack, you'll need it. Without sessions setup, you will receive a Runtime error like:
|
123
|
-
|
124
|
-
```
|
125
|
-
RuntimeError: you need to set up a session middleware *before* Rack::Protection::RemoteToken.
|
126
|
-
```
|
127
|
-
|
128
|
-
See [examples/ui/basic.ru](https://github.com/jnunemaker/flipper/blob/master/examples/ui/basic.ru) for a more full example
|
129
|
-
|
130
|
-
### Configuration
|
131
|
-
|
132
|
-
Flipper UI can be customized via `configure`, which yields a configuration instance.
|
133
|
-
|
134
|
-
#### Description
|
135
|
-
|
136
|
-
We can associate a `description` for each `feature` by providing a descriptions source:
|
137
|
-
|
138
|
-
```ruby
|
139
|
-
Flipper::UI.configure do |config|
|
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
|
-
|
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
|
148
|
-
end
|
149
|
-
```
|
150
|
-
|
151
|
-
Descriptions show up in the UI like so:
|
152
|
-
|
153
|
-
![description](images/description.png)
|
154
|
-
|
155
|
-
#### Banner
|
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.
|
158
|
-
|
159
|
-
```ruby
|
160
|
-
Flipper::UI.configure do |config|
|
161
|
-
config.banner_text = 'Production Environment'
|
162
|
-
config.banner_class = 'danger'
|
163
|
-
end
|
164
|
-
```
|
165
|
-
|
166
|
-
By default the `environment` is set to an empty string so no banner will show. If you wish to customize the look of the banner, you can set `banner_class` to one of the bootstrap color classes: `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `light`, or `dark`. The default `banner_class` is `danger`.
|
167
|
-
|
168
|
-
The above configuration results in:
|
169
|
-
|
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
|
-
```
|
181
|
-
|
182
|
-
## Contributing
|
183
|
-
|
184
|
-
1. Fork it
|
185
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
186
|
-
3. **Fire up the app** (`script/server`)
|
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
|
data/docs/ui/images/banner.png
DELETED
Binary file
|
Binary file
|
data/docs/ui/images/feature.png
DELETED
Binary file
|
data/docs/ui/images/features.png
DELETED
Binary file
|