summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2016-02-04 13:16:48 +0100
committerKamil Trzcinski <ayufan@ayufan.eu>2016-02-04 13:16:48 +0100
commit6fea7c386ff27e5081ff3532b06f71d29eee956b (patch)
treee1a1035725399135e86a6341c8349dfdab417107 /app
parentd231b6b9182ce9f68f267af0a073136c898f6892 (diff)
parente933a50b6b8e7feec76bcc71313c14736967cd7a (diff)
downloadgitlab-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')
-rw-r--r--app/assets/javascripts/api.js.coffee3
-rw-r--r--app/assets/javascripts/dropzone_input.js.coffee4
-rw-r--r--app/assets/javascripts/project.js.coffee16
-rw-r--r--app/assets/javascripts/project_select.js.coffee3
-rw-r--r--app/assets/stylesheets/framework/buttons.scss8
-rw-r--r--app/assets/stylesheets/framework/common.scss4
-rw-r--r--app/assets/stylesheets/framework/header.scss8
-rw-r--r--app/assets/stylesheets/framework/nav.scss86
-rw-r--r--app/assets/stylesheets/pages/explore.scss8
-rw-r--r--app/assets/stylesheets/pages/groups.scss20
-rw-r--r--app/assets/stylesheets/pages/projects.scss92
-rw-r--r--app/controllers/admin/application_settings_controller.rb2
-rw-r--r--app/controllers/admin/spam_logs_controller.rb17
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/controllers/dashboard/projects_controller.rb1
-rw-r--r--app/controllers/projects/avatars_controller.rb12
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/projects/raw_controller.rb15
-rw-r--r--app/helpers/application_settings_helper.rb4
-rw-r--r--app/helpers/explore_helper.rb13
-rw-r--r--app/helpers/projects_helper.rb17
-rw-r--r--app/helpers/search_helper.rb4
-rw-r--r--app/mailers/email_rejection_mailer.rb2
-rw-r--r--app/models/application_setting.rb8
-rw-r--r--app/models/ci/commit.rb6
-rw-r--r--app/models/merge_request.rb5
-rw-r--r--app/models/spam_log.rb10
-rw-r--r--app/models/spam_report.rb5
-rw-r--r--app/models/tree.rb2
-rw-r--r--app/models/user.rb1
-rw-r--r--app/services/create_spam_log_service.rb13
-rw-r--r--app/views/admin/application_settings/_form.html.haml23
-rw-r--r--app/views/admin/spam_logs/_spam_log.html.haml32
-rw-r--r--app/views/admin/spam_logs/index.html.haml21
-rw-r--r--app/views/dashboard/_groups_head.html.haml20
-rw-r--r--app/views/dashboard/_projects_head.html.haml11
-rw-r--r--app/views/dashboard/groups/index.html.haml9
-rw-r--r--app/views/dashboard/issues.html.haml3
-rw-r--r--app/views/dashboard/merge_requests.html.haml3
-rw-r--r--app/views/dashboard/milestones/index.html.haml9
-rw-r--r--app/views/explore/projects/_dropdown.html.haml12
-rw-r--r--app/views/explore/projects/_filter.html.haml2
-rw-r--r--app/views/explore/projects/_nav.html.haml10
-rw-r--r--app/views/explore/projects/index.html.haml6
-rw-r--r--app/views/explore/projects/starred.html.haml12
-rw-r--r--app/views/explore/projects/trending.html.haml10
-rw-r--r--app/views/groups/_projects.html.haml17
-rw-r--r--app/views/groups/milestones/index.html.haml16
-rw-r--r--app/views/help/ui.html.haml24
-rw-r--r--app/views/layouts/nav/_admin.html.haml14
-rw-r--r--app/views/projects/blob/_image.html.haml2
-rw-r--r--app/views/projects/blob/_text.html.haml1
-rw-r--r--app/views/projects/builds/index.html.haml23
-rw-r--r--app/views/projects/forks/index.html.haml64
-rw-r--r--app/views/projects/labels/index.html.haml13
-rw-r--r--app/views/projects/milestones/index.html.haml15
-rw-r--r--app/views/projects/wikis/_nav.html.haml18
-rw-r--r--app/views/shared/_file_highlight.html.haml2
-rw-r--r--app/views/shared/_milestones_filter.html.haml21
-rw-r--r--app/views/shared/_new_project_item_select.html.haml8
-rw-r--r--app/views/shared/groups/_group.html.haml19
-rw-r--r--app/views/shared/projects/_project.html.haml4
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 += ' &middot; '.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)
- &nbsp;
+ %span
+ = render_ci_status(ci_commit)
- if forks
%span
= icon('code-fork')