Merge branch '11489-branded-appearance-to-ce' into 'master'
Branded appearance to CE Closes #11489 The difference with the EE version is only that there is no distinction between light and dark logos, though this wasn't used anyway. If this is fine, I'll create a MR on EE too. TODO: - [x] Copy docs - [x] Make new screenshots - [ ] Remove Custom Welcome message feature? @rymai: I was unsure what labels to add to ping you, so I just ping you like this 😉 /cc @DouweM See merge request !2927
This commit is contained in:
commit
2ea8f71bb4
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)}
|
||||
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||

|
||||
|
||||
## 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.
|
||||
|
||||

|
||||
|
||||
After saving the page, your GitLab login page will have the details you filled in:
|
||||
|
||||

|
||||
Binary file not shown.
|
After Width: | Height: | Size: 357 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 307 KiB |
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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 New Issue