Skip to content

Commit

Permalink
Merge pull request #853 from flippercloud/nav-items
Browse files Browse the repository at this point in the history
UI: Replace breadcrumbs with configurable nav
  • Loading branch information
bkeepers authored Mar 2, 2024
2 parents b59a7a9 + 2b52b0f commit 7b870c6
Show file tree
Hide file tree
Showing 16 changed files with 96 additions and 113 deletions.
3 changes: 3 additions & 0 deletions examples/ui/basic.ru
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ Flipper::UI.configure do |config|
'6' => '<a href="https://opensoul.org">Brandon</a>',
}
end

config.application_href = "https://example.com"
end

# You can uncomment these to get some default data:
Expand All @@ -63,5 +65,6 @@ end
use Rack::Reloader

run Flipper::UI.app { |builder|
builder.use Rack::Reloader, 1
builder.use Rack::Session::Cookie, secret: "_super_secret"
}
31 changes: 10 additions & 21 deletions lib/flipper/ui/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,6 @@ def initialize(flipper, request)
@request = request
@code = 200
@headers = {Rack::CONTENT_TYPE => 'text/plain'}
@breadcrumbs =
if Flipper::UI.configuration.application_breadcrumb_href
[Breadcrumb.new('App', Flipper::UI.configuration.application_breadcrumb_href)]
else
[]
end
end

# Public: Runs the request method for the provided request.
Expand Down Expand Up @@ -202,16 +196,6 @@ def active?
end
end

# Public: Add a breadcrumb to the trail.
#
# text - The String text for the breadcrumb.
# href - The String href for the anchor tag (optional). If nil, breadcrumb
# is assumed to be the end of the trail.
def breadcrumb(text, href = nil)
breadcrumb_href = href.nil? ? href : "#{script_name}#{href}"
@breadcrumbs << Breadcrumb.new(text, breadcrumb_href)
end

# Private
def view_with_layout(&block)
view :layout, &block
Expand All @@ -235,6 +219,16 @@ def script_name
request.env['SCRIPT_NAME']
end

# Internal: Generate urls relative to the app's script name.
#
# url_for("feature") # => "http://localhost:9292/flipper/feature"
# url_for("/thing") # => "http://localhost:9292/thing"
# url_for("https://example.com") # => "https://example.com"
#
def url_for(*parts)
URI.join(request.base_url, script_name + '/', *parts).to_s
end

# Private
def views_path
self.class.views_path
Expand Down Expand Up @@ -262,11 +256,6 @@ def valid_request_method?
# to inform people of that fact.
def render_read_only
status 403

breadcrumb 'Home', '/'
breadcrumb 'Features', '/features'
breadcrumb 'Noooooope'

halt view_response(:read_only)
end

Expand Down
6 changes: 0 additions & 6 deletions lib/flipper/ui/actions/actors_gate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,6 @@ class ActorsGate < UI::Action
def get
feature = flipper[feature_name]
@feature = Decorators::Feature.new(feature)

breadcrumb 'Home', '/'
breadcrumb 'Features', '/features'
breadcrumb @feature.key, "/features/#{@feature.key}"
breadcrumb 'Add Actor'

view_response :add_actor
end

Expand Down
9 changes: 0 additions & 9 deletions lib/flipper/ui/actions/add_feature.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,9 @@ def get

unless Flipper::UI.configuration.feature_creation_enabled
status 403

breadcrumb 'Home', '/'
breadcrumb 'Features', '/features'
breadcrumb 'Noooooope'

halt view_response(:feature_creation_disabled)
end

breadcrumb 'Home', '/'
breadcrumb 'Features', '/features'
breadcrumb 'Add'

view_response :add_feature
end
end
Expand Down
7 changes: 0 additions & 7 deletions lib/flipper/ui/actions/feature.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ def get
@page_title = "#{@feature.key} // Features"
@percentages = [0, 1, 5, 10, 25, 50, 100]

