Skip to content
Snippets Groups Projects
Commit 76ec9079 authored by Eugen Rochko's avatar Eugen Rochko
Browse files

Improved admin UI

parent 66801326
No related branches found
No related tags found
No related merge requests found
Showing
with 252 additions and 37 deletions
...@@ -45,6 +45,7 @@ gem 'rack-timeout-puma' ...@@ -45,6 +45,7 @@ gem 'rack-timeout-puma'
gem 'sidekiq' gem 'sidekiq'
gem 'ledermann-rails-settings' gem 'ledermann-rails-settings'
gem 'pg_search' gem 'pg_search'
gem 'simple-navigation'
gem 'react-rails' gem 'react-rails'
gem 'browserify-rails' gem 'browserify-rails'
......
...@@ -353,6 +353,8 @@ GEM ...@@ -353,6 +353,8 @@ GEM
connection_pool (~> 2.2, >= 2.2.0) connection_pool (~> 2.2, >= 2.2.0)
rack-protection (>= 1.5.0) rack-protection (>= 1.5.0)
redis (~> 3.2, >= 3.2.1) redis (~> 3.2, >= 3.2.1)
simple-navigation (4.0.3)
activesupport (>= 2.3.2)
simple_form (3.2.1) simple_form (3.2.1)
actionpack (> 4, < 5.1) actionpack (> 4, < 5.1)
activemodel (> 4, < 5.1) activemodel (> 4, < 5.1)
...@@ -458,6 +460,7 @@ DEPENDENCIES ...@@ -458,6 +460,7 @@ DEPENDENCIES
sass-rails (~> 5.0) sass-rails (~> 5.0)
sdoc (~> 0.4.0) sdoc (~> 0.4.0)
sidekiq sidekiq
simple-navigation
simple_form simple_form
simplecov simplecov
uglifier (>= 1.3.0) uglifier (>= 1.3.0)
......
...@@ -26,6 +26,12 @@ const Notifications = React.createClass({ ...@@ -26,6 +26,12 @@ const Notifications = React.createClass({
trackScroll: React.PropTypes.bool trackScroll: React.PropTypes.bool
}, },
getDefaultProps () {
return {
trackScroll: true
};
},
mixins: [PureRenderMixin], mixins: [PureRenderMixin],
componentWillMount () { componentWillMount () {
......
.admin-wrapper {
width: 100%;
height: 100%;
position: fixed;
background: #1a1c23;
overflow-y: scroll;
.sidebar {
width: 240px;
position: fixed;
left: 0;
height: 100%;
background: #282c37;
.logo {
display: block;
margin: 40px auto;
width: 100px;
height: 100px;
}
ul {
list-style: none;
a {
display: block;
padding: 15px 25px;
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
transition: all 200ms linear;
i.fa {
margin-right: 5px;
}
&:hover {
color: #fff;
background-color: darken(#282c37, 5%);
transition: all 100ms linear;
}
&.selected {
color: #fff;
background-color: #2b90d9;
&:hover {
background-color: lighten(#2b90d9, 5%);
}
}
}
}
}
.content {
margin-left: 240px;
padding: 15px;
}
}
.filters {
display: flex;
margin-bottom: 20px;
padding-left: 8px;
.filter-subset {
flex: 0 0 auto;
margin-right: 40px;
ul {
margin-top: 5px;
list-style: none;
li {
display: inline-block;
margin-right: 5px;
}
}
strong {
font-weight: 500;
text-transform: uppercase;
font-size: 12px;
}
a {
display: inline-block;
color: rgba(255, 255, 255, 0.7);
text-decoration: none;
text-transform: uppercase;
font-size: 12px;
font-weight: 500;
border-bottom: 2px solid #282c37;
&:hover {
color: #fff;
border-bottom: 2px solid lighten(#282c37, 5%);
}
&.selected {
color: #2b90d9;
border-bottom: 2px solid #2b90d9;
}
}
}
}
...@@ -235,3 +235,4 @@ body { ...@@ -235,3 +235,4 @@ body {
@import 'components'; @import 'components';
@import 'about'; @import 'about';
@import 'tables'; @import 'tables';
@import 'admin';
...@@ -7,15 +7,15 @@ ...@@ -7,15 +7,15 @@
th, td { th, td {
padding: 8px; padding: 8px;
line-height: 1.42857143; line-height: 18px;
vertical-align: top; vertical-align: top;
border-top: 1px solid #ddd; border-top: 1px solid #282c37;
text-align: left; text-align: left;
} }
& > thead > tr > th { & > thead > tr > th {
vertical-align: bottom; vertical-align: bottom;
border-bottom: 2px solid #ddd; border-bottom: 2px solid #282c37;
border-top: 0; border-top: 0;
font-weight: 500; font-weight: 500;
} }
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
font-weight: 500; font-weight: 500;
} }
& > tbody > tr:nth-child(odd) > td, & > tbody > tr:nth-child(odd) > th {
background: lighten(#1a1c23, 2%);
}
a { a {
color: #2b90d9; color: #2b90d9;
text-decoration: underline; text-decoration: underline;
...@@ -38,20 +42,20 @@ samp { ...@@ -38,20 +42,20 @@ samp {
font-family: 'Roboto Mono', monospace; font-family: 'Roboto Mono', monospace;
} }
.filters { a.table-action-link {
list-style: none; text-decoration: none;
margin-bottom: 20px; display: inline-block;
margin-right: 5px;
padding: 0 10px;
color: rgba(255, 255, 255, 0.7);
font-weight: 500;
li { &:hover {
display: inline-block; color: #fff;
} }
a { i.fa {
color: #2b90d9; font-weight: 400;
text-decoration: underline; margin-right: 5px;
&:hover {
text-decoration: none;
}
} }
} }
...@@ -4,7 +4,7 @@ class Admin::AccountsController < ApplicationController ...@@ -4,7 +4,7 @@ class Admin::AccountsController < ApplicationController
before_action :require_admin! before_action :require_admin!
before_action :set_account, except: :index before_action :set_account, except: :index
layout 'public' layout 'admin'
def index def index
@accounts = Account.alphabetic.paginate(page: params[:page], per_page: 40) @accounts = Account.alphabetic.paginate(page: params[:page], per_page: 40)
......
# frozen_string_literal: true
class Admin::DomainBlocksController < ApplicationController
before_action :require_admin!
layout 'admin'
def index
@blocks = DomainBlock.paginate(page: params[:page], per_page: 40)
end
def create
end
end
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
class Admin::PubsubhubbubController < ApplicationController class Admin::PubsubhubbubController < ApplicationController
before_action :require_admin! before_action :require_admin!
layout 'public' layout 'admin'
def index def index
@subscriptions = Subscription.order('id desc').includes(:account).paginate(page: params[:page], per_page: 40) @subscriptions = Subscription.order('id desc').includes(:account).paginate(page: params[:page], per_page: 40)
......
# frozen_string_literal: true
module Admin::AccountsHelper module Admin::AccountsHelper
def filter_params(more_params)
params.permit(:local, :remote, :by_domain, :silenced, :suspended, :recent).merge(more_params)
end
def filter_link_to(text, more_params)
link_to text, filter_params(more_params), class: params.merge(more_params).compact == params.compact ? 'selected' : ''
end
def table_link_to(icon, text, path)
link_to safe_join([fa_icon(icon), text]), path, class: 'table-action-link'
end
end end
# frozen_string_literal: true
module Admin::DomainBlocksHelper
end
# frozen_string_literal: true
module Admin::PubsubhubbubHelper module Admin::PubsubhubbubHelper
end end
%ul.filters - content_for :page_title do
%li= link_to 'Local', admin_accounts_path(local: '1') Accounts
%li= link_to 'Remote', admin_accounts_path(remote: '1')
%li= link_to 'Silenced', admin_accounts_path(silenced: '1') .filters
%li= link_to 'Suspended', admin_accounts_path(suspended: '1') .filter-subset
%li= link_to 'Most recent', admin_accounts_path(recent: '1') %strong Location
%ul
%li= filter_link_to 'All', local: nil, remote: nil
%li= filter_link_to 'Local', local: '1', remote: nil
%li= filter_link_to 'Remote', remote: '1', local: nil
.filter-subset
%strong Moderation
%ul
%li= filter_link_to 'All', silenced: nil, suspended: nil
%li= filter_link_to 'Silenced', silenced: '1'
%li= filter_link_to 'Suspended', suspended: '1'
.filter-subset
%strong Order
%ul
%li= filter_link_to 'Alphabetic', recent: nil
%li= filter_link_to 'Most recent', recent: '1'
%table.table %table.table
%thead %thead
...@@ -38,6 +53,9 @@ ...@@ -38,6 +53,9 @@
%i.fa.fa-check %i.fa.fa-check
- else - else
%i.fa.fa-times %i.fa.fa-times
%td= link_to 'Edit', admin_account_path(account.id) %td
= table_link_to 'circle', 'Open in web', web_path("accounts/#{account.id}")
= table_link_to 'globe', 'Open public', TagManager.instance.url_for(account)
= table_link_to 'pencil', 'Edit', admin_account_path(account.id)
= will_paginate @accounts, pagination_options = will_paginate @accounts, pagination_options
- content_for :page_title do
Domain Blocks
%table.table
%thead
%tr
%th Domain
%tbody
- @blocks.each do |block|
%tr
%td
%samp= block.domain
= will_paginate @blocks, pagination_options
- content_for :page_title do
PubSubHubbub
%table.table %table.table
%thead %thead
%tr %tr
......
- content_for :content do
.admin-wrapper
.sidebar
= link_to root_path do
= image_tag 'logo.png', class: 'logo'
= render_navigation
.content
= yield
= render template: "layouts/application"
# frozen_string_literal: true
SimpleNavigation::Configuration.run do |navigation|
navigation.items do |primary|
primary.item :accounts, safe_join([fa_icon('users fw'), 'Accounts']), admin_accounts_url
primary.item :pubsubhubbubs, safe_join([fa_icon('paper-plane-o fw'), 'PubSubHubbub']), admin_pubsubhubbub_index_url
primary.item :domain_blocks, safe_join([fa_icon('lock fw'), 'Domain Blocks']), admin_domain_blocks_url
primary.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url
primary.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url
end
end
...@@ -6,8 +6,8 @@ Rails.application.routes.draw do ...@@ -6,8 +6,8 @@ Rails.application.routes.draw do
mount ActionCable.server, at: 'cable' mount ActionCable.server, at: 'cable'
authenticate :user, lambda { |u| u.admin? } do authenticate :user, lambda { |u| u.admin? } do
mount Sidekiq::Web, at: 'sidekiq' mount Sidekiq::Web, at: 'sidekiq', as: :sidekiq
mount PgHero::Engine, at: 'pghero' mount PgHero::Engine, at: 'pghero', as: :pghero
end end
use_doorkeeper do use_doorkeeper do
...@@ -46,6 +46,7 @@ Rails.application.routes.draw do ...@@ -46,6 +46,7 @@ Rails.application.routes.draw do
namespace :admin do namespace :admin do
resources :pubsubhubbub, only: [:index] resources :pubsubhubbub, only: [:index]
resources :domain_blocks, only: [:index, :create]
resources :accounts, only: [:index, :show, :update] do resources :accounts, only: [:index, :show, :update] do
member do member do
......
require 'rails_helper'
RSpec.describe Admin::DomainBlocksController, type: :controller do
before do
sign_in Fabricate(:user, admin: true), scope: :user
end
describe 'GET #index' do
it 'returns http success' do
get :index
expect(response).to have_http_status(:success)
end
end
end
require 'rails_helper' require 'rails_helper'
# Specs in this file have access to a helper object that includes
# the Admin::AccountsHelper. For example:
#
# describe Admin::AccountsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe Admin::AccountsHelper, type: :helper do RSpec.describe Admin::AccountsHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment