summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/application.js.coffee3
-rw-r--r--app/assets/javascripts/logo.js.coffee2
-rw-r--r--app/assets/javascripts/profile.js.coffee49
-rw-r--r--app/assets/stylesheets/application.scss7
-rw-r--r--app/assets/stylesheets/framework.scss1
-rw-r--r--app/assets/stylesheets/framework/mixins.scss6
-rw-r--r--app/assets/stylesheets/framework/progress.scss5
-rw-r--r--app/assets/stylesheets/framework/variables.scss2
-rw-r--r--app/assets/stylesheets/pages/appearances.scss11
-rw-r--r--app/assets/stylesheets/pages/issuable.scss9
-rw-r--r--app/assets/stylesheets/pages/profile.scss36
-rw-r--r--app/assets/stylesheets/pages/todos.scss35
-rw-r--r--app/controllers/admin/appearances_controller.rb57
-rw-r--r--app/controllers/profiles_controller.rb3
-rw-r--r--app/controllers/uploads_controller.rb5
-rw-r--r--app/helpers/appearances_helper.rb28
-rw-r--r--app/models/appearance.rb9
-rw-r--r--app/models/milestone.rb2
-rw-r--r--app/models/project.rb5
-rw-r--r--app/models/repository.rb49
-rw-r--r--app/models/user.rb8
-rw-r--r--app/services/git_push_service.rb6
-rw-r--r--app/services/git_tag_push_service.rb2
-rw-r--r--app/services/projects/destroy_service.rb6
-rw-r--r--app/uploaders/avatar_uploader.rb11
-rw-r--r--app/validators/url_validator.rb3
-rw-r--r--app/views/admin/appearances/_form.html.haml58
-rw-r--r--app/views/admin/appearances/preview.html.haml29
-rw-r--r--app/views/admin/appearances/show.html.haml7
-rw-r--r--app/views/dashboard/todos/_todo.html.haml6
-rw-r--r--app/views/layouts/nav/_admin.html.haml5
-rw-r--r--app/views/profiles/show.html.haml19
-rw-r--r--app/views/projects/diffs/_warning.html.haml11
-rw-r--r--app/views/shared/issuable/_participants.html.haml5
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml31
-rw-r--r--app/workers/repository_fork_worker.rb2
-rw-r--r--app/workers/repository_import_worker.rb2
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 @@
&nbsp;
%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
+ &times;
+ %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