flipper-ui 0.26.2 → 0.27.1
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.
- checksums.yaml +4 -4
- data/examples/ui/authorization.ru +3 -0
- data/examples/ui/basic.ru +4 -1
- data/examples/ui/read_only.ru +3 -0
- data/lib/flipper/ui/action.rb +6 -1
- data/lib/flipper/ui/actions/export.rb +19 -0
- data/lib/flipper/ui/actions/import.rb +19 -0
- data/lib/flipper/ui/actions/settings.rb +21 -0
- data/lib/flipper/ui/middleware.rb +3 -0
- data/lib/flipper/ui/views/layout.erb +6 -0
- data/lib/flipper/ui/views/settings.erb +26 -0
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/ui/actions/export_spec.rb +49 -0
- data/spec/flipper/ui/actions/import_spec.rb +41 -0
- data/spec/flipper/ui/actions/settings_spec.rb +27 -0
- metadata +14 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65f98a2ad17e351b3e366d5fcc570e7783e6e2d757bcb585d49b4b32251c8d8b
|
4
|
+
data.tar.gz: 3a267dc1a8c6cd8d69a2774772c2b5de03e39c3ba2170f707f0c86feb246a57f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6100a0f6f8a04877b106afe6a686a730f451ae285b31705297dd8db1b2596a061c0da758a5639e4ac55cbe46e7b59e0c1aa507b8734cfc7e69edebae08fd2f95
|
7
|
+
data.tar.gz: c7d0e4d58c421381c766421046ed013e1218fde1518567bec0429af960d3e4ed531881e7afd39d06ce826d0dd987cb8cb4439bbc347e4f5760cce3e350ed7972
|
@@ -5,6 +5,7 @@
|
|
5
5
|
# http://localhost:9999/
|
6
6
|
#
|
7
7
|
require 'bundler/setup'
|
8
|
+
require 'rack/reloader'
|
8
9
|
require "flipper/ui"
|
9
10
|
require "flipper/adapters/pstore"
|
10
11
|
|
@@ -40,6 +41,8 @@ end
|
|
40
41
|
# Flipper.enable_percentage_of_actors(:new_cache, 15)
|
41
42
|
# Flipper.add("a/b")
|
42
43
|
|
44
|
+
use Rack::Reloader
|
45
|
+
|
43
46
|
run Flipper::UI.app { |builder|
|
44
47
|
builder.use Rack::Session::Cookie, secret: "_super_secret"
|
45
48
|
builder.use FlipperReadOnlyMiddleware
|
data/examples/ui/basic.ru
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
# http://localhost:9999/
|
10
10
|
#
|
11
11
|
require 'bundler/setup'
|
12
|
+
require 'rack/reloader'
|
12
13
|
require "flipper/ui"
|
13
14
|
require "flipper/adapters/pstore"
|
14
15
|
|
@@ -26,7 +27,7 @@ Flipper::UI.configure do |config|
|
|
26
27
|
config.feature_creation_enabled = true
|
27
28
|
config.feature_removal_enabled = true
|
28
29
|
config.cloud_recommendation = true
|
29
|
-
config.confirm_fully_enable =
|
30
|
+
config.confirm_fully_enable = false
|
30
31
|
# config.show_feature_description_in_list = true
|
31
32
|
config.descriptions_source = lambda do |_keys|
|
32
33
|
{
|
@@ -54,6 +55,8 @@ end
|
|
54
55
|
# Flipper.enable_percentage_of_actors(:new_cache, 15)
|
55
56
|
# Flipper.add("a/b")
|
56
57
|
|
58
|
+
use Rack::Reloader
|
59
|
+
|
57
60
|
run Flipper::UI.app { |builder|
|
58
61
|
builder.use Rack::Session::Cookie, secret: "_super_secret"
|
59
62
|
}
|
data/examples/ui/read_only.ru
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
# http://localhost:9999/
|
10
10
|
#
|
11
11
|
require 'bundler/setup'
|
12
|
+
require 'rack/reloader'
|
12
13
|
require "flipper/ui"
|
13
14
|
require "flipper/adapters/pstore"
|
14
15
|
|
@@ -38,6 +39,8 @@ end
|
|
38
39
|
# Flipper.enable_percentage_of_actors(:new_cache, 15)
|
39
40
|
# Flipper.add("a/b")
|
40
41
|
|
42
|
+
use Rack::Reloader
|
43
|
+
|
41
44
|
run Flipper::UI.app { |builder|
|
42
45
|
builder.use Rack::Session::Cookie, secret: "_super_secret"
|
43
46
|
}
|
data/lib/flipper/ui/action.rb
CHANGED
@@ -174,7 +174,12 @@ module Flipper
|
|
174
174
|
# Returns a response.
|
175
175
|
def json_response(object)
|
176
176
|
header 'Content-Type', 'application/json'
|
177
|
-
body =
|
177
|
+
body = case object
|
178
|
+
when String
|
179
|
+
object
|
180
|
+
else
|
181
|
+
JSON.dump(object)
|
182
|
+
end
|
178
183
|
halt [@code, @headers, [body]]
|
179
184
|
end
|
180
185
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'flipper/ui/action'
|
2
|
+
require 'flipper/ui/util'
|
3
|
+
|
4
|
+
module Flipper
|
5
|
+
module UI
|
6
|
+
module Actions
|
7
|
+
class Export < UI::Action
|
8
|
+
route %r{\A/settings\/export/?\Z}
|
9
|
+
|
10
|
+
def post
|
11
|
+
header 'Content-Disposition', "Attachment;filename=flipper_#{flipper.adapter.adapter.name}_#{Time.now.to_i}.json"
|
12
|
+
|
13
|
+
export = flipper.export(format: :json, version: 1)
|
14
|
+
json_response export.contents
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'flipper/ui/action'
|
2
|
+
require 'flipper/ui/util'
|
3
|
+
|
4
|
+
module Flipper
|
5
|
+
module UI
|
6
|
+
module Actions
|
7
|
+
class Import < UI::Action
|
8
|
+
route %r{\A/settings\/import/?\Z}
|
9
|
+
|
10
|
+
def post
|
11
|
+
contents = params['file'][:tempfile].read
|
12
|
+
export = Flipper::Exporters::Json::Export.new(contents: contents)
|
13
|
+
flipper.import(export)
|
14
|
+
redirect_to "/features"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'flipper/ui/action'
|
2
|
+
require 'flipper/ui/util'
|
3
|
+
|
4
|
+
module Flipper
|
5
|
+
module UI
|
6
|
+
module Actions
|
7
|
+
class Settings < UI::Action
|
8
|
+
route %r{\A/settings/?\Z}
|
9
|
+
|
10
|
+
def get
|
11
|
+
@page_title = 'Settings'
|
12
|
+
|
13
|
+
breadcrumb 'Home', '/'
|
14
|
+
breadcrumb 'Settings'
|
15
|
+
|
16
|
+
view_response :settings
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -25,6 +25,9 @@ module Flipper
|
|
25
25
|
@action_collection.add UI::Actions::PercentageOfActorsGate
|
26
26
|
@action_collection.add UI::Actions::Feature
|
27
27
|
@action_collection.add UI::Actions::Features
|
28
|
+
@action_collection.add UI::Actions::Export
|
29
|
+
@action_collection.add UI::Actions::Import
|
30
|
+
@action_collection.add UI::Actions::Settings
|
28
31
|
|
29
32
|
# Static Assets/Files
|
30
33
|
@action_collection.add UI::Actions::File
|
@@ -17,6 +17,12 @@
|
|
17
17
|
</div>
|
18
18
|
<%- end -%>
|
19
19
|
|
20
|
+
<div class="container text-muted small mb-3">
|
21
|
+
<a href="https://www.flippercloud.io/docs/ui?utm_source=oss&utm_medium=ui&utm_campaign=docs">Docs</a> •
|
22
|
+
<a href="<%= script_name %>/settings">Settings</a> •
|
23
|
+
Version: <%= Flipper::VERSION %>
|
24
|
+
</div>
|
25
|
+
|
20
26
|
<nav aria-label="breadcrumb">
|
21
27
|
<ol class="breadcrumb bg-white border align-items-center mb-4">
|
22
28
|
<% @breadcrumbs.each do |breadcrumb| %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<div class="card mb-4 ">
|
2
|
+
<div class="card-header">
|
3
|
+
<h4 class="m-0">Export</h4>
|
4
|
+
</div>
|
5
|
+
<div class="card-body">
|
6
|
+
<form action="<%= script_name %>/settings/export" method="post">
|
7
|
+
<%== csrf_input_tag %>
|
8
|
+
<p>Download all your feature data in a single file.</p>
|
9
|
+
<input type="submit" value="Download" class="btn btn-sm btn-light">
|
10
|
+
</form>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="card">
|
15
|
+
<div class="card-header">
|
16
|
+
<h4 class="m-0">Import</h4>
|
17
|
+
</div>
|
18
|
+
<div class="card-body">
|
19
|
+
<p>Import a backup file to restore your feature data. This will overwrite any of your existing feature data so be sure you are uploading the correct export.</p>
|
20
|
+
<form action="<%= script_name %>/settings/import" method="post" class="form-inline" enctype="multipart/form-data">
|
21
|
+
<%== csrf_input_tag %>
|
22
|
+
<input type="file" name="file" class="form-control form-control-sm mr-sm-2 mb-2 mb-sm-0">
|
23
|
+
<input type="submit" value="Import" class="btn btn-sm btn-light">
|
24
|
+
</form>
|
25
|
+
</div>
|
26
|
+
</div>
|
data/lib/flipper/version.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
RSpec.describe Flipper::UI::Actions::Features do
|
2
|
+
let(:token) do
|
3
|
+
if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
|
4
|
+
Rack::Protection::AuthenticityToken.random_token
|
5
|
+
else
|
6
|
+
'a'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:session) do
|
11
|
+
{ :csrf => token, 'csrf' => token, '_csrf_token' => token }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "POST /settings/export" do
|
15
|
+
before do
|
16
|
+
flipper.enable_percentage_of_actors :search, 10
|
17
|
+
flipper.enable_percentage_of_time :search, 15
|
18
|
+
flipper.enable_actor :search, Flipper::Actor.new('User;1')
|
19
|
+
flipper.enable_actor :search, Flipper::Actor.new('User;100')
|
20
|
+
flipper.enable_group :search, :admins
|
21
|
+
flipper.enable_group :search, :employees
|
22
|
+
flipper.enable :plausible
|
23
|
+
flipper.disable :google_analytics
|
24
|
+
|
25
|
+
post '/settings/export',
|
26
|
+
{'authenticity_token' => token},
|
27
|
+
'rack.session' => session
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'responds with success' do
|
31
|
+
expect(last_response.status).to be(200)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'sets content disposition' do
|
35
|
+
expect(last_response.headers['Content-Disposition']).to match(/Attachment;filename=flipper_memory_[0-9]*\.json/)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'renders json' do
|
39
|
+
data = JSON.parse(last_response.body)
|
40
|
+
expect(last_response.headers['Content-Type']).to eq('application/json')
|
41
|
+
expect(data['version']).to eq(1)
|
42
|
+
expect(data['features']).to eq({
|
43
|
+
"search"=> {"boolean"=>nil, "groups"=>["admins", "employees"], "actors"=>["User;1", "User;100"], "percentage_of_actors"=>"10", "percentage_of_time"=>"15"},
|
44
|
+
"plausible"=> {"boolean"=>"true", "groups"=>[], "actors"=>[], "percentage_of_actors"=>nil, "percentage_of_time"=>nil},
|
45
|
+
"google_analytics"=> {"boolean"=>nil, "groups"=>[], "actors"=>[], "percentage_of_actors"=>nil, "percentage_of_time"=>nil},
|
46
|
+
})
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
RSpec.describe Flipper::UI::Actions::Import do
|
2
|
+
let(:token) do
|
3
|
+
if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
|
4
|
+
Rack::Protection::AuthenticityToken.random_token
|
5
|
+
else
|
6
|
+
'a'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:session) do
|
11
|
+
{ :csrf => token, 'csrf' => token, '_csrf_token' => token }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "POST /settings/import" do
|
15
|
+
before do
|
16
|
+
flipper.enable :plausible
|
17
|
+
flipper.disable :google_analytics
|
18
|
+
path = FlipperRoot.join("spec", "fixtures", "flipper_pstore_1679087600.json")
|
19
|
+
|
20
|
+
post '/settings/import',
|
21
|
+
{
|
22
|
+
'authenticity_token' => token,
|
23
|
+
'file' => Rack::Test::UploadedFile.new(path, "application/json"),
|
24
|
+
},
|
25
|
+
'rack.session' => session
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'imports the file export' do
|
29
|
+
expect(flipper[:search].actors_value).to eq(Set.new(['john', 'another', 'testing']))
|
30
|
+
expect(flipper[:search].groups_value).to eq(Set.new(['admins']))
|
31
|
+
expect(flipper[:google_analytics_tag].percentage_of_actors_value).to eq(100)
|
32
|
+
expect(flipper[:new_pricing].boolean_value).to eq(true)
|
33
|
+
expect(flipper[:nope].boolean_value).to eq(false)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'responds with redirect to settings' do
|
37
|
+
expect(last_response.status).to be(302)
|
38
|
+
expect(last_response.headers['Location']).to eq('/features')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
RSpec.describe Flipper::UI::Actions::Settings do
|
2
|
+
let(:token) do
|
3
|
+
if Rack::Protection::AuthenticityToken.respond_to?(:random_token)
|
4
|
+
Rack::Protection::AuthenticityToken.random_token
|
5
|
+
else
|
6
|
+
'a'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:session) do
|
11
|
+
{ :csrf => token, 'csrf' => token, '_csrf_token' => token }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'GET /settings' do
|
15
|
+
before do
|
16
|
+
get '/settings'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'responds with success' do
|
20
|
+
expect(last_response.status).to be(200)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'renders template' do
|
24
|
+
expect(last_response.body).to include('Download')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
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.27.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-03-
|
11
|
+
date: 2023-03-20 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.27.1
|
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.27.1
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: erubi
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,13 +116,16 @@ files:
|
|
116
116
|
- lib/flipper/ui/actions/actors_gate.rb
|
117
117
|
- lib/flipper/ui/actions/add_feature.rb
|
118
118
|
- lib/flipper/ui/actions/boolean_gate.rb
|
119
|
+
- lib/flipper/ui/actions/export.rb
|
119
120
|
- lib/flipper/ui/actions/feature.rb
|
120
121
|
- lib/flipper/ui/actions/features.rb
|
121
122
|
- lib/flipper/ui/actions/file.rb
|
122
123
|
- lib/flipper/ui/actions/groups_gate.rb
|
123
124
|
- lib/flipper/ui/actions/home.rb
|
125
|
+
- lib/flipper/ui/actions/import.rb
|
124
126
|
- lib/flipper/ui/actions/percentage_of_actors_gate.rb
|
125
127
|
- lib/flipper/ui/actions/percentage_of_time_gate.rb
|
128
|
+
- lib/flipper/ui/actions/settings.rb
|
126
129
|
- lib/flipper/ui/configuration.rb
|
127
130
|
- lib/flipper/ui/configuration/option.rb
|
128
131
|
- lib/flipper/ui/decorators/feature.rb
|
@@ -142,18 +145,22 @@ files:
|
|
142
145
|
- lib/flipper/ui/views/features.erb
|
143
146
|
- lib/flipper/ui/views/layout.erb
|
144
147
|
- lib/flipper/ui/views/read_only.erb
|
148
|
+
- lib/flipper/ui/views/settings.erb
|
145
149
|
- lib/flipper/version.rb
|
146
150
|
- spec/flipper/ui/action_spec.rb
|
147
151
|
- spec/flipper/ui/actions/actors_gate_spec.rb
|
148
152
|
- spec/flipper/ui/actions/add_feature_spec.rb
|
149
153
|
- spec/flipper/ui/actions/boolean_gate_spec.rb
|
154
|
+
- spec/flipper/ui/actions/export_spec.rb
|
150
155
|
- spec/flipper/ui/actions/feature_spec.rb
|
151
156
|
- spec/flipper/ui/actions/features_spec.rb
|
152
157
|
- spec/flipper/ui/actions/file_spec.rb
|
153
158
|
- spec/flipper/ui/actions/groups_gate_spec.rb
|
154
159
|
- spec/flipper/ui/actions/home_spec.rb
|
160
|
+
- spec/flipper/ui/actions/import_spec.rb
|
155
161
|
- spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb
|
156
162
|
- spec/flipper/ui/actions/percentage_of_time_gate_spec.rb
|
163
|
+
- spec/flipper/ui/actions/settings_spec.rb
|
157
164
|
- spec/flipper/ui/configuration_spec.rb
|
158
165
|
- spec/flipper/ui/decorators/feature_spec.rb
|
159
166
|
- spec/flipper/ui/decorators/gate_spec.rb
|
@@ -188,13 +195,16 @@ test_files:
|
|
188
195
|
- spec/flipper/ui/actions/actors_gate_spec.rb
|
189
196
|
- spec/flipper/ui/actions/add_feature_spec.rb
|
190
197
|
- spec/flipper/ui/actions/boolean_gate_spec.rb
|
198
|
+
- spec/flipper/ui/actions/export_spec.rb
|
191
199
|
- spec/flipper/ui/actions/feature_spec.rb
|
192
200
|
- spec/flipper/ui/actions/features_spec.rb
|
193
201
|
- spec/flipper/ui/actions/file_spec.rb
|
194
202
|
- spec/flipper/ui/actions/groups_gate_spec.rb
|
195
203
|
- spec/flipper/ui/actions/home_spec.rb
|
204
|
+
- spec/flipper/ui/actions/import_spec.rb
|
196
205
|
- spec/flipper/ui/actions/percentage_of_actors_gate_spec.rb
|
197
206
|
- spec/flipper/ui/actions/percentage_of_time_gate_spec.rb
|
207
|
+
- spec/flipper/ui/actions/settings_spec.rb
|
198
208
|
- spec/flipper/ui/configuration_spec.rb
|
199
209
|
- spec/flipper/ui/decorators/feature_spec.rb
|
200
210
|
- spec/flipper/ui/decorators/gate_spec.rb
|