breadcrumb 'Home', '/'
breadcrumb 'Features', '/features'
breadcrumb @feature.key

view_response :feature
end

Expand All @@ -31,9 +27,6 @@ def delete
unless Flipper::UI.configuration.feature_removal_enabled
status 403

breadcrumb 'Home', '/'
breadcrumb 'Features', '/features'

halt view_response(:feature_removal_disabled)
end

Expand Down
7 changes: 0 additions & 7 deletions lib/flipper/ui/actions/features.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ def get

@show_blank_slate = @features.empty?

breadcrumb 'Home', '/'
breadcrumb 'Features'

view_response :features
end

Expand All @@ -41,10 +38,6 @@ def post
unless Flipper::UI.configuration.feature_creation_enabled
status 403

breadcrumb 'Home', '/'
breadcrumb 'Features', '/features'
breadcrumb 'Noooooope'

halt view_response(:feature_creation_disabled)
end

Expand Down
5 changes: 0 additions & 5 deletions lib/flipper/ui/actions/groups_gate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ def get
feature = flipper[feature_name]
@feature = Decorators::Feature.new(feature)

breadcrumb 'Home', '/'
breadcrumb 'Features', '/features'
breadcrumb @feature.key, "/features/#{@feature.key}"
breadcrumb 'Add Group'

view_response :add_group
end

Expand Down
3 changes: 0 additions & 3 deletions lib/flipper/ui/actions/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ class Settings < UI::Action
def get
@page_title = 'Settings'

breadcrumb 'Home', '/'
breadcrumb 'Settings'

view_response :settings
end
end
Expand Down
18 changes: 16 additions & 2 deletions lib/flipper/ui/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,20 @@ class Configuration
# (feature_creation_enabled and feature_removal_enabled).
attr_accessor :read_only

# Public: If you set this, the UI will always have a first breadcrumb that
# Public: If you set this, the UI will always have a first nav item that
# says "App" which points to this href. The href can be a path (ie: "/")
# or full url ("https://app.example.com/").
attr_accessor :application_breadcrumb_href
attr_accessor :application_href
alias_method :application_breadcrumb_href, :application_href
alias_method :application_breadcrumb_href=, :application_href=

# Public: An array of nav items to show. By default "Features" and
# "Settings" are shown, but you can add your own. Each item must have
# a `:title` and `:href` key:
#
# config.nav_items << { title: "Custom", href: "/custom/page" }
#
attr_accessor :nav_items

# Public: Is feature creation allowed from the UI? Defaults to true. If
# set to false, users of the UI cannot create features. All feature
Expand Down Expand Up @@ -97,6 +107,10 @@ def initialize
@confirm_fully_enable = false
@confirm_disable = true
@read_only = false
@nav_items = [
{ title: "Features", href: "features" },
{ title: "Settings", href: "settings" },
]
end

def using_descriptions?
Expand Down
6 changes: 5 additions & 1 deletion lib/flipper/ui/views/add_actor.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
<% end %>

<div class="card">
<h4 class="card-header">Enable Actor for <%= @feature.key %></h4>
<h4 class="card-header">
<a class="link-dark" href="<%= script_name %>/features/<%= @feature.key %>"><%= @feature.key %></a>
/
Enable Actor
</h4>
<div class="card-body">
<p>
Turn on this feature for actors.
Expand Down
5 changes: 4 additions & 1 deletion lib/flipper/ui/views/add_group.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
<% end %>

<div class="card">
<h4 class="card-header">Enable Group for <%= @feature.key %></h4>
<h4 class="card-header">
<a class="link-dark" href="<%= script_name %>/features/<%= @feature.key %>"><%= @feature.key %></a>
/
Enable Group</h4>
<div class="card-body">
<% if @feature.disabled_groups.empty? %>
<p>All groups are enabled for this feature which means there is nothing to add.</p>
Expand Down
9 changes: 7 additions & 2 deletions lib/flipper/ui/views/feature.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@
<div class="card">
<%# Gate State Header %>
<div class="card-header">
<span class="status <%= @feature.color_class %> me-2"></span>
<%= @feature.gate_state_title %>
<div class="row align-items-center">
<h4 class="col text-truncate mb-0"><%= feature_name %></h4>
<div class="col-auto">
<span class="status <%= @feature.color_class %> me-2"></span>
<%= @feature.gate_state_title %>
</div>
</div>
</div>

