diff options
| author | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-02-04 13:16:48 +0100 |
|---|---|---|
| committer | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-02-04 13:16:48 +0100 |
| commit | 6fea7c386ff27e5081ff3532b06f71d29eee956b (patch) | |
| tree | e1a1035725399135e86a6341c8349dfdab417107 /app | |
| parent | d231b6b9182ce9f68f267af0a073136c898f6892 (diff) | |
| parent | e933a50b6b8e7feec76bcc71313c14736967cd7a (diff) | |
| download | gitlab-ce-6fea7c386ff27e5081ff3532b06f71d29eee956b.tar.gz | |
Merge remote-tracking branch 'origin/master' into ci-permissions
# Conflicts:
# app/views/projects/builds/index.html.haml
Diffstat (limited to 'app')
62 files changed, 521 insertions, 316 deletions
diff --git a/app/assets/javascripts/api.js.coffee b/app/assets/javascripts/api.js.coffee index 746fa3cea87..3e0fdb3f795 100644 --- a/app/assets/javascripts/api.js.coffee +++ b/app/assets/javascripts/api.js.coffee @@ -47,7 +47,7 @@ callback(namespaces) # Return projects list. Filtered by query - projects: (query, callback) -> + projects: (query, order, callback) -> url = Api.buildUrl(Api.projects_path) $.ajax( @@ -55,6 +55,7 @@ data: private_token: gon.api_token search: query + order_by: order per_page: 20 dataType: "json" ).done (projects) -> diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee index c714c0fa939..b502131a99d 100644 --- a/app/assets/javascripts/dropzone_input.js.coffee +++ b/app/assets/javascripts/dropzone_input.js.coffee @@ -65,8 +65,7 @@ class @DropzoneInput return success: (header, response) -> - child = $(dropzone[0]).children("textarea") - $(child).val $(child).val() + response.link.markdown + "\n" + pasteText response.link.markdown return error: (temp, errorMessage) -> @@ -128,6 +127,7 @@ class @DropzoneInput beforeSelection = $(child).val().substring 0, caretStart afterSelection = $(child).val().substring caretEnd, textEnd $(child).val beforeSelection + text + afterSelection + child.get(0).setSelectionRange caretStart + text.length, caretEnd + text.length form_textarea.trigger "input" getFilename = (e) -> diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index d7a658f8faa..76bc4ff42a2 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -50,3 +50,19 @@ class @Project $('#notifications-button').empty().append("<i class='fa fa-bell'></i>" + label + "<i class='fa fa-angle-down'></i>") $(@).parents('ul').find('li.active').removeClass 'active' $(@).parent().addClass 'active' + + @projectSelectDropdown() + + projectSelectDropdown: -> + new ProjectSelect() + + $('.project-item-select').on 'click', (e) => + @changeProject $(e.currentTarget).val() + + $('.js-projects-dropdown-toggle').on 'click', (e) -> + e.preventDefault() + + $('.js-projects-dropdown').select2('open') + + changeProject: (url) -> + window.location = url diff --git a/app/assets/javascripts/project_select.js.coffee b/app/assets/javascripts/project_select.js.coffee index 0ae274f3363..be8ab9b428d 100644 --- a/app/assets/javascripts/project_select.js.coffee +++ b/app/assets/javascripts/project_select.js.coffee @@ -3,6 +3,7 @@ class @ProjectSelect $('.ajax-project-select').each (i, select) -> @groupId = $(select).data('group-id') @includeGroups = $(select).data('include-groups') + @orderBy = $(select).data('order-by') || 'id' placeholder = "Search for project" placeholder += " or group" if @includeGroups @@ -28,7 +29,7 @@ class @ProjectSelect if @groupId Api.groupProjects @groupId, query.term, projectsCallback else - Api.projects query.term, projectsCallback + Api.projects query.term, @orderBy, projectsCallback id: (project) -> project.web_url diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index c99292c3f83..11df4c24056 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -82,8 +82,7 @@ &.btn-success, &.btn-new, &.btn-create, - &.btn-save, - &.btn-green { + &.btn-save { @include btn-green; } @@ -159,7 +158,6 @@ .input-group-btn { .btn { - @include btn-gray; @include btn-middle; &:hover { @@ -186,8 +184,4 @@ border: 1px solid #c6cacf !important; background-color: #e4e7ed !important; } - - .btn-green { - @include btn-green - } } diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 6ea2219073c..ea56d9e12a0 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -376,11 +376,11 @@ table { margin-bottom: $gl-padding; } -.new-project-item-select-holder { +.project-item-select-holder { display: inline-block; position: relative; - .new-project-item-select { + .project-item-select { position: absolute; top: 0; right: 0; diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index f875b1460e7..7871a33b6c5 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -73,7 +73,6 @@ header { .title { margin: 0; - overflow: hidden; font-size: 19px; line-height: $header-height; font-weight: normal; @@ -88,6 +87,13 @@ header { text-decoration: underline; } } + + .dropdown-toggle-caret { + position: relative; + top: -2px; + margin-left: 5px; + font-size: 10px; + } } .navbar-collapse { diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index c537d97fb24..e6c59f5a291 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -37,3 +37,89 @@ } } } + +.top-area { + @include clearfix; + + border-bottom: 1px solid #EEE; + + .nav-text { + padding-top: 16px; + padding-bottom: 11px; + display: inline-block; + width: 50%; + line-height: 28px; + + /* Small devices (phones, tablets, 768px and lower) */ + @media (max-width: $screen-sm-min) { + width: 100%; + } + } + + .nav-links { + display: inline-block; + width: 50%; + margin-bottom: 0px; + border-bottom: none; + + /* Small devices (phones, tablets, 768px and lower) */ + @media (max-width: $screen-sm-min) { + width: 100%; + } + } + + .nav-controls { + width: 50%; + display: inline-block; + float: right; + text-align: right; + padding: 11px 0; + margin-bottom: 0px; + + > .dropdown { + margin-right: 10px; + display: inline-block; + } + + > .btn { + display: inline-block; + } + + input { + height: 34px; + display: inline-block; + position: relative; + top: 1px; + margin-right: 10px; + + /* Medium devices (desktops, 992px and up) */ + @media (min-width: $screen-md-min) { width: 200px; } + + /* Large devices (large desktops, 1200px and up) */ + @media (min-width: $screen-lg-min) { width: 250px; } + + &.input-short { + /* Medium devices (desktops, 992px and up) */ + @media (min-width: $screen-md-min) { width: 170px; } + + /* Large devices (large desktops, 1200px and up) */ + @media (min-width: $screen-lg-min) { width: 210px; } + } + } + + /* Hide on extra small devices (phones) */ + @media (max-width: $screen-xs-max) { + display: none; + } + + /* Small devices (tablets, 768px and lower) */ + @media (max-width: $screen-sm-max) { + width: 100%; + text-align: left; + + input { + width: 300px; + } + } + } +} diff --git a/app/assets/stylesheets/pages/explore.scss b/app/assets/stylesheets/pages/explore.scss index da06fe9954e..9b92128624c 100644 --- a/app/assets/stylesheets/pages/explore.scss +++ b/app/assets/stylesheets/pages/explore.scss @@ -6,11 +6,3 @@ font-size: 30px; } } - -.explore-trending-block { - .lead { - line-height: 32px; - font-size: 18px; - margin-top: 10px; - } -} diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index fdd86979a36..ec6c099df5b 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -4,7 +4,7 @@ input[type='search'] { width: 225px; vertical-align: bottom; - + @media (max-width: $screen-xs-max) { width: 100px; vertical-align: bottom; @@ -21,3 +21,21 @@ height: 42px; } } + +.group-row { + &.no-description { + .group-name { + line-height: 44px; + } + } + + .stats { + float: right; + line-height: 44px; + color: $gl-gray; + + span { + margin-right: 15px; + } + } +} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index e4ea47cc4a2..dd4ff39c5b8 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -281,36 +281,6 @@ margin-top: -1px; } -.top-area { - border-bottom: 1px solid #EEE; - - ul.nav-links { - display: inline-block; - width: 50%; - margin-bottom: 0px; - border-bottom: none; - } - - .projects-search-form { - width: 50%; - display: inline-block; - float: right; - padding-top: 11px; - text-align: right; - - .btn-green { - margin-left: 10px; - float: right; - } - } - - @media (max-width: $screen-xs-max) { - .projects-search-form { - padding-top: 15px; - } - } -} - .fork-namespaces { .fork-thumbnail { text-align: center; @@ -386,22 +356,6 @@ pre.light-well { border-color: #f1f1f1; } -.projects-search-form { - padding: $gl-padding 0; - padding-bottom: 0; - margin-bottom: 0px; - - input { - display: inline-block; - width: calc(100% - 151px); - } - - .btn { - display: inline-block; - width: 135px; - } -} - .git-empty { margin: 0 7px 0 7px; @@ -461,6 +415,10 @@ pre.light-well { a:hover { text-decoration: none; } + + > span { + margin-left: 10px; + } } .project-description { @@ -559,52 +517,12 @@ pre.light-well { } } -.cannot-be-merged, +.cannot-be-merged, .cannot-be-merged:hover { color: #E62958; margin-top: 2px; } -/* - * Forks list rendered on Project's forks page - */ - -.forks-top-block { - padding: 16px 0; -} - -.projects-search-form { - .dropdown-toggle.btn { - margin-top: -3px; - } - - &.fork-search-form { - margin: 0; - margin-top: -$gl-padding; - padding-bottom: 0; - - input { - /* Small devices (tablets, 768px and up) */ - @media (min-width: $screen-sm-min) { width: 180px; } - - /* Medium devices (desktops, 992px and up) */ - @media (min-width: $screen-md-min) { width: 350px; } - - /* Large devices (large desktops, 1200px and up) */ - @media (min-width: $screen-lg-min) { width: 400px; } - } - - .sort-forks { - width: 160px; - } - - .fork-link { - float: right; - margin-left: $gl-padding; - } - } -} - .private-forks-notice .private-fork-icon { i:nth-child(1) { color: #2AA056; diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 9943745208e..1515086b16d 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -79,6 +79,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :recaptcha_private_key, :sentry_enabled, :sentry_dsn, + :akismet_enabled, + :akismet_api_key, restricted_visibility_levels: [], import_sources: [] ) diff --git a/app/controllers/admin/spam_logs_controller.rb b/app/controllers/admin/spam_logs_controller.rb new file mode 100644 index 00000000000..377e9741e5f --- /dev/null +++ b/app/controllers/admin/spam_logs_controller.rb @@ -0,0 +1,17 @@ +class Admin::SpamLogsController < Admin::ApplicationController + def index + @spam_logs = SpamLog.order(id: :desc).page(params[:page]) + end + + def destroy + spam_log = SpamLog.find(params[:id]) + + if params[:remove_user] + spam_log.remove_user + redirect_to admin_spam_logs_path, notice: "User #{spam_log.user.username} was successfully removed." + else + spam_log.destroy + render nothing: true + end + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 824175c8a6c..7fa2f68ef07 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -60,6 +60,8 @@ class ApplicationController < ActionController::Base params[:authenticity_token].presence elsif params[:private_token].presence params[:private_token].presence + elsif request.headers['PRIVATE-TOKEN'].present? + request.headers['PRIVATE-TOKEN'] end user = user_token && User.find_by_authentication_token(user_token.to_s) diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 0b7fcdf5e9e..721e2a6bcbd 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -3,6 +3,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController def index @projects = current_user.authorized_projects.sorted_by_activity.non_archived + @projects = @projects.sort(@sort = params[:sort]) @projects = @projects.includes(:namespace) @last_push = current_user.recent_push diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 548f1b9ebfe..f7e6bb34443 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -2,15 +2,13 @@ class Projects::AvatarsController < Projects::ApplicationController before_action :project def show - @blob = @project.repository.blob_at_branch('master', @project.avatar_in_git) + @blob = @repository.blob_at_branch('master', @project.avatar_in_git) if @blob headers['X-Content-Type-Options'] = 'nosniff' - send_data( - @blob.data, - type: @blob.mime_type, - disposition: 'inline', - filename: @blob.name - ) + headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) + headers['Content-Disposition'] = 'inline' + headers['Content-Type'] = @blob.content_type + head :ok # 'render nothing: true' messes up the Content-Type else render_404 end diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index bb72232edd7..495a432347e 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -33,6 +33,7 @@ class Projects::BlobController < Projects::ApplicationController def edit @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha + blob.load_all_data!(@repository) end def update @@ -51,6 +52,7 @@ class Projects::BlobController < Projects::ApplicationController def preview @content = params[:content] + @blob.load_all_data!(@repository) diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true) diff_lines = diffy.diff.scan(/.*\n/)[2..-1] diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines) diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb index be7d5c187fe..87b4d08da0e 100644 --- a/app/controllers/projects/raw_controller.rb +++ b/app/controllers/projects/raw_controller.rb @@ -15,7 +15,10 @@ class Projects::RawController < Projects::ApplicationController if @blob.lfs_pointer? send_lfs_object else - stream_data + headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) + headers['Content-Disposition'] = 'inline' + headers['Content-Type'] = get_blob_type + head :ok # 'render nothing: true' messes up the Content-Type end else render_404 @@ -34,16 +37,6 @@ class Projects::RawController < Projects::ApplicationController end end - def stream_data - type = get_blob_type - - send_data( - @blob.data, - type: type, - disposition: 'inline' - ) - end - def send_lfs_object lfs_object = find_lfs_object diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 7d6b58ee21a..23693629a4c 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -23,6 +23,10 @@ module ApplicationSettingsHelper current_application_settings.user_oauth_applications end + def askimet_enabled? + current_application_settings.akismet_enabled? + end + # Return a group of checkboxes that use Bootstrap's button plugin for a # toggle button effect. def restricted_level_checkboxes(help_block_id) diff --git a/app/helpers/explore_helper.rb b/app/helpers/explore_helper.rb index 0d291f9a87e..3648757428b 100644 --- a/app/helpers/explore_helper.rb +++ b/app/helpers/explore_helper.rb @@ -10,8 +10,19 @@ module ExploreHelper options = exist_opts.merge(options) - path = explore_projects_path + path = if explore_controller? + explore_projects_path + elsif current_action?(:starred) + starred_dashboard_projects_path + else + dashboard_projects_path + end + path << "?#{options.to_param}" path end + + def explore_controller? + controller.class.name.split("::").first == "Explore" + end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 4543eff0d63..6b5fad1963a 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -53,14 +53,23 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - project_link = link_to(simple_sanitize(project.name), project_path(project)) + project_link = link_to project_path(project), { class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}" } do + link_output = simple_sanitize(project.name) + link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user + + if current_user + link_output += project_select_tag :project_path, + class: "project-item-select js-projects-dropdown", + data: { include_groups: false, order_by: 'last_activity_at' } + end + + link_output + end full_title = namespace_link + ' / ' + project_link full_title += ' · '.html_safe + link_to(simple_sanitize(name), url) if name - content_tag :span do - full_title - end + full_title end def remove_project_message(project) diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index d4f78258626..1eb790b1796 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -70,7 +70,7 @@ module SearchHelper # Autocomplete results for the current user's groups def groups_autocomplete(term, limit = 5) - Group.search(term).limit(limit).map do |group| + current_user.authorized_groups.search(term).limit(limit).map do |group| { label: "group: #{search_result_sanitize(group.name)}", url: group_path(group) @@ -80,7 +80,7 @@ module SearchHelper # Autocomplete results for the current user's projects def projects_autocomplete(term, limit = 5) - ProjectsFinder.new.execute(current_user).search_by_title(term). + current_user.authorized_projects.search_by_title(term). sorted_by_stars.non_archived.limit(limit).map do |p| { label: "project: #{search_result_sanitize(p.name_with_namespace)}", diff --git a/app/mailers/email_rejection_mailer.rb b/app/mailers/email_rejection_mailer.rb index 883f1c73ad4..76db31a4c45 100644 --- a/app/mailers/email_rejection_mailer.rb +++ b/app/mailers/email_rejection_mailer.rb @@ -10,7 +10,7 @@ class EmailRejectionMailer < BaseMailer subject: "[Rejected] #{@original_message.subject}" } - headers['Message-ID'] = SecureRandom.hex + headers['Message-ID'] = "<#{SecureRandom.hex}@#{Gitlab.config.gitlab.host}>" headers['In-Reply-To'] = @original_message.message_id headers['References'] = @original_message.message_id diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 59563b8823c..9cafc78f761 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -88,6 +88,10 @@ class ApplicationSetting < ActiveRecord::Base presence: true, if: :sentry_enabled + validates :akismet_api_key, + presence: true, + if: :akismet_enabled + validates_each :restricted_visibility_levels do |record, attr, value| unless value.nil? value.each do |level| @@ -143,7 +147,9 @@ class ApplicationSetting < ActiveRecord::Base shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, - two_factor_grace_period: 48 + two_factor_grace_period: 48, + recaptcha_enabled: false, + akismet_enabled: false ) end diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb index d2a29236942..ecbd2078b1d 100644 --- a/app/models/ci/commit.rb +++ b/app/models/ci/commit.rb @@ -205,7 +205,11 @@ module Ci end def ci_yaml_file - @ci_yaml_file ||= project.repository.blob_at(sha, '.gitlab-ci.yml').data + @ci_yaml_file ||= begin + blob = project.repository.blob_at(sha, '.gitlab-ci.yml') + blob.load_all_data!(project.repository) + blob.data + end rescue nil end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 89b6c49b362..ddc476447ca 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -258,7 +258,7 @@ class MergeRequest < ActiveRecord::Base end def work_in_progress? - !!(title =~ /\A\[?WIP\]?:? /i) + !!(title =~ /\A\[?WIP(\]|:| )/i) end def mergeable? @@ -284,7 +284,8 @@ class MergeRequest < ActiveRecord::Base def can_remove_source_branch?(current_user) !source_project.protected_branch?(source_branch) && !source_project.root_ref?(source_branch) && - Ability.abilities.allowed?(current_user, :push_code, source_project) + Ability.abilities.allowed?(current_user, :push_code, source_project) && + last_commit == source_project.commit(source_branch) end def mr_and_commit_notes diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb new file mode 100644 index 00000000000..12df68ef83b --- /dev/null +++ b/app/models/spam_log.rb @@ -0,0 +1,10 @@ +class SpamLog < ActiveRecord::Base + belongs_to :user + + validates :user, presence: true + + def remove_user + user.block + user.destroy + end +end diff --git a/app/models/spam_report.rb b/app/models/spam_report.rb new file mode 100644 index 00000000000..cdc7321b08e --- /dev/null +++ b/app/models/spam_report.rb @@ -0,0 +1,5 @@ +class SpamReport < ActiveRecord::Base + belongs_to :user + + validates :user, presence: true +end diff --git a/app/models/tree.rb b/app/models/tree.rb index b28f31cdd6e..7c4ed6e393b 100644 --- a/app/models/tree.rb +++ b/app/models/tree.rb @@ -39,6 +39,8 @@ class Tree git_repo = repository.raw_repository @readme = Gitlab::Git::Blob.find(git_repo, sha, readme_path) + @readme.load_all_data!(git_repo) + @readme end def trees diff --git a/app/models/user.rb b/app/models/user.rb index 4214f01f6a4..234c1cd89f9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -138,6 +138,7 @@ class User < ActiveRecord::Base has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy has_one :abuse_report, dependent: :destroy + has_many :spam_logs, dependent: :destroy has_many :builds, dependent: :nullify, class_name: 'Ci::Build' diff --git a/app/services/create_spam_log_service.rb b/app/services/create_spam_log_service.rb new file mode 100644 index 00000000000..59a66fde47a --- /dev/null +++ b/app/services/create_spam_log_service.rb @@ -0,0 +1,13 @@ +class CreateSpamLogService < BaseService + def initialize(project, user, params) + super(project, user, params) + end + + def execute + spam_params = params.merge({ user_id: @current_user.id, + project_id: @project.id } ) + spam_log = SpamLog.new(spam_params) + spam_log.save + spam_log + end +end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index b0f1a34cbec..b4e3d96d405 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -218,20 +218,37 @@ = f.label :recaptcha_enabled do = f.check_box :recaptcha_enabled Enable reCAPTCHA - %span.help-block#recaptcha_help_block Helps preventing bots from creating accounts + %span.help-block#recaptcha_help_block Helps prevent bots from creating accounts .form-group = f.label :recaptcha_site_key, 'reCAPTCHA Site Key', class: 'control-label col-sm-2' .col-sm-10 = f.text_field :recaptcha_site_key, class: 'form-control' .help-block - Generate site and private keys here: - %a{ href: 'http://www.google.com/recaptcha', target: '_blank'} http://www.google.com/recaptcha + Generate site and private keys at + %a{ href: 'http://www.google.com/recaptcha', target: 'blank'} http://www.google.com/recaptcha + .form-group = f.label :recaptcha_private_key, 'reCAPTCHA Private Key', class: 'control-label col-sm-2' .col-sm-10 = f.text_field :recaptcha_private_key, class: 'form-control' + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :akismet_enabled do + = f.check_box :akismet_enabled + Enable Akismet + %span.help-block#akismet_help_block Helps prevent bots from creating issues + + .form-group + = f.label :akismet_api_key, 'Akismet API Key', class: 'control-label col-sm-2' + .col-sm-10 + = f.text_field :akismet_api_key, class: 'form-control' + .help-block + Generate API key at + %a{ href: 'http://www.akismet.com', target: 'blank'} http://www.akismet.com + %fieldset %legend Error Reporting and Logging %p diff --git a/app/views/admin/spam_logs/_spam_log.html.haml b/app/views/admin/spam_logs/_spam_log.html.haml new file mode 100644 index 00000000000..8aea67f4497 --- /dev/null +++ b/app/views/admin/spam_logs/_spam_log.html.haml @@ -0,0 +1,32 @@ +- user = spam_log.user +%tr + %td + = time_ago_with_tooltip(spam_log.created_at) + %td + - if user + = link_to user.name, [:admin, user] + .light.small + Joined #{time_ago_with_tooltip(user.created_at)} + - else + (removed) + %td + = spam_log.source_ip + %td + = spam_log.via_api? ? 'Y' : 'N' + %td + = spam_log.noteable_type + %td + = spam_log.title + %td + = truncate(spam_log.description, length: 100) + %td + - if user + = link_to 'Remove user', admin_spam_log_path(spam_log, remove_user: true), + data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, method: :delete, class: "btn btn-xs btn-remove" + %td + - if user && !user.blocked? + = link_to 'Block user', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-xs" + - else + .btn.btn-xs.disabled + Already Blocked + = link_to 'Remove log', [:admin, spam_log], remote: true, method: :delete, class: "btn btn-xs btn-close js-remove-tr" diff --git a/app/views/admin/spam_logs/index.html.haml b/app/views/admin/spam_logs/index.html.haml new file mode 100644 index 00000000000..0fdd5bd9960 --- /dev/null +++ b/app/views/admin/spam_logs/index.html.haml @@ -0,0 +1,21 @@ +- page_title "Spam Logs" +%h3.page-title Spam Logs +%hr +- if @spam_logs.present? + .table-holder + %table.table + %thead + %tr + %th Date + %th User + %th Source IP + %th API? + %th Type + %th Title + %th Description + %th Primary Action + %th + = render @spam_logs + = paginate @spam_logs +- else + %h4 There are no Spam Logs diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index 6ca97a692b4..3d17f74b709 100644 --- a/app/views/dashboard/_groups_head.html.haml +++ b/app/views/dashboard/_groups_head.html.haml @@ -1,7 +1,13 @@ -%ul.nav-links - = nav_link(page: dashboard_groups_path) do - = link_to dashboard_groups_path, title: 'Your groups', data: {placement: 'right'} do - Your Groups - = nav_link(page: explore_groups_path) do - = link_to explore_groups_path, title: 'Explore groups', data: {placement: 'bottom'} do - Explore Groups +.top-area + %ul.nav-links + = nav_link(page: dashboard_groups_path) do + = link_to dashboard_groups_path, title: 'Your groups' do + Your Groups + = nav_link(page: explore_groups_path) do + = link_to explore_groups_path, title: 'Explore groups' do + Explore Groups + - if current_user.can_create_group? + .nav-controls + = link_to new_group_path, class: "btn btn-new" do + = icon('plus') + New Group diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 5c4b58cd688..d865a2c6fae 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -8,13 +8,14 @@ = nav_link(page: starred_dashboard_projects_path) do = link_to starred_dashboard_projects_path, title: 'Starred Projects', data: {placement: 'right'} do Starred Projects - = nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path], html_options: { class: 'hidden-xs' }) do + = nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path]) do = link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do Explore Projects - .projects-search-form - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs', spellcheck: false + .nav-controls + = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs input-short', spellcheck: false + = render 'explore/projects/dropdown' - if current_user.can_create_project? - = link_to new_project_path, class: 'btn btn-green' do - %i.fa.fa-plus + = link_to new_project_path, class: 'btn btn-new' do + = icon('plus') New Project diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index d5b7e729e7b..caca91af536 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -2,15 +2,6 @@ - header_title "Groups", dashboard_groups_path = render 'dashboard/groups_head' -.gray-content-block - - if current_user.can_create_group? - %span.pull-right.hidden-xs - = link_to new_group_path, class: "btn btn-new" do - %i.fa.fa-plus - New Group - .oneline - Group members have access to all group projects. - %ul.content-list - @group_members.each do |group_member| - group = group_member.group diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 2d3da01178a..f363f035974 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -16,8 +16,5 @@ = render 'shared/issuable/filter', type: :issues -.gray-content-block.second-block - List all issues from all projects you have access to. - .prepend-top-default = render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index c5a5ec21f78..bbe4cc1f824 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -7,8 +7,5 @@ = render 'shared/issuable/filter', type: :merge_requests -.gray-content-block.second-block - List all merge requests from all projects you have access to. - .prepend-top-default = render 'shared/merge_requests' diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index bec1692a4de..917bfbd47e9 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -1,14 +1,11 @@ - page_title "Milestones" - header_title "Milestones", dashboard_milestones_path -.project-issuable-filter - .controls - = render 'shared/new_project_item_select', path: 'milestones/new', label: "New Milestone", include_groups: true - +.top-area = render 'shared/milestones_filter' -.gray-content-block - List all milestones from all projects you have access to. + .nav-controls + = render 'shared/new_project_item_select', path: 'milestones/new', label: "New Milestone", include_groups: true .milestones %ul.content-list diff --git a/app/views/explore/projects/_dropdown.html.haml b/app/views/explore/projects/_dropdown.html.haml index a988d4c8154..87c556adc7d 100644 --- a/app/views/explore/projects/_dropdown.html.haml +++ b/app/views/explore/projects/_dropdown.html.haml @@ -3,19 +3,13 @@ %span.light - if @sort.present? = sort_options_hash[@sort] - - elsif current_page?(trending_explore_projects_path) || current_page?(explore_root_path) - Trending projects - - elsif current_page?(starred_explore_projects_path) - Most stars - else - = sort_title_recently_created + = sort_title_recently_updated %b.caret %ul.dropdown-menu %li - = link_to trending_explore_projects_path do - Trending projects - = link_to starred_explore_projects_path do - Most stars + = link_to explore_projects_filter_path(sort: sort_value_name) do + = sort_title_name = link_to explore_projects_filter_path(sort: sort_value_recently_created) do = sort_title_recently_created = link_to explore_projects_filter_path(sort: sort_value_oldest_created) do diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml index 28b12c8dca8..66a4b535ae5 100644 --- a/app/views/explore/projects/_filter.html.haml +++ b/app/views/explore/projects/_filter.html.haml @@ -2,6 +2,7 @@ = form_tag explore_projects_filter_path, method: :get, class: 'form-inline form-tiny' do |f| .form-group = search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search", spellcheck: false + = hidden_field_tag :sort, @sort .form-group = button_tag 'Search', class: "btn" @@ -46,4 +47,3 @@ = link_to explore_projects_filter_path(tag: tag.name) do %i.fa.fa-tag = tag.name - = render 'explore/projects/dropdown' diff --git a/app/views/explore/projects/_nav.html.haml b/app/views/explore/projects/_nav.html.haml new file mode 100644 index 00000000000..614b5431779 --- /dev/null +++ b/app/views/explore/projects/_nav.html.haml @@ -0,0 +1,10 @@ +%ul.nav-links + = nav_link(page: [trending_explore_projects_path, explore_root_path]) do + = link_to trending_explore_projects_path do + Trending + = nav_link(page: starred_explore_projects_path) do + = link_to starred_explore_projects_path do + Most stars + = nav_link(page: explore_projects_path) do + = link_to explore_projects_path do + All diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index b9a958fbe7b..bee8518d57a 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -6,7 +6,11 @@ - else = render 'explore/head' -.gray-content-block.clearfix.second-block +.top-area + = render 'explore/projects/nav' + +.gray-content-block.second-block.clearfix = render 'filter' + = render 'projects', projects: @projects = paginate @projects, theme: "gitlab" diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 95d46e331f8..16f52f7a530 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -6,12 +6,6 @@ - else = render 'explore/head' -.explore-trending-block - .gray-content-block.second-block - .pull-right - = render 'explore/projects/dropdown' - .oneline - %i.fa.fa-star - See most starred projects - = render 'projects', projects: @starred_projects - = paginate @starred_projects, theme: 'gitlab' += render 'explore/projects/nav' += render 'projects', projects: @starred_projects += paginate @starred_projects, theme: 'gitlab' diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index fa0b718e48b..adcda810061 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -6,11 +6,5 @@ - else = render 'explore/head' -.explore-trending-block - .gray-content-block.second-block - .pull-right - = render 'explore/projects/dropdown' - .oneline - %i.fa.fa-comments-o - See most discussed projects for last month - = render 'projects', projects: @trending_projects += render 'explore/projects/nav' += render 'projects', projects: @trending_projects diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml index bbafc08435a..a829479bb38 100644 --- a/app/views/groups/_projects.html.haml +++ b/app/views/groups/_projects.html.haml @@ -1,11 +1,10 @@ -.projects-list-holder - .projects-search-form - .input-group - = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false - - if can? current_user, :create_projects, @group - %span.input-group-btn - = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-green' do - %i.fa.fa-plus - New Project +.projects-list-holder.prepend-top-default + .input-group + = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false + - if can? current_user, :create_projects, @group + %span.input-group-btn + = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-new' do + = icon('plus') + New Project = render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false, skip_namespace: true diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index b221d3a89a4..ab307708b75 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -1,17 +1,15 @@ - page_title "Milestones" - header_title group_title(@group, "Milestones", group_milestones_path(@group)) -.project-issuable-filter - .controls - - if can?(current_user, :admin_milestones, @group) - .pull-right - %span.pull-right.hidden-xs - = link_to new_group_milestone_path(@group), class: "btn btn-new" do - = icon('plus') - New Milestone - +.top-area = render 'shared/milestones_filter' + .nav-controls + - if can?(current_user, :admin_milestones, @group) + = link_to new_group_milestone_path(@group), class: "btn btn-new" do + = icon('plus') + New Milestone + .gray-content-block Only milestones from %strong #{@group.name} diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml index 7b45bd09050..746386cab58 100644 --- a/app/views/help/ui.html.haml +++ b/app/views/help/ui.html.haml @@ -139,7 +139,31 @@ %h2#navs Navigation %h4 + %code .top-area + %p Holder for top page navigation. Includes navigation, search field, sorting and button + + .example + .top-area + %ul.nav-links + %li.active + %a Open + %li + %a Closed + .nav-controls + = text_field_tag 'sample', nil, class: 'form-control' + .dropdown + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + %span Sort by name + %b.caret + %ul.dropdown-menu + %li + %a Sort by date + + = link_to 'New issue', '#', class: 'btn btn-new' + + %h4 %code .nav-links + %p Only nav links without button and search .example %ul.nav-links %li.active diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index cffdb52cc23..ac1d5429382 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -1,6 +1,6 @@ %ul.nav.nav-sidebar = nav_link(controller: :dashboard, html_options: {class: 'home'}) do - = link_to admin_root_path, title: "Stats" do + = link_to admin_root_path, title: 'Overview' do = icon('dashboard fw') %span Overview @@ -25,13 +25,13 @@ %span Deploy Keys = nav_link path: ['runners#index', 'runners#show'] do - = link_to admin_runners_path do + = link_to admin_runners_path, title: 'Runners' do = icon('cog fw') %span Runners %span.count= number_with_delimiter(Ci::Runner.count(:all)) = nav_link path: 'builds#index' do - = link_to admin_builds_path do + = link_to admin_builds_path, title: 'Builds' do = icon('link fw') %span Builds @@ -82,6 +82,14 @@ Abuse Reports %span.count= number_with_delimiter(AbuseReport.count(:all)) + - if askimet_enabled? + = nav_link(controller: :spam_logs) do + = link_to admin_spam_logs_path, title: "Spam Logs" do + = icon('exclamation-triangle fw') + %span + Spam Logs + %span.count= number_with_delimiter(SpamLog.count(:all)) + = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do = link_to admin_application_settings_path, title: 'Settings' do = icon('cogs fw') diff --git a/app/views/projects/blob/_image.html.haml b/app/views/projects/blob/_image.html.haml index c090f690d1d..51fa91b08e4 100644 --- a/app/views/projects/blob/_image.html.haml +++ b/app/views/projects/blob/_image.html.haml @@ -1,2 +1,2 @@ .file-content.image_file - %img{ src: "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"} + %img{ src: namespace_project_raw_path(@project.namespace, @project, @id)} diff --git a/app/views/projects/blob/_text.html.haml b/app/views/projects/blob/_text.html.haml index 906e5ccb360..d09cd73558c 100644 --- a/app/views/projects/blob/_text.html.haml +++ b/app/views/projects/blob/_text.html.haml @@ -1,3 +1,4 @@ +- blob.load_all_data!(@repository) - if markup?(blob.name) .file-content.wiki = render_markup(blob.name, blob.data) diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index 2a2a4745bed..5e3bd14565e 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -1,18 +1,7 @@ - page_title "Builds" = render "header_title" -.project-issuable-filter - .controls - - if can?(current_user, :update_build, @project) - .pull-left.hidden-xs - - if @all_builds.running_or_pending.any? - = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), - data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post - - = link_to ci_lint_path, class: 'btn btn-default' do - = icon('wrench') - %span CI Lint - +.top-area %ul.nav-links %li{class: ('active' if @scope.nil?)} = link_to project_builds_path(@project) do @@ -32,6 +21,16 @@ %span.badge.js-running-count = number_with_delimiter(@all_builds.finished.count(:id)) + .nav-controls + - if can?(current_user, :update_build, @project) + - if @all_builds.running_or_pending.any? + = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), + data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + + = link_to ci_lint_path, class: 'btn btn-default' do + = icon('wrench') + %span CI Lint + .gray-content-block #{(@scope || 'running').capitalize} builds from this project diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml index a362185210a..acb2353d3ca 100644 --- a/app/views/projects/forks/index.html.haml +++ b/app/views/projects/forks/index.html.haml @@ -1,44 +1,42 @@ -.gray-content-block.top-block.clearfix.white.forks-top-block - .pull-left +.top-area + .nav-text - public_count = @public_forks.size - protected_count = @protected_forks.size - full_count_title = "#{public_count} public and #{protected_count} private" == #{pluralize(@all_forks.size, 'fork')}: #{full_count_title} - .pull-right - .projects-search-form.fork-search-form - = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control', - spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' } + .nav-controls + = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control input-short', + spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' } - .dropdown.inline.prepend-left-10 - %button.dropdown-toggle.btn.sort-forks{type: 'button', 'data-toggle' => 'dropdown'} - %span.light sort: - - if @sort.present? - = sort_options_hash[@sort] - - else + .dropdown + %button.dropdown-toggle.btn.sort-forks{type: 'button', 'data-toggle' => 'dropdown'} + %span.light sort: + - if @sort.present? + = sort_options_hash[@sort] + - else + = sort_title_recently_created + %b.caret + %ul.dropdown-menu.dropdown-menu-align-right + %li + - excluded_filters = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id] + = link_to page_filter_path(sort: sort_value_recently_created, without: excluded_filters) do = sort_title_recently_created - %b.caret - %ul.dropdown-menu.dropdown-menu-align-right - %li - - excluded_filters = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id] - = link_to page_filter_path(sort: sort_value_recently_created, without: excluded_filters) do - = sort_title_recently_created - = link_to page_filter_path(sort: sort_value_oldest_created, without: excluded_filters) do - = sort_title_oldest_created - = link_to page_filter_path(sort: sort_value_recently_updated, without: excluded_filters) do - = sort_title_recently_updated - = link_to page_filter_path(sort: sort_value_oldest_updated, without: excluded_filters) do - = sort_title_oldest_updated + = link_to page_filter_path(sort: sort_value_oldest_created, without: excluded_filters) do + = sort_title_oldest_created + = link_to page_filter_path(sort: sort_value_recently_updated, without: excluded_filters) do + = sort_title_recently_updated + = link_to page_filter_path(sort: sort_value_oldest_updated, without: excluded_filters) do + = sort_title_oldest_updated - .fork-link.inline - - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'pull-right btn btn-new' do - = icon('code-fork fw') - Fork - - else - = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'pull-right btn btn-new' do - = icon('code-fork fw') - Fork + - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 + = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do + = icon('code-fork fw') + Fork + - else + = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do + = icon('code-fork fw') + Fork .projects-list-holder diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 9081bcfe9b3..cc41130a9dc 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,13 +1,14 @@ - page_title "Labels" = render "header_title" -.gray-content-block.top-block - - if can? current_user, :admin_label, @project - = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do - = icon('plus') - New label - .oneline +.top-area + .nav-text Labels can be applied to issues and merge requests. + .nav-controls + - if can? current_user, :admin_label, @project + = link_to new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new" do + = icon('plus') + New label .labels - if @labels.present? diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 114b06457a5..abe567af1dd 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -2,17 +2,14 @@ = render "header_title" -.project-issuable-filter - .controls - - if can?(current_user, :admin_milestone, @project) - = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do - %i.fa.fa-plus - New Milestone - +.top-area = render 'shared/milestones_filter' -.gray-content-block - Milestone allows you to group issues and set due date for it + .nav-controls + - if can?(current_user, :admin_milestone, @project) + = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "btn btn-new", title: "New Milestone" do + = icon('plus') + New Milestone .milestones %ul.content-list diff --git a/app/views/projects/wikis/_nav.html.haml b/app/views/projects/wikis/_nav.html.haml index 69ba301e231..56a53ffff2a 100644 --- a/app/views/projects/wikis/_nav.html.haml +++ b/app/views/projects/wikis/_nav.html.haml @@ -1,12 +1,4 @@ -.project-issuable-filter - .controls - - if can?(current_user, :create_wiki, @project) - = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do - %i.fa.fa-plus - New Page - - = render 'projects/wikis/new' - +.top-area %ul.nav-links = nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do = link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home) @@ -17,3 +9,11 @@ = nav_link(path: 'wikis#git_access') do = link_to namespace_project_wikis_git_access_path(@project.namespace, @project) do Git Access + + .nav-controls + - if can?(current_user, :create_wiki, @project) + = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do + = icon('plus') + New Page + + = render 'projects/wikis/new' diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml index ee242c94db8..57856031d6e 100644 --- a/app/views/shared/_file_highlight.html.haml +++ b/app/views/shared/_file_highlight.html.haml @@ -1,7 +1,7 @@ .file-content.code.js-syntax-highlight .line-numbers - if blob.data.present? - - blob.data.lines.each_index do |index| + - blob.data.each_line.each_with_index do |_, index| - offset = defined?(first_line_number) ? first_line_number : 1 - i = index + offset -# We're not using `link_to` because it is too slow once we get to thousands of lines. diff --git a/app/views/shared/_milestones_filter.html.haml b/app/views/shared/_milestones_filter.html.haml index f77feeb79cd..cf16c203f9c 100644 --- a/app/views/shared/_milestones_filter.html.haml +++ b/app/views/shared/_milestones_filter.html.haml @@ -1,11 +1,10 @@ -.milestones-filters - %ul.nav-links - %li{class: ("active" if params[:state].blank? || params[:state] == 'opened')} - = link_to milestones_filter_path(state: 'opened') do - Open - %li{class: ("active" if params[:state] == 'closed')} - = link_to milestones_filter_path(state: 'closed') do - Closed - %li{class: ("active" if params[:state] == 'all')} - = link_to milestones_filter_path(state: 'all') do - All +%ul.nav-links + %li{class: ("active" if params[:state].blank? || params[:state] == 'opened')} + = link_to milestones_filter_path(state: 'opened') do + Open + %li{class: ("active" if params[:state] == 'closed')} + = link_to milestones_filter_path(state: 'closed') do + Closed + %li{class: ("active" if params[:state] == 'all')} + = link_to milestones_filter_path(state: 'all') do + All diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml index c4431d66927..1c58345278a 100644 --- a/app/views/shared/_new_project_item_select.html.haml +++ b/app/views/shared/_new_project_item_select.html.haml @@ -1,6 +1,6 @@ - if @projects.any? - .prepend-left-10.new-project-item-select-holder - = project_select_tag :project_path, class: "new-project-item-select", data: { include_groups: local_assigns[:include_groups] } + .prepend-left-10.project-item-select-holder + = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at' } %a.btn.btn-new.new-project-item-select-button = icon('plus') = local_assigns[:label] @@ -8,12 +8,12 @@ :javascript $('.new-project-item-select-button').on('click', function() { - $('.new-project-item-select').select2('open'); + $('.project-item-select').select2('open'); }); var relativePath = '#{local_assigns[:path]}'; - $('.new-project-item-select').on('click', function() { + $('.project-item-select').on('click', function() { window.location = $(this).val() + '/' + relativePath; }); diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index 778b20fb4f2..f7fe6b02641 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -1,5 +1,8 @@ - group_member = local_assigns[:group_member] -%li +- css_class = '' unless local_assigns[:css_class] +- css_class += " no-description" if group.description.blank? + +%li.group-row{ class: css_class } - if group_member .controls.hidden-xs - if can?(current_user, :admin_group, group) @@ -9,6 +12,15 @@ = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do %i.fa.fa-sign-out + .stats + %span + = icon('home') + = number_with_delimiter(group.projects.count) + + %span + = icon('users') + = number_with_delimiter(group.users.count) + = image_tag group_icon(group), class: "avatar s46 hidden-xs" = link_to group, class: 'group-name' do %span.item-title= group.name @@ -17,5 +29,6 @@ as %span #{group_member.human_access} - %div.light - #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")} + - if group.description.present? + .light + = markdown(group.description, pipeline: :description) diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index 2aeeed63c95..e196fc51d2d 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -29,8 +29,8 @@ .project-controls - if ci_commit - = render_ci_status(ci_commit) - + %span + = render_ci_status(ci_commit) - if forks %span = icon('code-fork') |
