diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-07 21:13:36 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-07 21:13:36 +0000 |
commit | c19944d9970b788d8523cee6ee05217a8afd7646 (patch) | |
tree | e2d15e8c0d541b9b2fe26b9b82f23661df120f94 /app | |
parent | 3ff3d897d6529aabb21aa6aed54eb430a9cf0fe2 (diff) | |
download | gitlab-ce-c19944d9970b788d8523cee6ee05217a8afd7646.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
41 files changed, 135 insertions, 63 deletions
diff --git a/app/assets/javascripts/authentication/webauthn/authenticate.js b/app/assets/javascripts/authentication/webauthn/authenticate.js index 47cb7a40f76..748945a680b 100644 --- a/app/assets/javascripts/authentication/webauthn/authenticate.js +++ b/app/assets/javascripts/authentication/webauthn/authenticate.js @@ -1,3 +1,4 @@ +import { WEBAUTHN_AUTHENTICATE } from './constants'; import WebAuthnError from './error'; import WebAuthnFlow from './flow'; import { supported, convertGetParams, convertGetResponse } from './util'; @@ -44,7 +45,7 @@ export default class WebAuthnAuthenticate { this.renderAuthenticated(JSON.stringify(convertedResponse)); }) .catch((err) => { - this.flow.renderError(new WebAuthnError(err, 'authenticate')); + this.flow.renderError(new WebAuthnError(err, WEBAUTHN_AUTHENTICATE)); }); } diff --git a/app/assets/javascripts/authentication/webauthn/components/registration.vue b/app/assets/javascripts/authentication/webauthn/components/registration.vue index 1cc57046562..9a3644e0325 100644 --- a/app/assets/javascripts/authentication/webauthn/components/registration.vue +++ b/app/assets/javascripts/authentication/webauthn/components/registration.vue @@ -30,10 +30,10 @@ import { STATE_UNSUPPORTED, STATE_WAITING, WEBAUTHN_DOCUMENTATION_PATH, + WEBAUTHN_REGISTER, } from '~/authentication/webauthn/constants'; import WebAuthnError from '~/authentication/webauthn/error'; import { - FLOW_REGISTER, convertCreateParams, convertCreateResponse, isHTTPS, @@ -123,7 +123,7 @@ export default { this.credentials = JSON.stringify(convertCreateResponse(credentials)); this.state = STATE_SUCCESS; } catch (error) { - this.errorMessage = new WebAuthnError(error, FLOW_REGISTER).message(); + this.errorMessage = new WebAuthnError(error, WEBAUTHN_REGISTER).message(); this.state = STATE_ERROR; } }, diff --git a/app/assets/javascripts/authentication/webauthn/constants.js b/app/assets/javascripts/authentication/webauthn/constants.js index 6646cb2eb3f..c41e6d2bd58 100644 --- a/app/assets/javascripts/authentication/webauthn/constants.js +++ b/app/assets/javascripts/authentication/webauthn/constants.js @@ -38,6 +38,8 @@ export const STATE_SUCCESS = 'success'; export const STATE_UNSUPPORTED = 'unsupported'; export const STATE_WAITING = 'waiting'; +export const WEBAUTHN_AUTHENTICATE = 'authenticate'; +export const WEBAUTHN_REGISTER = 'register'; export const WEBAUTHN_DOCUMENTATION_PATH = helpPagePath( 'user/profile/account/two_factor_authentication', { anchor: 'set-up-a-webauthn-device' }, diff --git a/app/assets/javascripts/authentication/webauthn/error.js b/app/assets/javascripts/authentication/webauthn/error.js index a1a3f861c25..40dbecd8bc9 100644 --- a/app/assets/javascripts/authentication/webauthn/error.js +++ b/app/assets/javascripts/authentication/webauthn/error.js @@ -1,5 +1,6 @@ import { __ } from '~/locale'; -import { isHTTPS, FLOW_AUTHENTICATE, FLOW_REGISTER } from './util'; +import { WEBAUTHN_AUTHENTICATE, WEBAUTHN_REGISTER } from './constants'; +import { isHTTPS } from './util'; export default class WebAuthnError { constructor(error, flowType) { @@ -13,9 +14,9 @@ export default class WebAuthnError { message() { if (this.errorName === 'NotSupportedError') { return __('Your device is not compatible with GitLab. Please try another device'); - } else if (this.errorName === 'InvalidStateError' && this.flowType === FLOW_AUTHENTICATE) { + } else if (this.errorName === 'InvalidStateError' && this.flowType === WEBAUTHN_AUTHENTICATE) { return __('This device has not been registered with us.'); - } else if (this.errorName === 'InvalidStateError' && this.flowType === FLOW_REGISTER) { + } else if (this.errorName === 'InvalidStateError' && this.flowType === WEBAUTHN_REGISTER) { return __('This device has already been registered with us.'); } else if (this.errorName === 'SecurityError' && this.httpsDisabled) { return __( diff --git a/app/assets/javascripts/authentication/webauthn/register.js b/app/assets/javascripts/authentication/webauthn/register.js index 62ebf85abe4..c00d3ede2c1 100644 --- a/app/assets/javascripts/authentication/webauthn/register.js +++ b/app/assets/javascripts/authentication/webauthn/register.js @@ -2,6 +2,7 @@ import { __ } from '~/locale'; import WebAuthnError from './error'; import WebAuthnFlow from './flow'; import { supported, isHTTPS, convertCreateParams, convertCreateResponse } from './util'; +import { WEBAUTHN_REGISTER } from './constants'; // Register WebAuthn devices for users to authenticate with. // @@ -40,7 +41,7 @@ export default class WebAuthnRegister { publicKey: this.webauthnOptions, }) .then((cred) => this.renderRegistered(JSON.stringify(convertCreateResponse(cred)))) - .catch((err) => this.flow.renderError(new WebAuthnError(err, 'register'))); + .catch((err) => this.flow.renderError(new WebAuthnError(err, WEBAUTHN_REGISTER))); } renderSetup() { diff --git a/app/assets/javascripts/authentication/webauthn/util.js b/app/assets/javascripts/authentication/webauthn/util.js index 4e1409b9ed9..0ff0f0e6a29 100644 --- a/app/assets/javascripts/authentication/webauthn/util.js +++ b/app/assets/javascripts/authentication/webauthn/util.js @@ -8,9 +8,6 @@ export function isHTTPS() { return window.location.protocol.startsWith('https'); } -export const FLOW_AUTHENTICATE = 'authenticate'; -export const FLOW_REGISTER = 'register'; - /** * Converts a base64 string to an ArrayBuffer * diff --git a/app/assets/javascripts/issues/create_merge_request_dropdown.js b/app/assets/javascripts/issues/create_merge_request_dropdown.js index caf82e482ea..c821c18bcb9 100644 --- a/app/assets/javascripts/issues/create_merge_request_dropdown.js +++ b/app/assets/javascripts/issues/create_merge_request_dropdown.js @@ -7,7 +7,7 @@ import { import confidentialMergeRequestState from '~/confidential_merge_request/state'; import DropLab from '~/filtered_search/droplab/drop_lab_deprecated'; import ISetter from '~/filtered_search/droplab/plugins/input_setter'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { __, sprintf } from '~/locale'; import { mergeUrlParams } from '~/lib/utils/url_utility'; diff --git a/app/assets/javascripts/issues/issue.js b/app/assets/javascripts/issues/issue.js index de1c689e590..b7fd99d8042 100644 --- a/app/assets/javascripts/issues/issue.js +++ b/app/assets/javascripts/issues/issue.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import { joinPaths } from '~/lib/utils/url_utility'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants'; import axios from '~/lib/utils/axios_utils'; import { addDelimiter } from '~/lib/utils/text_utility'; diff --git a/app/assets/javascripts/issues/list/components/issues_list_app.vue b/app/assets/javascripts/issues/list/components/issues_list_app.vue index 35727566fba..f03ecdc4125 100644 --- a/app/assets/javascripts/issues/list/components/issues_list_app.vue +++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue @@ -7,7 +7,7 @@ import IssueCardStatistics from 'ee_else_ce/issues/list/components/issue_card_st import IssueCardTimeInfo from 'ee_else_ce/issues/list/components/issue_card_time_info.vue'; import getIssuesQuery from 'ee_else_ce/issues/list/queries/get_issues.query.graphql'; import getIssuesCountsQuery from 'ee_else_ce/issues/list/queries/get_issues_counts.query.graphql'; -import { createAlert, VARIANT_INFO } from '~/flash'; +import { createAlert, VARIANT_INFO } from '~/alert'; import { TYPENAME_USER } from '~/graphql_shared/constants'; import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils'; import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue'; diff --git a/app/assets/javascripts/issues/manual_ordering.js b/app/assets/javascripts/issues/manual_ordering.js index 1bb53dfd50d..f22062cf048 100644 --- a/app/assets/javascripts/issues/manual_ordering.js +++ b/app/assets/javascripts/issues/manual_ordering.js @@ -1,5 +1,5 @@ import Sortable from 'sortablejs'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { s__ } from '~/locale'; import { getSortableDefaultOptions, sortableStart } from '~/sortable/utils'; diff --git a/app/assets/javascripts/issues/related_merge_requests/store/actions.js b/app/assets/javascripts/issues/related_merge_requests/store/actions.js index 4c81f1d9bc1..ad5b61424dc 100644 --- a/app/assets/javascripts/issues/related_merge_requests/store/actions.js +++ b/app/assets/javascripts/issues/related_merge_requests/store/actions.js @@ -1,4 +1,4 @@ -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { normalizeHeaders } from '~/lib/utils/common_utils'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/issues/show/components/app.vue b/app/assets/javascripts/issues/show/components/app.vue index 0be11c5c537..851808b628e 100644 --- a/app/assets/javascripts/issues/show/components/app.vue +++ b/app/assets/javascripts/issues/show/components/app.vue @@ -1,7 +1,7 @@ <script> import { GlIcon, GlBadge, GlIntersectionObserver, GlTooltipDirective } from '@gitlab/ui'; import Visibility from 'visibilityjs'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { IssuableStatusText, STATUS_CLOSED, @@ -277,7 +277,7 @@ export default { }, }, created() { - this.flashContainer = null; + this.alert = null; this.service = new Service(this.endpoint); this.poll = new Poll({ resource: this.service, @@ -395,7 +395,7 @@ export default { ? { ...formState, issue_type: issueState.issueType } : formState; - this.clearFlash(); + this.alert?.dismiss(); return this.service .updateIssuable(issuablePayload) @@ -431,7 +431,7 @@ export default { errMsg += `. ${message}`; } - this.flashContainer = createAlert({ + this.alert = createAlert({ message: errMsg, }); }) @@ -448,13 +448,6 @@ export default { this.isStickyHeaderShowing = true; }, - clearFlash() { - if (this.flashContainer) { - this.flashContainer.close(); - this.flashContainer = null; - } - }, - handleSaveDescription(description) { this.updateFormState(); this.setFormState({ description }); diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue index b36a456f41b..6e072e12bd9 100644 --- a/app/assets/javascripts/issues/show/components/description.vue +++ b/app/assets/javascripts/issues/show/components/description.vue @@ -7,7 +7,7 @@ import getIssueDetailsQuery from 'ee_else_ce/work_items/graphql/get_issue_detail import SafeHtml from '~/vue_shared/directives/safe_html'; import { convertToGraphQLId } from '~/graphql_shared/utils'; import { TYPENAME_ISSUE, TYPENAME_WORK_ITEM } from '~/graphql_shared/constants'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { TYPE_ISSUE } from '~/issues/constants'; import { __, s__, sprintf } from '~/locale'; import { getSortableDefaultOptions, isDragging } from '~/sortable/utils'; diff --git a/app/assets/javascripts/issues/show/components/header_actions.vue b/app/assets/javascripts/issues/show/components/header_actions.vue index d77cb1fa1c2..ba986bd0020 100644 --- a/app/assets/javascripts/issues/show/components/header_actions.vue +++ b/app/assets/javascripts/issues/show/components/header_actions.vue @@ -10,7 +10,7 @@ import { GlTooltipDirective, } from '@gitlab/ui'; import { mapActions, mapGetters, mapState } from 'vuex'; -import { createAlert, VARIANT_SUCCESS } from '~/flash'; +import { createAlert, VARIANT_SUCCESS } from '~/alert'; import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants'; import { STATUS_CLOSED, TYPE_INCIDENT, TYPE_ISSUE } from '~/issues/constants'; import { ISSUE_STATE_EVENT_CLOSE, ISSUE_STATE_EVENT_REOPEN } from '~/issues/show/constants'; diff --git a/app/assets/javascripts/issues/show/components/incidents/create_timeline_event.vue b/app/assets/javascripts/issues/show/components/incidents/create_timeline_event.vue index c2b7d33c14c..ac64c35bf15 100644 --- a/app/assets/javascripts/issues/show/components/incidents/create_timeline_event.vue +++ b/app/assets/javascripts/issues/show/components/incidents/create_timeline_event.vue @@ -3,7 +3,7 @@ import { produce } from 'immer'; import { sortBy } from 'lodash'; import { GlIcon } from '@gitlab/ui'; import { sprintf } from '~/locale'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { convertToGraphQLId } from '~/graphql_shared/utils'; import { TYPENAME_ISSUE } from '~/graphql_shared/constants'; import { timelineFormI18n } from './constants'; diff --git a/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue index 1c677c0d9e6..4ec64ef838d 100644 --- a/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue +++ b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue @@ -1,6 +1,6 @@ <script> import { GlTab, GlTabs } from '@gitlab/ui'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { trackIncidentDetailsViewsOptions } from '~/incidents/constants'; import { s__ } from '~/locale'; import Tracking from '~/tracking'; diff --git a/app/assets/javascripts/issues/show/components/incidents/timeline_events_list.vue b/app/assets/javascripts/issues/show/components/incidents/timeline_events_list.vue index 10b80529a66..5aef4b1b809 100644 --- a/app/assets/javascripts/issues/show/components/incidents/timeline_events_list.vue +++ b/app/assets/javascripts/issues/show/components/incidents/timeline_events_list.vue @@ -1,6 +1,6 @@ <script> import { formatDate } from '~/lib/utils/datetime_utility'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { sprintf } from '~/locale'; import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending'; diff --git a/app/assets/javascripts/issues/show/components/incidents/utils.js b/app/assets/javascripts/issues/show/components/incidents/utils.js index ce33e91c3b8..2072961ce29 100644 --- a/app/assets/javascripts/issues/show/components/incidents/utils.js +++ b/app/assets/javascripts/issues/show/components/incidents/utils.js @@ -1,4 +1,4 @@ -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { s__ } from '~/locale'; export const displayAndLogError = (error) => diff --git a/app/assets/javascripts/pages/groups/new/components/app.vue b/app/assets/javascripts/pages/groups/new/components/app.vue index 68f813d9375..38fb96d40b7 100644 --- a/app/assets/javascripts/pages/groups/new/components/app.vue +++ b/app/assets/javascripts/pages/groups/new/components/app.vue @@ -11,6 +11,10 @@ export default { NewNamespacePage, }, props: { + groupsUrl: { + type: String, + required: true, + }, parentGroupUrl: { type: String, required: false, @@ -39,7 +43,10 @@ export default { { text: this.parentGroupName, href: this.parentGroupUrl }, { text: s__('GroupsNew|New subgroup'), href: '#' }, ] - : [{ text: s__('GroupsNew|New group'), href: '#' }]; + : [ + { text: s__('GroupsNew|Groups'), href: this.groupsUrl }, + { text: s__('GroupsNew|New group'), href: '#' }, + ]; }, panels() { return [ diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js index acaee097dc1..b16c5f3da9f 100644 --- a/app/assets/javascripts/pages/groups/new/index.js +++ b/app/assets/javascripts/pages/groups/new/index.js @@ -22,6 +22,7 @@ initFilePickers(); function initNewGroupCreation(el) { const { hasErrors, + groupsUrl, parentGroupUrl, parentGroupName, importExistingGroupPath, @@ -31,6 +32,7 @@ function initNewGroupCreation(el) { } = el.dataset; const props = { + groupsUrl, parentGroupUrl, parentGroupName, importExistingGroupPath, diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js index 3a293956089..f871cd804e7 100644 --- a/app/assets/javascripts/pages/projects/commit/show/index.js +++ b/app/assets/javascripts/pages/projects/commit/show/index.js @@ -4,7 +4,7 @@ import Vue from 'vue'; import loadAwardsHandler from '~/awards_handler'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import Diff from '~/diff'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import initDeprecatedNotes from '~/init_deprecated_notes'; import { initDiffStatsDropdown } from '~/init_diff_stats_dropdown'; import axios from '~/lib/utils/axios_utils'; diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js index 6f7ce7d59c3..b52b7ed4caa 100644 --- a/app/assets/javascripts/pages/users/activity_calendar.js +++ b/app/assets/javascripts/pages/users/activity_calendar.js @@ -184,6 +184,7 @@ export default class ActivityCalendar { }); return `translate(${this.daySizeWithSpace * i + 1 + this.daySizeWithSpace}, 18)`; }) + .attr('data-testid', 'user-contrib-cell-group') .selectAll('rect') .data((stamp) => stamp) .enter() @@ -195,6 +196,7 @@ export default class ActivityCalendar { .attr('data-level', (stamp) => getLevelFromContributions(stamp.count)) .attr('title', (stamp) => formatTooltipText(stamp)) .attr('class', 'user-contrib-cell has-tooltip') + .attr('data-testid', 'user-contrib-cell') .attr('data-html', true) .attr('data-container', 'body') .on('click', this.clickDay); diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js index 3a23f9ff49c..430022f9a9b 100644 --- a/app/assets/javascripts/pages/users/user_tabs.js +++ b/app/assets/javascripts/pages/users/user_tabs.js @@ -253,7 +253,7 @@ export default class UserTabs { timestamps: data, calendarActivitiesPath, utcOffset, - firstDayOfTheWeek: gon.first_day_of_week, + firstDayOfWeek: gon.first_day_of_week, monthsAgo, }); } diff --git a/app/assets/javascripts/projects/new/components/app.vue b/app/assets/javascripts/projects/new/components/app.vue index 8d883e7126c..251db16d8e3 100644 --- a/app/assets/javascripts/projects/new/components/app.vue +++ b/app/assets/javascripts/projects/new/components/app.vue @@ -59,6 +59,10 @@ export default { SafeHtml, }, props: { + projectsUrl: { + type: String, + required: true, + }, parentGroupUrl: { type: String, required: false, @@ -89,9 +93,11 @@ export default { computed: { initialBreadcrumbs() { return [ - this.parentGroupUrl && { text: this.parentGroupName, href: this.parentGroupUrl }, + this.parentGroupUrl + ? { text: this.parentGroupName, href: this.parentGroupUrl } + : { text: s__('ProjectsNew|Projects'), href: this.projectsUrl }, { text: s__('ProjectsNew|New project'), href: '#' }, - ].filter(Boolean); + ]; }, availablePanels() { return this.isCiCdAvailable ? PANELS : PANELS.filter((p) => p.name !== CI_CD_PANEL); diff --git a/app/assets/javascripts/projects/new/index.js b/app/assets/javascripts/projects/new/index.js index 0b190b6a88b..7330874eefe 100644 --- a/app/assets/javascripts/projects/new/index.js +++ b/app/assets/javascripts/projects/new/index.js @@ -17,6 +17,7 @@ export function initNewProjectCreation() { isCiCdAvailable, parentGroupUrl, parentGroupName, + projectsUrl, } = el.dataset; const props = { @@ -25,6 +26,7 @@ export function initNewProjectCreation() { newProjectGuidelines, parentGroupUrl, parentGroupName, + projectsUrl, }; const provide = { diff --git a/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue b/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue index 634b7da3def..93581dbbd40 100644 --- a/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue +++ b/app/assets/javascripts/vue_shared/alert_details/components/system_notes/system_note.vue @@ -33,7 +33,11 @@ export default { </script> <template> - <li :id="noteAnchorId" class="timeline-entry note system-note note-wrapper gl-p-0!"> + <li + :id="noteAnchorId" + class="timeline-entry note system-note note-wrapper gl-p-0!" + data-qa-selector="alert_system_note_container" + > <div class="gl-display-inline-flex gl-align-items-center gl-relative"> <div class="gl-display-inline gl-bg-white gl-text-gray-200 gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-full gl-box-sizing-content-box gl-p-3 gl-mt-n2 gl-mr-6" diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue index 741395b3193..fff8a95c193 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue @@ -1,6 +1,6 @@ <script> import { GlFilteredSearchSuggestion } from '@gitlab/ui'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { __ } from '~/locale'; import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue'; diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue index fcabeab1d8a..63ffded9e8e 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/crm_contact_token.vue @@ -3,7 +3,7 @@ import { GlFilteredSearchSuggestion } from '@gitlab/ui'; import { TYPENAME_CRM_CONTACT } from '~/graphql_shared/constants'; import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import { isPositiveInteger } from '~/lib/utils/number_utils'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue index 6d681aab3ca..a251035b683 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/release_token.vue @@ -1,6 +1,6 @@ <script> import { GlFilteredSearchSuggestion } from '@gitlab/ui'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { __ } from '~/locale'; import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue'; import { OPTIONS_NONE_ANY } from '../constants'; diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/user_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/user_token.vue index 28e65c1185f..c294c23abfc 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/user_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/user_token.vue @@ -1,7 +1,7 @@ <script> import { GlAvatar, GlFilteredSearchSuggestion } from '@gitlab/ui'; import { compact } from 'lodash'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { __ } from '~/locale'; import { OPTIONS_NONE_ANY } from '../constants'; diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue index d06bc7b8f98..dd9d2ce66cd 100644 --- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue +++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue @@ -10,7 +10,7 @@ import { } from '@gitlab/ui'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { glEmojiTag } from '~/emoji'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { followUser, unfollowUser } from '~/rest_api'; import { isUserBusy } from '~/set_status_modal/utils'; import Tracking from '~/tracking'; diff --git a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue index a4fb30a03a1..4c2b082242b 100644 --- a/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue +++ b/app/assets/javascripts/vue_shared/security_reports/components/artifact_downloads/merge_request_artifact_download.vue @@ -1,6 +1,6 @@ <script> import { reportTypeToSecurityReportTypeEnum } from 'ee_else_ce/vue_shared/security_reports/constants'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { s__ } from '~/locale'; import SecurityReportDownloadDropdown from '~/vue_shared/security_reports/components/security_report_download_dropdown.vue'; import securityReportMergeRequestDownloadPathsQuery from '~/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql'; diff --git a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue index b739baad5d7..0cff5edf628 100644 --- a/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue +++ b/app/assets/javascripts/vue_shared/security_reports/security_reports_app.vue @@ -1,6 +1,6 @@ <script> import { mapActions, mapGetters } from 'vuex'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { s__ } from '~/locale'; import ReportSection from '~/ci/reports/components/report_section.vue'; import { ERROR, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '~/ci/reports/constants'; diff --git a/app/graphql/mutations/design_management/update.rb b/app/graphql/mutations/design_management/update.rb new file mode 100644 index 00000000000..5dc20730a90 --- /dev/null +++ b/app/graphql/mutations/design_management/update.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Mutations + module DesignManagement + class Update < ::Mutations::BaseMutation + graphql_name "DesignManagementUpdate" + + authorize :update_design + + argument :id, ::Types::GlobalIDType[::DesignManagement::Design], + required: true, + description: "ID of the design to update." + + argument :description, GraphQL::Types::String, + required: false, + description: copy_field_description(Types::DesignManagement::DesignType, :description) + + field :design, Types::DesignManagement::DesignType, + null: false, + description: "Updated design." + + def resolve(id:, description:) + design = authorized_find!(id: id) + design.update(description: description) + + { + design: design.reset, + errors: errors_on_object(design) + } + end + + private + + def find_object(id:) + GitlabSchema.find_by_gid(id) + end + end + end +end diff --git a/app/graphql/types/design_management/design_type.rb b/app/graphql/types/design_management/design_type.rb index cc4c0e19ec7..be5edd17643 100644 --- a/app/graphql/types/design_management/design_type.rb +++ b/app/graphql/types/design_management/design_type.rb @@ -15,6 +15,11 @@ module Types implements(Types::CurrentUserTodos) implements(Types::TodoableInterface) + field :description, + GraphQL::Types::String, + null: true, + description: 'Description of the design.' + field :web_url, GraphQL::Types::String, null: false, @@ -25,6 +30,8 @@ module Types resolver: Resolvers::DesignManagement::VersionsResolver, description: "All versions related to this design ordered newest first." + markdown_field :description_html, null: true + # Returns a `DesignManagement::Version` for this query based on the # `atVersion` argument passed to a parent node if present, or otherwise # the most recent `Version` for the issue. diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index 108c55f1292..75235405763 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -117,6 +117,7 @@ module Types mount_mutation Mutations::DesignManagement::Upload, calls_gitaly: true mount_mutation Mutations::DesignManagement::Delete, calls_gitaly: true mount_mutation Mutations::DesignManagement::Move + mount_mutation Mutations::DesignManagement::Update mount_mutation Mutations::ContainerExpirationPolicies::Update mount_mutation Mutations::ContainerRepositories::Destroy mount_mutation Mutations::ContainerRepositories::DestroyTags diff --git a/app/policies/issue_policy.rb b/app/policies/issue_policy.rb index d1e35793c64..804709ed072 100644 --- a/app/policies/issue_policy.rb +++ b/app/policies/issue_policy.rb @@ -59,6 +59,7 @@ class IssuePolicy < IssuablePolicy rule { ~can?(:read_issue) }.policy do prevent :read_design prevent :create_design + prevent :update_design prevent :destroy_design end diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index fbe0f9bfeea..2bdd8b23c62 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -464,6 +464,7 @@ class ProjectPolicy < BasePolicy enable :read_alert_management_alert enable :update_alert_management_alert enable :create_design + enable :update_design enable :move_design enable :destroy_design enable :read_terraform_state @@ -750,6 +751,7 @@ class ProjectPolicy < BasePolicy prevent :read_design prevent :read_design_activity prevent :create_design + prevent :update_design prevent :destroy_design prevent :move_design end diff --git a/app/services/resource_access_tokens/create_service.rb b/app/services/resource_access_tokens/create_service.rb index 396d6a19dea..8bddf154017 100644 --- a/app/services/resource_access_tokens/create_service.rb +++ b/app/services/resource_access_tokens/create_service.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -require 'securerandom' - module ResourceAccessTokens class CreateService < BaseService + include Gitlab::Utils::StrongMemoize + def initialize(current_user, resource, params = {}) @resource_type = resource.class.name.downcase @resource = resource @@ -45,6 +45,14 @@ module ResourceAccessTokens attr_reader :resource_type, :resource + def username_and_email_generator + Gitlab::Utils::UsernameAndEmailGenerator.new( + username_prefix: "#{resource_type}_#{resource.id}_bot", + email_domain: "noreply.#{Gitlab.config.gitlab.host}" + ) + end + strong_memoize_attr :username_and_email_generator + def has_permission_to_create? %w(project group).include?(resource_type) && can?(current_user, :create_resource_access_tokens, resource) end @@ -65,25 +73,13 @@ module ResourceAccessTokens def default_user_params { name: params[:name] || "#{resource.name.to_s.humanize} bot", - email: generate_email, - username: generate_username, + email: username_and_email_generator.email, + username: username_and_email_generator.username, user_type: :project_bot, skip_confirmation: true # Bot users should always have their emails confirmed. } end - def generate_username - username - end - - def generate_email - "#{username}@noreply.#{Gitlab.config.gitlab.host}" - end - - def username - @username ||= "#{resource_type}_#{resource.id}_bot_#{SecureRandom.hex(8)}" - end - def create_personal_access_token(user) PersonalAccessTokens::CreateService.new( current_user: user, target_user: user, params: personal_access_token_params diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 0878fbf9a35..a5cbc443fa4 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -6,7 +6,7 @@ .group-edit-container - .js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s }.merge(subgroup_creation_data(@group), + .js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s, groups_url: dashboard_groups_url }.merge(subgroup_creation_data(@group), verification_for_group_creation_data) } .row{ 'v-cloak': true } diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index b493a8d0ce8..f4a5862b2c0 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -8,7 +8,15 @@ .project-edit-errors = render 'projects/errors' - .js-new-project-creation{ data: { is_ci_cd_available: remote_mirror_setting_enabled?.to_s, has_errors: @project.errors.any?.to_s, new_project_guidelines: brand_new_project_guidelines, push_to_create_project_command: push_to_create_project_command, working_with_projects_help_path: help_page_path("user/project/working_with_projects"), parent_group_url: @project.parent && group_url(@project.parent), parent_group_name: @project.parent&.name } } + .js-new-project-creation{ data: { + is_ci_cd_available: remote_mirror_setting_enabled?.to_s, + has_errors: @project.errors.any?.to_s, + new_project_guidelines: brand_new_project_guidelines, + push_to_create_project_command: push_to_create_project_command, + working_with_projects_help_path: help_page_path("user/project/working_with_projects"), + parent_group_url: @project.parent && group_url(@project.parent), + parent_group_name: @project.parent&.name, + projects_url: dashboard_projects_url } } .row{ 'v-cloak': true } #blank-project-pane.tab-pane.active |