Skip to content

Commit a68a39e

Browse files
committed
Merge branch '18608-lock-issues-v2' into 'master'
Resolve "Lock issue and merge request" Closes #18608 See merge request gitlab-org/gitlab-ce!14531
2 parents 8c4dea2 + 26f6065 commit a68a39e

File tree

72 files changed

+1281
-129
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1281
-129
lines changed

app/assets/javascripts/diff.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ class Diff {
1717
}
1818
});
1919

20-
FilesCommentButton.init($diffFile);
20+
const tab = document.getElementById('diffs');
21+
if (!tab || (tab && tab.dataset && tab.dataset.isLocked !== '')) FilesCommentButton.init($diffFile);
2122

2223
$diffFile.each((index, file) => new gl.ImageFile(file));
2324

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

+22-8
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
import TaskList from '../../task_list';
88
import * as constants from '../constants';
99
import eventHub from '../event_hub';
10-
import confidentialIssue from '../../vue_shared/components/issue/confidential_issue_warning.vue';
10+
import issueWarning from '../../vue_shared/components/issue/issue_warning.vue';
1111
import issueNoteSignedOutWidget from './issue_note_signed_out_widget.vue';
12+
import issueDiscussionLockedWidget from './issue_discussion_locked_widget.vue';
1213
import markdownField from '../../vue_shared/components/markdown/field.vue';
1314
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
15+
import issuableStateMixin from '../mixins/issuable_state';
1416
1517
export default {
1618
name: 'issueCommentForm',
@@ -26,8 +28,9 @@
2628
};
2729
},
2830
components: {
29-
confidentialIssue,
31+
issueWarning,
3032
issueNoteSignedOutWidget,
33+
issueDiscussionLockedWidget,
3134
markdownField,
3235
userAvatarLink,
3336
},
@@ -55,6 +58,9 @@
5558
isIssueOpen() {
5659
return this.issueState === constants.OPENED || this.issueState === constants.REOPENED;
5760
},
61+
canCreateNote() {
62+
return this.getIssueData.current_user.can_create_note;
63+
},
5864
issueActionButtonTitle() {
5965
if (this.note.length) {
6066
const actionText = this.isIssueOpen ? 'close' : 'reopen';
@@ -90,9 +96,6 @@
9096
endpoint() {
9197
return this.getIssueData.create_note_path;
9298
},
93-
isConfidentialIssue() {
94-
return this.getIssueData.confidential;
95-
},
9699
},
97100
methods: {
98101
...mapActions([
@@ -220,6 +223,9 @@
220223
});
221224
},
222225
},
226+
mixins: [
227+
issuableStateMixin,
228+
],
223229
mounted() {
224230
// jQuery is needed here because it is a custom event being dispatched with jQuery.
225231
$(document).on('issuable:change', (e, isClosed) => {
@@ -235,6 +241,7 @@
235241
<template>
236242
<div>
237243
<issue-note-signed-out-widget v-if="!isLoggedIn" />
244+
<issue-discussion-locked-widget v-else-if="!canCreateNote" />
238245
<ul
239246
v-else
240247
class="notes notes-form timeline">
@@ -253,15 +260,22 @@
253260
<div class="timeline-content timeline-content-form">
254261
<form
255262
ref="commentForm"
256-
class="new-note js-quick-submit common-note-form gfm-form js-main-target-form">
257-
<confidentialIssue v-if="isConfidentialIssue" />
263+
class="new-note js-quick-submit common-note-form gfm-form js-main-target-form"
264+
>
265+
258266
<div class="error-alert"></div>
267+
268+
<issue-warning
269+
v-if="hasWarning(getIssueData)"
270+
:is-locked="isLocked(getIssueData)"
271+
:is-confidential="isConfidential(getIssueData)"
272+
/>
273+
259274
<markdown-field
260275
:markdown-preview-path="markdownPreviewPath"
261276
:markdown-docs-path="markdownDocsPath"
262277
:quick-actions-docs-path="quickActionsDocsPath"
263278
:add-spacing-classes="false"
264-
:is-confidential-issue="isConfidentialIssue"
265279
ref="markdownField">
266280
<textarea
267281
id="note-body"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<script>
2+
export default {
3+
computed: {
4+
lockIcon() {
5+
return gl.utils.spriteIcon('lock');
6+
},
7+
},
8+
};
9+
10+
</script>
11+
12+
<template>
13+
<div class="disabled-comment text-center">
14+
<span class="issuable-note-warning">
15+
<span class="icon" v-html="lockIcon"></span>
16+
<span>This issue is locked. Only <b>project members</b> can comment.</span>
17+
</span>
18+
</div>
19+
</template>

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

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<script>
22
import { mapGetters } from 'vuex';
33
import eventHub from '../event_hub';
4-
import confidentialIssue from '../../vue_shared/components/issue/confidential_issue_warning.vue';
4+
import issueWarning from '../../vue_shared/components/issue/issue_warning.vue';
55
import markdownField from '../../vue_shared/components/markdown/field.vue';
6+
import issuableStateMixin from '../mixins/issuable_state';
67
78
export default {
89
name: 'issueNoteForm',
@@ -39,12 +40,13 @@
3940
};
4041
},
4142
components: {
42-
confidentialIssue,
43+
issueWarning,
4344
markdownField,
4445
},
4546
computed: {
4647
...mapGetters([
4748
'getDiscussionLastNote',
49+
'getIssueData',
4850
'getIssueDataByProp',
4951
'getNotesDataByProp',
5052
'getUserDataByProp',
@@ -67,9 +69,6 @@
6769
isDisabled() {
6870
return !this.note.length || this.isSubmitting;
6971
},
70-
isConfidentialIssue() {
71-
return this.getIssueDataByProp('confidential');
72-
},
7372
},
7473
methods: {
7574
handleUpdate() {
@@ -95,6 +94,9 @@
9594
this.$emit('cancelFormEdition', shouldConfirm, this.noteBody !== this.note);
9695
},
9796
},
97+
mixins: [
98+
issuableStateMixin,
99+
],
98100
mounted() {
99101
this.$refs.textarea.focus();
100102
},
@@ -125,7 +127,13 @@
125127
<div class="flash-container timeline-content"></div>
126128
<form
127129
class="edit-note common-note-form js-quick-submit gfm-form">
128-
<confidentialIssue v-if="isConfidentialIssue" />
130+
131+
<issue-warning
132+
v-if="hasWarning(getIssueData)"
133+
:is-locked="isLocked(getIssueData)"
134+
:is-confidential="isConfidential(getIssueData)"
135+
/>
136+
129137
<markdown-field
130138
:markdown-preview-path="markdownPreviewPath"
131139
:markdown-docs-path="markdownDocsPath"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export default {
2+
methods: {
3+
isConfidential(issue) {
4+
return !!issue.confidential;
5+
},
6+
7+
isLocked(issue) {
8+
return !!issue.discussion_locked;
9+
},
10+
11+
hasWarning(issue) {
12+
return this.isConfidential(issue) || this.isLocked(issue);
13+
},
14+
},
15+
};

app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue

+7-7
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ export default {
4747
</script>
4848

4949
<template>
50-
<div class="block confidentiality">
50+
<div class="block issuable-sidebar-item confidentiality">
5151
<div class="sidebar-collapsed-icon">
52-
<i class="fa" :class="faEye" aria-hidden="true" data-hidden="true"></i>
52+
<i class="fa" :class="faEye" aria-hidden="true"></i>
5353
</div>
5454
<div class="title hide-collapsed">
5555
Confidentiality
@@ -62,19 +62,19 @@ export default {
6262
Edit
6363
</a>
6464
</div>
65-
<div class="value confidential-value hide-collapsed">
65+
<div class="value sidebar-item-value hide-collapsed">
6666
<editForm
6767
v-if="edit"
6868
:toggle-form="toggleForm"
6969
:is-confidential="isConfidential"
7070
:update-confidential-attribute="updateConfidentialAttribute"
7171
/>
72-
<div v-if="!isConfidential" class="no-value confidential-value">
73-
<i class="fa fa-eye is-not-confidential"></i>
72+
<div v-if="!isConfidential" class="no-value sidebar-item-value">
73+
<i class="fa fa-eye sidebar-item-icon"></i>
7474
Not confidential
7575
</div>
76-
<div v-else class="value confidential-value hide-collapsed">
77-
<i aria-hidden="true" data-hidden="true" class="fa fa-eye-slash is-confidential"></i>
76+
<div v-else class="value sidebar-item-value hide-collapsed">
77+
<i aria-hidden="true" class="fa fa-eye-slash sidebar-item-icon is-active"></i>
7878
This issue is confidential
7979
</div>
8080
</div>

app/assets/javascripts/sidebar/components/confidential/edit_form.vue

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
import editFormButtons from './edit_form_buttons.vue';
33
44
export default {
5-
components: {
6-
editFormButtons,
7-
},
85
props: {
96
isConfidential: {
107
required: true,
@@ -19,12 +16,16 @@ export default {
1916
type: Function,
2017
},
2118
},
19+
20+
components: {
21+
editFormButtons,
22+
},
2223
};
2324
</script>
2425

2526
<template>
2627
<div class="dropdown open">
27-
<div class="dropdown-menu confidential-warning-message">
28+
<div class="dropdown-menu sidebar-item-warning-message">
2829
<div>
2930
<p v-if="!isConfidential">
3031
You are going to turn on the confidentiality. This means that only team members with

app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export default {
1515
},
1616
},
1717
computed: {
18-
onOrOff() {
18+
toggleButtonText() {
1919
return this.isConfidential ? 'Turn Off' : 'Turn On';
2020
},
2121
updateConfidentialBool() {
@@ -26,7 +26,7 @@ export default {
2626
</script>
2727

2828
<template>
29-
<div class="confidential-warning-message-actions">
29+
<div class="sidebar-item-warning-message-actions">
3030
<button
3131
type="button"
3232
class="btn btn-default append-right-10"
@@ -39,7 +39,7 @@ export default {
3939
class="btn btn-close"
4040
@click.prevent="updateConfidentialAttribute(updateConfidentialBool)"
4141
>
42-
{{ onOrOff }}
42+
{{ toggleButtonText }}
4343
</button>
4444
</div>
4545
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<script>
2+
import editFormButtons from './edit_form_buttons.vue';
3+
import issuableMixin from '../../../vue_shared/mixins/issuable';
4+
5+
export default {
6+
props: {
7+
isLocked: {
8+
required: true,
9+
type: Boolean,
10+
},
11+
12+
toggleForm: {
13+
required: true,
14+
type: Function,
15+
},
16+
17+
updateLockedAttribute: {
18+
required: true,
19+
type: Function,
20+
},
21+
22+
issuableType: {
23+
required: true,
24+
type: String,
25+
},
26+
},
27+
28+
mixins: [
29+
issuableMixin,
30+
],
31+
32+
components: {
33+
editFormButtons,
34+
},
35+
};
36+
</script>
37+
38+
<template>
39+
<div class="dropdown open">
40+
<div class="dropdown-menu sidebar-item-warning-message">
41+
<p class="text" v-if="isLocked">
42+
Unlock this {{ issuableDisplayName(issuableType) }}?
43+
<strong>Everyone</strong>
44+
will be able to comment.
45+
</p>
46+
47+
<p class="text" v-else>
48+
Lock this {{ issuableDisplayName(issuableType) }}?
49+
Only
50+
<strong>project members</strong>
51+
will be able to comment.
52+
</p>
53+
54+
<edit-form-buttons
55+
:is-locked="isLocked"
56+
:toggle-form="toggleForm"
57+
:update-locked-attribute="updateLockedAttribute"
58+
/>
59+
</div>
60+
</div>
61+
</template>

0 commit comments

Comments
 (0)