diff options
Diffstat (limited to 'app')
29 files changed, 312 insertions, 224 deletions
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index da56e3cdbc8..b7ebe6a5c89 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -55,7 +55,7 @@ class Dispatcher when 'projects:merge_requests:index' shortcut_handler = new ShortcutsNavigation() MergeRequests.init() - when 'dashboard:show' + when 'dashboard:show', 'root:show' new Dashboard() new Activities() when 'dashboard:projects:starred' diff --git a/app/assets/javascripts/profile.js.coffee b/app/assets/javascripts/profile.js.coffee index 40459a9a155..bb0b66b86e1 100644 --- a/app/assets/javascripts/profile.js.coffee +++ b/app/assets/javascripts/profile.js.coffee @@ -1,10 +1,8 @@ class @Profile constructor: -> - $('.edit_user .application-theme input, .edit_user .code-preview-theme input').click -> - # Submit the form - $('.edit_user').submit() - - new Flash("Appearance settings saved", "notice") + # Automatically submit the Preferences form when any of its radio buttons change + $('.js-preferences-form').on 'change.preference', 'input[type=radio]', -> + $(this).parents('form').submit() $('.update-username form').on 'ajax:before', -> $('.loading-gif').show() @@ -18,7 +16,6 @@ class @Profile $('.update-notifications').on 'ajax:complete', -> $(this).find('.btn-save').enable() - $('.js-choose-user-avatar-button').bind "click", -> form = $(this).closest("form") form.find(".js-user-avatar-input").click() diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 015ff2ce4ec..1a5f11df7d1 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -36,25 +36,25 @@ @import "font-awesome"; /** + * UI themes: + */ +@import "themes/**/*"; + +/** * Generic css (forms, nav etc): */ -@import "generic/*"; +@import "generic/**/*"; /** * Page specific styles (issues, projects etc): */ -@import "pages/*"; +@import "pages/**/*"; /** * Code highlight */ -@import "highlight/*"; - -/** - * UI themes: - */ -@import "themes/*"; +@import "highlight/**/*"; /** * Styles for JS behaviors. diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 5a5fbc468a3..8e4f0eb2b25 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -17,67 +17,6 @@ } } -/* - * Appearance settings - * - */ -.themes_opts { - label { - margin-right: 20px; - text-align: center; - - .prev { - height: 80px; - width: 160px; - margin-bottom: 10px; - @include border-radius(4px); - - &.classic { - background: #31363e; - } - - &.default { - background: #888888; - } - - &.modern { - background: #009871; - } - - &.gray { - background: #373737; - } - - &.violet { - background: #548; - } - - &.blue { - background: #2980b9; - } - } - } -} - -.code_highlight_opts { - margin-top: 10px; - - label { - margin-right: 20px; - text-align: center; - - .prev { - width: 160px; - margin-bottom: 10px; - - img { - max-width: 100%; - @include border-radius(4px); - } - } - } -} - .oauth-buttons { .btn-group { margin-right: 10px; diff --git a/app/assets/stylesheets/pages/profiles/preferences.scss b/app/assets/stylesheets/pages/profiles/preferences.scss new file mode 100644 index 00000000000..e5859fe7384 --- /dev/null +++ b/app/assets/stylesheets/pages/profiles/preferences.scss @@ -0,0 +1,56 @@ +.application-theme { + label { + margin-right: 20px; + text-align: center; + + .preview { + @include border-radius(4px); + + height: 80px; + margin-bottom: 10px; + width: 160px; + + &.ui_blue { + background: $theme-blue; + } + + &.ui_charcoal { + background: $theme-charcoal; + } + + &.ui_graphite { + background: $theme-graphite; + } + + &.ui_gray { + background: $theme-gray; + } + + &.ui_green { + background: $theme-green; + } + + &.ui_violet { + background: $theme-violet; + } + } + } +} + +.syntax-theme { + label { + margin-right: 20px; + text-align: center; + + .preview { + margin-bottom: 10px; + width: 160px; + + img { + @include border-radius(4px); + + max-width: 100%; + } + } + } +} diff --git a/app/assets/stylesheets/pages/themes.scss b/app/assets/stylesheets/pages/themes.scss deleted file mode 100644 index e69de29bb2d..00000000000 --- a/app/assets/stylesheets/pages/themes.scss +++ /dev/null diff --git a/app/assets/stylesheets/themes/gitlab-theme.scss b/app/assets/stylesheets/themes/gitlab-theme.scss index 10fcaf18fa9..7cabeaefb93 100644 --- a/app/assets/stylesheets/themes/gitlab-theme.scss +++ b/app/assets/stylesheets/themes/gitlab-theme.scss @@ -1,3 +1,11 @@ +/** + * Styles the GitLab application with a specific color theme + * + * $color-light - + * $color - + * $color-darker - + * $color-dark - + */ @mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { header { &.navbar-gitlab { @@ -77,3 +85,36 @@ } } } + +$theme-blue: #2980B9; +$theme-charcoal: #474D57; +$theme-graphite: #888888; +$theme-gray: #373737; +$theme-green: #019875; +$theme-violet: #554488; + +body { + &.ui_blue { + @include gitlab-theme(#BECDE9, $theme-blue, #1970A9, #096099); + } + + &.ui_charcoal { + @include gitlab-theme(#979DA7, $theme-charcoal, #373D47, #24272D); + } + + &.ui_graphite { + @include gitlab-theme(#CCCCCC, $theme-graphite, #777777, #666666); + } + + &.ui_gray { + @include gitlab-theme(#979797, $theme-gray, #272727, #222222); + } + + &.ui_green { + @include gitlab-theme(#AADDCC, $theme-green, #018865, #017855); + } + + &.ui_violet { + @include gitlab-theme(#9988CC, $theme-violet, #443366, #332255); + } +} diff --git a/app/assets/stylesheets/themes/ui_basic.scss b/app/assets/stylesheets/themes/ui_basic.scss deleted file mode 100644 index 63e8dce1e92..00000000000 --- a/app/assets/stylesheets/themes/ui_basic.scss +++ /dev/null @@ -1,8 +0,0 @@ -/** - * This file represent some UI that can be changed - * during web app restyle or theme select. - * - */ -.ui_basic { - @include gitlab-theme(#CCCCCC, #888888, #777777, #666666); -} diff --git a/app/assets/stylesheets/themes/ui_blue.scss b/app/assets/stylesheets/themes/ui_blue.scss deleted file mode 100644 index cf995622b6b..00000000000 --- a/app/assets/stylesheets/themes/ui_blue.scss +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Blue GitLab UI theme - */ -.ui_blue { - @include gitlab-theme(#BECDE9, #2980b9, #1970a9, #096099); -} diff --git a/app/assets/stylesheets/themes/ui_color.scss b/app/assets/stylesheets/themes/ui_color.scss deleted file mode 100644 index 6babccec0da..00000000000 --- a/app/assets/stylesheets/themes/ui_color.scss +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Violet GitLab UI theme - */ -.ui_color { - @include gitlab-theme(#98C, #548, #436, #325); -} diff --git a/app/assets/stylesheets/themes/ui_gray.scss b/app/assets/stylesheets/themes/ui_gray.scss deleted file mode 100644 index f8e4a6ea7da..00000000000 --- a/app/assets/stylesheets/themes/ui_gray.scss +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Gray GitLab UI theme - */ -.ui_gray { - @include gitlab-theme(#979797, #373737, #272727, #222222); -} diff --git a/app/assets/stylesheets/themes/ui_mars.scss b/app/assets/stylesheets/themes/ui_mars.scss deleted file mode 100644 index fda96b64cd9..00000000000 --- a/app/assets/stylesheets/themes/ui_mars.scss +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Classic GitLab UI theme - */ -.ui_mars { - @include gitlab-theme(#979DA7, #474D57, #373D47, #24272D); -} diff --git a/app/assets/stylesheets/themes/ui_modern.scss b/app/assets/stylesheets/themes/ui_modern.scss deleted file mode 100644 index 8261e80b35f..00000000000 --- a/app/assets/stylesheets/themes/ui_modern.scss +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Modern GitLab UI theme - */ -.ui_modern { - @include gitlab-theme(#ADC, #019875, #018865, #017855); -} diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb new file mode 100644 index 00000000000..538b09ca54d --- /dev/null +++ b/app/controllers/profiles/preferences_controller.rb @@ -0,0 +1,38 @@ +class Profiles::PreferencesController < Profiles::ApplicationController + before_action :user + + def show + end + + def update + begin + if @user.update_attributes(preferences_params) + flash[:notice] = 'Preferences saved.' + else + flash[:alert] = 'Failed to save preferences.' + end + rescue ArgumentError => e + # Raised when `dashboard` is given an invalid value. + flash[:alert] = "Failed to save preferences (#{e.message})." + end + + respond_to do |format| + format.html { redirect_to profile_preferences_path } + format.js + end + end + + private + + def user + @user = current_user + end + + def preferences_params + params.require(:user).permit( + :color_scheme_id, + :dashboard, + :theme_id + ) + end +end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index f4366c18e7b..b4af9e490ed 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -8,9 +8,6 @@ class ProfilesController < Profiles::ApplicationController def show end - def design - end - def applications @applications = current_user.oauth_applications @authorized_tokens = current_user.oauth_authorized_tokens @@ -29,7 +26,6 @@ class ProfilesController < Profiles::ApplicationController respond_to do |format| format.html { redirect_to :back } - format.js end end @@ -65,10 +61,21 @@ class ProfilesController < Profiles::ApplicationController def user_params params.require(:user).permit( - :email, :password, :password_confirmation, :bio, :name, - :username, :skype, :linkedin, :twitter, :website_url, - :color_scheme_id, :theme_id, :avatar, :hide_no_ssh_key, - :hide_no_password, :location, :public_email + :avatar, + :bio, + :email, + :hide_no_password, + :hide_no_ssh_key, + :linkedin, + :location, + :name, + :password, + :password_confirmation, + :public_email, + :skype, + :twitter, + :username, + :website_url ) end end diff --git a/app/controllers/root_controller.rb b/app/controllers/root_controller.rb new file mode 100644 index 00000000000..fdfe00dc135 --- /dev/null +++ b/app/controllers/root_controller.rb @@ -0,0 +1,28 @@ +# RootController +# +# This controller exists solely to handle requests to `root_url`. When a user is +# logged in and has customized their `dashboard` setting, they will be +# redirected to their preferred location. +# +# For users who haven't customized the setting, we simply delegate to +# `DashboardController#show`, which is the default. +class RootController < DashboardController + before_action :redirect_to_custom_dashboard, only: [:show] + + def show + super + end + + private + + def redirect_to_custom_dashboard + return unless current_user + + case current_user.dashboard + when 'stars' + redirect_to starred_dashboard_projects_path + else + return + end + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a539ec49f7a..10d7aa11209 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -2,26 +2,6 @@ require 'digest/md5' require 'uri' module ApplicationHelper - COLOR_SCHEMES = { - 1 => 'white', - 2 => 'dark', - 3 => 'solarized-light', - 4 => 'solarized-dark', - 5 => 'monokai', - } - COLOR_SCHEMES.default = 'white' - - # Helper method to access the COLOR_SCHEMES - # - # The keys are the `color_scheme_ids` - # The values are the `name` of the scheme. - # - # The preview images are `name-scheme-preview.png` - # The stylesheets should use the css class `.name` - def color_schemes - COLOR_SCHEMES.freeze - end - # Check if a particular controller is the current one # # args - One or more controller names to check @@ -138,18 +118,6 @@ module ApplicationHelper Emoji.names.to_s end - def app_theme - Gitlab::Theme.css_class_by_id(current_user.try(:theme_id)) - end - - def theme_type - Gitlab::Theme.type_css_class_by_id(current_user.try(:theme_id)) - end - - def user_color_scheme_class - COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user) - end - # Define whenever show last push event # with suggestion to create MR def show_last_push_widget?(event) diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 2777944fc9d..9aabe01f60e 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -2,6 +2,7 @@ require 'nokogiri' module GitlabMarkdownHelper include Gitlab::Markdown + include PreferencesHelper # Use this in places where you would normally use link_to(gfm(...), ...). # diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb new file mode 100644 index 00000000000..bceff4fd52e --- /dev/null +++ b/app/helpers/preferences_helper.rb @@ -0,0 +1,53 @@ +# Helper methods for per-User preferences +module PreferencesHelper + COLOR_SCHEMES = { + 1 => 'white', + 2 => 'dark', + 3 => 'solarized-light', + 4 => 'solarized-dark', + 5 => 'monokai', + } + COLOR_SCHEMES.default = 'white' + + # Helper method to access the COLOR_SCHEMES + # + # The keys are the `color_scheme_ids` + # The values are the `name` of the scheme. + # + # The preview images are `name-scheme-preview.png` + # The stylesheets should use the css class `.name` + def color_schemes + COLOR_SCHEMES.freeze + end + + # Maps `dashboard` values to more user-friendly option text + DASHBOARD_CHOICES = { + projects: 'Your Projects (default)', + stars: 'Starred Projects' + }.with_indifferent_access.freeze + + # Returns an Array usable by a select field for more user-friendly option text + def dashboard_choices + defined = User.dashboards + + if defined.size != DASHBOARD_CHOICES.size + # Ensure that anyone adding new options updates this method too + raise RuntimeError, "`User` defines #{defined.size} dashboard choices," + + " but `DASHBOARD_CHOICES` defined #{DASHBOARD_CHOICES.size}." + else + defined.map do |key, _| + # Use `fetch` so `KeyError` gets raised when a key is missing + [DASHBOARD_CHOICES.fetch(key), key] + end + end + end + + def user_application_theme + theme = Gitlab::Themes.by_id(current_user.try(:theme_id)) + theme.css_class + end + + def user_color_scheme_class + COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user) + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 8be0b622704..6ac287203b1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -50,12 +50,13 @@ # bitbucket_access_token :string(255) # bitbucket_access_token_secret :string(255) # location :string(255) +# public_email :string(255) default(""), not null # encrypted_otp_secret :string(255) # encrypted_otp_secret_iv :string(255) # encrypted_otp_secret_salt :string(255) # otp_required_for_login :boolean # otp_backup_codes :text -# public_email :string(255) default(""), not null +# dashboard :integer default(0) # require 'carrierwave/orm/activerecord' @@ -701,4 +702,8 @@ class User < ActiveRecord::Base def can_be_removed? !solo_owned_groups.present? end + + # User's Dashboard preference + # Note: When adding an option, it MUST go on the end of the array. + enum dashboard: [:projects, :stars] end diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 173033f7eab..678ed3c2c1f 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,10 +1,10 @@ !!! 5 %html{ lang: "en"} = render "layouts/head" - %body{class: "#{app_theme}", :'data-page' => body_data_page} - / Ideally this would be inside the head, but turbolinks only evaluates page-specific JS in the body. + %body{class: "#{user_application_theme}", 'data-page' => body_data_page} + -# Ideally this would be inside the head, but turbolinks only evaluates page-specific JS in the body. = yield :scripts_body_top - + - if current_user = render "layouts/header/default", title: header_title - else diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index d406f5764a7..1987bf1592a 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -1,7 +1,7 @@ !!! 5 %html{ lang: "en"} = render "layouts/head" - %body.ui_mars.login-page.application + %body.ui_charcoal.login-page.application = render "layouts/header/empty" = render "layouts/broadcast" .container.navless-container diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml index 2e3a2b16eb7..2af265a2296 100644 --- a/app/views/layouts/errors.html.haml +++ b/app/views/layouts/errors.html.haml @@ -1,7 +1,7 @@ !!! 5 %html{ lang: "en"} = render "layouts/head" - %body{class: "#{app_theme} application"} + %body{class: "#{user_application_theme} application"} = render "layouts/header/empty" .container.navless-container = render "layouts/flash" diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index d46dba4a240..687c1fc3dd2 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -1,6 +1,6 @@ %ul.nav.nav-sidebar - = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do - = link_to root_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do + = nav_link(path: ['dashboard#show', 'root#show'], html_options: {class: 'home'}) do + = link_to dashboard_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do = icon('dashboard fw') %span Your Projects diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index ac37fd4c1c1..121665bd536 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -38,11 +38,12 @@ %span SSH Keys %span.count= current_user.keys.count - = nav_link(path: 'profiles#design') do - = link_to design_profile_path, title: 'Design', data: {placement: 'right'} do + = nav_link(controller: :preferences) do + = link_to profile_preferences_path, title: 'Preferences', data: {placement: 'right'} do + -# TODO (rspeicher): Better icon? = icon('image fw') %span - Design + Preferences = nav_link(path: 'profiles#history') do = link_to history_profile_path, title: 'History', data: {placement: 'right'} do = icon('history fw') diff --git a/app/views/profiles/design.html.haml b/app/views/profiles/design.html.haml deleted file mode 100644 index f450ec1c018..00000000000 --- a/app/views/profiles/design.html.haml +++ /dev/null @@ -1,56 +0,0 @@ -- page_title "Design" -%h3.page-title - = page_title -%p.light - Appearance settings will be saved to your profile and made available across all devices. -%hr - -= form_for @user, url: profile_path, remote: true, method: :put do |f| - .panel.panel-default.application-theme - .panel-heading - Application theme - .panel-body - .themes_opts - = label_tag do - .prev.default - = f.radio_button :theme_id, 1 - Graphite - - = label_tag do - .prev.classic - = f.radio_button :theme_id, 2 - Charcoal - - = label_tag do - .prev.modern - = f.radio_button :theme_id, 3 - Green - - = label_tag do - .prev.gray - = f.radio_button :theme_id, 4 - Gray - - = label_tag do - .prev.violet - = f.radio_button :theme_id, 5 - Violet - - = label_tag do - .prev.blue - = f.radio_button :theme_id, 6 - Blue - %br - .clearfix - - .panel.panel-default.code-preview-theme - .panel-heading - Code preview theme - .panel-body - .code_highlight_opts - - color_schemes.each do |color_scheme_id, color_scheme| - = label_tag do - .prev - = image_tag "#{color_scheme}-scheme-preview.png" - = f.radio_button :color_scheme_id, color_scheme_id - = color_scheme.gsub(/[-_]+/, ' ').humanize diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml new file mode 100644 index 00000000000..aa99280fde6 --- /dev/null +++ b/app/views/profiles/preferences/show.html.haml @@ -0,0 +1,42 @@ +- page_title 'Preferences' +%h3.page-title + = page_title +%p.light + These settings allow you to customize the appearance and behavior of the site. + They are saved with your account and will persist to any device you use to + access the site. +%hr + += form_for @user, url: profile_preferences_path, remote: true, method: :put, html: {class: 'js-preferences-form form-horizontal'} do |f| + .panel.panel-default.application-theme + .panel-heading + Application theme + .panel-body + - Gitlab::Themes.each do |theme| + = label_tag do + .preview{class: theme.css_class} + = f.radio_button :theme_id, theme.id + = theme.name + + .panel.panel-default.syntax-theme + .panel-heading + Syntax highlighting theme + .panel-body + - color_schemes.each do |color_scheme_id, color_scheme| + = label_tag do + .preview= image_tag "#{color_scheme}-scheme-preview.png" + = f.radio_button :color_scheme_id, color_scheme_id + = color_scheme.tr('-_', ' ').titleize + + .panel.panel-default + .panel-heading + Behavior + .panel-body + .form-group + = f.label :dashboard, class: 'control-label' do + Default Dashboard + = link_to('(?)', help_page_path('profile', 'preferences') + '#default-dashboard', target: '_blank') + .col-sm-10 + = f.select :dashboard, dashboard_choices, {}, class: 'form-control' + .panel-footer + = f.submit 'Save', class: 'btn btn-save' diff --git a/app/views/profiles/preferences/update.js.erb b/app/views/profiles/preferences/update.js.erb new file mode 100644 index 00000000000..6c4b0ce757d --- /dev/null +++ b/app/views/profiles/preferences/update.js.erb @@ -0,0 +1,9 @@ +// Remove body class for any previous theme, re-add current one +$('body').removeClass('<%= Gitlab::Themes.body_classes %>') +$('body').addClass('<%= user_application_theme %>') + +// Re-enable the "Save" button +$('input[type=submit]').enable() + +// Show the notice flash message +new Flash('<%= flash.discard(:notice) %>', 'notice') diff --git a/app/views/profiles/update.js.erb b/app/views/profiles/update.js.erb deleted file mode 100644 index db37619136d..00000000000 --- a/app/views/profiles/update.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -// Remove body class for any previous theme, re-add current one -$('body').removeClass('<%= Gitlab::Theme.body_classes %>') -$('body').addClass('<%= app_theme %> <%= theme_type %>') |