summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/sidebar
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/sidebar')
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue60
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form.vue38
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue38
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/mutations/update_issue_confidential.mutation.graphql (renamed from app/assets/javascripts/sidebar/components/confidential/queries/update_issue_confidential.mutation.graphql)1
-rw-r--r--app/assets/javascripts/sidebar/components/lock/edit_form.vue62
-rw-r--r--app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue57
-rw-r--r--app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue129
-rw-r--r--app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue140
-rw-r--r--app/assets/javascripts/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql8
-rw-r--r--app/assets/javascripts/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql8
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/todo_toggle/todo.vue2
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js33
-rw-r--r--app/assets/javascripts/sidebar/services/sidebar_service.js4
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js2
17 files changed, 327 insertions, 263 deletions
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index 0906d5abec3..14c14d0bad1 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -1,5 +1,5 @@
<script>
-import Flash from '~/flash';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import eventHub from '~/sidebar/event_hub';
import Store from '~/sidebar/stores/sidebar_store';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
diff --git a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
index 0987603cafd..c6f7d5e44ad 100644
--- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
@@ -1,12 +1,10 @@
<script>
-import { mapState, mapActions } from 'vuex';
-import { __ } from '~/locale';
-import Flash from '~/flash';
+import { mapState } from 'vuex';
+import { __, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '~/sidebar/event_hub';
import EditForm from './edit_form.vue';
-import recaptchaModalImplementor from '~/vue_shared/mixins/recaptcha_modal_implementor';
export default {
components: {
@@ -16,7 +14,6 @@ export default {
directives: {
tooltip,
},
- mixins: [recaptchaModalImplementor],
props: {
fullPath: {
required: true,
@@ -26,9 +23,10 @@ export default {
required: true,
type: Boolean,
},
- service: {
- required: true,
- type: Object,
+ issuableType: {
+ required: false,
+ type: String,
+ default: 'issue',
},
},
data() {
@@ -37,45 +35,36 @@ export default {
};
},
computed: {
- ...mapState({ confidential: ({ noteableData }) => noteableData.confidential }),
+ ...mapState({
+ confidential: ({ noteableData, confidential }) => {
+ if (noteableData) {
+ return noteableData.confidential;
+ }
+ return Boolean(confidential);
+ },
+ }),
confidentialityIcon() {
return this.confidential ? 'eye-slash' : 'eye';
},
tooltipLabel() {
return this.confidential ? __('Confidential') : __('Not confidential');
},
+ confidentialText() {
+ return sprintf(__('This %{issuableType} is confidential'), {
+ issuableType: this.issuableType,
+ });
+ },
},
created() {
- eventHub.$on('updateConfidentialAttribute', this.updateConfidentialAttribute);
eventHub.$on('closeConfidentialityForm', this.toggleForm);
},
beforeDestroy() {
- eventHub.$off('updateConfidentialAttribute', this.updateConfidentialAttribute);
eventHub.$off('closeConfidentialityForm', this.toggleForm);
},
methods: {
- ...mapActions(['setConfidentiality']),
toggleForm() {
this.edit = !this.edit;
},
- closeForm() {
- this.edit = false;
- },
- updateConfidentialAttribute() {
- // TODO: rm when FF is defaulted to on.
- const confidential = !this.confidential;
- this.service
- .update('issue', { confidential })
- .then(({ data }) => this.checkForSpam(data))
- .then(() => window.location.reload())
- .catch(error => {
- if (error.name === 'SpamError') {
- this.openRecaptcha();
- } else {
- Flash(__('Something went wrong trying to change the confidentiality of this issue'));
- }
- });
- },
},
};
</script>
@@ -109,7 +98,12 @@ export default {
>
</div>
<div class="value sidebar-item-value hide-collapsed">
- <edit-form v-if="edit" :is-confidential="confidential" :full-path="fullPath" />
+ <edit-form
+ v-if="edit"
+ :confidential="confidential"
+ :full-path="fullPath"
+ :issuable-type="issuableType"
+ />
<div v-if="!confidential" class="no-value sidebar-item-value" data-testid="not-confidential">
<icon :size="16" name="eye" aria-hidden="true" class="sidebar-item-icon inline" />
{{ __('Not confidential') }}
@@ -121,10 +115,8 @@ export default {
aria-hidden="true"
class="sidebar-item-icon inline is-active"
/>
- {{ __('This issue is confidential') }}
+ {{ confidentialText }}
</div>
</div>
-
- <recaptcha-modal v-if="showRecaptcha" :html="recaptchaHTML" @close="closeRecaptcha" />
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
index 9dd4f04acdb..17e44cf0e1d 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
@@ -1,13 +1,15 @@
<script>
+import { GlSprintf } from '@gitlab/ui';
import editFormButtons from './edit_form_buttons.vue';
-import { s__ } from '../../../locale';
+import { __ } from '../../../locale';
export default {
components: {
editFormButtons,
+ GlSprintf,
},
props: {
- isConfidential: {
+ confidential: {
required: true,
type: Boolean,
},
@@ -15,16 +17,20 @@ export default {
required: true,
type: String,
},
+ issuableType: {
+ required: true,
+ type: String,
+ },
},
computed: {
confidentialityOnWarning() {
- return s__(
- 'confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue.',
+ return __(
+ 'You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}.',
);
},
confidentialityOffWarning() {
- return s__(
- 'confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue.',
+ return __(
+ 'You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}.',
);
},
},
@@ -35,9 +41,23 @@ export default {
<div class="dropdown show">
<div class="dropdown-menu sidebar-item-warning-message">
<div>
- <p v-if="!isConfidential" v-html="confidentialityOnWarning"></p>
- <p v-else v-html="confidentialityOffWarning"></p>
- <edit-form-buttons :full-path="fullPath" />
+ <p v-if="!confidential">
+ <gl-sprintf :message="confidentialityOnWarning">
+ <template #strong="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ <template #issuableType>{{ issuableType }}</template>
+ </gl-sprintf>
+ </p>
+ <p v-else>
+ <gl-sprintf :message="confidentialityOffWarning">
+ <template #strong="{ content }">
+ <strong>{{ content }}</strong>
+ </template>
+ <template #issuableType>{{ issuableType }}</template>
+ </gl-sprintf>
+ </p>
+ <edit-form-buttons :full-path="fullPath" :confidential="confidential" />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
index 80928649a03..86bfacbfb9e 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
@@ -1,22 +1,24 @@
<script>
import $ from 'jquery';
import { GlLoadingIcon } from '@gitlab/ui';
-import { mapActions, mapState } from 'vuex';
+import { mapActions } from 'vuex';
import { __ } from '~/locale';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import Flash from '~/flash';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import eventHub from '../../event_hub';
export default {
components: {
GlLoadingIcon,
},
- mixins: [glFeatureFlagsMixin()],
props: {
fullPath: {
required: true,
type: String,
},
+ confidential: {
+ required: true,
+ type: Boolean,
+ },
},
data() {
return {
@@ -24,7 +26,6 @@ export default {
};
},
computed: {
- ...mapState({ confidential: ({ noteableData }) => noteableData.confidential }),
toggleButtonText() {
if (this.isLoading) {
return __('Applying');
@@ -34,7 +35,7 @@ export default {
},
},
methods: {
- ...mapActions(['updateConfidentialityOnIssue']),
+ ...mapActions(['updateConfidentialityOnIssuable']),
closeForm() {
eventHub.$emit('closeConfidentialityForm');
$(this.$el).trigger('hidden.gl.dropdown');
@@ -43,18 +44,19 @@ export default {
this.isLoading = true;
const confidential = !this.confidential;
- if (this.glFeatures.confidentialApolloSidebar) {
- this.updateConfidentialityOnIssue({ confidential, fullPath: this.fullPath })
- .catch(() => {
- Flash(__('Something went wrong trying to change the confidentiality of this issue'));
- })
- .finally(() => {
- this.closeForm();
- this.isLoading = false;
- });
- } else {
- eventHub.$emit('updateConfidentialAttribute');
- }
+ this.updateConfidentialityOnIssuable({ confidential, fullPath: this.fullPath })
+ .then(() => {
+ eventHub.$emit('updateIssuableConfidentiality', confidential);
+ })
+ .catch(err => {
+ Flash(
+ err || __('Something went wrong trying to change the confidentiality of this issue'),
+ );
+ })
+ .finally(() => {
+ this.closeForm();
+ this.isLoading = false;
+ });
},
},
};
diff --git a/app/assets/javascripts/sidebar/components/confidential/queries/update_issue_confidential.mutation.graphql b/app/assets/javascripts/sidebar/components/confidential/mutations/update_issue_confidential.mutation.graphql
index 2459aa346c9..5caf5f6b555 100644
--- a/app/assets/javascripts/sidebar/components/confidential/queries/update_issue_confidential.mutation.graphql
+++ b/app/assets/javascripts/sidebar/components/confidential/mutations/update_issue_confidential.mutation.graphql
@@ -3,5 +3,6 @@ mutation updateIssueConfidential($input: IssueSetConfidentialInput!) {
issue {
confidential
}
+ errors
}
}
diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form.vue b/app/assets/javascripts/sidebar/components/lock/edit_form.vue
index 630da751704..65b51169420 100644
--- a/app/assets/javascripts/sidebar/components/lock/edit_form.vue
+++ b/app/assets/javascripts/sidebar/components/lock/edit_form.vue
@@ -1,40 +1,20 @@
<script>
+import { GlSprintf } from '@gitlab/ui';
import editFormButtons from './edit_form_buttons.vue';
-import issuableMixin from '../../../vue_shared/mixins/issuable';
-import { __, sprintf } from '../../../locale';
export default {
components: {
editFormButtons,
+ GlSprintf,
},
- mixins: [issuableMixin],
props: {
isLocked: {
required: true,
type: Boolean,
},
-
- updateLockedAttribute: {
+ issuableDisplayName: {
required: true,
- type: Function,
- },
- },
- computed: {
- lockWarning() {
- return sprintf(
- __(
- 'Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment.',
- ),
- { issuableDisplayName: this.issuableDisplayName },
- );
- },
- unlockWarning() {
- return sprintf(
- __(
- 'Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment.',
- ),
- { issuableDisplayName: this.issuableDisplayName },
- );
+ type: String,
},
},
};
@@ -42,12 +22,38 @@ export default {
<template>
<div class="dropdown show">
- <div class="dropdown-menu sidebar-item-warning-message">
- <p v-if="isLocked" class="text" v-html="unlockWarning"></p>
+ <div class="dropdown-menu sidebar-item-warning-message" data-testid="warning-text">
+ <p v-if="isLocked" class="text">
+ <gl-sprintf
+ :message="
+ __(
+ 'Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment.',
+ )
+ "
+ >
+ <template #issuableDisplayName>{{ issuableDisplayName }}</template>
+ <template #strong="{ content }"
+ ><strong>{{ content }}</strong></template
+ >
+ </gl-sprintf>
+ </p>
- <p v-else class="text" v-html="lockWarning"></p>
+ <p v-else class="text">
+ <gl-sprintf
+ :message="
+ __(
+ 'Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment.',
+ )
+ "
+ >
+ <template #issuableDisplayName>{{ issuableDisplayName }}</template>
+ <template #strong="{ content }"
+ ><strong>{{ content }}</strong></template
+ >
+ </gl-sprintf>
+ </p>
- <edit-form-buttons :is-locked="isLocked" :update-locked-attribute="updateLockedAttribute" />
+ <edit-form-buttons :is-locked="isLocked" :issuable-display-name="issuableDisplayName" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
index 2e85ded8ade..ea7230ae488 100644
--- a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
@@ -1,39 +1,63 @@
<script>
import $ from 'jquery';
-import { __ } from '~/locale';
+import { GlLoadingIcon } from '@gitlab/ui';
+import { mapActions } from 'vuex';
+import { __, sprintf } from '../../../locale';
+import { deprecatedCreateFlash as Flash } from '~/flash';
import eventHub from '../../event_hub';
export default {
+ components: {
+ GlLoadingIcon,
+ },
+ inject: ['fullPath'],
props: {
isLocked: {
required: true,
type: Boolean,
},
-
- updateLockedAttribute: {
+ issuableDisplayName: {
required: true,
- type: Function,
+ type: String,
},
},
-
+ data() {
+ return {
+ isLoading: false,
+ };
+ },
computed: {
buttonText() {
- return this.isLocked ? __('Unlock') : __('Lock');
- },
+ if (this.isLoading) {
+ return __('Applying');
+ }
- toggleLock() {
- return !this.isLocked;
+ return this.isLocked ? __('Unlock') : __('Lock');
},
},
-
methods: {
+ ...mapActions(['updateLockedAttribute']),
closeForm() {
eventHub.$emit('closeLockForm');
$(this.$el).trigger('hidden.gl.dropdown');
},
submitForm() {
- this.closeForm();
- this.updateLockedAttribute(this.toggleLock);
+ this.isLoading = true;
+
+ this.updateLockedAttribute({
+ locked: !this.isLocked,
+ fullPath: this.fullPath,
+ })
+ .catch(() => {
+ const flashMessage = __(
+ 'Something went wrong trying to change the locked state of this %{issuableDisplayName}',
+ );
+ Flash(sprintf(flashMessage, { issuableDisplayName: this.issuableDisplayName }));
+ })
+ .finally(() => {
+ this.closeForm();
+ this.isLoading = false;
+ });
},
},
};
@@ -45,7 +69,14 @@ export default {
{{ __('Cancel') }}
</button>
- <button type="button" class="btn btn-close" @click.prevent="submitForm">
+ <button
+ type="button"
+ data-testid="lock-toggle"
+ class="btn btn-close"
+ :disabled="isLoading"
+ @click.prevent="submitForm"
+ >
+ <gl-loading-icon v-if="isLoading" inline />
{{ buttonText }}
</button>
</div>
diff --git a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
new file mode 100644
index 00000000000..1b4968fabf6
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
@@ -0,0 +1,129 @@
+<script>
+import { mapGetters } from 'vuex';
+import { __ } from '~/locale';
+import tooltip from '~/vue_shared/directives/tooltip';
+import Icon from '~/vue_shared/components/icon.vue';
+import eventHub from '~/sidebar/event_hub';
+import editForm from './edit_form.vue';
+
+export default {
+ issue: 'issue',
+ locked: {
+ icon: 'lock',
+ class: 'value',
+ iconClass: 'is-active',
+ displayText: __('Locked'),
+ },
+ unlocked: {
+ class: ['no-value hide-collapsed'],
+ icon: 'lock-open',
+ iconClass: '',
+ displayText: __('Unlocked'),
+ },
+ components: {
+ editForm,
+ Icon,
+ },
+
+ directives: {
+ tooltip,
+ },
+
+ props: {
+ isEditable: {
+ required: true,
+ type: Boolean,
+ },
+ },
+ data() {
+ return {
+ isLockDialogOpen: false,
+ };
+ },
+ computed: {
+ ...mapGetters(['getNoteableData']),
+ issuableDisplayName() {
+ const isInIssuePage = this.getNoteableData.targetType === this.$options.issue;
+ return isInIssuePage ? __('issue') : __('merge request');
+ },
+ isLocked() {
+ return this.getNoteableData.discussion_locked;
+ },
+ lockStatus() {
+ return this.isLocked ? this.$options.locked : this.$options.unlocked;
+ },
+
+ tooltipLabel() {
+ return this.isLocked ? __('Locked') : __('Unlocked');
+ },
+ },
+
+ created() {
+ eventHub.$on('closeLockForm', this.toggleForm);
+ },
+
+ beforeDestroy() {
+ eventHub.$off('closeLockForm', this.toggleForm);
+ },
+
+ methods: {
+ toggleForm() {
+ if (this.isEditable) {
+ this.isLockDialogOpen = !this.isLockDialogOpen;
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="block issuable-sidebar-item lock">
+ <div
+ v-tooltip
+ :title="tooltipLabel"
+ class="sidebar-collapsed-icon"
+ data-testid="sidebar-collapse-icon"
+ data-container="body"
+ data-placement="left"
+ data-boundary="viewport"
+ @click="toggleForm"
+ >
+ <icon :name="lockStatus.icon" class="sidebar-item-icon is-active" />
+ </div>
+
+ <div class="title hide-collapsed">
+ {{ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) }}
+ <a
+ v-if="isEditable"
+ class="float-right lock-edit"
+ href="#"
+ data-testid="edit-link"
+ data-track-event="click_edit_button"
+ data-track-label="right_sidebar"
+ data-track-property="lock_issue"
+ @click.prevent="toggleForm"
+ >
+ {{ __('Edit') }}
+ </a>
+ </div>
+
+ <div class="value sidebar-item-value hide-collapsed">
+ <edit-form
+ v-if="isLockDialogOpen"
+ data-testid="edit-form"
+ :is-locked="isLocked"
+ :issuable-display-name="issuableDisplayName"
+ />
+
+ <div data-testid="lock-status" class="sidebar-item-value" :class="lockStatus.class">
+ <icon
+ :size="16"
+ :name="lockStatus.icon"
+ class="sidebar-item-icon"
+ :class="lockStatus.iconClass"
+ />
+ {{ lockStatus.displayText }}
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
deleted file mode 100644
index 728f655d33d..00000000000
--- a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
+++ /dev/null
@@ -1,140 +0,0 @@
-<script>
-import { __, sprintf } from '~/locale';
-import Flash from '~/flash';
-import tooltip from '~/vue_shared/directives/tooltip';
-import issuableMixin from '~/vue_shared/mixins/issuable';
-import Icon from '~/vue_shared/components/icon.vue';
-import eventHub from '~/sidebar/event_hub';
-import editForm from './edit_form.vue';
-
-export default {
- components: {
- editForm,
- Icon,
- },
-
- directives: {
- tooltip,
- },
-
- mixins: [issuableMixin],
-
- props: {
- isLocked: {
- required: true,
- type: Boolean,
- },
-
- isEditable: {
- required: true,
- type: Boolean,
- },
-
- mediator: {
- required: true,
- type: Object,
- validator(mediatorObject) {
- return mediatorObject.service && mediatorObject.service.update && mediatorObject.store;
- },
- },
- },
-
- computed: {
- lockIcon() {
- return this.isLocked ? 'lock' : 'lock-open';
- },
-
- isLockDialogOpen() {
- return this.mediator.store.isLockDialogOpen;
- },
-
- tooltipLabel() {
- return this.isLocked ? __('Locked') : __('Unlocked');
- },
- },
-
- created() {
- eventHub.$on('closeLockForm', this.toggleForm);
- },
-
- beforeDestroy() {
- eventHub.$off('closeLockForm', this.toggleForm);
- },
-
- methods: {
- toggleForm() {
- if (this.isEditable) {
- this.mediator.store.isLockDialogOpen = !this.mediator.store.isLockDialogOpen;
- }
- },
- updateLockedAttribute(locked) {
- this.mediator.service
- .update(this.issuableType, {
- discussion_locked: locked,
- })
- .then(() => window.location.reload())
- .catch(() =>
- Flash(
- sprintf(
- __(
- 'Something went wrong trying to change the locked state of this %{issuableDisplayName}',
- ),
- {
- issuableDisplayName: this.issuableDisplayName,
- },
- ),
- ),
- );
- },
- },
-};
-</script>
-
-<template>
- <div class="block issuable-sidebar-item lock">
- <div
- v-tooltip
- :title="tooltipLabel"
- class="sidebar-collapsed-icon"
- data-container="body"
- data-placement="left"
- data-boundary="viewport"
- @click="toggleForm"
- >
- <icon :name="lockIcon" class="sidebar-item-icon is-active" />
- </div>
-
- <div class="title hide-collapsed">
- {{ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) }}
- <a
- v-if="isEditable"
- class="float-right lock-edit"
- href="#"
- data-track-event="click_edit_button"
- data-track-label="right_sidebar"
- data-track-property="lock_issue"
- @click.prevent="toggleForm"
- >
- {{ __('Edit') }}
- </a>
- </div>
-
- <div class="value sidebar-item-value hide-collapsed">
- <edit-form
- v-if="isLockDialogOpen"
- :is-locked="isLocked"
- :update-locked-attribute="updateLockedAttribute"
- :issuable-type="issuableType"
- />
-
- <div v-if="isLocked" class="value sidebar-item-value">
- <icon :size="16" name="lock" class="sidebar-item-icon inline is-active" />
- {{ __('Locked') }}
- </div>
-
- <div v-else class="no-value sidebar-item-value hide-collapsed">
- <icon :size="16" name="lock-open" class="sidebar-item-icon inline" /> {{ __('Unlocked') }}
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql b/app/assets/javascripts/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql
new file mode 100644
index 00000000000..2a1bcdf7136
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql
@@ -0,0 +1,8 @@
+mutation updateIssueLocked($input: IssueSetLockedInput!) {
+ issueSetLocked(input: $input) {
+ issue {
+ discussionLocked
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql b/app/assets/javascripts/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql
new file mode 100644
index 00000000000..8590c8e71a6
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql
@@ -0,0 +1,8 @@
+mutation updateMergeRequestLocked($input: MergeRequestSetLockedInput!) {
+ mergeRequestSetLocked(input: $input) {
+ mergeRequest {
+ discussionLocked
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
index 91fe5fc50a9..ee1c98e9d69 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
@@ -1,6 +1,6 @@
<script>
import Store from '../../stores/sidebar_store';
-import Flash from '../../../flash';
+import { deprecatedCreateFlash as Flash } from '../../../flash';
import { __ } from '../../../locale';
import subscriptions from './subscriptions.vue';
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index 5cf574e1387..67a8f11b760 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -1,4 +1,5 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import TimeTrackingHelpState from './help_state.vue';
import TimeTrackingCollapsedState from './collapsed_state.vue';
import TimeTrackingSpentOnlyPane from './spent_only_pane.vue';
@@ -11,6 +12,7 @@ import eventHub from '../../event_hub';
export default {
name: 'IssuableTimeTracker',
components: {
+ GlIcon,
TimeTrackingCollapsedState,
TimeTrackingEstimateOnlyPane,
TimeTrackingSpentOnlyPane,
@@ -111,7 +113,7 @@ export default {
class="close-help-button float-right"
@click="toggleHelpState(false)"
>
- <i class="fa fa-close" aria-hidden="true"> </i>
+ <gl-icon name="close" />
</div>
</div>
<div class="time-tracking-content hide-collapsed">
diff --git a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
index 3b7df369237..5281c03ab3f 100644
--- a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
+++ b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
@@ -6,7 +6,7 @@ import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
const MARK_TEXT = __('Mark as done');
-const TODO_TEXT = __('Add a To Do');
+const TODO_TEXT = __('Add a To-Do');
export default {
directives: {
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 2c108835c36..015219200db 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -5,13 +5,14 @@ import SidebarTimeTracking from './components/time_tracking/sidebar_time_trackin
import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
import ConfidentialIssueSidebar from './components/confidential/confidential_issue_sidebar.vue';
import SidebarMoveIssue from './lib/sidebar_move_issue';
-import LockIssueSidebar from './components/lock/lock_issue_sidebar.vue';
+import IssuableLockForm from './components/lock/issuable_lock_form.vue';
import sidebarParticipants from './components/participants/sidebar_participants.vue';
import sidebarSubscriptions from './components/subscriptions/sidebar_subscriptions.vue';
import Translate from '../vue_shared/translate';
import createDefaultClient from '~/lib/graphql';
import { store } from '~/notes/stores';
import { isInIssuePage } from '~/lib/utils/common_utils';
+import mergeRequestStore from '~/mr_notes/stores';
Vue.use(Translate);
Vue.use(VueApollo);
@@ -79,24 +80,28 @@ function mountConfidentialComponent(mediator) {
});
}
-function mountLockComponent(mediator) {
+function mountLockComponent() {
const el = document.getElementById('js-lock-entry-point');
-
- if (!el) return;
+ const { fullPath } = getSidebarOptions();
const dataNode = document.getElementById('js-lock-issue-data');
const initialData = JSON.parse(dataNode.innerHTML);
- const LockComp = Vue.extend(LockIssueSidebar);
-
- new LockComp({
- propsData: {
- isLocked: initialData.is_locked,
- isEditable: initialData.is_editable,
- mediator,
- issuableType: isInIssuePage() ? 'issue' : 'merge_request',
- },
- }).$mount(el);
+ return el
+ ? new Vue({
+ el,
+ store: isInIssuePage() ? store : mergeRequestStore,
+ provide: {
+ fullPath,
+ },
+ render: createElement =>
+ createElement(IssuableLockForm, {
+ props: {
+ isEditable: initialData.is_editable,
+ },
+ }),
+ })
+ : undefined;
}
function mountParticipantsComponent(mediator) {
diff --git a/app/assets/javascripts/sidebar/services/sidebar_service.js b/app/assets/javascripts/sidebar/services/sidebar_service.js
index 3b8903b4a4c..8714bea1729 100644
--- a/app/assets/javascripts/sidebar/services/sidebar_service.js
+++ b/app/assets/javascripts/sidebar/services/sidebar_service.js
@@ -1,7 +1,7 @@
-import axios from '~/lib/utils/axios_utils';
-import createGqClient, { fetchPolicies } from '~/lib/graphql';
import sidebarDetailsQuery from 'ee_else_ce/sidebar/queries/sidebarDetails.query.graphql';
import sidebarDetailsForHealthStatusFeatureFlagQuery from 'ee_else_ce/sidebar/queries/sidebarDetailsForHealthStatusFeatureFlag.query.graphql';
+import axios from '~/lib/utils/axios_utils';
+import createGqClient, { fetchPolicies } from '~/lib/graphql';
export const gqClient = createGqClient(
{},
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index 34621fc1036..8f1f76a2e02 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -1,6 +1,6 @@
import Store from 'ee_else_ce/sidebar/stores/sidebar_store';
import { visitUrl } from '../lib/utils/url_utility';
-import Flash from '../flash';
+import { deprecatedCreateFlash as Flash } from '../flash';
import Service from './services/sidebar_service';
import { __ } from '~/locale';