debian-mirror-gitlab/app/assets/javascripts/boards/components/board_form.vue

389 lines
10 KiB
Vue
Raw Normal View History

2019-09-30 21:07:59 +05:30
<script>
2021-09-04 01:27:46 +05:30
import { GlModal, GlAlert } from '@gitlab/ui';
import { mapGetters, mapActions, mapState } from 'vuex';
2021-11-11 11:23:49 +05:30
import { TYPE_USER, TYPE_ITERATION, TYPE_MILESTONE } from '~/graphql_shared/constants';
2021-03-08 18:12:59 +05:30
import { convertToGraphQLId } from '~/graphql_shared/utils';
2021-09-30 23:02:18 +05:30
import { getParameterByName, visitUrl } from '~/lib/utils/url_utility';
2021-03-11 19:13:27 +05:30
import { __, s__ } from '~/locale';
2021-03-08 18:12:59 +05:30
import { fullLabelId, fullBoardId } from '../boards_util';
2021-03-11 19:13:27 +05:30
import { formType } from '../constants';
2019-09-30 21:07:59 +05:30
2021-03-08 18:12:59 +05:30
import createBoardMutation from '../graphql/board_create.mutation.graphql';
import destroyBoardMutation from '../graphql/board_destroy.mutation.graphql';
2021-03-11 19:13:27 +05:30
import updateBoardMutation from '../graphql/board_update.mutation.graphql';
import BoardConfigurationOptions from './board_configuration_options.vue';
2021-01-03 14:25:43 +05:30
2019-09-30 21:07:59 +05:30
const boardDefaults = {
id: false,
name: '',
labels: [],
2021-10-27 15:23:28 +05:30
milestone: {},
2021-03-08 18:12:59 +05:30
iteration_id: undefined,
2019-09-30 21:07:59 +05:30
assignee: {},
weight: null,
2021-01-03 14:25:43 +05:30
hide_backlog_list: false,
hide_closed_list: false,
2019-09-30 21:07:59 +05:30
};
export default {
2021-02-22 17:27:13 +05:30
i18n: {
[formType.new]: { title: s__('Board|Create new board'), btnText: s__('Board|Create board') },
[formType.delete]: { title: s__('Board|Delete board'), btnText: __('Delete') },
[formType.edit]: { title: s__('Board|Edit board'), btnText: __('Save changes') },
scopeModalTitle: s__('Board|Board scope'),
cancelButtonText: __('Cancel'),
deleteErrorMessage: s__('Board|Failed to delete board. Please try again.'),
saveErrorMessage: __('Unable to save your changes. Please try again.'),
deleteConfirmationMessage: s__('Board|Are you sure you want to delete this board?'),
titleFieldLabel: __('Title'),
titleFieldPlaceholder: s__('Board|Enter board name'),
},
2019-09-30 21:07:59 +05:30
components: {
BoardScope: () => import('ee_component/boards/components/board_scope.vue'),
2021-02-22 17:27:13 +05:30
GlModal,
2021-01-03 14:25:43 +05:30
BoardConfigurationOptions,
2021-09-04 01:27:46 +05:30
GlAlert,
2019-09-30 21:07:59 +05:30
},
2021-03-08 18:12:59 +05:30
inject: {
fullPath: {
default: '',
},
rootPath: {
default: '',
},
},
2019-09-30 21:07:59 +05:30
props: {
canAdminBoard: {
type: Boolean,
required: true,
},
2020-11-24 15:15:51 +05:30
labelsPath: {
2019-09-30 21:07:59 +05:30
type: String,
required: true,
},
2020-11-24 15:15:51 +05:30
labelsWebUrl: {
2019-09-30 21:07:59 +05:30
type: String,
required: true,
},
scopedIssueBoardFeatureEnabled: {
type: Boolean,
required: false,
default: false,
},
projectId: {
type: Number,
required: false,
default: 0,
},
groupId: {
type: Number,
required: false,
default: 0,
},
weights: {
type: Array,
required: false,
default: () => [],
},
enableScopedLabels: {
type: Boolean,
required: false,
default: false,
},
2021-02-22 17:27:13 +05:30
currentBoard: {
type: Object,
required: true,
},
2021-03-11 19:13:27 +05:30
currentPage: {
type: String,
required: true,
},
2021-02-22 17:27:13 +05:30
},
2019-09-30 21:07:59 +05:30
data() {
return {
board: { ...boardDefaults, ...this.currentBoard },
isLoading: false,
};
},
computed: {
2021-09-04 01:27:46 +05:30
...mapState(['error']),
2021-04-29 21:17:54 +05:30
...mapGetters(['isIssueBoard', 'isGroupBoard', 'isProjectBoard']),
2019-09-30 21:07:59 +05:30
isNewForm() {
2021-02-22 17:27:13 +05:30
return this.currentPage === formType.new;
2019-09-30 21:07:59 +05:30
},
isDeleteForm() {
2021-02-22 17:27:13 +05:30
return this.currentPage === formType.delete;
2019-09-30 21:07:59 +05:30
},
isEditForm() {
2021-02-22 17:27:13 +05:30
return this.currentPage === formType.edit;
2019-09-30 21:07:59 +05:30
},
buttonText() {
2021-02-22 17:27:13 +05:30
return this.$options.i18n[this.currentPage].btnText;
2019-09-30 21:07:59 +05:30
},
buttonKind() {
if (this.isNewForm) {
return 'success';
}
if (this.isDeleteForm) {
return 'danger';
}
2021-04-29 21:17:54 +05:30
return 'confirm';
2019-09-30 21:07:59 +05:30
},
title() {
if (this.readonly) {
2021-02-22 17:27:13 +05:30
return this.$options.i18n.scopeModalTitle;
2019-09-30 21:07:59 +05:30
}
2021-02-22 17:27:13 +05:30
return this.$options.i18n[this.currentPage].title;
2019-09-30 21:07:59 +05:30
},
readonly() {
return !this.canAdminBoard;
},
submitDisabled() {
return this.isLoading || this.board.name.length === 0;
},
2021-02-22 17:27:13 +05:30
primaryProps() {
return {
text: this.buttonText,
attributes: [
{
variant: this.buttonKind,
disabled: this.submitDisabled,
loading: this.isLoading,
'data-qa-selector': 'save_changes_button',
},
],
};
},
cancelProps() {
return {
text: this.$options.i18n.cancelButtonText,
};
},
2021-03-08 18:12:59 +05:30
currentMutation() {
return this.board.id ? updateBoardMutation : createBoardMutation;
},
2021-04-29 21:17:54 +05:30
deleteMutation() {
return destroyBoardMutation;
},
2021-04-17 20:07:23 +05:30
baseMutationVariables() {
2021-03-08 18:12:59 +05:30
const { board } = this;
2021-04-17 20:07:23 +05:30
const variables = {
2021-03-08 18:12:59 +05:30
name: board.name,
hideBacklogList: board.hide_backlog_list,
hideClosedList: board.hide_closed_list,
2021-02-22 17:27:13 +05:30
};
2021-03-08 18:12:59 +05:30
return board.id
? {
2021-04-17 20:07:23 +05:30
...variables,
2021-03-08 18:12:59 +05:30
id: fullBoardId(board.id),
}
: {
2021-04-17 20:07:23 +05:30
...variables,
projectPath: this.isProjectBoard ? this.fullPath : undefined,
groupPath: this.isGroupBoard ? this.fullPath : undefined,
2021-03-08 18:12:59 +05:30
};
2021-02-22 17:27:13 +05:30
},
2021-04-29 21:17:54 +05:30
issueBoardScopeMutationVariables() {
2021-04-17 20:07:23 +05:30
return {
weight: this.board.weight,
2021-11-11 11:23:49 +05:30
assigneeId: this.board.assignee?.id
? convertToGraphQLId(TYPE_USER, this.board.assignee.id)
: null,
2021-10-27 15:23:28 +05:30
milestoneId: this.board.milestone?.id
? convertToGraphQLId(TYPE_MILESTONE, this.board.milestone.id)
2021-04-17 20:07:23 +05:30
: null,
iterationId: this.board.iteration_id
2021-09-30 23:02:18 +05:30
? convertToGraphQLId(TYPE_ITERATION, this.board.iteration_id)
2021-04-17 20:07:23 +05:30
: null,
};
},
2021-04-29 21:17:54 +05:30
boardScopeMutationVariables() {
return {
labelIds: this.board.labels.map(fullLabelId),
...(this.isIssueBoard && this.issueBoardScopeMutationVariables),
};
},
2021-04-17 20:07:23 +05:30
mutationVariables() {
return {
...this.baseMutationVariables,
...(this.scopedIssueBoardFeatureEnabled ? this.boardScopeMutationVariables : {}),
};
},
2019-09-30 21:07:59 +05:30
},
mounted() {
this.resetFormState();
if (this.$refs.name) {
this.$refs.name.focus();
}
},
methods: {
2021-09-04 01:27:46 +05:30
...mapActions(['setError', 'unsetError']),
2021-04-17 20:07:23 +05:30
boardCreateResponse(data) {
return data.createBoard.board.webPath;
},
boardUpdateResponse(data) {
const path = data.updateBoard.board.webPath;
const param = getParameterByName('group_by')
? `?group_by=${getParameterByName('group_by')}`
: '';
return `${path}${param}`;
},
2021-09-04 01:27:46 +05:30
cancel() {
this.$emit('cancel');
},
2021-03-08 18:12:59 +05:30
async createOrUpdateBoard() {
const response = await this.$apollo.mutate({
mutation: this.currentMutation,
variables: { input: this.mutationVariables },
});
2021-02-22 17:27:13 +05:30
2021-03-08 18:12:59 +05:30
if (!this.board.id) {
2021-04-17 20:07:23 +05:30
return this.boardCreateResponse(response.data);
2021-03-08 18:12:59 +05:30
}
2021-02-22 17:27:13 +05:30
2021-04-17 20:07:23 +05:30
return this.boardUpdateResponse(response.data);
2021-02-22 17:27:13 +05:30
},
2021-04-29 21:17:54 +05:30
async deleteBoard() {
await this.$apollo.mutate({
mutation: this.deleteMutation,
variables: {
id: fullBoardId(this.board.id),
},
});
},
2021-03-08 18:12:59 +05:30
async submit() {
2019-09-30 21:07:59 +05:30
if (this.board.name.length === 0) return;
this.isLoading = true;
if (this.isDeleteForm) {
2021-03-08 18:12:59 +05:30
try {
2021-04-29 21:17:54 +05:30
await this.deleteBoard();
2021-03-08 18:12:59 +05:30
visitUrl(this.rootPath);
} catch {
2021-09-04 01:27:46 +05:30
this.setError({ message: this.$options.i18n.deleteErrorMessage });
2021-03-08 18:12:59 +05:30
} finally {
this.isLoading = false;
}
2019-09-30 21:07:59 +05:30
} else {
2021-03-08 18:12:59 +05:30
try {
const url = await this.createOrUpdateBoard();
visitUrl(url);
} catch {
2021-09-04 01:27:46 +05:30
this.setError({ message: this.$options.i18n.saveErrorMessage });
2021-03-08 18:12:59 +05:30
} finally {
this.isLoading = false;
}
2019-09-30 21:07:59 +05:30
}
},
resetFormState() {
if (this.isNewForm) {
// Clear the form when we open the "New board" modal
this.board = { ...boardDefaults };
} else if (this.currentBoard && Object.keys(this.currentBoard).length) {
this.board = { ...boardDefaults, ...this.currentBoard };
}
},
2021-09-04 01:27:46 +05:30
setIteration(iterationId) {
this.board.iteration_id = iterationId;
},
setBoardLabels(labels) {
labels.forEach((label) => {
if (label.set && !this.board.labels.find((l) => l.id === label.id)) {
2021-11-11 11:23:49 +05:30
this.board.labels.push({
...label,
textColor: label.text_color,
});
2021-09-04 01:27:46 +05:30
} else if (!label.set) {
this.board.labels = this.board.labels.filter((selected) => selected.id !== label.id);
}
});
},
2021-10-27 15:23:28 +05:30
setAssignee(assigneeId) {
this.$set(this.board, 'assignee', {
id: assigneeId,
});
},
setMilestone(milestoneId) {
this.$set(this.board, 'milestone', {
id: milestoneId,
});
},
setWeight(weight) {
this.$set(this.board, 'weight', weight);
},
2019-09-30 21:07:59 +05:30
},
};
</script>
<template>
2021-02-22 17:27:13 +05:30
<gl-modal
modal-id="board-config-modal"
modal-class="board-config-modal"
content-class="gl-absolute gl-top-7"
visible
2019-09-30 21:07:59 +05:30
:hide-footer="readonly"
:title="title"
2021-02-22 17:27:13 +05:30
:action-primary="primaryProps"
:action-cancel="cancelProps"
@primary="submit"
2019-09-30 21:07:59 +05:30
@cancel="cancel"
2021-02-22 17:27:13 +05:30
@close="cancel"
@hide.prevent
2019-09-30 21:07:59 +05:30
>
2021-09-04 01:27:46 +05:30
<gl-alert
v-if="error"
class="gl-mb-3"
variant="danger"
:dismissible="true"
@dismiss="unsetError"
>
{{ error }}
</gl-alert>
2021-02-22 17:27:13 +05:30
<p v-if="isDeleteForm" data-testid="delete-confirmation-message">
{{ $options.i18n.deleteConfirmationMessage }}
</p>
<form v-else class="js-board-config-modal" data-testid="board-form-wrapper" @submit.prevent>
<div v-if="!readonly" class="gl-mb-5" data-testid="board-form">
<label class="gl-font-weight-bold gl-font-lg" for="board-new-name">
{{ $options.i18n.titleFieldLabel }}
</label>
<input
id="board-new-name"
ref="name"
v-model="board.name"
class="form-control"
data-qa-selector="board_name_field"
type="text"
:placeholder="$options.i18n.titleFieldPlaceholder"
@keyup.enter="submit"
2021-01-03 14:25:43 +05:30
/>
2021-02-22 17:27:13 +05:30
</div>
2021-01-03 14:25:43 +05:30
2021-02-22 17:27:13 +05:30
<board-configuration-options
2021-03-08 18:12:59 +05:30
:hide-backlog-list.sync="board.hide_backlog_list"
:hide-closed-list.sync="board.hide_closed_list"
2021-03-11 19:13:27 +05:30
:readonly="readonly"
2021-02-22 17:27:13 +05:30
/>
<board-scope
2021-04-29 21:17:54 +05:30
v-if="scopedIssueBoardFeatureEnabled"
2021-02-22 17:27:13 +05:30
:collapse-scope="isNewForm"
:board="board"
:can-admin-board="canAdminBoard"
:labels-path="labelsPath"
:labels-web-url="labelsWebUrl"
:enable-scoped-labels="enableScopedLabels"
:project-id="projectId"
:group-id="groupId"
:weights="weights"
2021-03-08 18:12:59 +05:30
@set-iteration="setIteration"
2021-09-04 01:27:46 +05:30
@set-board-labels="setBoardLabels"
2021-10-27 15:23:28 +05:30
@set-assignee="setAssignee"
@set-milestone="setMilestone"
@set-weight="setWeight"
2021-02-22 17:27:13 +05:30
/>
</form>
</gl-modal>
2019-09-30 21:07:59 +05:30
</template>