diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-19 08:27:35 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-19 08:27:35 +0000 |
commit | 7e9c479f7de77702622631cff2628a9c8dcbc627 (patch) | |
tree | c8f718a08e110ad7e1894510980d2155a6549197 /app/assets/javascripts/boards/components/sidebar | |
parent | e852b0ae16db4052c1c567d9efa4facc81146e88 (diff) | |
download | gitlab-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')
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> |