summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2017-12-20 10:25:09 +0000
committerFilipa Lacerda <filipa@gitlab.com>2017-12-20 10:25:09 +0000
commitfd1811d36434df0d030ad7e35d595f1dd1bca5ea (patch)
tree8ea9071cee778b5a6de3fb41bb81b26104153213 /app
parent30ea58dabb8ea468c355b3456cf4fc14576a6e07 (diff)
parentfebb0b9a8014f5b480ff7baab1d189fce49210a5 (diff)
downloadgitlab-ce-layout-nav-es-module.tar.gz
Merge branch 'master' into layout-nav-es-modulelayout-nav-es-module
* master: (21 commits) Prevent some specs from mangling the gitlab-shell checkout Line up search dropdown with other nav dropdowns Fix onion-skin re-entering state Remove related links in MR widget when empty state Show inline edit button for issues Fix tags in the Activity tab not being clickable Fix shortcut links on help page Don't link LFS-objects multiple times. [CE->EE] Fix spec/lib/gitlab/git/gitlab_projects_spec.rb Tidy up the documentation of Gitlab HA/Gitlab Application Make sure two except won't overwrite each other Update axios.md Remove transitionend event from GL dropdown Preserve gem path so that we use the same gems Load commit in batches for pipelines#index BlobViewer::PackageJson - if private link to homepage Do not generate links for private NPM modules in blob view Remove block styling from search dropdown Fix sidebar height when performance bar enabled Remove all dropdown animations and set display: none if they're not open ...
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/commit/image_file.js1
-rw-r--r--app/assets/javascripts/docs/docs_bundle.js13
-rw-r--r--app/assets/javascripts/gl_dropdown.js24
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue2
-rw-r--r--app/assets/javascripts/issue_show/components/title.vue2
-rw-r--r--app/assets/javascripts/issue_show/index.js7
-rw-r--r--app/assets/javascripts/shortcuts.js10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js28
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js5
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js17
-rw-r--r--app/assets/stylesheets/framework/contextual-sidebar.scss6
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss19
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss5
-rw-r--r--app/assets/stylesheets/pages/issuable.scss4
-rw-r--r--app/assets/stylesheets/pages/search.scss14
-rw-r--r--app/controllers/projects/pipelines_controller.rb2
-rw-r--r--app/models/blob_viewer/dependency_manager.rb13
-rw-r--r--app/models/blob_viewer/package_json.rb18
-rw-r--r--app/models/ci/pipeline.rb13
-rw-r--r--app/models/commit.rb20
-rw-r--r--app/models/repository.rb12
-rw-r--r--app/services/projects/unlink_fork_service.rb2
-rw-r--r--app/views/events/event/_push.html.haml3
-rw-r--r--app/views/help/index.html.haml10
-rw-r--r--app/views/projects/blob/viewers/_dependency_manager.html.haml2
-rw-r--r--app/views/projects/issues/show.html.haml5
-rw-r--r--app/views/projects/pipelines/_info.html.haml50
-rw-r--r--app/workers/expire_pipeline_cache_worker.rb2
29 files changed, 183 insertions, 128 deletions
diff --git a/app/assets/javascripts/commit/image_file.js b/app/assets/javascripts/commit/image_file.js
index 5662802525e..b6a0ece7907 100644
--- a/app/assets/javascripts/commit/image_file.js
+++ b/app/assets/javascripts/commit/image_file.js
@@ -176,6 +176,7 @@ export default class ImageFile {
left: dragTrackWidth
});
+ $frameAdded.css('opacity', 1);
framePadding = parseInt($frameAdded.css('right').replace('px', ''), 10);
_this.initDraggable($dragger, framePadding, function(e, left) {
diff --git a/app/assets/javascripts/docs/docs_bundle.js b/app/assets/javascripts/docs/docs_bundle.js
new file mode 100644
index 00000000000..a32bd6d0fc7
--- /dev/null
+++ b/app/assets/javascripts/docs/docs_bundle.js
@@ -0,0 +1,13 @@
+import Mousetrap from 'mousetrap';
+
+function addMousetrapClick(el, key) {
+ el.addEventListener('click', () => Mousetrap.trigger(key));
+}
+
+function domContentLoaded() {
+ addMousetrapClick(document.querySelector('.js-trigger-shortcut'), '?');
+ addMousetrapClick(document.querySelector('.js-trigger-search-bar'), 's');
+}
+
+document.addEventListener('DOMContentLoaded', domContentLoaded);
+
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
index cf4a70e321e..64f258aed64 100644
--- a/app/assets/javascripts/gl_dropdown.js
+++ b/app/assets/javascripts/gl_dropdown.js
@@ -300,7 +300,7 @@ GitLabDropdown = (function() {
return function(data) {
_this.fullData = data;
_this.parseData(_this.fullData);
- _this.focusTextInput(true);
+ _this.focusTextInput();
if (_this.options.filterable && _this.filter && _this.filter.input && _this.filter.input.val() && _this.filter.input.val().trim() !== '') {
return _this.filter.input.trigger('input');
}
@@ -790,24 +790,16 @@ GitLabDropdown = (function() {
return [selectedObject, isMarking];
};
- GitLabDropdown.prototype.focusTextInput = function(triggerFocus = false) {
+ GitLabDropdown.prototype.focusTextInput = function() {
if (this.options.filterable) {
- this.dropdown.one('transitionend', () => {
- const initialScrollTop = $(window).scrollTop();
+ const initialScrollTop = $(window).scrollTop();
- if (this.dropdown.is('.open')) {
- this.filterInput.focus();
- }
-
- if ($(window).scrollTop() < initialScrollTop) {
- $(window).scrollTop(initialScrollTop);
- }
- });
+ if (this.dropdown.is('.open')) {
+ this.filterInput.focus();
+ }
- if (triggerFocus) {
- // This triggers after a ajax request
- // in case of slow requests, the dropdown transition could already be finished
- this.dropdown.trigger('transitionend');
+ if ($(window).scrollTop() < initialScrollTop) {
+ $(window).scrollTop(initialScrollTop);
}
}
};
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 25ebe5314e0..952f49d522e 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -32,7 +32,7 @@ export default {
showInlineEditButton: {
type: Boolean,
required: false,
- default: false,
+ default: true,
},
showDeleteButton: {
type: Boolean,
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue
index a363d06d950..b7e6eadd440 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issue_show/components/title.vue
@@ -79,7 +79,7 @@
v-tooltip
v-if="showInlineEditButton && canUpdate"
type="button"
- class="btn btn-default btn-edit btn-svg"
+ class="btn btn-default btn-edit btn-svg js-issuable-edit"
v-html="pencilIcon"
title="Edit title and description"
data-placement="bottom"
diff --git a/app/assets/javascripts/issue_show/index.js b/app/assets/javascripts/issue_show/index.js
index 7b762496ba5..75dfdedcf1b 100644
--- a/app/assets/javascripts/issue_show/index.js
+++ b/app/assets/javascripts/issue_show/index.js
@@ -1,5 +1,4 @@
import Vue from 'vue';
-import eventHub from './event_hub';
import issuableApp from './components/app.vue';
import '../vue_shared/vue_resource_interceptor';
@@ -7,12 +6,6 @@ document.addEventListener('DOMContentLoaded', () => {
const initialDataEl = document.getElementById('js-issuable-app-initial-data');
const props = JSON.parse(initialDataEl.innerHTML.replace(/&quot;/g, '"'));
- $('.js-issuable-edit').on('click', (e) => {
- e.preventDefault();
-
- eventHub.$emit('open.form');
- });
-
return new Vue({
el: document.getElementById('js-issuable-app'),
components: {
diff --git a/app/assets/javascripts/shortcuts.js b/app/assets/javascripts/shortcuts.js
index 130730b1700..d2f0d7410da 100644
--- a/app/assets/javascripts/shortcuts.js
+++ b/app/assets/javascripts/shortcuts.js
@@ -51,7 +51,10 @@ export default class Shortcuts {
}
onToggleHelp(e) {
- e.preventDefault();
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+
Shortcuts.toggleHelp(this.enabledHelp);
}
@@ -112,6 +115,9 @@ export default class Shortcuts {
static focusSearch(e) {
$('#search').focus();
- e.preventDefault();
+
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
}
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
index 9cb3edead86..8a9129c385b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js
@@ -62,7 +62,7 @@ export default {
return this.mr.hasCI;
},
shouldRenderRelatedLinks() {
- return !!this.mr.relatedLinks;
+ return !!this.mr.relatedLinks && !this.mr.isNothingToMergeState;
},
shouldRenderDeployments() {
return this.mr.deployments.length;
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
index 7c15abfff10..2bace3311c8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
@@ -1,30 +1,32 @@
+import { stateKey } from './state_maps';
+
export default function deviseState(data) {
if (data.project_archived) {
- return 'archived';
+ return stateKey.archived;
} else if (data.branch_missing) {
- return 'missingBranch';
+ return stateKey.missingBranch;
} else if (!data.commits_count) {
- return 'nothingToMerge';
+ return stateKey.nothingToMerge;
} else if (this.mergeStatus === 'unchecked') {
- return 'checking';
+ return stateKey.checking;
} else if (data.has_conflicts) {
- return 'conflicts';
+ return stateKey.conflicts;
} else if (data.work_in_progress) {
- return 'workInProgress';
+ return stateKey.workInProgress;
} else if (this.onlyAllowMergeIfPipelineSucceeds && this.isPipelineFailed) {
- return 'pipelineFailed';
+ return stateKey.pipelineFailed;
} else if (this.hasMergeableDiscussionsState) {
- return 'unresolvedDiscussions';
+ return stateKey.unresolvedDiscussions;
} else if (this.isPipelineBlocked) {
- return 'pipelineBlocked';
+ return stateKey.pipelineBlocked;
} else if (this.hasSHAChanged) {
- return 'shaMismatch';
+ return stateKey.shaMismatch;
} else if (this.mergeWhenPipelineSucceeds) {
- return this.mergeError ? 'autoMergeFailed' : 'mergeWhenPipelineSucceeds';
+ return this.mergeError ? stateKey.autoMergeFailed : stateKey.mergeWhenPipelineSucceeds;
} else if (!this.canMerge) {
- return 'notAllowedToMerge';
+ return stateKey.notAllowedToMerge;
} else if (this.canBeMerged) {
- return 'readyToMerge';
+ return stateKey.readyToMerge;
}
return null;
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index 707766e08e4..93d31a2a684 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -1,5 +1,6 @@
import Timeago from 'timeago.js';
import { getStateKey } from '../dependencies';
+import { stateKey } from './state_maps';
import { formatDate } from '../../lib/utils/datetime_utility';
export default class MergeRequestStore {
@@ -120,6 +121,10 @@ export default class MergeRequestStore {
}
}
+ get isNothingToMergeState() {
+ return this.state === stateKey.nothingToMerge;
+ }
+
static getEventObject(event) {
return {
author: MergeRequestStore.getAuthorObject(event),
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js b/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
index 9074a064a6d..de980c175fb 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js
@@ -31,6 +31,23 @@ const statesToShowHelpWidget = [
'autoMergeFailed',
];
+export const stateKey = {
+ archived: 'archived',
+ missingBranch: 'missingBranch',
+ nothingToMerge: 'nothingToMerge',
+ checking: 'checking',
+ conflicts: 'conflicts',
+ workInProgress: 'workInProgress',
+ pipelineFailed: 'pipelineFailed',
+ unresolvedDiscussions: 'unresolvedDiscussions',
+ pipelineBlocked: 'pipelineBlocked',
+ shaMismatch: 'shaMismatch',
+ autoMergeFailed: 'autoMergeFailed',
+ mergeWhenPipelineSucceeds: 'mergeWhenPipelineSucceeds',
+ notAllowedToMerge: 'notAllowedToMerge',
+ readyToMerge: 'readyToMerge',
+};
+
export default {
stateToComponentMap,
statesToShowHelpWidget,
diff --git a/app/assets/stylesheets/framework/contextual-sidebar.scss b/app/assets/stylesheets/framework/contextual-sidebar.scss
index 8baf7ca23a4..2e417315ed7 100644
--- a/app/assets/stylesheets/framework/contextual-sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual-sidebar.scss
@@ -9,12 +9,6 @@
padding-left: $contextual-sidebar-width;
}
- // Override position: absolute
- .right-sidebar {
- position: fixed;
- height: calc(100% - #{$header-height});
- }
-
.issues-bulk-update.right-sidebar.right-sidebar-expanded .issuable-sidebar-header {
padding: 10px 0 15px;
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 478269f3fcf..bc907a390d8 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -16,27 +16,18 @@
@mixin set-visible {
transform: translateY(0);
- visibility: visible;
- opacity: 1;
- transition-duration: 100ms, 150ms, 25ms;
- transition-delay: 35ms, 50ms, 25ms;
+ display: block;
}
@mixin set-invisible {
transform: translateY(-10px);
- visibility: hidden;
- opacity: 0;
- transition-property: opacity, transform, visibility;
- transition-duration: 70ms, 250ms, 250ms;
- transition-timing-function: linear, $dropdown-animation-timing;
- transition-delay: 25ms, 50ms, 0ms;
+ display: none;
}
.open {
.dropdown-menu,
.dropdown-menu-nav {
@include set-visible;
- display: block;
min-height: 40px;
@media (max-width: $screen-xs-max) {
@@ -55,6 +46,11 @@
}
}
+// Get search dropdown to line up with other nav dropdowns
+.search-input-container .dropdown-menu {
+ margin-top: 11px;
+}
+
.dropdown-toggle {
padding: 6px 8px 6px 10px;
background-color: $white-light;
@@ -214,7 +210,6 @@
.dropdown-menu,
.dropdown-menu-nav {
@include set-invisible;
- display: block;
position: absolute;
width: auto;
top: 100%;
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 0742c0a2a09..d61809cb0a4 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -90,11 +90,6 @@
.right-sidebar {
border-left: 1px solid $border-color;
height: calc(100% - #{$header-height});
-
- &.affix {
- position: fixed;
- top: $header-height;
- }
}
.with-performance-bar .right-sidebar.affix {
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index e19196e0c41..e1637618ab2 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -122,7 +122,7 @@
}
.right-sidebar {
- position: absolute;
+ position: fixed;
top: $header-height;
bottom: 0;
right: 0;
@@ -502,7 +502,7 @@
top: $header-height + $performance-bar-height;
.issuable-sidebar {
- height: calc(100% - #{$header-height} - #{$performance-bar-height});
+ height: calc(100% - #{$performance-bar-height});
}
}
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index 49c8e546bf2..c9363188505 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -108,13 +108,6 @@ input[type="checkbox"]:hover {
// Custom dropdown positioning
.dropdown-menu {
- transition-property: opacity, transform;
- transition-duration: 250ms, 250ms;
- transition-delay: 0ms, 25ms;
- transition-timing-function: $dropdown-animation-timing;
- transform: translateY(0);
- opacity: 0;
- display: block;
left: -5px;
}
@@ -152,13 +145,6 @@ input[type="checkbox"]:hover {
background-color: $nav-badge-bg;
border-color: $border-color;
}
-
- .dropdown-menu {
- transition-duration: 100ms, 75ms;
- transition-delay: 75ms, 100ms;
- transform: translateY(7px);
- opacity: 1;
- }
}
&.has-value {
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 7ad7b3003af..e146d0d3cd5 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -29,6 +29,8 @@ class Projects::PipelinesController < Projects::ApplicationController
@pipelines_count = PipelinesFinder
.new(project).execute.count
+ @pipelines.map(&:commit) # List commits for batch loading
+
respond_to do |format|
format.html
format.json do
diff --git a/app/models/blob_viewer/dependency_manager.rb b/app/models/blob_viewer/dependency_manager.rb
index a8d9be945dc..cc4950240af 100644
--- a/app/models/blob_viewer/dependency_manager.rb
+++ b/app/models/blob_viewer/dependency_manager.rb
@@ -27,10 +27,17 @@ module BlobViewer
private
- def package_name_from_json(key)
- prepare!
+ def json_data
+ @json_data ||= begin
+ prepare!
+ JSON.parse(blob.data)
+ rescue
+ {}
+ end
+ end
- JSON.parse(blob.data)[key] rescue nil
+ def package_name_from_json(key)
+ json_data[key]
end
def package_name_from_method_call(name)
diff --git a/app/models/blob_viewer/package_json.rb b/app/models/blob_viewer/package_json.rb
index 09221efb56c..46cd2f04f4d 100644
--- a/app/models/blob_viewer/package_json.rb
+++ b/app/models/blob_viewer/package_json.rb
@@ -16,7 +16,25 @@ module BlobViewer
@package_name ||= package_name_from_json('name')
end
+ def package_type
+ private? ? 'private package' : super
+ end
+
def package_url
+ private? ? homepage : npm_url
+ end
+
+ private
+
+ def private?
+ !!json_data['private']
+ end
+
+ def homepage
+ json_data['homepage']
+ end
+
+ def npm_url
"https://www.npmjs.com/package/#{package_name}"
end
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 28f154581a9..d4690da3be6 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -287,8 +287,12 @@ module Ci
Ci::Pipeline.truncate_sha(sha)
end
+ # NOTE: This is loaded lazily and will never be nil, even if the commit
+ # cannot be found.
+ #
+ # Use constructs like: `pipeline.commit.present?`
def commit
- @commit ||= project.commit_by(oid: sha)
+ @commit ||= Commit.lazy(project, sha)
end
def branch?
@@ -338,12 +342,9 @@ module Ci
end
def latest?
- return false unless ref
-
- commit = project.commit(ref)
- return false unless commit
+ return false unless ref && commit.present?
- commit.sha == sha
+ project.commit(ref) == commit
end
def retried
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 13c31111134..2be07ca7d3c 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -86,6 +86,20 @@ class Commit
def valid_hash?(key)
!!(/\A#{COMMIT_SHA_PATTERN}\z/ =~ key)
end
+
+ def lazy(project, oid)
+ BatchLoader.for({ project: project, oid: oid }).batch do |items, loader|
+ items_by_project = items.group_by { |i| i[:project] }
+
+ items_by_project.each do |project, commit_ids|
+ oids = commit_ids.map { |i| i[:oid] }
+
+ project.repository.commits_by(oids: oids).each do |commit|
+ loader.call({ project: commit.project, oid: commit.id }, commit) if commit
+ end
+ end
+ end
+ end
end
attr_accessor :raw
@@ -103,7 +117,7 @@ class Commit
end
def ==(other)
- (self.class === other) && (raw == other.raw)
+ other.is_a?(self.class) && raw == other.raw
end
def self.reference_prefix
@@ -224,8 +238,8 @@ class Commit
notes.includes(:author)
end
- def method_missing(m, *args, &block)
- @raw.__send__(m, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
+ def method_missing(method, *args, &block)
+ @raw.__send__(method, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
end
def respond_to_missing?(method, include_private = false)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 4ec8ec9c8b2..387428d90a6 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -118,6 +118,18 @@ class Repository
@commit_cache[oid] = find_commit(oid)
end
+ def commits_by(oids:)
+ return [] unless oids.present?
+
+ commits = Gitlab::Git::Commit.batch_by_oid(raw_repository, oids)
+
+ if commits.present?
+ Commit.decorate(commits, @project)
+ else
+ []
+ end
+ end
+
def commits(ref, path: nil, limit: nil, offset: nil, skip_merges: false, after: nil, before: nil)
options = {
repo: raw_repository,
diff --git a/app/services/projects/unlink_fork_service.rb b/app/services/projects/unlink_fork_service.rb
index c499f384426..842fe4e09c4 100644
--- a/app/services/projects/unlink_fork_service.rb
+++ b/app/services/projects/unlink_fork_service.rb
@@ -5,7 +5,7 @@ module Projects
if fork_source = @project.fork_source
fork_source.lfs_objects.find_each do |lfs_object|
- lfs_object.projects << @project
+ lfs_object.projects << @project unless lfs_object.projects.include?(@project)
end
refresh_forks_count(fork_source)
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index 9a763887b30..f85f5c5be88 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -7,7 +7,8 @@
%span.pushed #{event.action_name} #{event.ref_type}
%strong
- commits_link = project_commits_path(project, event.ref_name)
- = link_to_if project.repository.branch_exists?(event.ref_name), event.ref_name, commits_link, class: 'ref-name'
+ - should_link = event.tag? ? project.repository.tag_exists?(event.ref_name) : project.repository.branch_exists?(event.ref_name)
+ = link_to_if should_link, event.ref_name, commits_link, class: 'ref-name'
= render "events/event_scope", event: event
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 021de4f0caf..b8692009225 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -1,3 +1,5 @@
+= webpack_bundle_tag 'docs'
+
%div
- if current_application_settings.help_page_text.present?
= markdown_field(current_application_settings, :help_page_text)
@@ -37,8 +39,12 @@
Quick help
%ul.well-list
%li= link_to 'See our website for getting help', support_url
- %li= link_to 'Use the search bar on the top of this page', '#', onclick: 'Shortcuts.focusSearch(event)'
- %li= link_to 'Use shortcuts', '#', onclick: 'Shortcuts.toggleHelp()'
+ %li
+ %button.btn-blank.btn-link.js-trigger-search-bar{ type: 'button' }
+ Use the search bar on the top of this page
+ %li
+ %button.btn-blank.btn-link.js-trigger-shortcut{ type: 'button' }
+ Use shortcuts
- unless current_application_settings.help_page_hide_commercial_content?
%li= link_to 'Get a support subscription', 'https://about.gitlab.com/pricing/'
%li= link_to 'Compare GitLab editions', 'https://about.gitlab.com/features/#compare'
diff --git a/app/views/projects/blob/viewers/_dependency_manager.html.haml b/app/views/projects/blob/viewers/_dependency_manager.html.haml
index a0f0215a5ff..87aa7c1dbf8 100644
--- a/app/views/projects/blob/viewers/_dependency_manager.html.haml
+++ b/app/views/projects/blob/viewers/_dependency_manager.html.haml
@@ -6,6 +6,6 @@
- if viewer.package_name
and defines a #{viewer.package_type} named
%strong<
- = link_to viewer.package_name, viewer.package_url, target: '_blank', rel: 'noopener noreferrer'
+ = link_to_if viewer.package_url.present?, viewer.package_name, viewer.package_url, target: '_blank', rel: 'noopener noreferrer'
= link_to 'Learn more', viewer.manager_url, target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index eab7879c7bf..1f28d8acff6 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -39,8 +39,6 @@
= icon('caret-down')
.dropdown-menu.dropdown-menu-align-right.hidden-lg
%ul
- - if can_update_issue
- %li= link_to 'Edit', edit_project_issue_path(@project, @issue), class: 'js-issuable-edit'
- unless current_user == @issue.author
%li= link_to 'Report abuse', new_abuse_report_path(user_id: @issue.author.id, ref_url: issue_url(@issue))
- if can_update_issue
@@ -52,9 +50,6 @@
%li.divider
%li= link_to 'New issue', new_project_issue_path(@project), title: 'New issue', id: 'new_issue_link'
- - if can_update_issue
- = link_to 'Edit', edit_project_issue_path(@project, @issue), class: 'hidden-xs hidden-sm btn btn-grouped js-issuable-edit'
-
= render 'shared/issuable/close_reopen_button', issuable: @issue, can_update: can_update_issue
- if can_report_spam
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 01ea9356af5..85946aec1f2 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -1,6 +1,6 @@
#js-pipeline-header-vue.pipeline-header-container
-- if @commit
+- if @commit.present?
.commit-box
%h3.commit-title
= markdown(@commit.title, pipeline: :single_line)
@@ -8,28 +8,28 @@
%pre.commit-description
= preserve(markdown(@commit.description, pipeline: :single_line))
-.info-well
- - if @commit.status
- .well-segment.pipeline-info
- .icon-container
- = icon('clock-o')
- = pluralize @pipeline.total_size, "job"
- - if @pipeline.ref
- from
- = link_to @pipeline.ref, project_ref_path(@project, @pipeline.ref), class: "ref-name"
- - if @pipeline.duration
- in
- = time_interval_in_words(@pipeline.duration)
- - if @pipeline.queued_duration
- = "(queued for #{time_interval_in_words(@pipeline.queued_duration)})"
+ .info-well
+ - if @commit.status
+ .well-segment.pipeline-info
+ .icon-container
+ = icon('clock-o')
+ = pluralize @pipeline.total_size, "job"
+ - if @pipeline.ref
+ from
+ = link_to @pipeline.ref, project_ref_path(@project, @pipeline.ref), class: "ref-name"
+ - if @pipeline.duration
+ in
+ = time_interval_in_words(@pipeline.duration)
+ - if @pipeline.queued_duration
+ = "(queued for #{time_interval_in_words(@pipeline.queued_duration)})"
- .well-segment.branch-info
- .icon-container.commit-icon
- = custom_icon("icon_commit")
- = link_to @commit.short_id, project_commit_path(@project, @pipeline.sha), class: "commit-sha js-details-short"
- = link_to("#", class: "js-details-expand hidden-xs hidden-sm") do
- %span.text-expander
- \...
- %span.js-details-content.hide
- = link_to @pipeline.sha, project_commit_path(@project, @pipeline.sha), class: "commit-sha commit-hash-full"
- = clipboard_button(text: @pipeline.sha, title: "Copy commit SHA to clipboard")
+ .well-segment.branch-info
+ .icon-container.commit-icon
+ = custom_icon("icon_commit")
+ = link_to @commit.short_id, project_commit_path(@project, @pipeline.sha), class: "commit-sha js-details-short"
+ = link_to("#", class: "js-details-expand hidden-xs hidden-sm") do
+ %span.text-expander
+ \...
+ %span.js-details-content.hide
+ = link_to @pipeline.sha, project_commit_path(@project, @pipeline.sha), class: "commit-sha commit-hash-full"
+ = clipboard_button(text: @pipeline.sha, title: "Copy commit SHA to clipboard")
diff --git a/app/workers/expire_pipeline_cache_worker.rb b/app/workers/expire_pipeline_cache_worker.rb
index 3e34de22c19..db73d37868a 100644
--- a/app/workers/expire_pipeline_cache_worker.rb
+++ b/app/workers/expire_pipeline_cache_worker.rb
@@ -13,7 +13,7 @@ class ExpirePipelineCacheWorker
store.touch(project_pipelines_path(project))
store.touch(project_pipeline_path(project, pipeline))
- store.touch(commit_pipelines_path(project, pipeline.commit)) if pipeline.commit
+ store.touch(commit_pipelines_path(project, pipeline.commit)) unless pipeline.commit.nil?
store.touch(new_merge_request_pipelines_path(project))
each_pipelines_merge_request_path(project, pipeline) do |path|
store.touch(path)