diff options
Diffstat (limited to 'app/assets/javascripts/boards/components/board_form.vue')
-rw-r--r-- | app/assets/javascripts/boards/components/board_form.vue | 228 |
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> |