summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/boards/components/board_form.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/boards/components/board_form.vue')
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue228
1 files changed, 145 insertions, 83 deletions
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index e4ef3600ff9..dab934352ca 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -1,11 +1,14 @@
<script>
-import { __ } from '~/locale';
+import { GlModal } from '@gitlab/ui';
+import { pick } from 'lodash';
+import { __, s__ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
-import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { visitUrl } from '~/lib/utils/url_utility';
import boardsStore from '~/boards/stores/boards_store';
+import { fullBoardId, getBoardsPath } from '../boards_util';
import BoardConfigurationOptions from './board_configuration_options.vue';
+import createBoardMutation from '../graphql/board.mutation.graphql';
const boardDefaults = {
id: false,
@@ -19,10 +22,28 @@ const boardDefaults = {
hide_closed_list: false,
};
+const formType = {
+ new: 'new',
+ delete: 'delete',
+ edit: 'edit',
+};
+
export default {
+ 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'),
+ },
components: {
BoardScope: () => import('ee_component/boards/components/board_scope.vue'),
- DeprecatedModal,
+ GlModal,
BoardConfigurationOptions,
},
props: {
@@ -63,36 +84,35 @@ export default {
required: false,
default: false,
},
+ currentBoard: {
+ type: Object,
+ required: true,
+ },
+ },
+ inject: {
+ endpoints: {
+ default: {},
+ },
},
data() {
return {
board: { ...boardDefaults, ...this.currentBoard },
- currentBoard: boardsStore.state.currentBoard,
currentPage: boardsStore.state.currentPage,
isLoading: false,
};
},
computed: {
isNewForm() {
- return this.currentPage === 'new';
+ return this.currentPage === formType.new;
},
isDeleteForm() {
- return this.currentPage === 'delete';
+ return this.currentPage === formType.delete;
},
isEditForm() {
- return this.currentPage === 'edit';
- },
- isVisible() {
- return this.currentPage !== '';
+ return this.currentPage === formType.edit;
},
buttonText() {
- if (this.isNewForm) {
- return __('Create board');
- }
- if (this.isDeleteForm) {
- return __('Delete');
- }
- return __('Save changes');
+ return this.$options.i18n[this.currentPage].btnText;
},
buttonKind() {
if (this.isNewForm) {
@@ -104,16 +124,11 @@ export default {
return 'info';
},
title() {
- if (this.isNewForm) {
- return __('Create new board');
- }
- if (this.isDeleteForm) {
- return __('Delete board');
- }
if (this.readonly) {
- return __('Board scope');
+ return this.$options.i18n.scopeModalTitle;
}
- return __('Edit board');
+
+ return this.$options.i18n[this.currentPage].title;
},
readonly() {
return !this.canAdminBoard;
@@ -121,6 +136,33 @@ export default {
submitDisabled() {
return this.isLoading || this.board.name.length === 0;
},
+ 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,
+ };
+ },
+ boardPayload() {
+ const { assignee, milestone, labels } = this.board;
+ return {
+ ...this.board,
+ assignee_id: assignee?.id,
+ milestone_id: milestone?.id,
+ label_ids: labels.length ? labels.map(b => b.id) : [''],
+ };
+ },
},
mounted() {
this.resetFormState();
@@ -129,6 +171,31 @@ export default {
}
},
methods: {
+ callBoardMutation(id) {
+ return this.$apollo.mutate({
+ mutation: createBoardMutation,
+ variables: {
+ ...pick(this.boardPayload, ['hideClosedList', 'hideBacklogList']),
+ id,
+ },
+ });
+ },
+ async updateBoard() {
+ const responses = await Promise.all([
+ // Remove unnecessary REST API call when https://gitlab.com/gitlab-org/gitlab/-/issues/282299#note_462996301 is resolved
+ getBoardsPath(this.endpoints.boardsEndpoint, this.boardPayload),
+ this.callBoardMutation(fullBoardId(this.boardPayload.id)),
+ ]);
+
+ return responses[0].data;
+ },
+ async createBoard() {
+ // TODO: change this to use `createBoard` mutation https://gitlab.com/gitlab-org/gitlab/-/issues/292466 is resolved
+ const boardData = await getBoardsPath(this.endpoints.boardsEndpoint, this.boardPayload);
+ this.callBoardMutation(fullBoardId(boardData.data.id));
+
+ return boardData.data || boardData;
+ },
submit() {
if (this.board.name.length === 0) return;
this.isLoading = true;
@@ -136,31 +203,21 @@ export default {
boardsStore
.deleteBoard(this.currentBoard)
.then(() => {
+ this.isLoading = false;
visitUrl(boardsStore.rootPath);
})
.catch(() => {
- Flash(__('Failed to delete board. Please try again.'));
+ Flash(this.$options.i18n.deleteErrorMessage);
this.isLoading = false;
});
} else {
- boardsStore
- .createBoard(this.board)
- .then(resp => {
- // This handles 2 use cases
- // - In create call we only get one parameter, the new board
- // - In update call, due to Promise.all, we get REST response in
- // array index 0
-
- if (Array.isArray(resp)) {
- return resp[0].data;
- }
- return resp.data ? resp.data : resp;
- })
+ const boardAction = this.boardPayload.id ? this.updateBoard : this.createBoard;
+ boardAction()
.then(data => {
visitUrl(data.board_path);
})
.catch(() => {
- Flash(__('Unable to save your changes. Please try again.'));
+ Flash(this.$options.i18n.saveErrorMessage);
this.isLoading = false;
});
}
@@ -181,53 +238,58 @@ export default {
</script>
<template>
- <deprecated-modal
- v-show="isVisible"
+ <gl-modal
+ modal-id="board-config-modal"
+ modal-class="board-config-modal"
+ content-class="gl-absolute gl-top-7"
+ visible
:hide-footer="readonly"
:title="title"
- :primary-button-label="buttonText"
- :kind="buttonKind"
- :submit-disabled="submitDisabled"
- modal-dialog-class="board-config-modal"
+ :action-primary="primaryProps"
+ :action-cancel="cancelProps"
+ @primary="submit"
@cancel="cancel"
- @submit="submit"
+ @close="cancel"
+ @hide.prevent
>
- <template #body>
- <p v-if="isDeleteForm">{{ __('Are you sure you want to delete this board?') }}</p>
- <form v-else class="js-board-config-modal" @submit.prevent>
- <div v-if="!readonly" class="append-bottom-20">
- <label class="label-bold gl-font-lg" for="board-new-name">{{ __('Title') }}</label>
- <input
- id="board-new-name"
- ref="name"
- v-model="board.name"
- class="form-control"
- data-qa-selector="board_name_field"
- type="text"
- :placeholder="__('Enter board name')"
- @keyup.enter="submit"
- />
- </div>
-
- <board-configuration-options
- :is-new-form="isNewForm"
- :board="board"
- :current-board="currentBoard"
+ <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"
/>
+ </div>
- <board-scope
- v-if="scopedIssueBoardFeatureEnabled"
- :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"
- />
- </form>
- </template>
- </deprecated-modal>
+ <board-configuration-options
+ :is-new-form="isNewForm"
+ :board="board"
+ :current-board="currentBoard"
+ />
+
+ <board-scope
+ v-if="scopedIssueBoardFeatureEnabled"
+ :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"
+ />
+ </form>
+ </gl-modal>
</template>