summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/boards/components/sidebar
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 08:27:35 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 08:27:35 +0000
commit7e9c479f7de77702622631cff2628a9c8dcbc627 (patch)
treec8f718a08e110ad7e1894510980d2155a6549197 /app/assets/javascripts/boards/components/sidebar
parente852b0ae16db4052c1c567d9efa4facc81146e88 (diff)
downloadgitlab-ce-7e9c479f7de77702622631cff2628a9c8dcbc627.tar.gz
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'app/assets/javascripts/boards/components/sidebar')
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue111
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue14
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue71
3 files changed, 187 insertions, 9 deletions
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
new file mode 100644
index 00000000000..6935ead2706
--- /dev/null
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_due_date.vue
@@ -0,0 +1,111 @@
+<script>
+import { mapGetters, mapActions } from 'vuex';
+import { GlButton, GlDatepicker } from '@gitlab/ui';
+import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
+import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ BoardEditableItem,
+ GlButton,
+ GlDatepicker,
+ },
+ data() {
+ return {
+ loading: false,
+ };
+ },
+ computed: {
+ ...mapGetters({ issue: 'activeIssue', projectPathForActiveIssue: 'projectPathForActiveIssue' }),
+ hasDueDate() {
+ return this.issue.dueDate != null;
+ },
+ parsedDueDate() {
+ if (!this.hasDueDate) {
+ return null;
+ }
+
+ return parsePikadayDate(this.issue.dueDate);
+ },
+ formattedDueDate() {
+ if (!this.hasDueDate) {
+ return '';
+ }
+
+ return dateInWords(this.parsedDueDate, true);
+ },
+ },
+ methods: {
+ ...mapActions(['setActiveIssueDueDate']),
+ async openDatePicker() {
+ await this.$nextTick();
+ this.$refs.datePicker.calendar.show();
+ },
+ async setDueDate(date) {
+ this.loading = true;
+ this.$refs.sidebarItem.collapse();
+
+ try {
+ const dueDate = date ? formatDate(date, 'yyyy-mm-dd') : null;
+ await this.setActiveIssueDueDate({ dueDate, projectPath: this.projectPathForActiveIssue });
+ } catch (e) {
+ createFlash({ message: this.$options.i18n.updateDueDateError });
+ } finally {
+ this.loading = false;
+ }
+ },
+ },
+ i18n: {
+ dueDate: __('Due date'),
+ removeDueDate: __('remove due date'),
+ updateDueDateError: __('An error occurred when updating the issue due date'),
+ },
+};
+</script>
+
+<template>
+ <board-editable-item
+ ref="sidebarItem"
+ class="board-sidebar-due-date"
+ :title="$options.i18n.dueDate"
+ :loading="loading"
+ @open="openDatePicker"
+ >
+ <template v-if="hasDueDate" #collapsed>
+ <div class="gl-display-flex gl-align-items-center">
+ <strong class="gl-text-gray-900">{{ formattedDueDate }}</strong>
+ <span class="gl-mx-2">-</span>
+ <gl-button
+ variant="link"
+ class="gl-text-gray-400!"
+ data-testid="reset-button"
+ :disabled="loading"
+ @click="setDueDate(null)"
+ >
+ {{ $options.i18n.removeDueDate }}
+ </gl-button>
+ </div>
+ </template>
+ <template>
+ <gl-datepicker
+ ref="datePicker"
+ :value="parsedDueDate"
+ show-clear-button
+ @input="setDueDate"
+ @clear="setDueDate(null)"
+ />
+ </template>
+ </board-editable-item>
+</template>
+<style>
+/*
+ * This can be removed after closing:
+ * https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1048
+ */
+.board-sidebar-due-date .gl-datepicker,
+.board-sidebar-due-date .gl-datepicker-input {
+ width: 100%;
+}
+</style>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
index 0f063c7582e..9d537a4ef2c 100644
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
@@ -21,9 +21,9 @@ export default {
},
inject: ['labelsFetchPath', 'labelsManagePath', 'labelsFilterBasePath'],
computed: {
- ...mapGetters({ issue: 'getActiveIssue' }),
+ ...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
selectedLabels() {
- const { labels = [] } = this.issue;
+ const { labels = [] } = this.activeIssue;
return labels.map(label => ({
...label,
@@ -31,17 +31,13 @@ export default {
}));
},
issueLabels() {
- const { labels = [] } = this.issue;
+ const { labels = [] } = this.activeIssue;
return labels.map(label => ({
...label,
scoped: isScopedLabel(label),
}));
},
- projectPath() {
- const { referencePath = '' } = this.issue;
- return referencePath.slice(0, referencePath.indexOf('#'));
- },
},
methods: {
...mapActions(['setActiveIssueLabels']),
@@ -55,7 +51,7 @@ export default {
.filter(label => !payload.find(selected => selected.id === label.id))
.map(label => label.id);
- const input = { addLabelIds, removeLabelIds, projectPath: this.projectPath };
+ const input = { addLabelIds, removeLabelIds, projectPath: this.projectPathForActiveIssue };
await this.setActiveIssueLabels(input);
} catch (e) {
createFlash({ message: __('An error occurred while updating labels.') });
@@ -68,7 +64,7 @@ export default {
try {
const removeLabelIds = [getIdFromGraphQLId(id)];
- const input = { removeLabelIds, projectPath: this.projectPath };
+ const input = { removeLabelIds, projectPath: this.projectPathForActiveIssue };
await this.setActiveIssueLabels(input);
} catch (e) {
createFlash({ message: __('An error occurred when removing the label.') });
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
new file mode 100644
index 00000000000..ed069cea630
--- /dev/null
+++ b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
@@ -0,0 +1,71 @@
+<script>
+import { mapGetters, mapActions } from 'vuex';
+import { GlToggle } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { __, s__ } from '~/locale';
+
+export default {
+ i18n: {
+ header: {
+ title: __('Notifications'),
+ /* Any change to subscribeDisabledDescription
+ must be reflected in app/helpers/notifications_helper.rb */
+ subscribeDisabledDescription: __(
+ 'Notifications have been disabled by the project or group owner',
+ ),
+ },
+ updateSubscribedErrorMessage: s__(
+ 'IssueBoards|An error occurred while setting notifications status.',
+ ),
+ },
+ components: {
+ GlToggle,
+ },
+ data() {
+ return {
+ loading: false,
+ };
+ },
+ computed: {
+ ...mapGetters(['activeIssue', 'projectPathForActiveIssue']),
+ notificationText() {
+ return this.activeIssue.emailsDisabled
+ ? this.$options.i18n.header.subscribeDisabledDescription
+ : this.$options.i18n.header.title;
+ },
+ },
+ methods: {
+ ...mapActions(['setActiveIssueSubscribed']),
+ async handleToggleSubscription() {
+ this.loading = true;
+
+ try {
+ await this.setActiveIssueSubscribed({
+ subscribed: !this.activeIssue.subscribed,
+ projectPath: this.projectPathForActiveIssue,
+ });
+ } catch (error) {
+ createFlash({ message: this.$options.i18n.updateSubscribedErrorMessage });
+ } finally {
+ this.loading = false;
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="gl-display-flex gl-align-items-center gl-justify-content-space-between"
+ data-testid="sidebar-notifications"
+ >
+ <span data-testid="notification-header-text"> {{ notificationText }} </span>
+ <gl-toggle
+ v-if="!activeIssue.emailsDisabled"
+ :value="activeIssue.subscribed"
+ :is-loading="loading"
+ data-testid="notification-subscribe-toggle"
+ @change="handleToggleSubscription"
+ />
+ </div>
+</template>