<% unless @feature.boolean_value %>
Expand Down
2 changes: 1 addition & 1 deletion lib/flipper/ui/views/features.erb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<h4 class="col m-0">Features</h4>
<%- if write_allowed? && Flipper::UI.configuration.feature_creation_enabled -%>
<div class="col-auto">
<a class="btn btn-primary" href="<%= script_name %>/features/new">Add Feature</a>
<a class="btn btn-primary btn-sm" href="<%= script_name %>/features/new">Add Feature</a>
</div>
<%- end -%>
</div>
Expand Down
35 changes: 22 additions & 13 deletions lib/flipper/ui/views/layout.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
<%- end -%>

<div class="container text-muted small mb-3">
<a href="https://www.flippercloud.io/docs/ui?utm_source=oss&utm_medium=ui&utm_campaign=docs">Docs</a> &bull;
<a href="<%= script_name %>/settings">Settings</a> &bull;
Version: <%= Flipper::VERSION %>
<a href="#" class="badge text-bg-warning ms-2 d-none" style="font-size:100%" id="new-version-badge" data-version="<%= Flipper::VERSION %>">
</a>

Expand All @@ -36,19 +33,31 @@
</a>
<% end %>
</div>
<nav>
<ul class="nav nav-underline mb-3 align-items-center">
<% if Flipper::UI.configuration.application_href %>
<li class="nav-item">
<a class="nav-link" href="<%= Flipper::UI.configuration.application_href %>">
‹ App
</a>
</li>
<% end %>

<nav aria-label="breadcrumb" class="card card-body mb-4">
<ol class="breadcrumb align-items-center mb-0">
<% @breadcrumbs.each do |breadcrumb| %>
<li class="breadcrumb-item <% if breadcrumb.active? %>active<% end %>">
<% if breadcrumb.active? %>
<%= breadcrumb.text %>
<% else %>
<a href="<%= breadcrumb.href %>"><%= breadcrumb.text %></a>
<% end %>

<% Flipper::UI.configuration.nav_items.each do |item| %>
<li class="nav-item">
<a href="<%= url_for(item[:href]) %>" class="nav-link<%= " active" if request.url.start_with?(url_for(item[:href])) %>">
<%= item[:title] %>
</a>
</li>
<% end %>
</ol>

<li class="nav-item ms-auto text-muted small">
<a href="https://www.flippercloud.io/docs/ui?utm_source=oss&utm_medium=ui&utm_campaign=docs">Docs</a>
&bull;
Version: <%= Flipper::VERSION %>
</li>
</ul>
</nav>

<div>
Expand Down
13 changes: 9 additions & 4 deletions spec/flipper/ui/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,19 @@
end
end

describe "#application_breadcrumb_href" do
describe "#application_href" do
it "has default value" do
expect(configuration.application_breadcrumb_href).to eq(nil)
expect(configuration.application_href).to eq(nil)
end

it "can be updated" do
configuration.application_breadcrumb_href = 'http://www.myapp.com'
expect(configuration.application_breadcrumb_href).to eq('http://www.myapp.com')
configuration.application_href = 'http://www.myapp.com'
expect(configuration.application_href).to eq('http://www.myapp.com')
end

it 'aliases application_breadcrumb_href to application_href' do
configuration.application_breadcrumb_href = "/myapp"
expect(configuration.application_href).to eq("/myapp")
end
end

Expand Down
Loading

0 comments on commit 7b870c6

Please sign in to comment.