flipper-ui 1.1.2 → 1.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58cc28253b1c2ef70dd3b9061c78730972414b34bf6510545f8d7c2f556641b5
4
- data.tar.gz: 1963c4edd52279f68bf89d490fdfbeb4b01ac447c1eeecec21da597f45174ecd
3
+ metadata.gz: b33985781ada74b2666ef3b636288e1c5316b7f32f8178f3adafccf3f30e7c4f
4
+ data.tar.gz: 637de7cc0214932ea6fa47aa4d3a4d32e3b8e4dd9b4e97417a610a9405fc7898
5
5
  SHA512:
6
- metadata.gz: 79b858119f2569bb550666bb812fbfba3a82ef93891f9e6dd807d4a4e96a9ed11344224b9728e0fe8241ce80fd103d9769a96dfb8f7ed6db416b140d2711367a
7
- data.tar.gz: 360f5f9b22c3a98451c9a52cb21188df68676cb1c0c626ee37cd37c635ce12f99719cbea57ea2aea1eac198de0c6030204c108095b5791bfab4f149b74d638c5
6
+ metadata.gz: ebc76af3eda0bf9b60912dc58b99fcaf65677a485cfa9ed4ca7a52bcf12934a6870680eb702869faa47f930575cc4b1046b3ddc34c2958f5cf7b4a504dbd7f48
7
+ data.tar.gz: a94f123f0e800036d602df242825c0452e081ccb91010f7642ecb118888b85e35c8eba63377f1fa3e1b05037ced0d2e9938413d554d0b52683709dafad11e2f7
data/examples/ui/basic.ru CHANGED
@@ -42,8 +42,8 @@ Flipper::UI.configure do |config|
42
42
 
43
43
  config.actor_names_source = lambda do |_keys|
44
44
  {
45
- '1' => 'John',
46
- '6' => 'Brandon',
45
+ '1' => '<a href="https://johnnunemaker.com">John</a>',
46
+ '6' => '<a href="https://opensoul.org">Brandon</a>',
47
47
  }
48
48
  end
49
49
  end
@@ -53,6 +53,7 @@ module Flipper
53
53
  style-src 'self' 'unsafe-inline';
54
54
  style-src-attr 'unsafe-inline' ;
55
55
  style-src-elem 'self';
56
+ connect-src https://www.flippercloud.io;
56
57
  CSP
57
58
 
58
59
  # Public: Call this in subclasses so the action knows its route.
@@ -108,7 +109,7 @@ module Flipper
108
109
  @flipper = flipper
109
110
  @request = request
110
111
  @code = 200
111
- @headers = { 'content-type' => 'text/plain' }
112
+ @headers = {Rack::CONTENT_TYPE => 'text/plain'}
112
113
  @breadcrumbs =
113
114
  if Flipper::UI.configuration.application_breadcrumb_href
114
115
  [Breadcrumb.new('App', Flipper::UI.configuration.application_breadcrumb_href)]
@@ -158,7 +159,7 @@ module Flipper
158
159
  #
159
160
  # Returns a response.
160
161
  def view_response(name)
161
- header 'content-type', 'text/html'
162
+ header Rack::CONTENT_TYPE, 'text/html'
162
163
  header 'content-security-policy', CONTENT_SECURITY_POLICY
163
164
  body = view_with_layout { view_without_layout name }
164
165
  halt [@code, @headers, [body]]
@@ -171,7 +172,7 @@ module Flipper
171
172
  #
172
173
  # Returns a response.
173
174
  def json_response(object)
174
- header 'content-type', 'application/json'
175
+ header Rack::CONTENT_TYPE, 'application/json'
175
176
  body = case object
176
177
  when String
177
178
  object
@@ -63,6 +63,10 @@ module Flipper
63
63
  # Default is false.
64
64
  attr_accessor :confirm_fully_enable
65
65
 
