diff options
author | Filipa Lacerda <filipa@gitlab.com> | 2018-02-12 16:49:41 +0000 |
---|---|---|
committer | Filipa Lacerda <filipa@gitlab.com> | 2018-02-12 16:49:41 +0000 |
commit | c33245e9999e0d00fd1da985fcc18af1618b211d (patch) | |
tree | fb5dcc83a109ba571a925f42991baeb5d728a3fa | |
parent | ab7342406256ab5f04d40af496ef014d7c525389 (diff) | |
download | gitlab-ce-c33245e9999e0d00fd1da985fcc18af1618b211d.tar.gz |
Reuse getter42923-close-issue
Add loading button for better UX
6 files changed, 42 insertions, 21 deletions
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index c96f3336d28..df796050e0d 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -9,10 +9,11 @@ import * as constants from '../constants'; import eventHub from '../event_hub'; import issueWarning from '../../vue_shared/components/issue/issue_warning.vue'; - import noteSignedOutWidget from './note_signed_out_widget.vue'; - import discussionLockedWidget from './discussion_locked_widget.vue'; import markdownField from '../../vue_shared/components/markdown/field.vue'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; + import loadingButton from '../../vue_shared/components/loading_button.vue'; + import noteSignedOutWidget from './note_signed_out_widget.vue'; + import discussionLockedWidget from './discussion_locked_widget.vue'; import issuableStateMixin from '../mixins/issuable_state'; export default { @@ -23,6 +24,7 @@ discussionLockedWidget, markdownField, userAvatarLink, + loadingButton, }, mixins: [ issuableStateMixin, @@ -41,11 +43,8 @@ 'getUserData', 'getNoteableData', 'getNotesData', - 'getIssueState', + 'issueState', ]), - issueState() { - return this.getIssueState; - }, isLoggedIn() { return this.getUserData.id; }, @@ -131,6 +130,8 @@ } }, handleSave(withIssueAction) { + this.isSubmitting = true; + if (this.note.length) { const noteData = { endpoint: this.endpoint, @@ -147,7 +148,6 @@ if (this.noteType === constants.DISCUSSION) { noteData.data.note.type = constants.DISCUSSION_NOTE; } - this.isSubmitting = true; this.note = ''; // Empty textarea while being requested. Repopulate in catch this.resizeTextarea(); this.stopPolling(); @@ -189,13 +189,24 @@ Please check your network connection and try again.`; this.toggleIssueState(); } }, + enableButton() { + this.isSubmitting = false; + }, toggleIssueState() { if (this.isIssueOpen) { this.closeIssue() - .catch(() => Flash(__('Something went wrong while closing the issue. Please try again later'))); + .then(() => this.enableButton()) + .catch(() => { + this.enableButton(); + Flash(__('Something went wrong while closing the issue. Please try again later')); + }); } else { this.reopenIssue() - .catch(() => Flash(__('Something went wrong while reopening the issue. Please try again later'))); + .then(() => this.enableButton()) + .catch(() => { + this.enableButton(); + Flash(__('Something went wrong while reopening the issue. Please try again later')); + }); } }, discard(shouldClear = true) { @@ -373,15 +384,19 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown" </li> </ul> </div> - <button - type="button" - @click="handleSave(true)" + + <loading-button v-if="canUpdateIssue" - :class="actionButtonClassNames" + :loading="isSubmitting" + @click="handleSave(true)" + :container-class="[ + actionButtonClassNames, + 'btn btn-comment btn-comment-and-close js-action-button' + ]" :disabled="isSubmitting" - class="btn btn-comment btn-comment-and-close js-action-button"> - {{ issueActionButtonTitle }} - </button> + :label="issueActionButtonTitle" + /> + <button type="button" v-if="note.length" diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index 1877d5bf959..4c846d69b86 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -77,10 +77,10 @@ export const reopenIssue = ({ commit, dispatch, state }) => service dispatch('emitStateChangedEvent', data); }); -export const emitStateChangedEvent = ({ commit }, data) => { +export const emitStateChangedEvent = ({ commit, getters }, data) => { const event = new CustomEvent('issuable_vue_app:change', { detail: { data, - isClosed: data.state === constants.CLOSED, + isClosed: getters.issueState === constants.CLOSED, } }); document.dispatchEvent(event); diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js index 38b48c3bbe4..82024104d73 100644 --- a/app/assets/javascripts/notes/stores/getters.js +++ b/app/assets/javascripts/notes/stores/getters.js @@ -8,7 +8,7 @@ export const getNotesDataByProp = state => prop => state.notesData[prop]; export const getNoteableData = state => state.noteableData; export const getNoteableDataByProp = state => prop => state.noteableData[prop]; -export const getIssueState = state => state.noteableData.state; +export const issueState = state => state.noteableData.state; export const getUserData = state => state.userData || {}; export const getUserDataByProp = state => prop => state.userData && state.userData[prop]; diff --git a/app/assets/javascripts/vue_shared/components/loading_button.vue b/app/assets/javascripts/vue_shared/components/loading_button.vue index ff8c0f7c1d2..6ae6b179f7f 100644 --- a/app/assets/javascripts/vue_shared/components/loading_button.vue +++ b/app/assets/javascripts/vue_shared/components/loading_button.vue @@ -40,7 +40,7 @@ required: false, }, containerClass: { - type: String, + type: [String, Array, Object], required: false, default: 'btn btn-align-content', }, diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js index 6508f4772d2..ab80ed7bbfb 100644 --- a/spec/javascripts/notes/stores/actions_spec.js +++ b/spec/javascripts/notes/stores/actions_spec.js @@ -109,7 +109,7 @@ describe('Actions Notes Store', () => { it('emits an event on the document', () => { document.addEventListener('issuable_vue_app:change', (event) => { expect(event.detail.data).toEqual({ id: '1', state: 'closed' }); - expect(event.detail.isClosed).toEqual(true); + expect(event.detail.isClosed).toEqual(false); }); store.dispatch('emitStateChangedEvent', { id: '1', state: 'closed' }); diff --git a/spec/javascripts/notes/stores/getters_spec.js b/spec/javascripts/notes/stores/getters_spec.js index c5a84b71788..919ffbfdef0 100644 --- a/spec/javascripts/notes/stores/getters_spec.js +++ b/spec/javascripts/notes/stores/getters_spec.js @@ -55,4 +55,10 @@ describe('Getters Notes Store', () => { expect(getters.getCurrentUserLastNote(state)).toEqual(individualNote.notes[0]); }); }); + + describe('issueState', () => { + it('should return the issue state', () => { + expect(getters.issueState(state)).toEqual(noteableDataMock.state); + }); + }); }); |