diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-11 03:06:24 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-11 03:06:24 +0300 |
commit | 133924c6cc443f5f69e1ab08d43b363d77677cb0 (patch) | |
tree | e893a7d36105fc4acec7038feae5f03bd34cfc2c /app | |
parent | f607152a0802a68067343ad73f989033cb8e9a06 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--[-rwxr-xr-x] | app/assets/images/ci_favicons/favicon_status_preparing.png | bin | 11341 -> 11341 bytes | |||
-rw-r--r-- | app/assets/javascripts/boards/components/issue_card_inner.vue | 10 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/url_utility.js | 8 | ||||
-rw-r--r-- | app/assets/javascripts/notes/components/discussion_filter.vue | 8 | ||||
-rw-r--r-- | app/assets/javascripts/notes/components/notes_app.vue | 27 | ||||
-rw-r--r-- | app/assets/javascripts/notes/constants.js | 3 | ||||
-rw-r--r-- | app/helpers/tags_helper.rb | 10 | ||||
-rw-r--r-- | app/models/project_services/slash_commands_service.rb | 7 | ||||
-rw-r--r-- | app/policies/global_policy.rb | 1 | ||||
-rw-r--r-- | app/views/admin/users/_user_deactivation_effects.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/tags/new.html.haml | 2 | ||||
-rw-r--r-- | app/workers/prune_old_events_worker.rb | 4 |
12 files changed, 61 insertions, 21 deletions
diff --git a/app/assets/images/ci_favicons/favicon_status_preparing.png b/app/assets/images/ci_favicons/favicon_status_preparing.png Binary files differindex f81baa0ece3..f81baa0ece3 100755..100644 --- a/app/assets/images/ci_favicons/favicon_status_preparing.png +++ b/app/assets/images/ci_favicons/favicon_status_preparing.png diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue index 1d53a21c8ac..40d75d53f75 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.vue +++ b/app/assets/javascripts/boards/components/issue_card_inner.vue @@ -99,7 +99,10 @@ export default { return !groupId ? referencePath.split('#')[0] : null; }, orderedLabels() { - return _.sortBy(this.issue.labels, 'title'); + return _.chain(this.issue.labels) + .filter(this.isNonListLabel) + .sortBy('title') + .value(); }, helpLink() { return boardsStore.scopedLabels.helpLink; @@ -130,6 +133,9 @@ export default { if (!label.id) return false; return true; }, + isNonListLabel(label) { + return label.id && !(this.list.type === 'label' && this.list.title === label.title); + }, filterByLabel(label) { if (!this.updateFilters) return; const labelTitle = encodeURIComponent(label.title); @@ -167,7 +173,7 @@ export default { </h4> </div> <div v-if="showLabelFooter" class="board-card-labels prepend-top-4 d-flex flex-wrap"> - <template v-for="label in orderedLabels" v-if="showLabel(label)"> + <template v-for="label in orderedLabels"> <issue-card-inner-scoped-label v-if="showScopedLabel(label)" :key="label.id" diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js index 7ead9d46fbb..4be0d05a9b7 100644 --- a/app/assets/javascripts/lib/utils/url_utility.js +++ b/app/assets/javascripts/lib/utils/url_utility.js @@ -88,6 +88,14 @@ export function getLocationHash(url = window.location.href) { } /** + * Returns a boolean indicating whether the URL hash contains the given string value + */ +export function doesHashExistInUrl(hashName) { + const hash = getLocationHash(); + return hash && hash.includes(hashName); +} + +/** * Apply the fragment to the given url by returning a new url string that includes * the fragment. If the given url already contains a fragment, the original fragment * will be removed. diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue index 743684e7046..6b1e3298f9a 100644 --- a/app/assets/javascripts/notes/components/discussion_filter.vue +++ b/app/assets/javascripts/notes/components/discussion_filter.vue @@ -1,13 +1,14 @@ <script> import $ from 'jquery'; import { mapGetters, mapActions } from 'vuex'; -import { getLocationHash } from '../../lib/utils/url_utility'; +import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility'; import Icon from '~/vue_shared/components/icon.vue'; import { DISCUSSION_FILTERS_DEFAULT_VALUE, HISTORY_ONLY_FILTER_VALUE, DISCUSSION_TAB_LABEL, DISCUSSION_FILTER_TYPES, + NOTE_UNDERSCORE, } from '../constants'; import notesEventHub from '../event_hub'; @@ -28,7 +29,9 @@ export default { }, data() { return { - currentValue: this.selectedValue, + currentValue: doesHashExistInUrl(NOTE_UNDERSCORE) + ? DISCUSSION_FILTERS_DEFAULT_VALUE + : this.selectedValue, defaultValue: DISCUSSION_FILTERS_DEFAULT_VALUE, displayFilters: true, }; @@ -50,7 +53,6 @@ export default { notesEventHub.$on('dropdownSelect', this.selectFilter); window.addEventListener('hashchange', this.handleLocationHash); - this.handleLocationHash(); }, mounted() { this.toggleCommentsForm(); diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index fd592e965bf..c6c97489e5e 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -1,7 +1,7 @@ <script> import { __ } from '~/locale'; import { mapGetters, mapActions } from 'vuex'; -import { getLocationHash } from '../../lib/utils/url_utility'; +import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility'; import Flash from '../../flash'; import * as constants from '../constants'; import eventHub from '../event_hub'; @@ -156,19 +156,17 @@ export default { this.isFetching = true; - return this.fetchDiscussions({ path: this.getNotesDataByProp('discussionsPath') }) - .then(() => { - this.initPolling(); - }) + return this.fetchDiscussions(this.getFetchDiscussionsConfig()) + .then(this.initPolling) .then(() => { this.setLoadingState(false); this.setNotesFetchedState(true); eventHub.$emit('fetchedNotesData'); this.isFetching = false; }) - .then(() => this.$nextTick()) - .then(() => this.startTaskList()) - .then(() => this.checkLocationHash()) + .then(this.$nextTick) + .then(this.startTaskList) + .then(this.checkLocationHash) .catch(() => { this.setLoadingState(false); this.setNotesFetchedState(true); @@ -199,9 +197,20 @@ export default { }, startReplying(discussionId) { return this.convertToDiscussion(discussionId) - .then(() => this.$nextTick()) + .then(this.$nextTick) .then(() => eventHub.$emit('startReplying', discussionId)); }, + getFetchDiscussionsConfig() { + const defaultConfig = { path: this.getNotesDataByProp('discussionsPath') }; + + if (doesHashExistInUrl(constants.NOTE_UNDERSCORE)) { + return Object.assign({}, defaultConfig, { + filter: constants.DISCUSSION_FILTERS_DEFAULT_VALUE, + persistFilter: false, + }); + } + return defaultConfig; + }, }, systemNote: constants.SYSTEM_NOTE, }; diff --git a/app/assets/javascripts/notes/constants.js b/app/assets/javascripts/notes/constants.js index bdfb6b8f105..68c117183a1 100644 --- a/app/assets/javascripts/notes/constants.js +++ b/app/assets/javascripts/notes/constants.js @@ -8,8 +8,6 @@ export const OPENED = 'opened'; export const REOPENED = 'reopened'; export const CLOSED = 'closed'; export const MERGED = 'merged'; -export const EMOJI_THUMBSUP = 'thumbsup'; -export const EMOJI_THUMBSDOWN = 'thumbsdown'; export const ISSUE_NOTEABLE_TYPE = 'issue'; export const EPIC_NOTEABLE_TYPE = 'epic'; export const MERGE_REQUEST_NOTEABLE_TYPE = 'MergeRequest'; @@ -19,6 +17,7 @@ export const DESCRIPTION_TYPE = 'changed the description'; export const HISTORY_ONLY_FILTER_VALUE = 2; export const DISCUSSION_FILTERS_DEFAULT_VALUE = 0; export const DISCUSSION_TAB_LABEL = 'show'; +export const NOTE_UNDERSCORE = 'note_'; export const NOTEABLE_TYPE_MAPPING = { Issue: ISSUE_NOTEABLE_TYPE, diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb index de0b92b6fd7..4984b51555d 100644 --- a/app/helpers/tags_helper.rb +++ b/app/helpers/tags_helper.rb @@ -28,4 +28,14 @@ module TagsHelper def protected_tag?(project, tag) ProtectedTag.protected?(project, tag.name) end + + def tag_description_help_text + text = s_('TagsPage|Optionally, add a message to the tag. Leaving this blank creates '\ + 'a %{link_start}lightweight tag.%{link_end}') % { + link_start: '<a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging\" target="_blank" rel="noopener noreferrer">', + link_end: '</a>' + } + + text.html_safe + end end diff --git a/app/models/project_services/slash_commands_service.rb b/app/models/project_services/slash_commands_service.rb index 5bfd06476f0..d436176a52c 100644 --- a/app/models/project_services/slash_commands_service.rb +++ b/app/models/project_services/slash_commands_service.rb @@ -33,9 +33,12 @@ class SlashCommandsService < Service return unless valid_token?(params[:token]) chat_user = find_chat_user(params) + user = chat_user&.user + + if user + unless user.can?(:use_slash_commands) + return Gitlab::SlashCommands::Presenters::Access.new.deactivated if user.deactivated? - if chat_user&.user - unless chat_user.user.can?(:use_slash_commands) return Gitlab::SlashCommands::Presenters::Access.new.access_denied(project) end diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb index 4d66a9e7d67..eca73f0a241 100644 --- a/app/policies/global_policy.rb +++ b/app/policies/global_policy.rb @@ -48,6 +48,7 @@ class GlobalPolicy < BasePolicy prevent :access_git prevent :access_api prevent :receive_notifications + prevent :use_slash_commands end rule { required_terms_not_accepted }.policy do diff --git a/app/views/admin/users/_user_deactivation_effects.html.haml b/app/views/admin/users/_user_deactivation_effects.html.haml index 6cc47214d77..dc3896e18c0 100644 --- a/app/views/admin/users/_user_deactivation_effects.html.haml +++ b/app/views/admin/users/_user_deactivation_effects.html.haml @@ -10,6 +10,8 @@ %li = s_('AdminUsers|The user will not receive any notifications') %li + = s_('AdminUsers|The user will not be able to use slash commands') + %li = s_('AdminUsers|When the user logs back in, their account will reactivate as a fully active account') %li = s_('AdminUsers|Personal projects, group and user history will be left intact') diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index 5e6d06d980e..a7f739ab13d 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -31,7 +31,7 @@ .col-sm-10 = text_area_tag :message, @message, required: false, class: 'form-control', rows: 5 .form-text.text-muted - = s_('TagsPage|Optionally, add a message to the tag.') + = tag_description_help_text %hr .form-group.row = label_tag :release_description, s_('TagsPage|Release notes'), class: 'col-form-label col-sm-2' diff --git a/app/workers/prune_old_events_worker.rb b/app/workers/prune_old_events_worker.rb index dc4b7670131..e2d1fb3ed35 100644 --- a/app/workers/prune_old_events_worker.rb +++ b/app/workers/prune_old_events_worker.rb @@ -6,13 +6,13 @@ class PruneOldEventsWorker # rubocop: disable CodeReuse/ActiveRecord def perform - # Contribution calendar shows maximum 12 months of events, we retain 2 years for data integrity. + # Contribution calendar shows maximum 12 months of events, we retain 3 years for data integrity. # Double nested query is used because MySQL doesn't allow DELETE subqueries on the same table. Event.unscoped.where( '(id IN (SELECT id FROM (?) ids_to_remove))', Event.unscoped.where( 'created_at < ?', - (2.years + 1.day).ago) + (3.years + 1.day).ago) .select(:id) .limit(10_000)) .delete_all |