Skip to content

Commit e30d680

Browse files
author
GitLab Bot
committed
Add latest changes from gitlab-org/gitlab@master
1 parent 844e3ef commit e30d680

File tree

18 files changed

+403
-112
lines changed

18 files changed

+403
-112
lines changed

app/assets/javascripts/batch_comments/components/preview_item.vue

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,17 @@ export default {
4141
titleText() {
4242
const file = this.discussion ? this.discussion.diff_file : this.draft;
4343
44-
if (file) {
44+
if (file?.file_path) {
4545
return file.file_path;
4646
}
4747
48-
return sprintf(__("%{authorsName}'s thread"), {
49-
authorsName: this.discussion.notes.find((note) => !note.system).author.name,
50-
});
48+
if (this.discussion) {
49+
return sprintf(__("%{authorsName}'s thread"), {
50+
authorsName: this.discussion.notes.find((note) => !note.system).author.name,
51+
});
52+
}
53+
54+
return __('Your new comment');
5155
},
5256
linePosition() {
5357
if (this.position?.position_type === IMAGE_DIFF_POSITION_TYPE) {
@@ -94,7 +98,7 @@ export default {
9498
<span class="review-preview-item-header">
9599
<gl-icon class="flex-shrink-0" :name="iconName" />
96100
<span class="bold text-nowrap gl-align-items-center">
97-
<span class="review-preview-item-header-text block-truncated">
101+
<span class="review-preview-item-header-text block-truncated gl-ml-2">
98102
{{ titleText }}
99103
</span>
100104
<template v-if="showLinePosition">

app/assets/javascripts/notes/components/comment_form.vue

Lines changed: 78 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export default {
8484
'getNoteableDataByProp',
8585
'getNotesData',
8686
'openState',
87+
'hasDrafts',
8788
]),
8889
...mapState(['isToggleStateButtonLoading']),
8990
isNoteTypeComment() {
@@ -171,6 +172,9 @@ export default {
171172
endpoint() {
172173
return this.getNoteableData.create_note_path;
173174
},
175+
draftEndpoint() {
176+
return this.getNotesData.draftsPath;
177+
},
174178
issuableTypeTitle() {
175179
return this.noteableType === constants.MERGE_REQUEST_NOTEABLE_TYPE
176180
? this.$options.i18n.mergeRequest
@@ -214,12 +218,15 @@ export default {
214218
this.errors = [this.$options.i18n.GENERIC_UNSUBMITTABLE_NETWORK];
215219
}
216220
},
217-
handleSave(withIssueAction) {
221+
handleSaveDraft() {
222+
this.handleSave({ isDraft: true });
223+
},
224+
handleSave({ withIssueAction = false, isDraft = false } = {}) {
218225
this.errors = [];
219226
220227
if (this.note.length) {
221228
const noteData = {
222-
endpoint: this.endpoint,
229+
endpoint: isDraft ? this.draftEndpoint : this.endpoint,
223230
data: {
224231
note: {
225232
noteable_type: this.noteableType,
@@ -229,6 +236,7 @@ export default {
229236
},
230237
merge_request_diff_head_sha: this.getNoteableData.diff_head_sha,
231238
},
239+
isDraft,
232240
};
233241
234242
if (this.noteType === constants.DISCUSSION) {
@@ -392,62 +400,82 @@ export default {
392400
</markdown-field>
393401
</comment-field-layout>
394402
<div class="note-form-actions">
395-
<gl-form-checkbox
396-
v-if="confidentialNotesEnabled && canSetConfidential"
397-
v-model="noteIsConfidential"
398-
class="gl-mb-6"
399-
data-testid="confidential-note-checkbox"
400-
>
401-
{{ $options.i18n.confidential }}
402-
<gl-icon
403-
v-gl-tooltip:tooltipcontainer.bottom
404-
name="question"
405-
:size="16"
406-
:title="$options.i18n.confidentialVisibility"
407-
class="gl-text-gray-500"
408-
/>
409-
</gl-form-checkbox>
410-
<gl-dropdown
411-
split
412-
:text="commentButtonTitle"
413-
class="gl-mr-3 js-comment-button js-comment-submit-button comment-type-dropdown"
414-
category="primary"
415-
variant="confirm"
416-
:disabled="disableSubmitButton"
417-
data-testid="comment-button"
418-
data-qa-selector="comment_button"
419-
:data-track-label="trackingLabel"
420-
data-track-event="click_button"
421-
@click="handleSave()"
422-
>
423-
<gl-dropdown-item
424-
is-check-item
425-
:is-checked="isNoteTypeComment"
426-
:selected="isNoteTypeComment"
427-
@click="setNoteTypeToComment"
403+
<template v-if="hasDrafts">
404+
<gl-button
405+
:disabled="disableSubmitButton"
406+
data-testid="add-to-review-button"
407+
type="submit"
408+
category="primary"
409+
variant="success"
410+
@click.prevent="handleSaveDraft()"
411+
>{{ __('Add to review') }}</gl-button
412+
>
413+
<gl-button
414+
:disabled="disableSubmitButton"
415+
data-testid="add-comment-now-button"
416+
category="secondary"
417+
@click.prevent="handleSave()"
418+
>{{ __('Add comment now') }}</gl-button
419+
>
420+
</template>
421+
<template v-else>
422+
<gl-form-checkbox
423+
v-if="confidentialNotesEnabled && canSetConfidential"
424+
v-model="noteIsConfidential"
425+
class="gl-mb-6"
426+
data-testid="confidential-note-checkbox"
428427
>
429-
<strong>{{ $options.i18n.submitButton.comment }}</strong>
430-
<p class="gl-m-0">{{ commentDescription }}</p>
431-
</gl-dropdown-item>
432-
<gl-dropdown-divider />
433-
<gl-dropdown-item
434-
is-check-item
435-
:is-checked="isNoteTypeDiscussion"
436-
:selected="isNoteTypeDiscussion"
437-
data-qa-selector="discussion_menu_item"
438-
@click="setNoteTypeToDiscussion"
428+
{{ $options.i18n.confidential }}
429+
<gl-icon
430+
v-gl-tooltip:tooltipcontainer.bottom
431+
name="question"
432+
:size="16"
433+
:title="$options.i18n.confidentialVisibility"
434+
class="gl-text-gray-500"
435+
/>
436+
</gl-form-checkbox>
437+
<gl-dropdown
438+
split
439+
:text="commentButtonTitle"
440+
class="gl-mr-3 js-comment-button js-comment-submit-button comment-type-dropdown"
441+
category="primary"
442+
variant="confirm"
443+
:disabled="disableSubmitButton"
444+
data-testid="comment-button"
445+
data-qa-selector="comment_button"
446+
:data-track-label="trackingLabel"
447+
data-track-event="click_button"
448+
@click="handleSave()"
439449
>
440-
<strong>{{ $options.i18n.submitButton.startThread }}</strong>
441-
<p class="gl-m-0">{{ startDiscussionDescription }}</p>
442-
</gl-dropdown-item>
443-
</gl-dropdown>
450+
<gl-dropdown-item
451+
is-check-item
452+
:is-checked="isNoteTypeComment"
453+
:selected="isNoteTypeComment"
454+
@click="setNoteTypeToComment"
455+
>
456+
<strong>{{ $options.i18n.submitButton.comment }}</strong>
457+
<p class="gl-m-0">{{ commentDescription }}</p>
458+
</gl-dropdown-item>
459+
<gl-dropdown-divider />
460+
<gl-dropdown-item
461+
is-check-item
462+
:is-checked="isNoteTypeDiscussion"
463+
:selected="isNoteTypeDiscussion"
464+
data-qa-selector="discussion_menu_item"
465+
@click="setNoteTypeToDiscussion"
466+
>
467+
<strong>{{ $options.i18n.submitButton.startThread }}</strong>
468+
<p class="gl-m-0">{{ startDiscussionDescription }}</p>
469+
</gl-dropdown-item>
470+
</gl-dropdown>
471+
</template>
444472
<gl-button
445473
v-if="canToggleIssueState"
446474
:loading="isToggleStateButtonLoading"
447475
:class="[actionButtonClassNames, 'btn-comment btn-comment-and-close']"
448476
:disabled="isSubmitting"
449477
data-testid="close-reopen-button"
450-
@click="handleSave(true)"
478+
@click="handleSave({ withIssueAction: true })"
451479
>{{ issueActionButtonTitle }}</gl-button
452480
>
453481
</div>

app/assets/javascripts/notes/components/notes_app.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import { mapGetters, mapActions } from 'vuex';
33
import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
44
import { __ } from '~/locale';
55
import initUserPopovers from '~/user_popovers';
6+
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
67
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
78
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
9+
import draftNote from '../../batch_comments/components/draft_note.vue';
810
import { deprecatedCreateFlash as Flash } from '../../flash';
911
import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
1012
import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
@@ -32,6 +34,8 @@ export default {
3234
discussionFilterNote,
3335
OrderedLayout,
3436
SidebarSubscription,
37+
draftNote,
38+
TimelineEntryItem,
3539
},
3640
mixins: [glFeatureFlagsMixin()],
3741
props: {
@@ -276,6 +280,9 @@ export default {
276280
<ul id="notes-list" class="notes main-notes-list timeline">
277281
<template v-for="discussion in allDiscussions">
278282
<skeleton-loading-container v-if="discussion.isSkeletonNote" :key="discussion.id" />
283+
<timeline-entry-item v-else-if="discussion.isDraft" :key="discussion.id">
284+
<draft-note :draft="discussion" />
285+
</timeline-entry-item>
279286
<template v-else-if="discussion.isPlaceholderNote">
280287
<placeholder-system-note
281288
v-if="discussion.placeholderType === $options.systemNote"

app/assets/javascripts/notes/stores/getters.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,23 @@ import { flattenDeep, clone } from 'lodash';
22
import * as constants from '../constants';
33
import { collapseSystemNotes } from './collapse_utils';
44

5-
export const discussions = (state) => {
5+
const getDraftComments = (state) => {
6+
if (!state.batchComments) {
7+
return [];
8+
}
9+
10+
return state.batchComments.drafts
11+
.filter((draft) => !draft.line_code && !draft.discussion_id)
12+
.map((x) => ({
13+
...x,
14+
// Treat a top-level draft note as individual_note so it's not included in
15+
// expand/collapse threads
16+
individual_note: true,
17+
}))
18+
.sort((a, b) => a.id - b.id);
19+
};
20+
21+
export const discussions = (state, getters, rootState) => {
622
let discussionsInState = clone(state.discussions);
723
// NOTE: not testing bc will be removed when backend is finished.
824

@@ -22,11 +38,15 @@ export const discussions = (state) => {
2238
.sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
2339
}
2440

41+
discussionsInState = collapseSystemNotes(discussionsInState);
42+
43+
discussionsInState = discussionsInState.concat(getDraftComments(rootState));
44+
2545
if (state.discussionSortOrder === constants.DESC) {
2646
discussionsInState = discussionsInState.reverse();
2747
}
2848

29-
return collapseSystemNotes(discussionsInState);
49+
return discussionsInState;
3050
};
3151

3252
export const convertedDisscussionIds = (state) => state.convertedDisscussionIds;
@@ -257,3 +277,6 @@ export const commentsDisabled = (state) => state.commentsDisabled;
257277

258278
export const suggestionsCount = (state, getters) =>
259279
Object.values(getters.notesById).filter((n) => n.suggestions.length).length;
280+
281+
export const hasDrafts = (state, getters, rootState, rootGetters) =>
282+
Boolean(rootGetters['batchComments/hasDrafts']);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.gl-badge.feature-highlight-badge {
2+
background-color: $purple-light;
3+
color: $purple;
4+
5+
&,
6+
&.sm {
7+
padding: 0.25rem;
8+
}
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
title: Allow Add Comment To Review
3+
merge_request: 51718
4+
author: Lee Tickett @leetickett
5+
type: added
Loading
-27 KB
Binary file not shown.
Loading

doc/user/discussions/index.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,22 +334,28 @@ comment itself.
334334

335335
![Unresolve status](img/mr_review_unresolve.png)
336336

337+
### Adding a new comment
338+
339+
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8225) in GitLab 13.10.
340+
341+
If you have a review in progress, you will be presented with the option to **Add to review**:
342+
343+
![New thread](img/mr_review_new_comment_v13_11.png)
344+
337345
### Submitting a review
338346

339347
If you have any comments that have not been submitted, a bar displays at the
340348
bottom of the screen with two buttons:
341349

342-
- **Discard**: Discards all comments that have not been submitted.
343-
- **Finish review**: Opens a list of comments ready to be submitted for review.
344-
Clicking **Submit review** publishes all comments. Any quick actions
345-
submitted are performed at this time.
350+
- **Pending comments**: Opens a list of comments ready to be submitted for review.
351+
- **Submit review**: Publishes all comments. Any quick actions submitted are performed at this time.
346352

347353
Alternatively, to finish the entire review from a pending comment:
348354

349-
- Click the **Finish review** button on the comment.
355+
- Click the **Submit review** button on the comment.
350356
- Use the `/submit_review` [quick action](../project/quick_actions.md) in the text of non-review comment.
351357

352-
![Review submission](img/review_preview.png)
358+
![Review submission](img/review_preview_v13_11.png)
353359

354360
Submitting the review sends a single email to every notifiable user of the
355361
merge request with all the comments associated to it.

doc/user/permissions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ The following table depicts the various user permission levels in a project.
108108
| Upload [Design Management](project/issues/design_management.md) files | | ||||
109109
| Create/edit [releases](project/releases/index.md)| | ||||
110110
| Delete [releases](project/releases/index.md)| | | |||
111+
| Manage merge approval rules (project settings) | | | |||
111112
| Create new merge request | | ||||
112113
| Create new branches | | ||||
113114
| Push to non-protected branches | | ||||
@@ -300,6 +301,7 @@ group.
300301
| View Value Stream analytics ||||||
301302
| View Billing **(FREE SAAS)** | | | | | ✓ (4) |
302303
| View Usage Quotas **(FREE SAAS)** | | | | | ✓ (4) |
304+
| Manage [group push rules](group/index.md#group-push-rules) **(PREMIUM)** | | | |||
303305
| View 2FA status of members | | | | ||
304306
| Filter members by 2FA status | | | | ||
305307
| Administer project compliance frameworks | | | | ||

locale/gitlab.pot

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23591,7 +23591,7 @@ msgstr ""
2359123591
msgid "Please enter a valid number"
2359223592
msgstr ""
2359323593

23594-
msgid "Please enter or upload a license."
23594+
msgid "Please enter or upload a valid license."
2359523595
msgstr ""
2359623596

2359723597
msgid "Please fill in a descriptive name for your group."
@@ -31872,6 +31872,9 @@ msgstr ""
3187231872
msgid "This epic does not exist or you don't have sufficient permission."
3187331873
msgstr ""
3187431874

31875+
msgid "This feature is part of your GitLab Ultimate trial."
31876+
msgstr ""
31877+
3187531878
msgid "This feature requires local storage to be enabled"
3187631879
msgstr ""
3187731880

@@ -36303,6 +36306,9 @@ msgstr ""
3630336306
msgid "Your new SCIM token"
3630436307
msgstr ""
3630536308

36309+
msgid "Your new comment"
36310+
msgstr ""
36311+
3630636312
msgid "Your new personal access token has been created."
3630736313
msgstr ""
3630836314

0 commit comments

Comments
 (0)