From 76c4dd062c4eeb853866ef8b6451c59f9e24221c Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 10 Aug 2023 06:09:29 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../behaviors/shortcuts/keybindings.js | 13 +- .../behaviors/shortcuts/shortcuts_issuable.js | 34 +- .../components/ci_variable_modal.vue | 66 ++-- .../ci/ci_variable_list/constants.js | 5 +- .../javascripts/ci/ci_variable_list/index.js | 8 - .../components/triggers_list.vue | 66 ++-- .../issues/show/components/header_actions.vue | 2 + .../javascripts/lib/print_markdown_dom.js | 50 +++ .../shared/wikis/components/wiki_export.vue | 40 +++ .../javascripts/pages/shared/wikis/show.js | 21 ++ .../components/custom_email.vue | 36 ++- .../components/custom_email_form.vue | 291 ++++++++++++++++++ .../custom_email_constants.js | 43 +++ .../projects/settings_service_desk/index.js | 3 + .../empty_state_with_any_issues.vue | 58 ++++ .../empty_state_without_any_issues.vue | 75 +++++ .../components/service_desk_list_app.vue | 24 +- .../javascripts/service_desk/constants.js | 10 +- app/assets/javascripts/service_desk/index.js | 2 + app/assets/stylesheets/print.scss | 36 +++ .../default_branch_changed_event.rb | 16 + .../mutations/ci/pipeline_trigger/create.rb | 38 +++ app/graphql/types/mutation_type.rb | 1 + app/models/concerns/has_repository.rb | 3 + app/views/ci/variables/_index.html.haml | 4 - .../projects/settings/ci_cd/show.html.haml | 4 +- app/views/projects/triggers/_form.html.haml | 4 + app/views/projects/triggers/_index.html.haml | 47 ++- app/views/shared/wikis/show.html.haml | 2 + .../feature_flags/development/print_wiki.yml | 8 + config/sidekiq_queues.yml | 2 + doc/administration/geo/setup/index.md | 19 +- .../performance/grafana_configuration.md | 116 +------ .../postgresql_versions.md | 1 + .../sidekiq/sidekiq_troubleshooting.md | 2 +- doc/api/graphql/reference/index.md | 24 ++ doc/ci/triggers/index.md | 5 +- doc/ci/variables/predefined_variables.md | 4 +- doc/development/api_graphql_styleguide.md | 9 +- doc/development/graphql_guide/monitoring.md | 17 +- .../testing_guide/testing_levels.md | 18 +- doc/update/versions/gitlab_16_changes.md | 25 ++ .../dependency_list/index.md | 3 + doc/user/project/integrations/webhooks.md | 1 + doc/user/search/advanced_search.md | 4 + locale/gitlab.pot | 107 +++++-- package.json | 1 + spec/features/issues/service_desk_spec.rb | 38 ++- spec/features/triggers_spec.rb | 7 +- .../components/ci_variable_modal_spec.js | 19 +- .../components/triggers_list_spec.js | 24 +- spec/frontend/lib/print_markdown_dom_spec.js | 102 ++++++ .../wikis/components/wiki_export_spec.js | 48 +++ .../components/custom_email_form_spec.js | 199 ++++++++++++ .../components/custom_email_spec.js | 52 +++- .../components/mock_data.js | 17 + .../empty_state_with_any_issues_spec.js | 74 +++++ .../empty_state_without_any_issues_spec.js | 89 ++++++ .../components/service_desk_list_app_spec.js | 68 +++- .../ci/pipeline_trigger/create_spec.rb | 75 +++++ spec/services/issues/update_service_spec.rb | 90 +----- .../merge_requests/update_service_spec.rb | 4 +- .../has_repository_shared_examples.rb | 14 + ...issuable_update_service_shared_examples.rb | 70 +++++ yarn.lock | 5 + 65 files changed, 1965 insertions(+), 398 deletions(-) create mode 100644 app/assets/javascripts/lib/print_markdown_dom.js create mode 100644 app/assets/javascripts/pages/shared/wikis/components/wiki_export.vue create mode 100644 app/assets/javascripts/projects/settings_service_desk/components/custom_email_form.vue create mode 100644 app/assets/javascripts/service_desk/components/empty_state_with_any_issues.vue create mode 100644 app/assets/javascripts/service_desk/components/empty_state_without_any_issues.vue create mode 100644 app/events/repositories/default_branch_changed_event.rb create mode 100644 app/graphql/mutations/ci/pipeline_trigger/create.rb create mode 100644 config/feature_flags/development/print_wiki.yml create mode 100644 spec/frontend/lib/print_markdown_dom_spec.js create mode 100644 spec/frontend/pages/shared/wikis/components/wiki_export_spec.js create mode 100644 spec/frontend/projects/settings_service_desk/components/custom_email_form_spec.js create mode 100644 spec/frontend/service_desk/components/empty_state_with_any_issues_spec.js create mode 100644 spec/frontend/service_desk/components/empty_state_without_any_issues_spec.js create mode 100644 spec/requests/api/graphql/mutations/ci/pipeline_trigger/create_spec.rb diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js index a6faa04b440..689f2f0898e 100644 --- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js +++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js @@ -399,6 +399,12 @@ export const ISSUABLE_CHANGE_LABEL = { defaultKeys: ['l'], }; +export const ISSUABLE_COPY_REF = { + id: 'issuables.copyIssuableRef', + description: __('Copy reference'), + defaultKeys: ['c r'], // eslint-disable-line @gitlab/require-i18n-strings +}; + export const ISSUE_MR_CHANGE_ASSIGNEE = { id: 'issuesMRs.changeAssignee', description: __('Change assignee'), @@ -606,7 +612,12 @@ const PROJECT_FILES_SHORTCUTS_GROUP = { const ISSUABLE_SHORTCUTS_GROUP = { id: 'issuables', name: __('Epics, issues, and merge requests'), - keybindings: [ISSUABLE_COMMENT_OR_REPLY, ISSUABLE_EDIT_DESCRIPTION, ISSUABLE_CHANGE_LABEL], + keybindings: [ + ISSUABLE_COMMENT_OR_REPLY, + ISSUABLE_EDIT_DESCRIPTION, + ISSUABLE_CHANGE_LABEL, + ISSUABLE_COPY_REF, + ], }; const ISSUE_MR_SHORTCUTS_GROUP = { diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js index 0c882ff9ea2..b0e515ac19d 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js @@ -14,6 +14,7 @@ import { ISSUABLE_COMMENT_OR_REPLY, ISSUABLE_EDIT_DESCRIPTION, MR_COPY_SOURCE_BRANCH_NAME, + ISSUABLE_COPY_REF, } from './keybindings'; import Shortcuts from './shortcuts'; @@ -21,15 +22,24 @@ export default class ShortcutsIssuable extends Shortcuts { constructor() { super(); - this.inMemoryButton = document.createElement('button'); - this.clipboardInstance = new ClipboardJS(this.inMemoryButton); - this.clipboardInstance.on('success', () => { + this.branchInMemoryButton = document.createElement('button'); + this.branchClipboardInstance = new ClipboardJS(this.branchInMemoryButton); + this.branchClipboardInstance.on('success', () => { toast(s__('GlobalShortcuts|Copied source branch name to clipboard.')); }); - this.clipboardInstance.on('error', () => { + this.branchClipboardInstance.on('error', () => { toast(s__('GlobalShortcuts|Unable to copy the source branch name at this time.')); }); + this.refInMemoryButton = document.createElement('button'); + this.refClipboardInstance = new ClipboardJS(this.refInMemoryButton); + this.refClipboardInstance.on('success', () => { + toast(s__('GlobalShortcuts|Copied reference to clipboard.')); + }); + this.refClipboardInstance.on('error', () => { + toast(s__('GlobalShortcuts|Unable to copy the reference at this time.')); + }); + this.bindCommands([ [ISSUE_MR_CHANGE_ASSIGNEE, () => ShortcutsIssuable.openSidebarDropdown('assignee')], [ISSUE_MR_CHANGE_MILESTONE, () => ShortcutsIssuable.openSidebarDropdown('milestone')], @@ -37,6 +47,7 @@ export default class ShortcutsIssuable extends Shortcuts { [ISSUABLE_COMMENT_OR_REPLY, ShortcutsIssuable.replyWithSelectedText], [ISSUABLE_EDIT_DESCRIPTION, ShortcutsIssuable.editIssue], [MR_COPY_SOURCE_BRANCH_NAME, () => this.copyBranchName()], + [ISSUABLE_COPY_REF, () => this.copyIssuableRef()], ]); /** @@ -163,9 +174,20 @@ export default class ShortcutsIssuable extends Shortcuts { const branchName = button?.dataset.clipboardText; if (branchName) { - this.inMemoryButton.dataset.clipboardText = branchName; + this.branchInMemoryButton.dataset.clipboardText = branchName; - this.inMemoryButton.dispatchEvent(new CustomEvent('click')); + this.branchInMemoryButton.dispatchEvent(new CustomEvent('click')); + } + } + + async copyIssuableRef() { + const refButton = document.querySelector('.js-copy-reference'); + const copiedRef = refButton?.dataset.clipboardText; + + if (copiedRef) { + this.refInMemoryButton.dataset.clipboardText = copiedRef; + + this.refInMemoryButton.dispatchEvent(new CustomEvent('click')); } } } diff --git a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue index 5468e42b6b3..86c0f34215e 100644 --- a/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue +++ b/app/assets/javascripts/ci/ci_variable_list/components/ci_variable_modal.vue @@ -25,6 +25,7 @@ import { AWS_TOKEN_CONSTANTS, ADD_CI_VARIABLE_MODAL_ID, AWS_TIP_DISMISSED_COOKIE_NAME, + AWS_TIP_TITLE, AWS_TIP_MESSAGE, CONTAINS_VARIABLE_REFERENCE_MESSAGE, defaultVariableState, @@ -62,10 +63,6 @@ export default { }, mixins: [glFeatureFlagsMixin(), trackingMixin], inject: [ - 'awsLogoSvgPath', - 'awsTipCommandsLink', - 'awsTipDeployLink', - 'awsTipLearnLink', 'containsVariableReferenceLink', 'environmentScopeLink', 'isProtectedByDefault', @@ -295,6 +292,7 @@ export default { }, }, i18n: { + awsTipTitle: AWS_TIP_TITLE, awsTipMessage: AWS_TIP_MESSAGE, containsVariableReferenceMessage: CONTAINS_VARIABLE_REFERENCE_MESSAGE, defaultScope: allEnvironments.text, @@ -305,6 +303,9 @@ export default { flagLink: helpPagePath('ci/variables/index', { anchor: 'define-a-cicd-variable-in-the-ui', }), + oidcLink: helpPagePath('ci/cloud_services/index', { + anchor: 'oidc-authorization-with-your-cloud-provider', + }), modalId: ADD_CI_VARIABLE_MODAL_ID, tokens: awsTokens, tokenList: awsTokenList, @@ -322,6 +323,23 @@ export default { @hidden="resetModalHandler" @shown="onShow" > + + + + + + +
- - -
-
-

- - - - -

-

- {{ __('Learn more about deploying to AWS') }} -

-
- -
-
-
+ { const { - awsLogoSvgPath, - awsTipCommandsLink, - awsTipDeployLink, - awsTipLearnLink, containsVariableReferenceLink, endpoint, environmentScopeLink, @@ -57,10 +53,6 @@ const mountCiVariableListApp = (containerEl) => { el: containerEl, apolloProvider, provide: { - awsLogoSvgPath, - awsTipCommandsLink, - awsTipDeployLink, - awsTipLearnLink, containsVariableReferenceLink, endpoint, environmentScopeLink, diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue index a1b264cfe54..0871d543d46 100644 --- a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue +++ b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue @@ -1,13 +1,5 @@ + diff --git a/app/assets/javascripts/pages/shared/wikis/show.js b/app/assets/javascripts/pages/shared/wikis/show.js index 9906cb595f8..9bc399d07b3 100644 --- a/app/assets/javascripts/pages/shared/wikis/show.js +++ b/app/assets/javascripts/pages/shared/wikis/show.js @@ -1,6 +1,7 @@ import Vue from 'vue'; import Wikis from './wikis'; import WikiContent from './components/wiki_content.vue'; +import WikiExport from './components/wiki_export.vue'; const mountWikiContentApp = () => { const el = document.querySelector('.js-async-wiki-page-content'); @@ -20,8 +21,28 @@ const mountWikiContentApp = () => { } }; +const mountWikiExportApp = () => { + const el = document.querySelector('#js-export-actions'); + + if (!el) return false; + const { target, title, stylesheet } = JSON.parse(el.dataset.options); + + return new Vue({ + el, + provide: { + target, + title, + stylesheet, + }, + render(createElement) { + return createElement(WikiExport); + }, + }); +}; + export const mountApplications = () => { // eslint-disable-next-line no-new new Wikis(); mountWikiContentApp(); + mountWikiExportApp(); }; diff --git a/app/assets/javascripts/projects/settings_service_desk/components/custom_email.vue b/app/assets/javascripts/projects/settings_service_desk/components/custom_email.vue index f90633c6e03..a1c1b1141a7 100644 --- a/app/assets/javascripts/projects/settings_service_desk/components/custom_email.vue +++ b/app/assets/javascripts/projects/settings_service_desk/components/custom_email.vue @@ -8,7 +8,9 @@ import { I18N_CARD_TITLE, I18N_GENERIC_ERROR, I18N_FEEDBACK_PARAGRAPH, + I18N_TOAST_SAVED, } from '../custom_email_constants'; +import CustomEmailForm from './custom_email_form.vue'; export default { components: { @@ -18,11 +20,13 @@ export default { GlSprintf, GlLink, GlCard, + CustomEmailForm, }, FEEDBACK_ISSUE_URL, I18N_LOADING_LABEL, I18N_CARD_TITLE, I18N_FEEDBACK_PARAGRAPH, + I18N_TOAST_SAVED, props: { incomingEmail: { type: String, @@ -38,6 +42,7 @@ export default { data() { return { loading: true, + submitting: false, customEmail: null, enabled: false, verificationState: null, @@ -47,6 +52,11 @@ export default { alertMessage: null, }; }, + computed: { + customEmailNotSetUp() { + return !this.enabled && this.verificationState === null && this.customEmail === null; + }, + }, mounted() { this.getCustomEmailDetails(); }, @@ -76,6 +86,21 @@ export default { this.smtpAddress = data.custom_email_smtp_address; this.errorMessage = data.error_message; }, + onSaveCustomEmail(requestData) { + this.alertMessage = null; + this.submitting = true; + + axios + .post(this.customEmailEndpoint, requestData) + .then(({ data }) => { + this.updateData(data); + this.$toast.show(this.$options.I18N_TOAST_SAVED); + }) + .catch(this.handleRequestError) + .finally(() => { + this.submitting = false; + }); + }, }, }; @@ -108,11 +133,20 @@ export default { {{ alertMessage }} + + +