diff options
Diffstat (limited to 'app')
37 files changed, 419 insertions, 116 deletions
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 0651bd20d26..c17d2186e29 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -31,8 +31,6 @@ #= require ace/ace #= require ace/ext-searchbox #= require underscore -#= require nprogress -#= require nprogress-turbolinks #= require dropzone #= require mousetrap #= require mousetrap/pause @@ -44,6 +42,7 @@ #= require jquery.nicescroll #= require_tree . #= require fuzzaldrin-plus +#= require cropper.js window.slugify = (text) -> text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase() diff --git a/app/assets/javascripts/logo.js.coffee b/app/assets/javascripts/logo.js.coffee index 35b2fbbba07..d14b7139237 100644 --- a/app/assets/javascripts/logo.js.coffee +++ b/app/assets/javascripts/logo.js.coffee @@ -1,4 +1,4 @@ -NProgress.configure(showSpinner: false) +Turbolinks.enableProgressBar(); defaultClass = 'tanuki-shape' pieces = [ diff --git a/app/assets/javascripts/profile.js.coffee b/app/assets/javascripts/profile.js.coffee index bb0b66b86e1..69d590a7533 100644 --- a/app/assets/javascripts/profile.js.coffee +++ b/app/assets/javascripts/profile.js.coffee @@ -16,11 +16,50 @@ 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() + # Avatar management + + $avatarInput = $('.js-user-avatar-input') + $filename = $('.js-avatar-filename') + $modalCrop = $('.modal-profile-crop') + $modalCropImg = $('.modal-profile-crop-image') + + $('.js-choose-user-avatar-button').on "click", -> + $form = $(this).closest("form") + $form.find(".js-user-avatar-input").click() + + $modalCrop.on 'shown.bs.modal', -> + setTimeout ( -> # The cropper must be asynchronously initialized + $modalCropImg.cropper + aspectRatio: 1 + modal: false + scalable: false + rotatable: false + zoomable: false + + crop: (event) -> + ['x', 'y'].forEach (key) -> + $("#user_avatar_crop_#{key}").val(Math.floor(event[key])) + $("#user_avatar_crop_size").val(Math.floor(event.width)) + ), 0 + + $modalCrop.on 'hidden.bs.modal', -> + $modalCropImg.attr('src', '').cropper('destroy') + $avatarInput.val('') + $filename.text($filename.data('label')) - $('.js-user-avatar-input').bind "change", -> + $('.js-upload-user-avatar').on 'click', -> + $('.edit_user').submit() + + $avatarInput.on "change", -> form = $(this).closest("form") filename = $(this).val().replace(/^.*[\\\/]/, '') - form.find(".js-avatar-filename").text(filename) + $filename.data('label', $filename.text()).text(filename) + + reader = new FileReader + + reader.onload = (event) -> + $modalCrop.modal('show') + $modalCropImg.attr('src', event.target.result) + + fileData = reader.readAsDataURL(this.files[0]) + diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 0c0451fe4dd..e2d590f4df4 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -9,6 +9,7 @@ *= require_self *= require dropzone/basic *= require cal-heatmap + *= require cropper.css */ /* @@ -25,12 +26,6 @@ @import "framework"; /* - * NProgress load bar css - */ -@import 'nprogress'; -@import 'nprogress-bootstrap'; - -/* * Font icons */ @import "font-awesome"; diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index fa7641b1676..e2a30f5ed34 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -26,6 +26,7 @@ @import "framework/mobile.scss"; @import "framework/nav.scss"; @import "framework/pagination.scss"; +@import "framework/progress.scss"; @import "framework/panels.scss"; @import "framework/selects.scss"; @import "framework/sidebar.scss"; diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss index 1d5000fe388..368bbfe5355 100644 --- a/app/assets/stylesheets/framework/mixins.scss +++ b/app/assets/stylesheets/framework/mixins.scss @@ -41,6 +41,12 @@ transition: $transition; } +@mixin transform($transform) { + -webkit-transform: $transform; + -ms-transform: $transform; + transform: $transform; +} + /** * Prefilled mixins * Mixins with fixed values diff --git a/app/assets/stylesheets/framework/progress.scss b/app/assets/stylesheets/framework/progress.scss new file mode 100644 index 00000000000..e9800bd24b5 --- /dev/null +++ b/app/assets/stylesheets/framework/progress.scss @@ -0,0 +1,5 @@ +html.turbolinks-progress-bar::before { + background-color: $progress-color!important; + height: 2px!important; + box-shadow: 0 0 10px $progress-color, 0 0 5px $progress-color; +} diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 2706d031d7b..7834cb0bfa5 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -7,7 +7,7 @@ $gl-header-color: #323232; $gl-link-color: #333c48; $md-text-color: #444; $md-link-color: #3084bb; -$nprogress-color: #c0392b; +$progress-color: #c0392b; $gl-font-size: 15px; $list-font-size: 15px; $sidebar_collapsed_width: 62px; diff --git a/app/assets/stylesheets/pages/appearances.scss b/app/assets/stylesheets/pages/appearances.scss new file mode 100644 index 00000000000..e2070f17c3b --- /dev/null +++ b/app/assets/stylesheets/pages/appearances.scss @@ -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; +} diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 374c66ef5af..b61d1f180b3 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -203,14 +203,7 @@ overflow: hidden; } - .issuable-count, - .issuable-nav, - .assignee > *, - .milestone > *, - .labels > *, - .participants > *, - .light > *, - .project-reference > * { + .hide-collapsed { display: none; } diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index 4767c65d9a7..de4d9fd80fa 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -78,3 +78,39 @@ max-width: 750px; margin: auto; } + +.modal-profile-crop { + .modal-dialog { + width: 500px; + } + + .modal-body { + p { + display: table; + margin: auto; + overflow: hidden; + } + + img { + display: block; + max-width: 400px; + max-height: 400px; + } + + .cropper-bg { + background: none; + } + + .cropper-crop-box { + box-sizing: content-box; + border: 999px solid transparentize(#ccc, 0.5); + @include transform(translate(-999px, -999px)); + } + } +} + +@media (max-width: 520px) { + .modal-profile-crop .modal-dialog { + width: auto; + } +} diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss index 2f57f21963d..0dc5a905f99 100644 --- a/app/assets/stylesheets/pages/todos.scss +++ b/app/assets/stylesheets/pages/todos.scss @@ -12,29 +12,10 @@ } } -.todos { - .panel { - border-top: none; - margin-bottom: 0; - } -} - .todo-item { font-size: $gl-font-size; - padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top); - border-bottom: 1px solid $table-border-color; - color: #7f8fa4; - - &.todo-inline { - .avatar { - position: relative; - top: -2px; - } - - .todo-title { - line-height: 40px; - } - } + padding-left: $gl-avatar-size + $gl-padding-top; + color: $secondary-text; a { color: #4c4e54; @@ -48,7 +29,7 @@ @include str-truncated(calc(100% - 174px)); font-weight: 600; - .author_name { + .author-name { color: #333; } } @@ -88,17 +69,7 @@ margin-bottom: 0; } } - - .todo-note-icon { - color: #777; - float: left; - font-size: $gl-font-size; - line-height: 16px; - margin-right: 5px; - } } - - &:last-child { border:none } } @media (max-width: $screen-xs-max) { diff --git a/app/controllers/admin/appearances_controller.rb b/app/controllers/admin/appearances_controller.rb new file mode 100644 index 00000000000..26cf74e4849 --- /dev/null +++ b/app/controllers/admin/appearances_controller.rb @@ -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 diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 28803164fcf..fa7a1148961 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -65,6 +65,9 @@ class ProfilesController < Profiles::ApplicationController def user_params params.require(:user).permit( + :avatar_crop_x, + :avatar_crop_y, + :avatar_crop_size, :avatar, :bio, :email, diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index 868b05929d7..509f4f412ca 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -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] diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb index c5820bf4c50..e0abc3a2869 100644 --- a/app/helpers/appearances_helper.rb +++ b/app/helpers/appearances_helper.rb @@ -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 diff --git a/app/models/appearance.rb b/app/models/appearance.rb new file mode 100644 index 00000000000..4cf8dd9a8ce --- /dev/null +++ b/app/models/appearance.rb @@ -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 diff --git a/app/models/milestone.rb b/app/models/milestone.rb index cbe65d70997..8f99e3bef9b 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -27,7 +27,7 @@ class Milestone < ActiveRecord::Base belongs_to :project has_many :issues - has_many :labels, through: :issues + has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues has_many :merge_requests has_many :participants, through: :issues, source: :assignee diff --git a/app/models/project.rb b/app/models/project.rb index 95ad88c76ae..6f5d592755a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -801,10 +801,7 @@ class Project < ActiveRecord::Base end def change_head(branch) - # Cached divergent commit counts are based on repository head - repository.expire_branch_cache - repository.expire_root_ref_cache - + repository.before_change_head gitlab_shell.update_repository_head(self.path_with_namespace, branch) reload_default_branch end diff --git a/app/models/repository.rb b/app/models/repository.rb index e050bd45254..a214a69d749 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -245,15 +245,6 @@ class Repository expire_emptiness_caches if empty? end - # Expires _all_ caches, including those that would normally only be expired - # under specific conditions. - def expire_all_caches! - expire_cache - expire_root_ref_cache - expire_emptiness_caches - expire_has_visible_content_cache - end - def expire_branch_cache(branch_name = nil) # When we push to the root branch we have to flush the cache for all other # branches as their statistics are based on the commits relative to the @@ -307,6 +298,46 @@ class Repository cache.expire(:branch_names) end + # Runs code just before a repository is deleted. + def before_delete + expire_cache if exists? + + expire_root_ref_cache + expire_emptiness_caches + end + + # Runs code just before the HEAD of a repository is changed. + def before_change_head + # Cached divergent commit counts are based on repository head + expire_branch_cache + expire_root_ref_cache + end + + # Runs code before creating a new tag. + def before_create_tag + expire_cache + end + + # Runs code after a repository has been forked/imported. + def after_import + expire_emptiness_caches + end + + # Runs code after a new commit has been pushed. + def after_push_commit(branch_name) + expire_cache(branch_name) + end + + # Runs code after a new branch has been created. + def after_create_branch + expire_has_visible_content_cache + end + + # Runs code after an existing branch has been removed. + def after_remove_branch + expire_has_visible_content_cache + end + def method_missing(m, *args, &block) if m == :lookup && !block_given? lookup_cache[m] ||= {} diff --git a/app/models/user.rb b/app/models/user.rb index 02ff2456f2b..6baf2468ade 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -98,6 +98,9 @@ class User < ActiveRecord::Base # Virtual attribute for authenticating by either username or email attr_accessor :login + # Virtual attributes to define avatar cropping + attr_accessor :avatar_crop_x, :avatar_crop_y, :avatar_crop_size + # # Relations # @@ -163,6 +166,11 @@ class User < ActiveRecord::Base validate :owns_public_email, if: ->(user) { user.public_email_changed? } validates :avatar, file_size: { maximum: 200.kilobytes.to_i } + validates :avatar_crop_x, :avatar_crop_y, :avatar_crop_size, + numericality: { only_integer: true }, + presence: true, + if: ->(user) { user.avatar? } + before_validation :generate_password, on: :create before_validation :restricted_signup_domains, on: :create before_validation :sanitize_attrs diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index a1711d234ff..9ba200f7bde 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -16,13 +16,13 @@ class GitPushService < BaseService # 5. Executes the project's services # def execute - @project.repository.expire_cache(branch_name) + @project.repository.after_push_commit(branch_name) if push_remove_branch? - @project.repository.expire_has_visible_content_cache + @project.repository.after_remove_branch @push_commits = [] elsif push_to_new_branch? - @project.repository.expire_has_visible_content_cache + @project.repository.after_create_branch # Re-find the pushed commits. if is_default_branch? diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb index 4144c7111d0..a62c5fc4fc4 100644 --- a/app/services/git_tag_push_service.rb +++ b/app/services/git_tag_push_service.rb @@ -2,7 +2,7 @@ class GitTagPushService attr_accessor :project, :user, :push_data def execute(project, user, oldrev, newrev, ref) - project.repository.expire_cache + project.repository.before_create_tag @project, @user = project, user @push_data = build_push_data(oldrev, newrev, ref) diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index f4dcb142850..df5054f08d7 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -76,11 +76,9 @@ module Projects end def flush_caches(project, wiki_path) - project.repository.expire_all_caches! if project.repository.exists? + project.repository.before_delete - wiki_repo = Repository.new(wiki_path, project) - - wiki_repo.expire_all_caches! if wiki_repo.exists? + Repository.new(wiki_path, project).before_delete end end end diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb index 6135c3ad96f..2c72df44ff0 100644 --- a/app/uploaders/avatar_uploader.rb +++ b/app/uploaders/avatar_uploader.rb @@ -2,11 +2,22 @@ class AvatarUploader < CarrierWave::Uploader::Base include UploaderHelper + include CarrierWave::MiniMagick storage :file after :store, :reset_events_cache + process :cropper + + def cropper + return unless model.respond_to?(:avatar_crop_size) && model.valid? + + manipulate! do |img| + img.crop "#{model.avatar_crop_size}x#{model.avatar_crop_size}+#{model.avatar_crop_x}+#{model.avatar_crop_y}" + end + end + def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end diff --git a/app/validators/url_validator.rb b/app/validators/url_validator.rb index 2848b9cd33d..a77beb2683d 100644 --- a/app/validators/url_validator.rb +++ b/app/validators/url_validator.rb @@ -29,8 +29,11 @@ class UrlValidator < ActiveModel::EachValidator end def valid_url?(value) + return false if value.nil? + options = default_options.merge(self.options) + value.strip! value =~ /\A#{URI.regexp(options[:protocols])}\z/ end end diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml new file mode 100644 index 00000000000..6f325914d14 --- /dev/null +++ b/app/views/admin/appearances/_form.html.haml @@ -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)} diff --git a/app/views/admin/appearances/preview.html.haml b/app/views/admin/appearances/preview.html.haml new file mode 100644 index 00000000000..dd4a64e80bc --- /dev/null +++ b/app/views/admin/appearances/preview.html.haml @@ -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" diff --git a/app/views/admin/appearances/show.html.haml b/app/views/admin/appearances/show.html.haml new file mode 100644 index 00000000000..089e8e4cb7a --- /dev/null +++ b/app/views/admin/appearances/show.html.haml @@ -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' diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml index 6975f6ed0db..f878d36e739 100644 --- a/app/views/dashboard/todos/_todo.html.haml +++ b/app/views/dashboard/todos/_todo.html.haml @@ -1,11 +1,11 @@ %li{class: "todo todo-#{todo.done? ? 'done' : 'pending'}", id: dom_id(todo) } - .todo-item{class: 'todo-block'} + .todo-item.todo-block = image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:'' .todo-title - %span.author_name + %span.author-name = link_to_author todo - %span.todo_label + %span.todo-label = todo_action_name(todo) = todo_target_link(todo) diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index ac1d5429382..280a1b93729 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -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 diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 5051c6bf83b..64c4bdceff9 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -90,6 +90,9 @@ %span.file_name.js-avatar-filename File name... = f.file_field :avatar, class: "js-user-avatar-input hidden" + = f.hidden_field :avatar_crop_x + = f.hidden_field :avatar_crop_y + = f.hidden_field :avatar_crop_size .light The maximum file size allowed is 200KB. - if @user.avatar? %hr @@ -99,3 +102,19 @@ .form-actions = f.submit 'Save changes', class: "btn btn-success" = link_to "Cancel", user_path(current_user), class: "btn btn-cancel" + +.modal.modal-profile-crop + .modal-dialog + .modal-content + .modal-header + %button.close{type: 'button', data: {dismiss: 'modal'}} + %span + × + %h4.modal-title + Crop your new profile picture + .modal-body + %p + %img.modal-profile-crop-image + .modal-footer + %button.btn.btn-primary.js-upload-user-avatar{:type => "button"} + Set new profile picture diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml index f99bc9a85eb..63ede71e6f1 100644 --- a/app/views/projects/diffs/_warning.html.haml +++ b/app/views/projects/diffs/_warning.html.haml @@ -3,17 +3,16 @@ Too many changes to show. .pull-right - unless diff_hard_limit_enabled? - = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true, format: nil)), class: "btn btn-sm btn-warning" + = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true, format: nil)), class: "btn btn-sm" - if current_controller?(:commit) or current_controller?(:merge_requests) - if current_controller?(:commit) - = link_to "Plain diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff), class: "btn btn-warning btn-sm" - = link_to "Email patch", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch), class: "btn btn-warning btn-sm" + = link_to "Plain diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff), class: "btn btn-sm" + = link_to "Email patch", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch), class: "btn btn-sm" - elsif @merge_request && @merge_request.persisted? - = link_to "Plain diff", merge_request_path(@merge_request, format: :diff), class: "btn btn-warning btn-sm" - = link_to "Email patch", merge_request_path(@merge_request, format: :patch), class: "btn btn-warning btn-sm" + = link_to "Plain diff", merge_request_path(@merge_request, format: :diff), class: "btn btn-sm" + = link_to "Email patch", merge_request_path(@merge_request, format: :patch), class: "btn btn-sm" %p To preserve performance only %strong #{shown_files_count} of #{diffs.size} files are displayed. - diff --git a/app/views/shared/issuable/_participants.html.haml b/app/views/shared/issuable/_participants.html.haml index ea61935487c..f1d92ef48b2 100644 --- a/app/views/shared/issuable/_participants.html.haml +++ b/app/views/shared/issuable/_participants.html.haml @@ -3,7 +3,8 @@ = icon('users') %span = participants.count - .title + .title.hide-collapsed = pluralize participants.count, "participant" - participants.each do |participant| - = link_to_member(@project, participant, name: false, size: 24) + %span.hide-collapsed + = link_to_member(@project, participant, name: false, size: 24) diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index a45775f36b5..36f06377886 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -1,14 +1,14 @@ %aside.right-sidebar{ class: sidebar_gutter_collapsed_class } .issuable-sidebar .block - %span.issuable-count.pull-left + %span.issuable-count.hide-collapsed.pull-left = issuable.iid of = issuables_count(issuable) %span.pull-right %a.gutter-toggle{href: '#'} = sidebar_gutter_toggle_icon - .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} + .issuable-nav.hide-collapsed.pull-right.btn-group{role: 'group', "aria-label" => '...'} - if prev_issuable = prev_issuable_for(issuable) = link_to 'Prev', [@project.namespace.becomes(Namespace), @project, prev_issuable], class: 'btn btn-default prev-btn' - else @@ -27,13 +27,13 @@ = link_to_member_avatar(issuable.assignee, size: 24) - else = icon('user') - .title + .title.hide-collapsed %label Assignee - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) .pull-right = link_to 'Edit', '#', class: 'edit-link' - .value + .value.hide-collapsed - if issuable.assignee %strong= link_to_member(@project, issuable.assignee, size: 24) - if issuable.instance_of?(MergeRequest) && !issuable.can_be_merged_by?(issuable.assignee) @@ -42,7 +42,7 @@ - else .light None - .selectbox + .selectbox.hide-collapsed = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true, current_user: true, first_user: true) .block.milestone @@ -53,13 +53,13 @@ = issuable.milestone.title - else No - .title + .title.hide-collapsed %label Milestone - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) .pull-right = link_to 'Edit', '#', class: 'edit-link' - .value + .value.hide-collapsed - if issuable.milestone %span.back-to-milestone = link_to namespace_project_milestone_path(@project.namespace, @project, issuable.milestone) do @@ -68,7 +68,7 @@ = issuable.milestone.title - else .light None - .selectbox + .selectbox.hide-collapsed = f.select(:milestone_id, milestone_options(issuable), { include_blank: true }, { class: 'select2 select2-compact js-select2 js-milestone', data: { placeholder: 'Select milestone' }}) = hidden_field_tag :issuable_context = f.submit class: 'btn hide' @@ -79,18 +79,18 @@ = icon('tags') %span = issuable.labels.count - .title + .title.hide-collapsed %label Labels - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) .pull-right = link_to 'Edit', '#', class: 'edit-link' - .value.issuable-show-labels + .value.issuable-show-labels.hide-collapsed - if issuable.labels.any? - issuable.labels.each do |label| = link_to_label(label, type: issuable.to_ability_name) - else .light None - .selectbox + .selectbox.hide-collapsed = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" } @@ -101,12 +101,12 @@ .block.light .sidebar-collapsed-icon = icon('rss') - .title + .title.hide-collapsed %label.light Notifications - subscribtion_status = subscribed ? 'subscribed' : 'unsubscribed' - %button.btn.btn-block.btn-gray.subscribe-button{:type => 'button'} + %button.btn.btn-block.btn-gray.subscribe-button.hide-collapsed{:type => 'button'} %span= subscribed ? 'Unsubscribe' : 'Subscribe' - .subscription-status{data: {status: subscribtion_status}} + .subscription-status.hide-collapsed{data: {status: subscribtion_status}} .unsubscribed{class: ( 'hidden' if subscribed )} You're not receiving notifications from this thread. .subscribed{class: ( 'hidden' unless subscribed )} @@ -116,8 +116,7 @@ .block.project-reference .sidebar-collapsed-icon = clipboard_button(clipboard_text: project_ref) - .title - .cross-project-reference + .cross-project-reference.hide-collapsed %span Reference: %cite{title: project_ref} diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index 2572b9d6d98..21d311579e3 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -27,7 +27,7 @@ class RepositoryForkWorker return end - project.repository.expire_emptiness_caches + project.repository.after_import project.import_finish end end diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index 0b6f746e118..2937493c614 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -18,7 +18,7 @@ class RepositoryImportWorker return end - project.repository.expire_emptiness_caches + project.repository.after_import project.import_finish end end |