Branded login page also in CE
The only major difference with the EE version is the change from a light and dark logo to only a header logo The dark logo wasn't used anyway, so it seemed to make sense to me to rename the field to the actual function of it
This commit is contained in:
parent
bb3563b5cd
commit
9a2869ab46
22 changed files with 394 additions and 15 deletions
11
app/assets/stylesheets/pages/appearances.scss
Normal file
11
app/assets/stylesheets/pages/appearances.scss
Normal file
|
@ -0,0 +1,11 @@
|
|||
.appearance-logo-preview {
|
||||
max-width: 400px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.appearance-light-logo-preview {
|
||||
background-color: $background-color;
|
||||
max-width: 72px;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
57
app/controllers/admin/appearances_controller.rb
Normal file
57
app/controllers/admin/appearances_controller.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
class Admin::AppearancesController < Admin::ApplicationController
|
||||
before_action :set_appearance, except: :create
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def preview
|
||||
end
|
||||
|
||||
def create
|
||||
@appearance = Appearance.new(appearance_params)
|
||||
|
||||
if @appearance.save
|
||||
redirect_to admin_appearances_path, notice: 'Appearance was successfully created.'
|
||||
else
|
||||
render action: 'show'
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
if @appearance.update(appearance_params)
|
||||
redirect_to admin_appearances_path, notice: 'Appearance was successfully updated.'
|
||||
else
|
||||
render action: 'show'
|
||||
end
|
||||
end
|
||||
|
||||
def logo
|
||||
@appearance.remove_logo!
|
||||
|
||||
@appearance.save
|
||||
|
||||
redirect_to admin_appearances_path, notice: 'Logo was succesfully removed.'
|
||||
end
|
||||
|
||||
def header_logos
|
||||
@appearance.remove_header_logo!
|
||||
@appearance.save
|
||||
|
||||
redirect_to admin_appearances_path, notice: 'Header logo was succesfully removed.'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_appearance
|
||||
@appearance = Appearance.last || Appearance.new
|
||||
end
|
||||
|
||||
# Only allow a trusted parameter "white list" through.
|
||||
def appearance_params
|
||||
params.require(:appearance).permit(
|
||||
:title, :description, :logo, :logo_cache, :header_logo, :header_logo_cache,
|
||||
:updated_by
|
||||
)
|
||||
end
|
||||
end
|
|
@ -55,14 +55,15 @@ class UploadsController < ApplicationController
|
|||
"user" => User,
|
||||
"project" => Project,
|
||||
"note" => Note,
|
||||
"group" => Group
|
||||
"group" => Group,
|
||||
"appearance" => Appearance
|
||||
}
|
||||
|
||||
upload_models[params[:model]]
|
||||
end
|
||||
|
||||
def upload_mount
|
||||
upload_mounts = %w(avatar attachment file)
|
||||
upload_mounts = %w(avatar attachment file logo header_logo)
|
||||
|
||||
if upload_mounts.include?(params[:mounted_as])
|
||||
params[:mounted_as]
|
||||
|
|
|
@ -1,21 +1,33 @@
|
|||
module AppearancesHelper
|
||||
def brand_item
|
||||
nil
|
||||
end
|
||||
|
||||
def brand_title
|
||||
'GitLab Community Edition'
|
||||
if brand_item && brand_item.title
|
||||
brand_item.title
|
||||
else
|
||||
'GitLab Community Edition'
|
||||
end
|
||||
end
|
||||
|
||||
def brand_image
|
||||
nil
|
||||
if brand_item.logo?
|
||||
image_tag brand_item.logo
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def brand_text
|
||||
nil
|
||||
markdown(brand_item.description)
|
||||
end
|
||||
|
||||
def brand_item
|
||||
@appearance ||= Appearance.first
|
||||
end
|
||||
|
||||
def brand_header_logo
|
||||
render 'shared/logo.svg'
|
||||
if brand_item && brand_item.header_logo?
|
||||
image_tag brand_item.header_logo
|
||||
else
|
||||
render 'shared/logo.svg'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
9
app/models/appearance.rb
Normal file
9
app/models/appearance.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class Appearance < ActiveRecord::Base
|
||||
validates :title, presence: true
|
||||
validates :description, presence: true
|
||||
validates :logo, file_size: { maximum: 1.megabyte }
|
||||
validates :header_logo, file_size: { maximum: 1.megabyte }
|
||||
|
||||
mount_uploader :logo, AttachmentUploader
|
||||
mount_uploader :header_logo, AttachmentUploader
|
||||
end
|
58
app/views/admin/appearances/_form.html.haml
Normal file
58
app/views/admin/appearances/_form.html.haml
Normal file
|
@ -0,0 +1,58 @@
|
|||
= form_for @appearance, url: admin_appearances_path, html: { class: 'form-horizontal'} do |f|
|
||||
- if @appearance.errors.any?
|
||||
.alert.alert-danger
|
||||
- @appearance.errors.full_messages.each do |msg|
|
||||
%p= msg
|
||||
|
||||
%fieldset.sign-in
|
||||
%legend
|
||||
Sign in/Sign up pages:
|
||||
.form-group
|
||||
= f.label :title, class: 'control-label'
|
||||
.col-sm-10
|
||||
= f.text_field :title, class: "form-control"
|
||||
.form-group
|
||||
= f.label :description, class: 'control-label'
|
||||
.col-sm-10
|
||||
= f.text_area :description, class: "form-control", rows: 10
|
||||
.hint
|
||||
Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('markdown', 'markdown'), target: '_blank'}.
|
||||
.form-group
|
||||
= f.label :logo, class: 'control-label'
|
||||
.col-sm-10
|
||||
- if @appearance.logo?
|
||||
= image_tag @appearance.logo_url, class: 'appearance-logo-preview'
|
||||
- if @appearance.persisted?
|
||||
%br
|
||||
= link_to 'Remove logo', logo_admin_appearances_path, data: { confirm: "Logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-logo"
|
||||
%hr
|
||||
= f.hidden_field :logo_cache
|
||||
= f.file_field :logo, class: ""
|
||||
.hint
|
||||
Maximum file size is 1MB. Pages are optimized for a 640x360 px logo.
|
||||
|
||||
%fieldset.app_logo
|
||||
%legend
|
||||
Navigation bar:
|
||||
.form-group
|
||||
= f.label :header_logo, 'Header logo', class: 'control-label'
|
||||
.col-sm-10
|
||||
- if @appearance.header_logo?
|
||||
= image_tag @appearance.header_logo_url, class: 'appearance-light-logo-preview'
|
||||
- if @appearance.persisted?
|
||||
%br
|
||||
= link_to 'Remove header logo', header_logos_admin_appearances_path, data: { confirm: "Header logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-logo"
|
||||
%hr
|
||||
= f.hidden_field :header_logo_cache
|
||||
= f.file_field :header_logo, class: ""
|
||||
.hint
|
||||
Maximum file size is 1MB. Pages are optimized for a 72x72 px header logo
|
||||
|
||||
.form-actions
|
||||
= f.submit 'Save', class: 'btn btn-save'
|
||||
- if @appearance.persisted?
|
||||
= link_to 'Preview last save', preview_admin_appearances_path, class: 'btn', target: '_blank'
|
||||
|
||||
- if @appearance.updated_at
|
||||
%span.pull-right
|
||||
Last edit #{time_ago_with_tooltip(@appearance.updated_at)}
|
29
app/views/admin/appearances/preview.html.haml
Normal file
29
app/views/admin/appearances/preview.html.haml
Normal file
|
@ -0,0 +1,29 @@
|
|||
- page_title "Preview | Appearance"
|
||||
%h3.page-title
|
||||
Appearance settings - Preview
|
||||
%hr
|
||||
|
||||
.ui-box
|
||||
.title
|
||||
Sign-in page
|
||||
%div
|
||||
.login-page
|
||||
.container
|
||||
.content
|
||||
.login-title
|
||||
%h1= brand_title
|
||||
%hr
|
||||
.container
|
||||
.content
|
||||
.row
|
||||
.col-sm-7
|
||||
.brand-image
|
||||
= brand_image
|
||||
.brand_text
|
||||
= brand_text
|
||||
.col-sm-4
|
||||
.login-box
|
||||
%h3.page-title Sign in
|
||||
= text_field_tag :login, nil, class: "form-control top", placeholder: "Username or Email"
|
||||
= password_field_tag :password, nil, class: "form-control bottom", placeholder: "Password"
|
||||
= button_tag "Sign in", class: "btn-create btn"
|
7
app/views/admin/appearances/show.html.haml
Normal file
7
app/views/admin/appearances/show.html.haml
Normal file
|
@ -0,0 +1,7 @@
|
|||
- page_title "Appearance"
|
||||
%h3.page-title
|
||||
Appearance settings
|
||||
%p.light
|
||||
You can modify the look and feel of GitLab here
|
||||
|
||||
= render 'form'
|
|
@ -56,6 +56,11 @@
|
|||
= icon('cog fw')
|
||||
%span
|
||||
Background Jobs
|
||||
= nav_link(controller: :appearances) do
|
||||
= link_to admin_appearances_path, title: 'Appearances' do
|
||||
= icon('image')
|
||||
%span
|
||||
Appearance
|
||||
|
||||
= nav_link(controller: :applications) do
|
||||
= link_to admin_applications_path, title: 'Applications' do
|
||||
|
|
|
@ -156,6 +156,11 @@ Rails.application.routes.draw do
|
|||
to: "uploads#show",
|
||||
constraints: { model: /note|user|group|project/, mounted_as: /avatar|attachment/, filename: /[^\/]+/ }
|
||||
|
||||
# Appearance
|
||||
get ":model/:mounted_as/:id/:filename",
|
||||
to: "uploads#show",
|
||||
constraints: { model: /appearance/, mounted_as: /logo|header_logo/, filename: /.+/ }
|
||||
|
||||
# Project markdown uploads
|
||||
get ":namespace_id/:project_id/:secret/:filename",
|
||||
to: "projects/uploads#show",
|
||||
|
@ -253,6 +258,14 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
resource :appearances, path: 'appearance' do
|
||||
member do
|
||||
get :preview
|
||||
delete :logo
|
||||
delete :header_logos
|
||||
end
|
||||
end
|
||||
|
||||
resource :application_settings, only: [:show, :update] do
|
||||
resources :services
|
||||
put :reset_runners_token
|
||||
|
|
14
db/migrate/20160222153918_create_appearances_ce.rb
Normal file
14
db/migrate/20160222153918_create_appearances_ce.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
class CreateAppearancesCE < ActiveRecord::Migration
|
||||
def change
|
||||
unless table_exists?(:appearances)
|
||||
create_table :appearances do |t|
|
||||
t.string :title
|
||||
t.text :description
|
||||
t.string :header_logo
|
||||
t.string :logo
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
11
db/schema.rb
11
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20160220123949) do
|
||||
ActiveRecord::Schema.define(version: 20160222153918) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -24,6 +24,15 @@ ActiveRecord::Schema.define(version: 20160220123949) do
|
|||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "appearances", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.text "description"
|
||||
t.string "header_logo"
|
||||
t.string "logo"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "application_settings", force: :cascade do |t|
|
||||
t.integer "default_projects_limit"
|
||||
t.boolean "signup_enabled"
|
||||
|
|
19
doc/customization/branded_login_page.md
Normal file
19
doc/customization/branded_login_page.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Changing the appearance of the login page
|
||||
|
||||
GitLab Community Edition offers a way to put your company's identity on the login page of your GitLab server and make it a branded login page.
|
||||
|
||||
By default, the page shows the GitLab logo and description.
|
||||
|
||||
![default_login_page](branded_login_page/default_login_page.png)
|
||||
|
||||
## Changing the appearance of the login page
|
||||
|
||||
Navigate to the **Admin** area and go to the **Appearance** page.
|
||||
|
||||
Fill in the required details like Title, Description and upload the company logo.
|
||||
|
||||
![appearance](branded_login_page/appearance.png)
|
||||
|
||||
After saving the page, your GitLab login page will have the details you filled in:
|
||||
|
||||
![company_login_page](branded_login_page/custom_sign_in.png)
|
BIN
doc/customization/branded_login_page/appearance.png
Normal file
BIN
doc/customization/branded_login_page/appearance.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 357 KiB |
BIN
doc/customization/branded_login_page/custom_sign_in.png
Normal file
BIN
doc/customization/branded_login_page/custom_sign_in.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 307 KiB |
BIN
doc/customization/branded_login_page/default_login_page.png
Normal file
BIN
doc/customization/branded_login_page/default_login_page.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 286 KiB |
|
@ -1,12 +1,12 @@
|
|||
# Customize the complete sign-in page (GitLab Enterprise Edition only)
|
||||
# Customize the complete sign-in page
|
||||
|
||||
Please see [Branded login page](http://doc.gitlab.com/ee/customization/branded_login_page.html)
|
||||
Please see [Branded login page](branded_login_page.md)
|
||||
|
||||
# Add a welcome message to the sign-in page (GitLab Community Edition)
|
||||
|
||||
It is possible to add a markdown-formatted welcome message to your GitLab
|
||||
sign-in page. Users of GitLab Enterprise Edition should use the [branded login
|
||||
page feature](/ee/customization/branded_login_page.html) instead.
|
||||
page feature](branded_login_page.md) instead.
|
||||
|
||||
The welcome message (extra_sign_in_text) can now be set/changed in the Admin UI.
|
||||
Admin area > Settings
|
||||
Admin area > Settings
|
||||
|
|
37
features/admin/appearance.feature
Normal file
37
features/admin/appearance.feature
Normal file
|
@ -0,0 +1,37 @@
|
|||
Feature: Admin Appearance
|
||||
Scenario: Create new appearance
|
||||
Given I sign in as an admin
|
||||
And I visit admin appearance page
|
||||
When submit form with new appearance
|
||||
Then I should be redirected to admin appearance page
|
||||
And I should see newly created appearance
|
||||
|
||||
Scenario: Preview appearance
|
||||
Given application has custom appearance
|
||||
And I sign in as an admin
|
||||
When I visit admin appearance page
|
||||
And I click preview button
|
||||
Then I should see a customized appearance
|
||||
|
||||
Scenario: Custom sign-in page
|
||||
Given application has custom appearance
|
||||
When I visit login page
|
||||
Then I should see a customized appearance
|
||||
|
||||
Scenario: Appearance logo
|
||||
Given application has custom appearance
|
||||
And I sign in as an admin
|
||||
And I visit admin appearance page
|
||||
When I attach a logo
|
||||
Then I should see a logo
|
||||
And I remove the logo
|
||||
Then I should see logo removed
|
||||
|
||||
Scenario: Header logos
|
||||
Given application has custom appearance
|
||||
And I sign in as an admin
|
||||
And I visit admin appearance page
|
||||
When I attach header logos
|
||||
Then I should see header logos
|
||||
And I remove the header logos
|
||||
Then I should see header logos removed
|
72
features/steps/admin/appearance.rb
Normal file
72
features/steps/admin/appearance.rb
Normal file
|
@ -0,0 +1,72 @@
|
|||
class Spinach::Features::AdminAppearance < Spinach::FeatureSteps
|
||||
include SharedAuthentication
|
||||
include SharedPaths
|
||||
|
||||
step 'submit form with new appearance' do
|
||||
fill_in 'appearance_title', with: 'MyCompany'
|
||||
fill_in 'appearance_description', with: 'dev server'
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I should be redirected to admin appearance page' do
|
||||
expect(current_path).to eq admin_appearances_path
|
||||
expect(page).to have_content 'Appearance settings'
|
||||
end
|
||||
|
||||
step 'I should see newly created appearance' do
|
||||
expect(page).to have_field('appearance_title', with: 'MyCompany')
|
||||
expect(page).to have_field('appearance_description', with: 'dev server')
|
||||
expect(page).to have_content 'Last edit'
|
||||
end
|
||||
|
||||
step 'I click preview button' do
|
||||
click_link "Preview"
|
||||
end
|
||||
|
||||
step 'application has custom appearance' do
|
||||
create(:appearance)
|
||||
end
|
||||
|
||||
step 'I should see a customized appearance' do
|
||||
expect(page).to have_content appearance.title
|
||||
expect(page).to have_content appearance.description
|
||||
end
|
||||
|
||||
step 'I attach a logo' do
|
||||
attach_file(:appearance_logo, Rails.root.join('spec', 'fixtures', 'dk.png'))
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I attach header logos' do
|
||||
attach_file(:appearance_header_logo, Rails.root.join('spec', 'fixtures', 'dk.png'))
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I should see a logo' do
|
||||
expect(page).to have_xpath('//img[@src="/uploads/appearance/logo/1/dk.png"]')
|
||||
end
|
||||
|
||||
step 'I should see header logos' do
|
||||
expect(page).to have_xpath('//img[@src="/uploads/appearance/header_logo/1/dk.png"]')
|
||||
end
|
||||
|
||||
step 'I remove the logo' do
|
||||
click_link 'Remove logo'
|
||||
end
|
||||
|
||||
step 'I remove the header logos' do
|
||||
click_link 'Remove header logo'
|
||||
end
|
||||
|
||||
step 'I should see logo removed' do
|
||||
expect(page).not_to have_xpath('//img[@src="/uploads/appearance/logo/1/gitlab_logo.png"]')
|
||||
end
|
||||
|
||||
step 'I should see header logos removed' do
|
||||
expect(page).not_to have_xpath('//img[@src="/uploads/appearance/header_logo/1/header_logo_light.png"]')
|
||||
end
|
||||
|
||||
def appearance
|
||||
Appearance.last
|
||||
end
|
||||
end
|
|
@ -7,6 +7,10 @@ module SharedPaths
|
|||
visit new_project_path
|
||||
end
|
||||
|
||||
step 'I visit login page' do
|
||||
visit new_user_session_path
|
||||
end
|
||||
|
||||
# ----------------------------------------
|
||||
# User
|
||||
# ----------------------------------------
|
||||
|
@ -187,6 +191,10 @@ module SharedPaths
|
|||
visit admin_groups_path
|
||||
end
|
||||
|
||||
step 'I visit admin appearance page' do
|
||||
visit admin_appearances_path
|
||||
end
|
||||
|
||||
step 'I visit admin teams page' do
|
||||
visit admin_teams_path
|
||||
end
|
||||
|
|
8
spec/factories/appearances.rb
Normal file
8
spec/factories/appearances.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Read about factories at https://github.com/thoughtbot/factory_girl
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :appearance do
|
||||
title "MepMep"
|
||||
description "This is my Community Edition instance"
|
||||
end
|
||||
end
|
10
spec/models/appearance_spec.rb
Normal file
10
spec/models/appearance_spec.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Appearance, type: :model do
|
||||
subject { create(:appearance) }
|
||||
|
||||
it { is_expected.to be_valid }
|
||||
|
||||
it { is_expected.to validate_presence_of(:title) }
|
||||
it { is_expected.to validate_presence_of(:description) }
|
||||
end
|
Loading…
Reference in a new issue