66
+ # Public: if you want to get a confirm pop up box while disabling a feature
67
+ # Default is false.
68
+ attr_accessor :confirm_disable
69
+
66
70
  VALID_BANNER_CLASS_VALUES = %w(
67
71
  danger
68
72
  dark
@@ -91,6 +95,7 @@ module Flipper
91
95
  @show_feature_description_in_list = false
92
96
  @actors_separator = ','
93
97
  @confirm_fully_enable = false
98
+ @confirm_disable = true
94
99
  @read_only = false
95
100
  end
96
101
 
@@ -14,7 +14,18 @@ $(function () {
14
14
  e.preventDefault();
15
15
  }
16
16
  });
17
-
17
+
18
+ $("#disable_feature__button").on("click", function (e) {
19
+ const featureName = $(e.target).data("confirmation-text");
20
+ const promptMessage = prompt(
21
+ `Are you sure you want to disable this feature for everyone? Please enter the name of the feature to confirm it: ${featureName}`
22
+ );
23
+
24
+ if (promptMessage !== featureName) {
25
+ e.preventDefault();
26
+ }
27
+ });
28
+
18
29
  $("#delete_feature__button").on("click", function (e) {
19
30
  const featureName = $(e.target).data("confirmation-text");
20
31
  const promptMessage = prompt(
@@ -0,0 +1,33 @@
1
+ // Get the latest release from RubyGems.org and show a badge if it's not the current version
2
+ function checkLatestRelease() {
3
+ // Skip check if last check was less than 1 day ago
4
+ if(localStorage.getItem('flipper.releaseCheckedAt') > new Date().getTime() - 86400000) return
5
+
6
+ // store the last time we checked for a new version
7
+ localStorage.setItem('flipper.releaseCheckedAt', new Date().getTime())
8
+
9
+ fetch('https://www.flippercloud.io/release.json').then(response => {
10
+ // Something went wrong, so just give up
11
+ if(!response.ok) return
12
+
13
+ response.json().then(release => {
14
+ localStorage.setItem('flipper.release', JSON.stringify(release))
15
+ showReleaseBadge()
16
+ })
17
+ })
18
+ }
19
+
20
+ // Show a badge if a new release is available
21
+ function showReleaseBadge() {
22
+ const badge = document.querySelector('#new-version-badge')
23
+ const release = JSON.parse(localStorage.getItem('flipper.release') || false)
24
+
25
+ if(!badge || !release || badge.dataset.version === release.version) return
26
+
27
+ badge.innerText = `${release.version} available!`
28
+ badge.setAttribute('href', release.changelog_uri)
29
+ badge.classList.remove('d-none')
30
+ }
31
+
32
+ checkLatestRelease()
33
+ showReleaseBadge()
@@ -66,7 +66,7 @@
66
66
  <div class="col col-mr-auto pl-md-5">
67
67
  <h6 class="m-0">
68
68
  <% if Flipper::UI::Util.present?(@feature.actor_names[item]) %>
69
- <%= "#{@feature.actor_names[item]} (#{item})" %>
69
+ <%== Sanitize.fragment("#{@feature.actor_names[item]} (#{item})", Sanitize::Config::BASIC) %>
70
70
  <% else %>
71
71
  <%= item %>
72
72
  <% end %>
@@ -263,8 +263,13 @@
263
263
 
264
264
  <% unless @feature.off? %>
265
265
  <div class="col">
266
- <button type="submit" name="action" value="Disable" class="btn btn-outline-danger btn-block">
267
- <span class="d-block" data-toggle="tooltip" title="Disable for everyone by clearing all percentages, groups and actors.">
266
+ <button type="submit" name="action" value="Disable" <% if Flipper::UI.configuration.confirm_disable %>id="disable_feature__button"<% end %> class="btn btn-outline-danger btn-block">
267
+ <span class="d-block" data-toggle="tooltip"
268
+ <% if Flipper::UI.configuration.confirm_disable %>
269
+ data-confirmation-text="<%= feature_name %>"
270
+ <% end %>
271
+ title="Disable for everyone by clearing all percentages, groups and actors."
272
+ >
268
273
  Disable
269
274
  </span>
270
275
  </button>
@@ -21,6 +21,20 @@
21
21
  <a href="https://www.flippercloud.io/docs/ui?utm_source=oss&utm_medium=ui&utm_campaign=docs">Docs</a> &bull;
22
22
  <a href="<%= script_name %>/settings">Settings</a> &bull;
23
23
  Version: <%= Flipper::VERSION %>
24
+ <a href="#" class="badge badge-warning ml-2 d-none" style="font-size:100%" id="new-version-badge" data-version="<%= Flipper::VERSION %>">
25
+ </a>
26
+
27
+ <% if Flipper.deprecated_ruby_version? %>
28
+ <a href="https://github.com/flippercloud/flipper/pull/776" class="badge badge-danger ml-2" style="font-size:100%">
29
+ Ruby <%= RUBY_VERSION %> deprecated
30
+ </a>
31
+ <% end %>
32
+
33
+ <% if defined?(Rails) && Flipper::Engine.deprecated_rails_version? %>
34
+ <a href="https://github.com/flippercloud/flipper/pull/776" class="badge badge-danger ml-2" style="font-size:100%">
35
+ Rails <%= Rails.version %> deprecated
36
+ </a>
37
+ <% end %>
24
38
  </div>
25
39
 
26
40
  <nav aria-label="breadcrumb">
@@ -60,6 +74,7 @@
60
74
  <script src="<%= script_name + jquery_js[:src] %>" integrity="<%= jquery_js[:hash] %>" crossorigin="anonymous"></script>
61
75
  <script src="<%= script_name + popper_js[:src] %>" integrity="<%= popper_js[:hash] %>" crossorigin="anonymous"></script>
62
76
  <script src="<%= script_name + bootstrap_js[:src] %>" integrity="<%= bootstrap_js[:hash] %>" crossorigin="anonymous"></script>
63
- <script src="<%= script_name %>/js/application.js"></script>
77
+ <script src="<%= script_name %>/js/application.js?v=<%= Flipper::VERSION %>"></script>
78
+ <script src="<%= script_name %>/js/version.js?v=<%= Flipper::VERSION %>"></script>
64
79
  </body>
65
80
  </html>
data/lib/flipper/ui.rb CHANGED
@@ -22,7 +22,7 @@ module Flipper
22
22
  env_key = options.fetch(:env_key, 'flipper')
23
23
  rack_protection_options = options.fetch(:rack_protection, use: :authenticity_token)
24
24
 
25
- app = ->(_) { [200, { 'content-type' => 'text/html' }, ['']] }
25
+ app = ->(_) { [200, { Rack::CONTENT_TYPE => 'text/html' }, ['']] }
26
26
  builder = Rack::Builder.new
27
27
  yield builder if block_given?
28
28
  builder.use Rack::Protection, rack_protection_options
@@ -1,3 +1,13 @@
1
1
  module Flipper
2
- VERSION = '1.1.2'.freeze
2
+ VERSION = '1.2.0'.freeze
3
+
4
+ REQUIRED_RUBY_VERSION = '2.6'.freeze
5
+ NEXT_REQUIRED_RUBY_VERSION = '3.0'.freeze
6
+
7
+ REQUIRED_RAILS_VERSION = '5.2'.freeze
8
+ NEXT_REQUIRED_RAILS_VERSION = '6.1.0'.freeze
9
+
10
+ def self.deprecated_ruby_version?
11
+ Gem::Version.new(RUBY_VERSION) < Gem::Version.new(NEXT_REQUIRED_RUBY_VERSION)
12
+ end
3
13
  end
@@ -68,7 +68,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
68
68
 
69
69
  it 'redirects back to feature' do
70
70
  expect(last_response.status).to be(302)
71
- expect(last_response.headers['Location']).to eq('/features/search')
71
+ expect(last_response.headers['location']).to eq('/features/search')
72
72
  end
73
73
 
74
74
  context "when feature name contains space" do
@@ -84,7 +84,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
84
84
 
85
85
  it "redirects back to feature" do
86
86
  expect(last_response.status).to be(302)
87
- expect(last_response.headers['Location']).to eq('/features/sp%20ace')
87
+ expect(last_response.headers['location']).to eq('/features/sp%20ace')
88
88
  end
89
89
  end
90
90
 
@@ -114,7 +114,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
114
114
 
115
115
  it 'redirects back to feature' do
116
116
  expect(last_response.status).to be(302)
117
- expect(last_response.headers['Location']).to eq('/features/search/actors?error=%22%22%20is%20not%20a%20valid%20actor%20value.')
117
+ expect(last_response.headers['location']).to eq('/features/search/actors?error=%22%22%20is%20not%20a%20valid%20actor%20value.')
118
118
  end
119
119
  end
120
120
 
@@ -123,7 +123,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
123
123
 
124
124
  it 'redirects back to feature' do
125
125
  expect(last_response.status).to be(302)
126
- expect(last_response.headers['Location']).to eq('/features/search/actors?error=%22%22%20is%20not%20a%20valid%20actor%20value.')
126
+ expect(last_response.headers['location']).to eq('/features/search/actors?error=%22%22%20is%20not%20a%20valid%20actor%20value.')
127
127
  end
128
128
  end
129
129
  end
@@ -175,7 +175,7 @@ RSpec.describe Flipper::UI::Actions::ActorsGate do
175
175
 
176
176
  it 'redirects back to feature' do
177
177
  expect(last_response.status).to be(302)
178
- expect(last_response.headers['Location']).to eq('/features/search')
178
+ expect(last_response.headers['location']).to eq('/features/search')
179
179
  end
180
180
 
181
181
  context 'value contains whitespace' do
@@ -25,7 +25,7 @@ RSpec.describe Flipper::UI::Actions::BooleanGate do
25
25
 
26
26
  it 'redirects back to feature' do
27
27
  expect(last_response.status).to be(302)
28
- expect(last_response.headers['Location']).to eq('/features/search')
28
+ expect(last_response.headers['location']).to eq('/features/search')
29
29
  end
30
30
  end
31
31
 
@@ -43,7 +43,7 @@ RSpec.describe Flipper::UI::Actions::BooleanGate do
43
43
 
44
44
  it 'redirects back to feature' do
45
45
  expect(last_response.status).to be(302)
46
- expect(last_response.headers['Location']).to eq('/features/sp%20ace')
46
+ expect(last_response.headers['location']).to eq('/features/sp%20ace')
47
47
  end
48
48
  end
49
49
 
@@ -61,7 +61,7 @@ RSpec.describe Flipper::UI::Actions::BooleanGate do
61
61
 
62
62
  it 'redirects back to feature' do
63
63
  expect(last_response.status).to be(302)
64
- expect(last_response.headers['Location']).to eq('/features/search')
64
+ expect(last_response.headers['location']).to eq('/features/search')
65
65
  end
66
66
  end
67
67
  end
@@ -33,12 +33,12 @@ RSpec.describe Flipper::UI::Actions::Features do
33
33
  end
34
34
 
35
35
  it 'sets content disposition' do
36
- expect(last_response.headers['Content-Disposition']).to match(/Attachment;filename=flipper_memory_[0-9]*\.json/)
36
+ expect(last_response.headers['content-disposition']).to match(/Attachment;filename=flipper_memory_[0-9]*\.json/)
37
37
  end
38
38
 
39
39
  it 'renders json' do
40
40
  data = JSON.parse(last_response.body)
41
- expect(last_response.headers['Content-Type']).to eq('application/json')
41
+ expect(last_response.headers['content-type']).to eq('application/json')
42
42
  expect(data['version']).to eq(1)
43
43
  expect(data['features']).to eq({
44
44
  "analytics" => {"boolean"=>nil, "expression"=>{"Equal"=>[{"Property"=>["plan"]}, "basic"]}, "groups"=>[], "actors"=>[], "percentage_of_actors"=>nil, "percentage_of_time"=>nil},
@@ -24,7 +24,7 @@ RSpec.describe Flipper::UI::Actions::Feature do
24
24
 
25
25
  it 'redirects to features' do
26
26
  expect(last_response.status).to be(302)
27
- expect(last_response.headers['Location']).to eq('/features')
27
+ expect(last_response.headers['location']).to eq('/features')
28
28
  end
29
29
 
30
30
  context "with space in feature name" do
@@ -41,7 +41,7 @@ RSpec.describe Flipper::UI::Actions::Feature do
41
41
 
42
42
  it 'redirects to features' do
43
43
  expect(last_response.status).to be(302)
44
- expect(last_response.headers['Location']).to eq('/features')
44
+ expect(last_response.headers['location']).to eq('/features')
45
45
  end
46
46
  end
47
47
 
@@ -80,7 +80,7 @@ RSpec.describe Flipper::UI::Actions::Feature do
80
80
 
81
81
  it 'redirects to features' do
82
82
  expect(last_response.status).to be(302)
83
- expect(last_response.headers['Location']).to eq('/features')
83
+ expect(last_response.headers['location']).to eq('/features')
84
84
  end
85
85
  end
86
86
 
@@ -138,14 +138,35 @@ RSpec.describe Flipper::UI::Actions::Feature do
138
138
  }
139
139
  }
140
140
  end
141
-
142
- get '/features/search'
143
141
  end
144
142
 
145
143
  it 'renders template with custom actor names' do
144
+ get '/features/search'
146
145
  expect(last_response.body).to include('Some Actor Name (some_actor_name)')
147
146
  expect(last_response.body).not_to include('Some Other Actor Name')
148
147
  end
148
+
149
+ it 'allows basic html' do
150
+ Flipper::UI.configure do |config|
151
+ config.actor_names_source = lambda { |_keys|
152
+ { "some_actor_name" => '<a href="/users/some_actor_name">Some Actor Name</a>', }
153
+ }
154
+ end
155
+
156
+ get '/features/search'
157
+ expect(last_response.body).to include('<a href="/users/some_actor_name" rel="nofollow">Some Actor Name</a>')
158
+ end
159
+
160
+ it 'sanitizes dangerous markup' do
161
+ Flipper::UI.configure do |config|
162
+ config.actor_names_source = lambda { |_keys|
163
+ { "some_actor_name" => '<a href="javascript:alert(\'hello\')">Some Actor Name</a>', }
164
+ }
165
+ end
166
+
167
+ get '/features/search'
168
+ expect(last_response.body).not_to include('javascript:alert')
169
+ end
149
170
  end
150
171
  end
151
172
 
@@ -104,7 +104,7 @@ RSpec.describe Flipper::UI::Actions::Features do
104
104
 
105
105
  it 'redirects to feature' do
106
106
  expect(last_response.status).to be(302)
107
- expect(last_response.headers['Location']).to eq('/features/notifications_next')
107
+ expect(last_response.headers['location']).to eq('/features/notifications_next')
108
108
  end
109
109
 
110
110
  context 'feature name has whitespace at beginning and end' do
@@ -124,7 +124,7 @@ RSpec.describe Flipper::UI::Actions::Features do
124
124
 
125
125
  it 'redirects to feature' do
126
126
  expect(last_response.status).to be(302)
127
- expect(last_response.headers['Location']).to eq('/features/notifications%20next')
127
+ expect(last_response.headers['location']).to eq('/features/notifications%20next')
128
128
  end
129
129
  end
130
130
 
@@ -138,7 +138,7 @@ RSpec.describe Flipper::UI::Actions::Features do
138
138
 
139
139
  it 'redirects back to feature' do
140
140
  expect(last_response.status).to be(302)
141
- expect(last_response.headers['Location']).to eq('/features/new?error=%22%22%20is%20not%20a%20valid%20feature%20name.')
141
+ expect(last_response.headers['location']).to eq('/features/new?error=%22%22%20is%20not%20a%20valid%20feature%20name.')
142
142
  end
143
143
  end
144
144
 
@@ -151,7 +151,7 @@ RSpec.describe Flipper::UI::Actions::Features do
151
151
 
152
152
  it 'redirects back to feature' do
153
153
  expect(last_response.status).to be(302)
154
- expect(last_response.headers['Location']).to eq('/features/new?error=%22%22%20is%20not%20a%20valid%20feature%20name.')
154
+ expect(last_response.headers['location']).to eq('/features/new?error=%22%22%20is%20not%20a%20valid%20feature%20name.')
155
155
  end
156
156
  end
157
157
  end
@@ -55,7 +55,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
55
55
 
56
56
  it 'redirects back to feature' do
57
57
  expect(last_response.status).to be(302)
58
- expect(last_response.headers['Location']).to eq('/features/search')
58
+ expect(last_response.headers['location']).to eq('/features/search')
59
59
  end
60
60
 
61
61
  context 'feature name contains space' do
@@ -71,7 +71,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
71
71
 
72
72
  it 'redirects back to feature' do
73
73
  expect(last_response.status).to be(302)
74
- expect(last_response.headers['Location']).to eq('/features/sp%20ace')
74
+ expect(last_response.headers['location']).to eq('/features/sp%20ace')
75
75
  end
76
76
  end
77
77
 
@@ -89,7 +89,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
89
89
 
90
90
  it 'redirects back to feature' do
91
91
  expect(last_response.status).to be(302)
92
- expect(last_response.headers['Location']).to eq('/features/search/groups?error=The%20group%20named%20%22not_here%22%20has%20not%20been%20registered.')
92
+ expect(last_response.headers['location']).to eq('/features/search/groups?error=The%20group%20named%20%22not_here%22%20has%20not%20been%20registered.')
93
93
  end
94
94
  end
95
95
 
@@ -98,7 +98,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
98
98
 
99
99
  it 'redirects back to feature' do
100
100
  expect(last_response.status).to be(302)
101
- expect(last_response.headers['Location']).to eq('/features/search/groups?error=The%20group%20named%20%22%22%20has%20not%20been%20registered.')
101
+ expect(last_response.headers['location']).to eq('/features/search/groups?error=The%20group%20named%20%22%22%20has%20not%20been%20registered.')
102
102
  end
103
103
  end
104
104
 
@@ -107,7 +107,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
107
107
 
108
108
  it 'redirects back to feature' do
109
109
  expect(last_response.status).to be(302)
110
- expect(last_response.headers['Location']).to eq('/features/search/groups?error=The%20group%20named%20%22%22%20has%20not%20been%20registered.')
110
+ expect(last_response.headers['location']).to eq('/features/search/groups?error=The%20group%20named%20%22%22%20has%20not%20been%20registered.')
111
111
  end
112
112
  end
113
113
  end
@@ -129,7 +129,7 @@ RSpec.describe Flipper::UI::Actions::GroupsGate do
129
129
 
130
130
  it 'redirects back to feature' do
131
131
  expect(last_response.status).to be(302)
132
- expect(last_response.headers['Location']).to eq('/features/search')
132
+ expect(last_response.headers['location']).to eq('/features/search')
133
133
  end
134
134
 
135
135
  context 'group name contains whitespace' do
@@ -8,7 +8,7 @@ RSpec.describe Flipper::UI::Actions::Home do
8
8
 
9
9
  it 'responds with redirect' do
10
10
  expect(last_response.status).to be(302)
11
- expect(last_response.headers['Location']).to eq('/features')
11
+ expect(last_response.headers['location']).to eq('/features')
12
12
  end
13
13
  end
14
14
  end
@@ -35,7 +35,7 @@ RSpec.describe Flipper::UI::Actions::Import do
35
35
 
36
36
  it 'responds with redirect to settings' do
37
37
  expect(last_response.status).to be(302)
38
- expect(last_response.headers['Location']).to eq('/features')
38
+ expect(last_response.headers['location']).to eq('/features')
39
39
  end
40
40
  end
41
41
  end
@@ -24,7 +24,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
24
24
 
25
25
  it 'redirects back to feature' do
26
26
  expect(last_response.status).to be(302)
27
- expect(last_response.headers['Location']).to eq('/features/search')
27
+ expect(last_response.headers['location']).to eq('/features/search')
28
28
  end
29
29
  end
30
30
 
@@ -41,7 +41,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
41
41
 
42
42
  it 'redirects back to feature' do
43
43
  expect(last_response.status).to be(302)
44
- expect(last_response.headers['Location']).to eq('/features/sp%20ace')
44
+ expect(last_response.headers['location']).to eq('/features/sp%20ace')
45
45
  end
46
46
  end
47
47
 
@@ -58,7 +58,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfActorsGate do
58
58
 
59
59
  it 'redirects back to feature' do
60
60
  expect(last_response.status).to be(302)
61
- expect(last_response.headers['Location']).to eq('/features/search?error=Invalid%20percentage%20of%20actors%20value:%20value%20must%20be%20a%20positive%20number%20less%20than%20or%20equal%20to%20100,%20but%20was%20555')
61
+ expect(last_response.headers['location']).to eq('/features/search?error=Invalid%20percentage%20of%20actors%20value:%20value%20must%20be%20a%20positive%20number%20less%20than%20or%20equal%20to%20100,%20but%20was%20555')
62
62
  end
63
63
  end
64
64
  end
@@ -24,7 +24,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
24
24
 
25
25
  it 'redirects back to feature' do
26
26
  expect(last_response.status).to be(302)
27
- expect(last_response.headers['Location']).to eq('/features/search')
27
+ expect(last_response.headers['location']).to eq('/features/search')
28
28
  end
29
29
  end
30
30
 
@@ -41,7 +41,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
41
41
 
42
42
  it 'redirects back to feature' do
43
43
  expect(last_response.status).to be(302)
44
- expect(last_response.headers['Location']).to eq('/features/sp%20ace')
44
+ expect(last_response.headers['location']).to eq('/features/sp%20ace')
45
45
  end
46
46
  end
47
47
 
@@ -58,7 +58,7 @@ RSpec.describe Flipper::UI::Actions::PercentageOfTimeGate do
58
58
 
59
59
  it 'redirects back to feature' do
60
60
  expect(last_response.status).to be(302)
61
- expect(last_response.headers['Location']).to eq('/features/search?error=Invalid%20percentage%20of%20time%20value:%20value%20must%20be%20a%20positive%20number%20less%20than%20or%20equal%20to%20100,%20but%20was%20555')
61
+ expect(last_response.headers['location']).to eq('/features/search?error=Invalid%20percentage%20of%20time%20value:%20value%20must%20be%20a%20positive%20number%20less%20than%20or%20equal%20to%20100,%20but%20was%20555')
62
62
  end
63
63
  end
64
64
  end
@@ -42,7 +42,7 @@ RSpec.describe Flipper::UI do
42
42
  { 'value' => 'User;6', 'operation' => 'enable', 'authenticity_token' => token },
43
43
  'rack.session' => session
44
44
  expect(last_response.status).to be(302)
45
- expect(last_response.headers['Location']).to eq('/features/refactor-images')
45
+ expect(last_response.headers['location']).to eq('/features/refactor-images')
46
46
  end
47
47
 
48
48
  describe 'configure' do
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: 1.1.2
4
+ version: 1.2.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: 2023-12-12 00:00:00.000000000 Z
11
+ date: 2024-01-11 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: 1.1.2
59
+ version: 1.2.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: 1.1.2
66
+ version: 1.2.0
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: erubi
69
69
  requirement: !ruby/object:Gem::Requirement
@@ -139,6 +139,7 @@ files:
139
139
  - lib/flipper/ui/public/js/bootstrap-4.6.0.min.js
140
140
  - lib/flipper/ui/public/js/jquery-3.6.0.slim.js
141
141
  - lib/flipper/ui/public/js/popper-1.12.9.min.js
142
+ - lib/flipper/ui/public/js/version.js
142
143
  - lib/flipper/ui/util.rb
143
144
  - lib/flipper/ui/views/add_actor.erb
144
145
  - lib/flipper/ui/views/add_feature.erb
@@ -178,7 +179,7 @@ metadata:
178
179
  homepage_uri: https://www.flippercloud.io
179
180
  source_code_uri: https://github.com/flippercloud/flipper
180
181
  bug_tracker_uri: https://github.com/flippercloud/flipper/issues
181
- changelog_uri: https://github.com/flippercloud/flipper/blob/main/Changelog.md
182
+ changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.2.0
182
183
  post_install_message:
183
184
  rdoc_options: []
184
185
  require_paths:
@@ -194,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
195
  - !ruby/object:Gem::Version
195
196
  version: '0'
196
197
  requirements: []
197
- rubygems_version: 3.4.10
198
+ rubygems_version: 3.5.3
198
199
  signing_key:
199
200
  specification_version: 4
200
201
  summary: Feature flag UI for the Flipper gem