summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2018-02-12 16:49:41 +0000
committerFilipa Lacerda <filipa@gitlab.com>2018-02-12 16:49:41 +0000
commitc33245e9999e0d00fd1da985fcc18af1618b211d (patch)
treefb5dcc83a109ba571a925f42991baeb5d728a3fa
parentab7342406256ab5f04d40af496ef014d7c525389 (diff)
downloadgitlab-ce-42923-close-issue.tar.gz
Reuse getter42923-close-issue
Add loading button for better UX
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue47
-rw-r--r--app/assets/javascripts/notes/stores/actions.js4
-rw-r--r--app/assets/javascripts/notes/stores/getters.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/loading_button.vue2
-rw-r--r--spec/javascripts/notes/stores/actions_spec.js2
-rw-r--r--spec/javascripts/notes/stores/getters_spec.js6
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);
+ });
+ });
});