summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2017-08-30 16:49:22 +0100
committerPhil Hughes <me@iamphill.com>2017-08-30 16:49:22 +0100
commit4d2d744ae9a2d4c3bb0f00805c27704b79e00d72 (patch)
tree839b1c3ab4c09c80f7d643fe69dae8a83c4e4eb4 /app
parent25a3b7fab905d09f6f064108f457a4e20c8915ff (diff)
parentf7c8434c7100c3c87eb2a75cd5a128e520d8c110 (diff)
downloadgitlab-ce-4d2d744ae9a2d4c3bb0f00805c27704b79e00d72.tar.gz
Merge branch 'master' into enable-new-navigaton-by-defaultenable-new-navigaton-by-default
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/droplab/drop_down.js7
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js82
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_hint.js2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_bundle.js1
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js5
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js14
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_token_keys.js20
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js21
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue6
-rw-r--r--app/assets/javascripts/lib/utils/sticky.js2
-rw-r--r--app/assets/javascripts/merge_request_tabs.js1
-rw-r--r--app/assets/javascripts/new_sidebar.js1
-rw-r--r--app/assets/javascripts/pipelines/components/navigation_tabs.vue54
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/identicon.vue (renamed from app/assets/javascripts/groups/components/group_identicon.vue)0
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss5
-rw-r--r--app/assets/stylesheets/framework/filters.scss18
-rw-r--r--app/assets/stylesheets/framework/selects.scss1
-rw-r--r--app/assets/stylesheets/framework/typography.scss4
-rw-r--r--app/assets/stylesheets/pages/editor.scss2
-rw-r--r--app/assets/stylesheets/pages/notifications.scss4
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss4
-rw-r--r--app/controllers/autocomplete_controller.rb18
-rw-r--r--app/controllers/concerns/issuable_collections.rb12
-rw-r--r--app/controllers/groups/milestones_controller.rb6
-rw-r--r--app/controllers/projects/issues_controller.rb2
-rw-r--r--app/finders/issuable_finder.rb10
-rw-r--r--app/helpers/application_helper.rb2
-rw-r--r--app/helpers/issuables_helper.rb2
-rw-r--r--app/helpers/milestones_helper.rb2
-rw-r--r--app/helpers/milestones_routing_helper.rb8
-rw-r--r--app/models/ci/runner.rb2
-rw-r--r--app/models/concerns/awardable.rb15
-rw-r--r--app/models/concerns/editable.rb2
-rw-r--r--app/models/concerns/milestoneish.rb8
-rw-r--r--app/models/dashboard_milestone.rb2
-rw-r--r--app/models/deployment.rb2
-rw-r--r--app/models/group_milestone.rb2
-rw-r--r--app/models/milestone.rb6
-rw-r--r--app/models/network/graph.rb4
-rw-r--r--app/models/project_services/chat_notification_service.rb6
-rw-r--r--app/models/project_services/hipchat_service.rb6
-rw-r--r--app/models/repository.rb55
-rw-r--r--app/models/user.rb3
-rw-r--r--app/policies/project_policy.rb6
-rw-r--r--app/services/akismet_service.rb2
-rw-r--r--app/services/git_push_service.rb10
-rw-r--r--app/services/milestones/close_service.rb2
-rw-r--r--app/services/milestones/create_service.rb2
-rw-r--r--app/services/milestones/destroy_service.rb2
-rw-r--r--app/services/milestones/reopen_service.rb2
-rw-r--r--app/services/projects/create_service.rb2
-rw-r--r--app/services/spam_service.rb2
-rw-r--r--app/services/system_note_service.rb2
-rw-r--r--app/views/groups/milestones/show.html.haml2
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml3
-rw-r--r--app/views/profiles/gpg_keys/index.html.haml2
-rw-r--r--app/views/projects/boards/_show.html.haml1
-rw-r--r--app/views/projects/commit/_signature_badge.html.haml2
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml7
-rw-r--r--app/views/shared/milestones/_milestone.html.haml8
-rw-r--r--app/views/shared/milestones/_top.html.haml8
62 files changed, 385 insertions, 113 deletions
diff --git a/app/assets/javascripts/droplab/drop_down.js b/app/assets/javascripts/droplab/drop_down.js
index 70cd337fb8a..3901bb177fe 100644
--- a/app/assets/javascripts/droplab/drop_down.js
+++ b/app/assets/javascripts/droplab/drop_down.js
@@ -85,6 +85,13 @@ class DropDown {
const renderableList = this.list.querySelector('ul[data-dynamic]') || this.list;
renderableList.innerHTML = children.join('');
+
+ const listEvent = new CustomEvent('render.dl', {
+ detail: {
+ list: this,
+ },
+ });
+ this.list.dispatchEvent(listEvent);
}
renderChildren(data) {
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
new file mode 100644
index 00000000000..f9bbbf0cbc1
--- /dev/null
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -0,0 +1,82 @@
+/* global Flash */
+
+import Ajax from '~/droplab/plugins/ajax';
+import Filter from '~/droplab/plugins/filter';
+import './filtered_search_dropdown';
+
+class DropdownEmoji extends gl.FilteredSearchDropdown {
+ constructor(options = {}) {
+ super(options);
+ this.config = {
+ Ajax: {
+ endpoint: `${gon.relative_url_root || ''}/autocomplete/award_emojis`,
+ method: 'setData',
+ loadingTemplate: this.loadingTemplate,
+ onError() {
+ /* eslint-disable no-new */
+ new Flash('An error occured fetching the dropdown data.');
+ /* eslint-enable no-new */
+ },
+ },
+ Filter: {
+ template: 'name',
+ },
+ };
+
+ import(/* webpackChunkName: 'emoji' */ '~/emoji')
+ .then(({ glEmojiTag }) => { this.glEmojiTag = glEmojiTag; })
+ .catch(() => { /* ignore error and leave emoji name in the search bar */ });
+
+ this.unbindEvents();
+ this.bindEvents();
+ }
+
+ bindEvents() {
+ super.bindEvents();
+
+ this.listRenderedWrapper = this.listRendered.bind(this);
+ this.dropdown.addEventListener('render.dl', this.listRenderedWrapper);
+ }
+
+ unbindEvents() {
+ this.dropdown.removeEventListener('render.dl', this.listRenderedWrapper);
+ super.unbindEvents();
+ }
+
+ listRendered() {
+ this.replaceEmojiElement();
+ }
+
+ itemClicked(e) {
+ super.itemClicked(e, (selected) => {
+ const name = selected.querySelector('.js-data-value').innerText.trim();
+ return gl.DropdownUtils.getEscapedText(name);
+ });
+ }
+
+ renderContent(forceShowList = false) {
+ this.droplab.changeHookList(this.hookId, this.dropdown, [Ajax, Filter], this.config);
+ super.renderContent(forceShowList);
+ }
+
+ replaceEmojiElement() {
+ if (!this.glEmojiTag) return;
+
+ // Replace empty gl-emoji tag to real content
+ const dropdownItems = [...this.dropdown.querySelectorAll('.filter-dropdown-item')];
+ dropdownItems.forEach((dropdownItem) => {
+ const name = dropdownItem.querySelector('.js-data-value').innerText;
+ const emojiTag = this.glEmojiTag(name);
+ const emojiElement = dropdownItem.querySelector('gl-emoji');
+ emojiElement.outerHTML = emojiTag;
+ });
+ }
+
+ init() {
+ this.droplab
+ .addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
+ }
+}
+
+window.gl = window.gl || {};
+gl.DropdownEmoji = DropdownEmoji;
diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js b/app/assets/javascripts/filtered_search/dropdown_hint.js
index a81389ab088..1c5ca1d3cf9 100644
--- a/app/assets/javascripts/filtered_search/dropdown_hint.js
+++ b/app/assets/javascripts/filtered_search/dropdown_hint.js
@@ -61,7 +61,7 @@ class DropdownHint extends gl.FilteredSearchDropdown {
.map(tokenKey => ({
icon: `fa-${tokenKey.icon}`,
hint: tokenKey.key,
- tag: `<${tokenKey.symbol}${tokenKey.key}>`,
+ tag: `<${tokenKey.tag}>`,
type: tokenKey.type,
}));
diff --git a/app/assets/javascripts/filtered_search/filtered_search_bundle.js b/app/assets/javascripts/filtered_search/filtered_search_bundle.js
index 132b6fe698a..6d5dd747224 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_bundle.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_bundle.js
@@ -1,3 +1,4 @@
+import './dropdown_emoji';
import './dropdown_hint';
import './dropdown_non_user';
import './dropdown_user';
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
index dd1c067df87..46c80dfd45e 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
@@ -58,6 +58,11 @@ class FilteredSearchDropdownManager {
},
element: this.container.querySelector('#js-dropdown-label'),
},
+ 'my-reaction': {
+ reference: null,
+ gl: 'DropdownEmoji',
+ element: this.container.querySelector('#js-dropdown-my-reaction'),
+ },
hint: {
reference: null,
gl: 'DropdownHint',
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index a31be2b0bc7..038239bf466 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -439,8 +439,13 @@ class FilteredSearchManager {
const match = this.filteredSearchTokenKeys.searchByKeyParam(keyParam);
if (match) {
- const indexOf = keyParam.indexOf('_');
- const sanitizedKey = indexOf !== -1 ? keyParam.slice(0, keyParam.indexOf('_')) : keyParam;
+ // Use lastIndexOf because the token key is allowed to contain underscore
+ // e.g. 'my_reaction' is the token key of 'my_reaction_emoji'
+ const lastIndexOf = keyParam.lastIndexOf('_');
+ let sanitizedKey = lastIndexOf !== -1 ? keyParam.slice(0, lastIndexOf) : keyParam;
+ // Replace underscore with hyphen in the sanitizedkey.
+ // e.g. 'my_reaction' => 'my-reaction'
+ sanitizedKey = sanitizedKey.replace('_', '-');
const symbol = match.symbol;
let quotationsToUse = '';
@@ -515,7 +520,10 @@ class FilteredSearchManager {
const condition = this.filteredSearchTokenKeys
.searchByConditionKeyValue(token.key, token.value.toLowerCase());
const { param } = this.filteredSearchTokenKeys.searchByKey(token.key) || {};
- const keyParam = param ? `${token.key}_${param}` : token.key;
+ // Replace hyphen with underscore to use as request parameter
+ // e.g. 'my-reaction' => 'my_reaction'
+ const underscoredKey = token.key.replace('-', '_');
+ const keyParam = param ? `${underscoredKey}_${param}` : underscoredKey;
let tokenPath = '';
if (condition) {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
index 025d4d8795b..be595d7df1a 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
@@ -4,26 +4,42 @@ const tokenKeys = [{
param: 'username',
symbol: '@',
icon: 'pencil',
+ tag: '@author',
}, {
key: 'assignee',
type: 'string',
param: 'username',
symbol: '@',
icon: 'user',
+ tag: '@assignee',
}, {
key: 'milestone',
type: 'string',
param: 'title',
symbol: '%',
icon: 'clock-o',
+ tag: '%milestone',
}, {
key: 'label',
type: 'array',
param: 'name[]',
symbol: '~',
icon: 'tag',
+ tag: '~label',
}];
+if (gon.current_user_id) {
+ // Appending tokenkeys only logged-in
+ tokenKeys.push({
+ key: 'my-reaction',
+ type: 'string',
+ param: 'emoji',
+ symbol: '',
+ icon: 'thumbs-up',
+ tag: 'emoji',
+ });
+}
+
const alternativeTokenKeys = [{
key: 'label',
type: 'string',
@@ -84,6 +100,10 @@ class FilteredSearchTokenKeys {
return tokenKeysWithAlternative.find((tokenKey) => {
let tokenKeyParam = tokenKey.key;
+ // Replace hyphen with underscore to compare keyParam with tokenKeyParam
+ // e.g. 'my-reaction' => 'my_reaction'
+ tokenKeyParam = tokenKeyParam.replace('-', '_');
+
if (tokenKey.param) {
tokenKeyParam += `_${tokenKey.param}`;
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
index 243ee4d723a..28e8240169d 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
@@ -132,6 +132,23 @@ class FilteredSearchVisualTokens {
.catch(() => { });
}
+ static updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue) {
+ const container = tokenValueContainer;
+ const element = tokenValueElement;
+
+ return import(/* webpackChunkName: 'emoji' */ '../emoji')
+ .then((Emoji) => {
+ if (!Emoji.isEmojiNameValid(tokenValue)) {
+ return;
+ }
+
+ container.dataset.originalValue = tokenValue;
+ element.innerHTML = Emoji.glEmojiTag(tokenValue);
+ })
+ // ignore error and leave emoji name in the search bar
+ .catch(() => { });
+ }
+
static renderVisualTokenValue(parentElement, tokenName, tokenValue) {
const tokenValueContainer = parentElement.querySelector('.value-container');
const tokenValueElement = tokenValueContainer.querySelector('.value');
@@ -144,6 +161,10 @@ class FilteredSearchVisualTokens {
FilteredSearchVisualTokens.updateUserTokenAppearance(
tokenValueContainer, tokenValueElement, tokenValue,
);
+ } else if (tokenType === 'my-reaction') {
+ FilteredSearchVisualTokens.updateEmojiTokenAppearance(
+ tokenValueContainer, tokenValueElement, tokenValue,
+ );
}
}
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index cb133cf7535..2060410e991 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -1,10 +1,10 @@
<script>
+import identicon from '../../vue_shared/components/identicon.vue';
import eventHub from '../event_hub';
-import groupIdenticon from './group_identicon.vue';
export default {
components: {
- groupIdenticon,
+ identicon,
},
props: {
group: {
@@ -205,7 +205,7 @@ export default {
class="avatar s40"
:src="group.avatarUrl"
/>
- <group-identicon
+ <identicon
v-else
:entity-id=group.id
:entity-name="group.name"
diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js
index ff2b66046b4..283c0ec0410 100644
--- a/app/assets/javascripts/lib/utils/sticky.js
+++ b/app/assets/javascripts/lib/utils/sticky.js
@@ -1,5 +1,5 @@
export const isSticky = (el, scrollY, stickyTop) => {
- const top = el.offsetTop - scrollY;
+ const top = Math.floor(el.offsetTop - scrollY);
if (top <= stickyTop) {
el.classList.add('is-stuck');
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 5a9b3d19f84..3b3620fe61b 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -253,6 +253,7 @@ import bp from './breakpoints';
loadDiff(source) {
if (this.diffsLoaded) {
+ document.dispatchEvent(new CustomEvent('scroll'));
return;
}
diff --git a/app/assets/javascripts/new_sidebar.js b/app/assets/javascripts/new_sidebar.js
index 2d1ed9e4076..b18d12b48b5 100644
--- a/app/assets/javascripts/new_sidebar.js
+++ b/app/assets/javascripts/new_sidebar.js
@@ -47,7 +47,6 @@ export default class NewNavSidebar {
if (this.$sidebar.length) {
this.$sidebar.toggleClass('sidebar-icons-only', collapsed);
- this.$page.toggleClass('page-with-new-sidebar', !collapsed);
this.$page.toggleClass('page-with-icon-sidebar', breakpoint === 'sm' ? true : collapsed);
}
NewNavSidebar.setCollapsedCookie(collapsed);
diff --git a/app/assets/javascripts/pipelines/components/navigation_tabs.vue b/app/assets/javascripts/pipelines/components/navigation_tabs.vue
index d2f6d47f043..73f7e3a0cad 100644
--- a/app/assets/javascripts/pipelines/components/navigation_tabs.vue
+++ b/app/assets/javascripts/pipelines/components/navigation_tabs.vue
@@ -1,23 +1,29 @@
<script>
-export default {
- name: 'PipelineNavigationTabs',
- props: {
- scope: {
- type: String,
- required: true,
+ export default {
+ name: 'PipelineNavigationTabs',
+ props: {
+ scope: {
+ type: String,
+ required: true,
+ },
+ count: {
+ type: Object,
+ required: true,
+ },
+ paths: {
+ type: Object,
+ required: true,
+ },
},
- count: {
- type: Object,
- required: true,
+ mounted() {
+ $(document).trigger('init.scrolling-tabs');
},
- paths: {
- type: Object,
- required: true,
+ methods: {
+ shouldRenderBadge(count) {
+ // 0 is valid in a badge, but evaluates to false, we need to check for undefined
+ return count !== undefined;
+ },
},
- },
- mounted() {
- $(document).trigger('init.scrolling-tabs');
- },
};
</script>
<template>
@@ -27,7 +33,9 @@ export default {
:class="{ active: scope === 'all'}">
<a :href="paths.allPath">
All
- <span class="badge js-totalbuilds-count">
+ <span
+ v-if="shouldRenderBadge(count.all)"
+ class="badge js-totalbuilds-count">
{{count.all}}
</span>
</a>
@@ -37,7 +45,9 @@ export default {
:class="{ active: scope === 'pending'}">
<a :href="paths.pendingPath">
Pending
- <span class="badge">
+ <span
+ v-if="shouldRenderBadge(count.pending)"
+ class="badge">
{{count.pending}}
</span>
</a>
@@ -47,7 +57,9 @@ export default {
:class="{ active: scope === 'running'}">
<a :href="paths.runningPath">
Running
- <span class="badge">
+ <span
+ v-if="shouldRenderBadge(count.running)"
+ class="badge">
{{count.running}}
</span>
</a>
@@ -57,7 +69,9 @@ export default {
:class="{ active: scope === 'finished'}">
<a :href="paths.finishedPath">
Finished
- <span class="badge">
+ <span
+ v-if="shouldRenderBadge(count.finished)"
+ class="badge">
{{count.finished}}
</span>
</a>
diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue
index 5df317a76bf..010063a0240 100644
--- a/app/assets/javascripts/pipelines/components/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines.vue
@@ -139,7 +139,9 @@
};
</script>
<template>
- <div :class="cssClass">
+ <div
+ class="pipelines-container"
+ :class="cssClass">
<div
class="top-area scrolling-tabs-container inner-page-scroll-tabs"
v-if="!isLoading && !shouldRenderEmptyState">
diff --git a/app/assets/javascripts/groups/components/group_identicon.vue b/app/assets/javascripts/vue_shared/components/identicon.vue
index 0edd820743f..0edd820743f 100644
--- a/app/assets/javascripts/groups/components/group_identicon.vue
+++ b/app/assets/javascripts/vue_shared/components/identicon.vue
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index a45d5a6dca0..4cf2f46c6d3 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -771,6 +771,11 @@
&::before {
top: 16px;
}
+
+ &.dropdown-menu-user-link::before {
+ top: 50%;
+ transform: translateY(-50%);
+ }
}
}
}
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index a5d33d410fb..b2847c348eb 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -225,6 +225,18 @@
color: $common-gray-dark;
}
+ gl-emoji {
+ display: inline-block;
+ font-family: inherit;
+ font-size: inherit;
+ vertical-align: inherit;
+
+ img {
+ height: 18px;
+ width: 18px;
+ }
+ }
+
.form-control {
position: relative;
min-width: 200px;
@@ -277,7 +289,7 @@
}
.filtered-search-input-dropdown-menu {
- max-height: 225px;
+ max-height: 260px;
max-width: 280px;
overflow: auto;
@@ -478,3 +490,7 @@
padding: 8px 16px;
text-align: center;
}
+
+.issues-details-filters {
+ @include new-style-dropdown;
+}
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index 9fccc68b5b6..8018eb8ba84 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -268,6 +268,7 @@
// TODO: change global style
.ajax-project-dropdown,
body[data-page="projects:blob:new"] #select2-drop,
+body[data-page="profiles:show"] #select2-drop,
body[data-page="projects:blob:edit"] #select2-drop {
&.select2-drop {
color: $gl-text-color;
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 71eec0e1a5e..3c0b4c82d19 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -10,8 +10,7 @@
color: $md-link-color;
}
- img {
- /*max-width: 100%;*/
+ img:not(.emoji) {
margin: 0 0 8px;
}
@@ -26,6 +25,7 @@
min-width: inherit;
min-height: inherit;
background-color: inherit;
+ max-width: 100%;
}
p a:not(.no-attachment-icon) img {
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index f6b8c8ee2bc..d3cd4d507de 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -204,6 +204,8 @@
.gitlab-ci-yml-selector,
.dockerfile-selector,
.template-type-selector {
+ @include new-style-dropdown;
+
display: inline-block;
vertical-align: top;
font-family: $regular_font;
diff --git a/app/assets/stylesheets/pages/notifications.scss b/app/assets/stylesheets/pages/notifications.scss
index bdf07a99daf..c28b1e68008 100644
--- a/app/assets/stylesheets/pages/notifications.scss
+++ b/app/assets/stylesheets/pages/notifications.scss
@@ -14,3 +14,7 @@
font-size: 18px;
}
}
+
+.notification-form {
+ @include new-style-dropdown;
+}
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index a408bde37d6..51656669c98 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -927,3 +927,7 @@ button.mini-pipeline-graph-dropdown-toggle {
}
}
}
+
+.pipelines-container .top-area .nav-controls > .btn:last-child {
+ float: none;
+}
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 3120916c5bb..59be955599d 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -1,5 +1,7 @@
class AutocompleteController < ApplicationController
- skip_before_action :authenticate_user!, only: [:users]
+ AWARD_EMOJI_MAX = 100
+
+ skip_before_action :authenticate_user!, only: [:users, :award_emojis]
before_action :load_project, only: [:users]
before_action :find_users, only: [:users]
@@ -48,6 +50,20 @@ class AutocompleteController < ApplicationController
render json: projects.to_json(only: [:id, :name_with_namespace], methods: :name_with_namespace)
end
+ def award_emojis
+ emoji_with_count = AwardEmoji
+ .limit(AWARD_EMOJI_MAX)
+ .where(user: current_user)
+ .group(:name)
+ .order('count_all DESC, name ASC')
+ .count
+
+ # Transform from hash to array to guarantee json order
+ # e.g. { 'thumbsup' => 2, 'thumbsdown' = 1 }
+ # => [{ name: 'thumbsup' }, { name: 'thumbsdown' }]
+ render json: emoji_with_count.map { |k, v| { name: k } }
+ end
+
private
def find_users
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index b43b2c5621f..a34a82b7ba6 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -15,7 +15,17 @@ module IssuableCollections
end
def merge_requests_collection
- merge_requests_finder.execute.preload(:source_project, :target_project, :author, :assignee, :labels, :milestone, :head_pipeline, target_project: :namespace, merge_request_diff: :merge_request_diff_commits)
+ merge_requests_finder.execute.preload(
+ :source_project,
+ :target_project,
+ :author,
+ :assignee,
+ :labels,
+ :milestone,
+ head_pipeline: :project,
+ target_project: :namespace,
+ merge_request_diff: :merge_request_diff_commits
+ )
end
def issues_finder
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index 5c10d7bc261..7a7bcb1a3d2 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -35,13 +35,13 @@ class Groups::MilestonesController < Groups::ApplicationController
end
def edit
- render_404 if @milestone.is_legacy_group_milestone?
+ render_404 if @milestone.legacy_group_milestone?
end
def update
# Keep this compatible with legacy group milestones where we have to update
# all projects milestones states at once.
- if @milestone.is_legacy_group_milestone?
+ if @milestone.legacy_group_milestone?
update_params = milestone_params.select { |key| key == "state_event" }
milestones = @milestone.milestones
else
@@ -67,7 +67,7 @@ class Groups::MilestonesController < Groups::ApplicationController
end
def milestone_path
- if @milestone.is_legacy_group_milestone?
+ if @milestone.legacy_group_milestone?
group_milestone_path(group, @milestone.safe_title, title: @milestone.title)
else
group_milestone_path(group, @milestone.iid)
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 8893a514207..1afaceac567 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -202,7 +202,7 @@ class Projects::IssuesController < Projects::ApplicationController
task_status: @issue.task_status
}
- if @issue.is_edited?
+ if @issue.edited?
response[:updated_at] = @issue.updated_at
response[:updated_by_name] = @issue.last_edited_by.name
response[:updated_by_path] = user_path(@issue.last_edited_by)
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 08a843ada97..7e0d3b5c979 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -18,6 +18,7 @@
# sort: string
# non_archived: boolean
# iids: integer[]
+# my_reaction_emoji: string
#
class IssuableFinder
include CreatedAtFilter
@@ -46,6 +47,7 @@ class IssuableFinder
items = by_iids(items)
items = by_milestone(items)
items = by_label(items)
+ items = by_my_reaction_emoji(items)
# Filtering by project HAS TO be the last because we use the project IDs yielded by the issuable query thus far
items = by_project(items)
@@ -371,6 +373,14 @@ class IssuableFinder
items
end
+ def by_my_reaction_emoji(items)
+ if params[:my_reaction_emoji].present? && current_user
+ items = items.awarded(current_user, params[:my_reaction_emoji])
+ end
+
+ items
+ end
+
def by_due_date(items)
if due_date?
if filter_by_no_due_date?
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index def71587b81..91655c69903 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -178,7 +178,7 @@ module ApplicationHelper
end
def edited_time_ago_with_tooltip(object, placement: 'top', html_class: 'time_ago', exclude_author: false)
- return unless object.is_edited?
+ return unless object.edited?
content_tag :small, class: 'edited-text' do
output = content_tag(:span, 'Edited ')
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 197c90c4081..2a748ce0a75 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -229,7 +229,7 @@ module IssuablesHelper
end
def updated_at_by(issuable)
- return {} unless issuable.is_edited?
+ return {} unless issuable.edited?
{
updatedAt: issuable.updated_at.to_time.iso8601,
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 86666022a2a..446a59030a6 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -164,7 +164,7 @@ module MilestonesHelper
def group_milestone_route(milestone, params = {})
params = nil if params.empty?
- if milestone.is_legacy_group_milestone?
+ if milestone.legacy_group_milestone?
group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: params)
else
group_milestone_path(@group, milestone.iid, milestone: params)
diff --git a/app/helpers/milestones_routing_helper.rb b/app/helpers/milestones_routing_helper.rb
index 766d5262018..a0b2616f224 100644
--- a/app/helpers/milestones_routing_helper.rb
+++ b/app/helpers/milestones_routing_helper.rb
@@ -1,16 +1,16 @@
module MilestonesRoutingHelper
def milestone_path(milestone, *args)
- if milestone.is_group_milestone?
+ if milestone.group_milestone?
group_milestone_path(milestone.group, milestone, *args)
- elsif milestone.is_project_milestone?
+ elsif milestone.project_milestone?
project_milestone_path(milestone.project, milestone, *args)
end
end
def milestone_url(milestone, *args)
- if milestone.is_group_milestone?
+ if milestone.group_milestone?
group_milestone_url(milestone.group, milestone, *args)
- elsif milestone.is_project_milestone?
+ elsif milestone.project_milestone?
project_milestone_url(milestone.project, milestone, *args)
end
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index c6d23898560..906a76ec560 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -142,7 +142,7 @@ module Ci
expire: RUNNER_QUEUE_EXPIRY_TIME, overwrite: false)
end
- def is_runner_queue_value_latest?(value)
+ def runner_queue_value_latest?(value)
ensure_runner_queue_value == value if value.present?
end
diff --git a/app/models/concerns/awardable.rb b/app/models/concerns/awardable.rb
index f4f9b037957..9adc309a22b 100644
--- a/app/models/concerns/awardable.rb
+++ b/app/models/concerns/awardable.rb
@@ -11,6 +11,21 @@ module Awardable
end
module ClassMethods
+ def awarded(user, name)
+ sql = <<~EOL
+ EXISTS (
+ SELECT TRUE
+ FROM award_emoji
+ WHERE user_id = :user_id AND
+ name = :name AND
+ awardable_type = :awardable_type AND
+ awardable_id = #{self.arel_table.name}.id
+ )
+ EOL
+
+ where(sql, user_id: user.id, name: name, awardable_type: self.name)
+ end
+
def order_upvotes_desc
order_votes_desc(AwardEmoji::UPVOTE_NAME)
end
diff --git a/app/models/concerns/editable.rb b/app/models/concerns/editable.rb
index 28623d257a6..c0a3099f676 100644
--- a/app/models/concerns/editable.rb
+++ b/app/models/concerns/editable.rb
@@ -1,7 +1,7 @@
module Editable
extend ActiveSupport::Concern
- def is_edited?
+ def edited?
last_edited_at.present? && last_edited_at != created_at
end
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index f0998465822..710fc1ed647 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -70,19 +70,19 @@ module Milestoneish
due_date && due_date.past?
end
- def is_group_milestone?
+ def group_milestone?
false
end
- def is_project_milestone?
+ def project_milestone?
false
end
- def is_legacy_group_milestone?
+ def legacy_group_milestone?
false
end
- def is_dashboard_milestone?
+ def dashboard_milestone?
false
end
diff --git a/app/models/dashboard_milestone.rb b/app/models/dashboard_milestone.rb
index fac7c5e5c85..86eb4ec76fc 100644
--- a/app/models/dashboard_milestone.rb
+++ b/app/models/dashboard_milestone.rb
@@ -3,7 +3,7 @@ class DashboardMilestone < GlobalMilestone
{ authorized_only: true }
end
- def is_dashboard_milestone?
+ def dashboard_milestone?
true
end
end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 056c49e7162..7bcded5b5e1 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -49,7 +49,7 @@ class Deployment < ActiveRecord::Base
# created before then could have a `sha` referring to a commit that no
# longer exists in the repository, so just ignore those.
begin
- project.repository.is_ancestor?(commit.id, sha)
+ project.repository.ancestor?(commit.id, sha)
rescue Rugged::OdbError
false
end
diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb
index 65249bd7bfc..98135ee3c8b 100644
--- a/app/models/group_milestone.rb
+++ b/app/models/group_milestone.rb
@@ -17,7 +17,7 @@ class GroupMilestone < GlobalMilestone
{ group_id: group.id }
end
- def is_legacy_group_milestone?
+ def legacy_group_milestone?
true
end
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 01e0d0155a3..a3070a12b7c 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -163,7 +163,7 @@ class Milestone < ActiveRecord::Base
# Milestone.first.to_reference(same_namespace_project) # => "gitlab-ce%1"
#
def to_reference(from_project = nil, format: :iid, full: false)
- return if is_group_milestone? && format != :name
+ return if group_milestone? && format != :name
format_reference = milestone_format_reference(format)
reference = "#{self.class.reference_prefix}#{format_reference}"
@@ -207,11 +207,11 @@ class Milestone < ActiveRecord::Base
group || project
end
- def is_group_milestone?
+ def group_milestone?
group_id.present?
end
- def is_project_milestone?
+ def project_milestone?
project_id.present?
end
diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb
index 0e5acb22d50..3845e485413 100644
--- a/app/models/network/graph.rb
+++ b/app/models/network/graph.rb
@@ -152,14 +152,14 @@ module Network
end
def find_free_parent_space(range, space_base, space_step, space_default)
- if is_overlap?(range, space_default)
+ if overlap?(range, space_default)
find_free_space(range, space_step, space_base, space_default)
else
space_default
end
end
- def is_overlap?(range, overlap_space)
+ def overlap?(range, overlap_space)
range.each do |i|
if i != range.first &&
i != range.last &&
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
index 7b15a5dd04d..818cfb01b14 100644
--- a/app/models/project_services/chat_notification_service.rb
+++ b/app/models/project_services/chat_notification_service.rb
@@ -101,9 +101,9 @@ class ChatNotificationService < Service
when "push", "tag_push"
ChatMessage::PushMessage.new(data)
when "issue"
- ChatMessage::IssueMessage.new(data) unless is_update?(data)
+ ChatMessage::IssueMessage.new(data) unless update?(data)
when "merge_request"
- ChatMessage::MergeMessage.new(data) unless is_update?(data)
+ ChatMessage::MergeMessage.new(data) unless update?(data)
when "note"
ChatMessage::NoteMessage.new(data)
when "pipeline"
@@ -136,7 +136,7 @@ class ChatNotificationService < Service
project.web_url
end
- def is_update?(data)
+ def update?(data)
data[:object_attributes][:action] == 'update'
end
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index f422e0ea036..976d85246a8 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -85,9 +85,9 @@ class HipchatService < Service
when "push", "tag_push"
create_push_message(data)
when "issue"
- create_issue_message(data) unless is_update?(data)
+ create_issue_message(data) unless update?(data)
when "merge_request"
- create_merge_request_message(data) unless is_update?(data)
+ create_merge_request_message(data) unless update?(data)
when "note"
create_note_message(data)
when "pipeline"
@@ -282,7 +282,7 @@ class HipchatService < Service
"<a href=\"#{project_url}\">#{project_name}</a>"
end
- def is_update?(data)
+ def update?(data)
data[:object_attributes][:action] == 'update'
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 9fb2e2aa306..090e3c896bd 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -60,6 +60,10 @@ class Repository
@project = project
end
+ def ==(other)
+ @disk_path == other.disk_path
+ end
+
def raw_repository
return nil unless full_path
@@ -75,6 +79,10 @@ class Repository
)
end
+ def inspect
+ "#<#{self.class.name}:#{@disk_path}>"
+ end
+
#
# Git repository can contains some hidden refs like:
# /refs/notes/*
@@ -944,7 +952,7 @@ class Repository
if branch_commit
same_head = branch_commit.id == root_ref_commit.id
- !same_head && is_ancestor?(branch_commit.id, root_ref_commit.id)
+ !same_head && ancestor?(branch_commit.id, root_ref_commit.id)
else
nil
end
@@ -958,12 +966,12 @@ class Repository
nil
end
- def is_ancestor?(ancestor_id, descendant_id)
+ def ancestor?(ancestor_id, descendant_id)
return false if ancestor_id.nil? || descendant_id.nil?
Gitlab::GitalyClient.migrate(:is_ancestor) do |is_enabled|
if is_enabled
- raw_repository.is_ancestor?(ancestor_id, descendant_id)
+ raw_repository.ancestor?(ancestor_id, descendant_id)
else
rugged_is_ancestor?(ancestor_id, descendant_id)
end
@@ -992,25 +1000,22 @@ class Repository
end
def with_repo_branch_commit(start_repository, start_branch_name)
- return yield(nil) if start_repository.empty_repo?
+ return yield nil if start_repository.empty_repo?
- branch_name_or_sha =
- if start_repository == self
- start_branch_name
- else
- tmp_ref = fetch_ref(
- start_repository.path_to_repo,
- "#{Gitlab::Git::BRANCH_REF_PREFIX}#{start_branch_name}",
- "refs/tmp/#{SecureRandom.hex}/head"
- )
+ if start_repository == self
+ yield commit(start_branch_name)
+ else
+ sha = start_repository.commit(start_branch_name).sha
- start_repository.commit(start_branch_name).sha
+ if branch_commit = commit(sha)
+ yield branch_commit
+ else
+ with_repo_tmp_commit(
+ start_repository, start_branch_name, sha) do |tmp_commit|
+ yield tmp_commit
+ end
end
-
- yield(commit(branch_name_or_sha))
-
- ensure
- rugged.references.delete(tmp_ref) if tmp_ref
+ end
end
def add_remote(name, url)
@@ -1219,4 +1224,16 @@ class Repository
.commits_by_message(query, revision: ref, path: path, limit: limit, offset: offset)
.map { |c| commit(c) }
end
+
+ def with_repo_tmp_commit(start_repository, start_branch_name, sha)
+ tmp_ref = fetch_ref(
+ start_repository.path_to_repo,
+ "#{Gitlab::Git::BRANCH_REF_PREFIX}#{start_branch_name}",
+ "refs/tmp/#{SecureRandom.hex}/head"
+ )
+
+ yield commit(sha)
+ ensure
+ rugged.references.delete(tmp_ref) if tmp_ref
+ end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index fbd08bc4d0a..70787de4b40 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -5,6 +5,7 @@ class User < ActiveRecord::Base
include Gitlab::ConfigHelper
include Gitlab::CurrentSettings
+ include Gitlab::SQL::Pattern
include Avatarable
include Referable
include Sortable
@@ -303,7 +304,7 @@ class User < ActiveRecord::Base
# Returns an ActiveRecord::Relation.
def search(query)
table = arel_table
- pattern = "%#{query}%"
+ pattern = User.to_pattern(query)
order = <<~SQL
CASE
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 0133091db57..a925fac7d3e 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -17,13 +17,13 @@ class ProjectPolicy < BasePolicy
desc "Project has public builds enabled"
condition(:public_builds, scope: :subject) { project.public_builds? }
- # For guest access we use #is_team_member? so we can use
+ # For guest access we use #team_member? so we can use
# project.members, which gets cached in subject scope.
# This is safe because team_access_level is guaranteed
# by ProjectAuthorization's validation to be at minimum
# GUEST
desc "User has guest access"
- condition(:guest) { is_team_member? }
+ condition(:guest) { team_member? }
desc "User has reporter access"
condition(:reporter) { team_access_level >= Gitlab::Access::REPORTER }
@@ -293,7 +293,7 @@ class ProjectPolicy < BasePolicy
private
- def is_team_member?
+ def team_member?
return false if @user.nil?
greedy_load_subject = false
diff --git a/app/services/akismet_service.rb b/app/services/akismet_service.rb
index 59153cbbc0a..7b5482b3cd1 100644
--- a/app/services/akismet_service.rb
+++ b/app/services/akismet_service.rb
@@ -7,7 +7,7 @@ class AkismetService
@options = options
end
- def is_spam?
+ def spam?
return false unless akismet_enabled?
params = {
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index e81a56672e2..bb61136e33b 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -30,7 +30,7 @@ class GitPushService < BaseService
@project.repository.after_create_branch
# Re-find the pushed commits.
- if is_default_branch?
+ if default_branch?
# Initial push to the default branch. Take the full history of that branch as "newly pushed".
process_default_branch
else
@@ -50,7 +50,7 @@ class GitPushService < BaseService
# Update the bare repositories info/attributes file using the contents of the default branches
# .gitattributes file
- update_gitattributes if is_default_branch?
+ update_gitattributes if default_branch?
end
execute_related_hooks
@@ -66,7 +66,7 @@ class GitPushService < BaseService
end
def update_caches
- if is_default_branch?
+ if default_branch?
if push_to_new_branch?
# If this is the initial push into the default branch, the file type caches
# will already be reset as a result of `Project#change_head`.
@@ -108,7 +108,7 @@ class GitPushService < BaseService
# Schedules processing of commit messages.
def process_commit_messages
- default = is_default_branch?
+ default = default_branch?
@push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit|
if commit.matches_cross_reference_regex?
@@ -202,7 +202,7 @@ class GitPushService < BaseService
Gitlab::Git.branch_ref?(params[:ref])
end
- def is_default_branch?
+ def default_branch?
Gitlab::Git.branch_ref?(params[:ref]) &&
(Gitlab::Git.ref_name(params[:ref]) == project.default_branch || project.default_branch.nil?)
end
diff --git a/app/services/milestones/close_service.rb b/app/services/milestones/close_service.rb
index 776ec4b287b..5b06c4b601d 100644
--- a/app/services/milestones/close_service.rb
+++ b/app/services/milestones/close_service.rb
@@ -1,7 +1,7 @@
module Milestones
class CloseService < Milestones::BaseService
def execute(milestone)
- if milestone.close && milestone.is_project_milestone?
+ if milestone.close && milestone.project_milestone?
event_service.close_milestone(milestone, current_user)
end
diff --git a/app/services/milestones/create_service.rb b/app/services/milestones/create_service.rb
index aef3124c7e3..ed2e833d833 100644
--- a/app/services/milestones/create_service.rb
+++ b/app/services/milestones/create_service.rb
@@ -3,7 +3,7 @@ module Milestones
def execute
milestone = parent.milestones.new(params)
- if milestone.save && milestone.is_project_milestone?
+ if milestone.save && milestone.project_milestone?
event_service.open_milestone(milestone, current_user)
end
diff --git a/app/services/milestones/destroy_service.rb b/app/services/milestones/destroy_service.rb
index 600ebcfbecb..b18651476a8 100644
--- a/app/services/milestones/destroy_service.rb
+++ b/app/services/milestones/destroy_service.rb
@@ -1,7 +1,7 @@
module Milestones
class DestroyService < Milestones::BaseService
def execute(milestone)
- return unless milestone.is_project_milestone?
+ return unless milestone.project_milestone?
Milestone.transaction do
update_params = { milestone: nil }
diff --git a/app/services/milestones/reopen_service.rb b/app/services/milestones/reopen_service.rb
index 5b8b682caaf..3efb33157c5 100644
--- a/app/services/milestones/reopen_service.rb
+++ b/app/services/milestones/reopen_service.rb
@@ -1,7 +1,7 @@
module Milestones
class ReopenService < Milestones::BaseService
def execute(milestone)
- if milestone.activate && milestone.is_project_milestone?
+ if milestone.activate && milestone.project_milestone?
event_service.reopen_milestone(milestone, current_user)
end
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index a0cd52014a2..71533da31b1 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -44,6 +44,8 @@ module Projects
@project.namespace_id = current_user.namespace_id
end
+ yield(@project) if block_given?
+
@project.creator = current_user
if forked_from_project_id
diff --git a/app/services/spam_service.rb b/app/services/spam_service.rb
index 3e65b7d31a3..73ea3018fbd 100644
--- a/app/services/spam_service.rb
+++ b/app/services/spam_service.rb
@@ -45,7 +45,7 @@ class SpamService
def check(api)
return false unless request && check_for_spam?
- return false unless akismet.is_spam?
+ return false unless akismet.spam?
create_spam_log(api)
true
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 1763f64a4e4..1f66a2668f9 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -142,7 +142,7 @@ module SystemNoteService
#
# Returns the created Note object
def change_milestone(noteable, project, author, milestone)
- format = milestone&.is_group_milestone? ? :name : :iid
+ format = milestone&.group_milestone? ? :name : :iid
body = milestone.nil? ? 'removed milestone' : "changed milestone to #{milestone.to_reference(project, format: format)}"
create_note(NoteSummary.new(noteable, project, author, body, action: 'milestone'))
diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml
index 54b1b7a734a..23b1a22240f 100644
--- a/app/views/groups/milestones/show.html.haml
+++ b/app/views/groups/milestones/show.html.haml
@@ -1,4 +1,4 @@
= render "header_title"
= render 'shared/milestones/top', milestone: @milestone, group: @group
-= render 'shared/milestones/tabs', milestone: @milestone, show_project_name: true if @milestone.is_legacy_group_milestone?
+= render 'shared/milestones/tabs', milestone: @milestone, show_project_name: true if @milestone.legacy_group_milestone?
= render 'shared/milestones/sidebar', milestone: @milestone, affix_offset: 102
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index 4db84771f4e..653452871a0 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -1,8 +1,9 @@
- breadcrumb_link = breadcrumb_title_link
+- container = @no_breadcrumb_container ? 'container-fluid' : container_class
- hide_top_links = @hide_top_links || false
%nav.breadcrumbs{ role: "navigation" }
- .breadcrumbs-container{ class: [container_class, @content_class] }
+ .breadcrumbs-container{ class: [container, @content_class] }
- if defined?(@new_sidebar)
= button_tag class: 'toggle-mobile-nav', type: 'button' do
%span.sr-only Open sidebar
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 720a97cddb7..8dbb8aef31b 100644
--- a/app/views/profiles/gpg_keys/index.html.haml
+++ b/app/views/profiles/gpg_keys/index.html.haml
@@ -12,7 +12,7 @@
Add a GPG key
%p.profile-settings-content
Before you can add a GPG key you need to
- = link_to 'generate it.', help_page_path('user/project/gpg_signed_commits/index.md')
+ = link_to 'generate it.', help_page_path('user/project/repository/gpg_signed_commits/index.md')
= render 'form'
%hr
%h5
diff --git a/app/views/projects/boards/_show.html.haml b/app/views/projects/boards/_show.html.haml
index 2076e46fde8..5354ec8522e 100644
--- a/app/views/projects/boards/_show.html.haml
+++ b/app/views/projects/boards/_show.html.haml
@@ -1,3 +1,4 @@
+- @no_breadcrumb_container = true
- @no_container = true
- @content_class = "issue-boards-content"
- page_title "Boards"
diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml
index a3783b31b86..d06b29db838 100644
--- a/app/views/projects/commit/_signature_badge.html.haml
+++ b/app/views/projects/commit/_signature_badge.html.haml
@@ -12,7 +12,7 @@
%span.monospace= signature.gpg_key_primary_keyid
- = link_to('Learn more about signing commits', help_page_path('user/project/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
+ = link_to('Learn more about signing commits', help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
%button{ class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } }
= label
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index f63b9698408..e81789ea7a2 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -93,6 +93,13 @@
%span.dropdown-label-box{ style: 'background: {{color}}' }
%span.label-title.js-data-value
{{title}}
+ #js-dropdown-my-reaction.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ %button.btn.btn-link
+ %gl-emoji
+ %span.js-data-value.prepend-left-10
+ {{name}}
%button.clear-search.hidden{ type: 'button' }
= icon('times')
.filter-dropdown-container
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index 6a85f7d0564..305e2542281 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -5,7 +5,7 @@
.row
.col-sm-6
%strong= link_to truncate(milestone.title, length: 100), milestone_path
- - if milestone.is_group_milestone?
+ - if milestone.group_milestone?
%span - Group Milestone
- else
%span - Project Milestone
@@ -18,10 +18,10 @@
&middot;
= link_to pluralize(milestone.merge_requests.size, 'Merge Request'), merge_requests_path
.col-sm-6= milestone_progress_bar(milestone)
- - if milestone.is_a?(GlobalMilestone) || milestone.is_group_milestone?
+ - if milestone.is_a?(GlobalMilestone) || milestone.group_milestone?
.row
.col-sm-6
- - if milestone.is_legacy_group_milestone?
+ - if milestone.legacy_group_milestone?
.expiration= render('shared/milestone_expired', milestone: milestone)
.projects
- milestone.milestones.each do |milestone|
@@ -31,7 +31,7 @@
- if @group
.col-sm-6.milestone-actions
- if can?(current_user, :admin_milestones, @group)
- - if milestone.is_group_milestone?
+ - if milestone.group_milestone?
= link_to edit_group_milestone_path(@group, milestone), class: "btn btn-xs btn-grouped" do
Edit
\
diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml
index 3014300fbe7..fd0760d83a5 100644
--- a/app/views/shared/milestones/_top.html.haml
+++ b/app/views/shared/milestones/_top.html.haml
@@ -22,7 +22,7 @@
- if group
.pull-right
- if can?(current_user, :admin_milestones, group)
- - if milestone.is_group_milestone?
+ - if milestone.group_milestone?
= link_to edit_group_milestone_path(group, milestone), class: "btn btn btn-grouped" do
Edit
- if milestone.active?
@@ -33,7 +33,7 @@
.detail-page-description.milestone-detail
%h2.title
= markdown_field(milestone, :title)
- - if @milestone.is_group_milestone? && @milestone.description.present?
+ - if @milestone.group_milestone? && @milestone.description.present?
%div
.description
.wiki
@@ -44,7 +44,7 @@
- close_msg = group ? 'You may close the milestone now.' : 'Navigate to the project to close the milestone.'
%span All issues for this milestone are closed. #{close_msg}
-- if @milestone.is_legacy_group_milestone? || @milestone.is_dashboard_milestone?
+- if @milestone.legacy_group_milestone? || @milestone.dashboard_milestone?
.table-holder
%table.table
%thead
@@ -67,7 +67,7 @@
Open
%td
= ms.expires_at
-- elsif @milestone.is_group_milestone?
+- elsif @milestone.group_milestone?
%br
View
= link_to 'Issues', issues_group_path(@group, milestone_title: milestone.title)