Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/batch_comments/components/submit_dropdown.vue')
-rw-r--r--app/assets/javascripts/batch_comments/components/submit_dropdown.vue247
1 files changed, 170 insertions, 77 deletions
diff --git a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
index fac45f32464..b5cb1862b45 100644
--- a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
@@ -1,39 +1,69 @@
<script>
-import { GlDropdown, GlButton, GlIcon, GlForm, GlFormCheckbox } from '@gitlab/ui';
+import {
+ GlDisclosureDropdown,
+ GlButton,
+ GlIcon,
+ GlForm,
+ GlFormCheckbox,
+ GlFormRadioGroup,
+} from '@gitlab/ui';
// eslint-disable-next-line no-restricted-imports
import { mapGetters, mapActions, mapState } from 'vuex';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __ } from '~/locale';
import { createAlert } from '~/alert';
import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
import { scrollToElement } from '~/lib/utils/common_utils';
+import { fetchPolicies } from '~/lib/graphql';
import { CLEAR_AUTOSAVE_ENTRY_EVENT } from '~/vue_shared/constants';
import markdownEditorEventHub from '~/vue_shared/components/markdown/eventhub';
import { trackSavedUsingEditor } from '~/vue_shared/components/markdown/tracking';
+import userCanApproveQuery from '../queries/can_approve.query.graphql';
export default {
+ apollo: {
+ userPermissions: {
+ fetchPolicy: fetchPolicies.NETWORK_ONLY,
+ query: userCanApproveQuery,
+ variables() {
+ return {
+ projectPath: this.projectPath.replace(/^\//, ''),
+ iid: `${this.getNoteableData.iid}`,
+ };
+ },
+ update: (data) => data.project?.mergeRequest?.userPermissions,
+ skip() {
+ return !this.dropdownVisible;
+ },
+ },
+ },
components: {
- GlDropdown,
+ GlDisclosureDropdown,
GlButton,
GlIcon,
GlForm,
+ GlFormRadioGroup,
GlFormCheckbox,
MarkdownEditor,
ApprovalPassword: () => import('ee_component/batch_comments/components/approval_password.vue'),
SummarizeMyReview: () =>
import('ee_component/batch_comments/components/summarize_my_review.vue'),
},
+ mixins: [glFeatureFlagsMixin()],
inject: {
canSummarize: { default: false },
},
data() {
return {
isSubmitting: false,
+ dropdownVisible: false,
noteData: {
noteable_type: '',
noteable_id: '',
note: '',
approve: false,
approval_password: '',
+ reviewer_state: 'reviewed',
},
formFieldProps: {
id: 'review-note-body',
@@ -42,17 +72,51 @@ export default {
'aria-label': __('Comment'),
'data-testid': 'comment-textarea',
},
+ userPermissions: {},
};
},
computed: {
...mapGetters(['getNotesData', 'getNoteableData', 'noteableType', 'getCurrentUserLastNote']),
...mapState('batchComments', ['shouldAnimateReviewButton']),
+ ...mapState('diffs', ['projectPath']),
autocompleteDataSources() {
return gl.GfmAutoComplete?.dataSources;
},
autosaveKey() {
return `submit_review_dropdown/${this.getNoteableData.id}`;
},
+ radioGroupOptions() {
+ return [
+ {
+ html: [
+ __('Comment'),
+ `<p class="help-text">
+ ${__('Submit general feedback without explicit approval.')}
+ </p>`,
+ ].join('<br />'),
+ value: 'reviewed',
+ },
+ {
+ html: [
+ __('Approve'),
+ `<p class="help-text">
+ ${__('Submit feedback and approve these changes.')}
+ </p>`,
+ ].join('<br />'),
+ value: 'approved',
+ disabled: !this.userPermissions.canApprove,
+ },
+ {
+ html: [
+ __('Request changes'),
+ `<p class="help-text">
+ ${__('Submit feedback that should be addressed before merging.')}
+ </p>`,
+ ].join('<br />'),
+ value: 'requested_changes',
+ },
+ ];
+ },
},
watch: {
'noteData.approve': function noteDataApproveWatch() {
@@ -60,21 +124,21 @@ export default {
this.repositionDropdown();
});
},
+ dropdownVisible(val) {
+ if (!val) {
+ this.userPermissions = {};
+ }
+ },
+ userPermissions: {
+ handler() {
+ this.repositionDropdown();
+ },
+ deep: true,
+ },
},
mounted() {
this.noteData.noteable_type = this.noteableType;
this.noteData.noteable_id = this.getNoteableData.id;
-
- // We override the Bootstrap Vue click outside behaviour
- // to allow for clicking in the autocomplete dropdowns
- // without this override the submit dropdown will close
- // whenever a item in the autocomplete dropdown is clicked
- const originalClickOutHandler = this.$refs.submitDropdown.$refs.dropdown.clickOutHandler;
- this.$refs.submitDropdown.$refs.dropdown.clickOutHandler = (e) => {
- if (!e.target.closest('.atwho-container')) {
- originalClickOutHandler(e);
- }
- };
},
methods: {
...mapActions('batchComments', ['publishReview']),
@@ -113,86 +177,115 @@ export default {
updateNote(note) {
this.noteData.note = note;
},
+ onBeforeClose({ originalEvent: { target }, preventDefault }) {
+ if (
+ target &&
+ [document.querySelector('.atwho-container'), document.querySelector('.dz-hidden-input')]
+ .filter(Boolean)
+ .some((el) => el.contains(target))
+ ) {
+ preventDefault();
+ }
+ },
+ setDropdownVisible(val) {
+ this.dropdownVisible = val;
+ },
},
restrictedToolbarItems: ['full-screen'],
};
</script>
<template>
- <gl-dropdown
+ <gl-disclosure-dropdown
ref="submitDropdown"
- right
- dropup
+ placement="right"
class="submit-review-dropdown"
:class="{ 'submit-review-dropdown-animated': shouldAnimateReviewButton }"
data-testid="submit-review-dropdown"
- variant="info"
- category="primary"
+ fluid-width
+ @beforeClose="onBeforeClose"
+ @shown="setDropdownVisible(true)"
+ @hidden="setDropdownVisible(false)"
>
- <template #button-content>
- {{ __('Finish review') }}
- <gl-icon class="dropdown-chevron" name="chevron-up" />
+ <template #toggle>
+ <gl-button variant="info" category="primary">
+ {{ __('Finish review') }}
+ <gl-icon class="dropdown-chevron" name="chevron-up" />
+ </gl-button>
</template>
- <gl-form data-testid="submit-gl-form" @submit.prevent="submitReview">
- <div class="gl-display-flex gl-mb-4 gl-align-items-center">
- <label for="review-note-body" class="gl-mb-0">
- {{ __('Summary comment (optional)') }}
- </label>
- <summarize-my-review
- v-if="canSummarize"
- :id="getNoteableData.id"
- class="gl-ml-auto"
- @input="updateNote"
- />
- </div>
- <div class="common-note-form gfm-form">
- <markdown-editor
- ref="markdownEditor"
- v-model="noteData.note"
- class="js-no-autosize"
- :is-submitting="isSubmitting"
- :render-markdown-path="getNoteableData.preview_note_path"
- :markdown-docs-path="getNotesData.markdownDocsPath"
- :form-field-props="formFieldProps"
- enable-autocomplete
- :autocomplete-data-sources="autocompleteDataSources"
- :disabled="isSubmitting"
- :restricted-tool-bar-items="$options.restrictedToolbarItems"
- :force-autosize="false"
- :autosave-key="autosaveKey"
- supports-quick-actions
- @input="$emit('input', $event)"
- @keydown.meta.enter="submitReview"
- @keydown.ctrl.enter="submitReview"
- />
- </div>
- <template v-if="getNoteableData.current_user.can_approve">
- <gl-form-checkbox
- v-model="noteData.approve"
- data-testid="approve_merge_request"
+ <template #default>
+ <gl-form
+ class="submit-review-dropdown-form gl-p-4"
+ data-testid="submit-gl-form"
+ @submit.prevent="submitReview"
+ >
+ <div class="gl-display-flex gl-mb-4 gl-align-items-center">
+ <label for="review-note-body" class="gl-mb-0">
+ {{ __('Summary comment (optional)') }}
+ </label>
+ <summarize-my-review
+ v-if="canSummarize"
+ :id="getNoteableData.id"
+ class="gl-ml-auto"
+ @input="updateNote"
+ />
+ </div>
+ <div class="common-note-form gfm-form">
+ <markdown-editor
+ ref="markdownEditor"
+ v-model="noteData.note"
+ class="js-no-autosize"
+ :is-submitting="isSubmitting"
+ :render-markdown-path="getNoteableData.preview_note_path"
+ :markdown-docs-path="getNotesData.markdownDocsPath"
+ :form-field-props="formFieldProps"
+ enable-autocomplete
+ :autocomplete-data-sources="autocompleteDataSources"
+ :disabled="isSubmitting"
+ :restricted-tool-bar-items="$options.restrictedToolbarItems"
+ :force-autosize="false"
+ :autosave-key="autosaveKey"
+ supports-quick-actions
+ @input="$emit('input', $event)"
+ @keydown.meta.enter="submitReview"
+ @keydown.ctrl.enter="submitReview"
+ />
+ </div>
+ <gl-form-radio-group
+ v-if="glFeatures.mrRequestChanges"
+ v-model="noteData.reviewer_state"
+ :options="radioGroupOptions"
class="gl-mt-4"
- >
- {{ __('Approve merge request') }}
- </gl-form-checkbox>
+ data-testid="reviewer_states"
+ />
+ <template v-else-if="userPermissions.canApprove">
+ <gl-form-checkbox
+ v-model="noteData.approve"
+ data-testid="approve_merge_request"
+ class="gl-mt-4"
+ >
+ {{ __('Approve merge request') }}
+ </gl-form-checkbox>
+ </template>
<approval-password
- v-if="getNoteableData.require_password_to_approve"
- v-show="noteData.approve"
+ v-if="userPermissions.canApprove && getNoteableData.require_password_to_approve"
+ v-show="noteData.approve || noteData.reviewer_state === 'approved'"
v-model="noteData.approval_password"
class="gl-mt-3"
data-testid="approve_password"
/>
- </template>
- <div class="gl-display-flex gl-justify-content-start gl-mt-4">
- <gl-button
- :loading="isSubmitting"
- variant="confirm"
- type="submit"
- class="js-no-auto-disable"
- data-testid="submit-review-button"
- >
- {{ __('Submit review') }}
- </gl-button>
- </div>
- </gl-form>
- </gl-dropdown>
+ <div class="gl-display-flex gl-justify-content-start gl-mt-4">
+ <gl-button
+ :loading="isSubmitting"
+ variant="confirm"
+ type="submit"
+ class="js-no-auto-disable"
+ data-testid="submit-review-button"
+ >
+ {{ __('Submit review') }}
+ </gl-button>
+ </div>
+ </gl-form>
+ </template>
+ </gl-disclosure-dropdown>
</template>