Use mapActions, mapGetters and mapMutations for components
This commit is contained in:
parent
4e81ad2ab9
commit
ffef16690c
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
/* global Flash */
|
||||
|
||||
import { mapActions } from 'vuex';
|
||||
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||
import markdownField from '../../vue_shared/components/markdown/field.vue';
|
||||
import issueNoteSignedOutWidget from './issue_note_signed_out_widget.vue';
|
||||
|
@ -60,6 +61,9 @@
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'saveNote'
|
||||
]),
|
||||
handleSave(withIssueAction) {
|
||||
if (this.note.length) {
|
||||
const noteData = {
|
||||
|
@ -79,7 +83,7 @@
|
|||
noteData.data.note.type = constants.DISCUSSION_NOTE;
|
||||
}
|
||||
|
||||
this.$store.dispatch('saveNote', noteData)
|
||||
this.saveNote(noteData)
|
||||
.then((res) => {
|
||||
if (res.errors) {
|
||||
if (res.errors.commands_only) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<script>
|
||||
/* global Flash */
|
||||
|
||||
import { mapActions } from 'vuex';
|
||||
import { TOGGLE_DISCUSSION } from '../stores/mutation_types';
|
||||
import { SYSTEM_NOTE } from '../constants';
|
||||
import issueNote from './issue_note.vue';
|
||||
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||
import issueNoteHeader from './issue_note_header.vue';
|
||||
|
@ -47,9 +49,15 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'saveNote',
|
||||
]),
|
||||
...mapMutations({
|
||||
toggleDiscussion: TOGGLE_DISCUSSION,
|
||||
}),
|
||||
componentName(note) {
|
||||
if (note.isPlaceholderNote) {
|
||||
if (note.placeholderType === 'systemNote') {
|
||||
if (note.placeholderType === SYSTEM_NOTE) {
|
||||
return placeholderSystemNote;
|
||||
}
|
||||
return placeholderNote;
|
||||
|
@ -61,9 +69,7 @@ export default {
|
|||
return note.isPlaceholderNote ? note.notes[0] : note;
|
||||
},
|
||||
toggleDiscussion() {
|
||||
this.$store.commit('toggleDiscussion', {
|
||||
discussionId: this.note.id,
|
||||
});
|
||||
this.toggleDiscussion({ discussionId: this.note.id });
|
||||
},
|
||||
showReplyForm() {
|
||||
this.isReplying = true;
|
||||
|
@ -93,13 +99,11 @@ export default {
|
|||
},
|
||||
};
|
||||
|
||||
this.$store.dispatch('saveNote', replyData)
|
||||
this.saveNote(replyData)
|
||||
.then(() => {
|
||||
this.isReplying = false;
|
||||
})
|
||||
.catch(() => {
|
||||
Flash('Something went wrong while adding your reply. Please try again.');
|
||||
});
|
||||
.catch(() => Flash('Something went wrong while adding your reply. Please try again.'));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -132,8 +136,7 @@ export default {
|
|||
:edited-at="note.last_updated_at"
|
||||
:edited-by="note.last_updated_by"
|
||||
actionText="Last updated"
|
||||
className="discussion-headline-light js-discussion-headline"
|
||||
/>
|
||||
className="discussion-headline-light js-discussion-headline" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
@ -162,7 +165,8 @@ export default {
|
|||
saveButtonTitle="Comment"
|
||||
:update-handler="saveReply"
|
||||
:cancel-handler="cancelReplyForm"
|
||||
ref="noteForm" />
|
||||
ref="noteForm"
|
||||
/>
|
||||
<issue-note-signed-out-widget v-if="!canReply" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
/* global Flash */
|
||||
|
||||
import { mapGetters } from 'vuex';
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||
import issueNoteHeader from './issue_note_header.vue';
|
||||
import issueNoteActions from './issue_note_actions.vue';
|
||||
|
@ -50,6 +50,11 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'deleteNote',
|
||||
'updateNote',
|
||||
'scrollToNoteIfNeeded',
|
||||
]),
|
||||
editHandler() {
|
||||
this.isEditing = true;
|
||||
},
|
||||
|
@ -59,13 +64,12 @@ export default {
|
|||
|
||||
if (isConfirmed) {
|
||||
this.isDeleting = true;
|
||||
this.$store
|
||||
.dispatch('deleteNote', this.note)
|
||||
this.deleteNote(this.note)
|
||||
.then(() => {
|
||||
this.isDeleting = false;
|
||||
})
|
||||
.catch(() => {
|
||||
new Flash('Something went wrong while deleting your note. Please try again.'); // eslint-disable-line
|
||||
Flash('Something went wrong while deleting your note. Please try again.');
|
||||
this.isDeleting = false;
|
||||
});
|
||||
}
|
||||
|
@ -81,14 +85,12 @@ export default {
|
|||
},
|
||||
};
|
||||
|
||||
this.$store.dispatch('updateNote', data)
|
||||
this.updateNote(data)
|
||||
.then(() => {
|
||||
this.isEditing = false;
|
||||
$(this.$refs.noteBody.$el).renderGFM();
|
||||
})
|
||||
.catch(() => {
|
||||
Flash('Something went wrong while editing your comment. Please try again.');
|
||||
});
|
||||
.catch(() => Flash('Something went wrong while editing your comment. Please try again.'));
|
||||
},
|
||||
formCancelHandler(shouldConfirm) {
|
||||
if (shouldConfirm && this.$refs.noteBody.$refs.noteForm.isDirty) {
|
||||
|
@ -106,7 +108,7 @@ export default {
|
|||
eventHub.$on('enterEditMode', ({ noteId }) => {
|
||||
if (noteId === this.note.id) {
|
||||
this.isEditing = true;
|
||||
this.$store.dispatch('scrollToNoteIfNeeded', $(this.$el));
|
||||
this.scrollToNoteIfNeeded($(this.$el));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -124,7 +126,8 @@ export default {
|
|||
:link-href="author.path"
|
||||
:img-src="author.avatar_url"
|
||||
:img-alt="author.name"
|
||||
:img-size="40" />
|
||||
:img-size="40"
|
||||
/>
|
||||
</div>
|
||||
<div class="timeline-content">
|
||||
<div class="note-header">
|
||||
|
@ -132,7 +135,8 @@ export default {
|
|||
:author="author"
|
||||
:created-at="note.created_at"
|
||||
:note-id="note.id"
|
||||
actionText="commented" />
|
||||
actionText="commented"
|
||||
/>
|
||||
<issue-note-actions
|
||||
:author-id="author.id"
|
||||
:note-id="note.id"
|
||||
|
@ -142,7 +146,8 @@ export default {
|
|||
:can-report-as-abuse="canReportAsAbuse"
|
||||
:report-abuse-path="note.report_abuse_path"
|
||||
:edit-handler="editHandler"
|
||||
:delete-handler="deleteHandler" />
|
||||
:delete-handler="deleteHandler"
|
||||
/>
|
||||
</div>
|
||||
<issue-note-body
|
||||
:note="note"
|
||||
|
@ -150,7 +155,8 @@ export default {
|
|||
:is-editing="isEditing"
|
||||
:form-update-handler="formUpdateHandler"
|
||||
:form-cancel-handler="formCancelHandler"
|
||||
ref="noteBody" />
|
||||
ref="noteBody"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import emojiSmiling from 'icons/_emoji_slightly_smiling_face.svg';
|
||||
import emojiSmile from 'icons/_emoji_smile.svg';
|
||||
import emojiSmiley from 'icons/_emoji_smiley.svg';
|
||||
import loadingIcon from '../../vue_shared/components/loadingIcon.vue';
|
||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -51,6 +51,9 @@ export default {
|
|||
emojiSmiley,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
loadingIcon,
|
||||
},
|
||||
computed: {
|
||||
shouldShowActionsDropdown() {
|
||||
return window.gon.current_user_id && (this.canEdit || this.canReportAsAbuse);
|
||||
|
@ -82,13 +85,16 @@ export default {
|
|||
<loading-icon />
|
||||
<span
|
||||
v-html="emojiSmiling"
|
||||
class="link-highlight award-control-icon-neutral"></span>
|
||||
class="link-highlight award-control-icon-neutral">
|
||||
</span>
|
||||
<span
|
||||
v-html="emojiSmiley"
|
||||
class="link-highlight award-control-icon-positive"></span>
|
||||
class="link-highlight award-control-icon-positive">
|
||||
</span>
|
||||
<span
|
||||
v-html="emojiSmile"
|
||||
class="link-highlight award-control-icon-super-positive"></span>
|
||||
class="link-highlight award-control-icon-super-positive">
|
||||
</span>
|
||||
</a>
|
||||
<div
|
||||
v-if="shouldShowActionsDropdown"
|
||||
|
@ -101,7 +107,8 @@ export default {
|
|||
data-container="body">
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-ellipsis-v icon"></i>
|
||||
class="fa fa-ellipsis-v icon">
|
||||
</i>
|
||||
</button>
|
||||
<ul class="dropdown-menu more-actions-dropdown dropdown-open-left">
|
||||
<template v-if="canEdit">
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
/* global Flash */
|
||||
|
||||
import { mapActions } from 'vuex';
|
||||
import emojiSmiling from 'icons/_emoji_slightly_smiling_face.svg';
|
||||
import emojiSmile from 'icons/_emoji_smile.svg';
|
||||
import emojiSmiley from 'icons/_emoji_smiley.svg';
|
||||
|
@ -78,6 +79,9 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'toggleAward',
|
||||
]),
|
||||
getAwardHTML(name) {
|
||||
return Emoji.glEmojiTag(name);
|
||||
},
|
||||
|
@ -92,7 +96,7 @@ export default {
|
|||
const restrictedEmojis = ['thumbsup', 'thumbsdown'];
|
||||
const { myUserId, noteAuthorId } = this;
|
||||
|
||||
// Users can not add :+1: and :-1: to their notes
|
||||
// Users can not add :+1: and :-1: to their own notes
|
||||
if (myUserId === noteAuthorId && restrictedEmojis.indexOf(awardName) > -1) {
|
||||
isAllowed = false;
|
||||
}
|
||||
|
@ -149,13 +153,11 @@ export default {
|
|||
awardName,
|
||||
};
|
||||
|
||||
this.$store.dispatch('toggleAward', data)
|
||||
this.toggleAward(data)
|
||||
.then(() => {
|
||||
$(this.$el).find('.award-control').tooltip('fixTitle');
|
||||
})
|
||||
.catch(() => {
|
||||
Flash('Something went wrong on our end.');
|
||||
});
|
||||
.catch(() => Flash('Something went wrong on our end.'));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -189,13 +191,16 @@ export default {
|
|||
type="button">
|
||||
<span
|
||||
v-html="emojiSmiling"
|
||||
class="award-control-icon award-control-icon-neutral"></span>
|
||||
class="award-control-icon award-control-icon-neutral">
|
||||
</span>
|
||||
<span
|
||||
v-html="emojiSmiley"
|
||||
class="award-control-icon award-control-icon-positive"></span>
|
||||
class="award-control-icon award-control-icon-positive">
|
||||
</span>
|
||||
<span
|
||||
v-html="emojiSmile"
|
||||
class="award-control-icon award-control-icon-super-positive"></span>
|
||||
class="award-control-icon award-control-icon-super-positive">
|
||||
</span>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-spinner fa-spin award-control-icon award-control-icon-loading"></i>
|
||||
|
|
|
@ -38,6 +38,7 @@ export default {
|
|||
</a>
|
||||
<time-ago-tooltip
|
||||
:time="editedAt"
|
||||
tooltip-placement="bottom" />
|
||||
tooltip-placement="bottom"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<script>
|
||||
import { mapMutations } from 'vuex';
|
||||
import timeAgoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
|
||||
import * as types from '../stores/mutation_types';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -52,12 +54,15 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
setTargetNoteHash: types.SET_TARGET_NOTE_HASH,
|
||||
}),
|
||||
handleToggle() {
|
||||
this.isExpanded = !this.isExpanded;
|
||||
this.toggleHandler();
|
||||
},
|
||||
updateTargetNoteHash() {
|
||||
this.$store.commit('setTargetNoteHash', this.noteTimestampLink);
|
||||
this.setTargetNoteHash(this.noteTimestampLink);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -81,13 +86,15 @@ export default {
|
|||
<span
|
||||
v-if="actionTextHtml"
|
||||
v-html="actionTextHtml"
|
||||
class="system-note-message"></span>
|
||||
class="system-note-message">
|
||||
</span>
|
||||
<a
|
||||
:href="noteTimestampLink"
|
||||
@click="updateTargetNoteHash">
|
||||
<time-ago-tooltip
|
||||
:time="createdAt"
|
||||
tooltipPlacement="bottom" />
|
||||
tooltipPlacement="bottom"
|
||||
/>
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
|
@ -101,7 +108,8 @@ export default {
|
|||
<i
|
||||
:class="toggleChevronClass"
|
||||
class="fa"
|
||||
aria-hidden="true"></i>
|
||||
aria-hidden="true">
|
||||
</i>
|
||||
Toggle discussion
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
/* global Flash */
|
||||
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import VueResource from 'vue-resource';
|
||||
import storeOptions from '../stores/issue_notes_store';
|
||||
import { mapGetters, mapActions, mapMutations } from 'vuex';
|
||||
import store from '../stores/';
|
||||
import * as constants from '../constants'
|
||||
import * as types from '../stores/mutation_types';
|
||||
import eventHub from '../event_hub';
|
||||
import issueNote from './issue_note.vue';
|
||||
import issueDiscussion from './issue_discussion.vue';
|
||||
|
@ -12,7 +13,7 @@ import issueSystemNote from './issue_system_note.vue';
|
|||
import issueCommentForm from './issue_comment_form.vue';
|
||||
import placeholderNote from './issue_placeholder_note.vue';
|
||||
import placeholderSystemNote from './issue_placeholder_system_note.vue';
|
||||
import store from './store';
|
||||
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||
|
||||
export default {
|
||||
name: 'IssueNotes',
|
||||
|
@ -27,19 +28,32 @@ export default {
|
|||
issueDiscussion,
|
||||
issueSystemNote,
|
||||
issueCommentForm,
|
||||
loadingIcon,
|
||||
placeholderNote,
|
||||
placeholderSystemNote,
|
||||
},
|
||||
computed: {
|
||||
...Vuex.mapGetters([
|
||||
...mapGetters([
|
||||
'notes',
|
||||
'notesById',
|
||||
]),
|
||||
},
|
||||
methods: {
|
||||
componentName(note) {
|
||||
...mapActions({
|
||||
actionFetchNotes: 'fetchNotes',
|
||||
}),
|
||||
...mapActions([
|
||||
'poll',
|
||||
'toggleAward',
|
||||
'scrollToNoteIfNeeded',
|
||||
]),
|
||||
...mapMutations({
|
||||
setLastFetchedAt: types.SET_LAST_FETCHED_AT,
|
||||
setTargetNoteHash: types.SET_TARGET_NOTE_HASH,
|
||||
}),
|
||||
getComponentName(note) {
|
||||
if (note.isPlaceholderNote) {
|
||||
if (note.placeholderType === 'systemNote') {
|
||||
if (note.placeholderType === constants.SYSTEM_NOTE) {
|
||||
return placeholderSystemNote;
|
||||
}
|
||||
return placeholderNote;
|
||||
|
@ -49,13 +63,13 @@ export default {
|
|||
|
||||
return issueDiscussion;
|
||||
},
|
||||
componentData(note) {
|
||||
getComponentData(note) {
|
||||
return note.individual_note ? note.notes[0] : note;
|
||||
},
|
||||
fetchNotes() {
|
||||
const { discussionsPath } = this.$el.parentNode.dataset;
|
||||
|
||||
this.$store.dispatch('fetchNotes', discussionsPath)
|
||||
this.actionFetchNotes(discussionsPath)
|
||||
.then(() => {
|
||||
this.isLoading = false;
|
||||
|
||||
|
@ -70,13 +84,13 @@ export default {
|
|||
},
|
||||
initPolling() {
|
||||
const { lastFetchedAt } = $('.js-notes-wrapper')[0].dataset;
|
||||
this.$store.commit('setLastFetchedAt', lastFetchedAt);
|
||||
this.setLastFetchedAt(lastFetchedAt);
|
||||
|
||||
// FIXME: @fatihacet Implement real polling mechanism
|
||||
setInterval(() => {
|
||||
this.$store.dispatch('poll')
|
||||
this.poll()
|
||||
.then((res) => {
|
||||
this.$store.commit('setLastFetchedAt', res.lastFetchedAt);
|
||||
this.setLastFetchedAt(res.lastFetchedAt);
|
||||
})
|
||||
.catch(() => {
|
||||
Flash('Something went wrong while fetching latest comments.');
|
||||
|
@ -88,10 +102,8 @@ export default {
|
|||
const { awardName, noteId } = data;
|
||||
const endpoint = this.notesById[noteId].toggle_award_path;
|
||||
|
||||
this.$store.dispatch('toggleAward', { endpoint, awardName, noteId })
|
||||
.catch(() => {
|
||||
Flash('Something went wrong on our end.');
|
||||
});
|
||||
this.toggleAward({ endpoint, awardName, noteId })
|
||||
.catch(() => {new Flash('Something went wrong on our end.')});
|
||||
});
|
||||
|
||||
$(document).on('issuable:change', (e, isClosed) => {
|
||||
|
@ -103,8 +115,8 @@ export default {
|
|||
const $el = $(`#${hash}`);
|
||||
|
||||
if (hash && $el) {
|
||||
this.$store.commit('setTargetNoteHash', hash);
|
||||
this.$store.dispatch('scrollToNoteIfNeeded', $el);
|
||||
this.setTargetNoteHash(hash);
|
||||
this.scrollToNoteIfNeeded($el);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -121,9 +133,7 @@ export default {
|
|||
<div
|
||||
v-if="isLoading"
|
||||
class="loading">
|
||||
<i
|
||||
class="fa fa-spinner fa-spin"
|
||||
aria-hidden="true"></i>
|
||||
<loading-icon />
|
||||
</div>
|
||||
<ul
|
||||
v-if="!isLoading"
|
||||
|
@ -131,9 +141,10 @@ export default {
|
|||
class="notes main-notes-list timeline">
|
||||
<component
|
||||
v-for="note in notes"
|
||||
:is="componentName(note)"
|
||||
:note="componentData(note)"
|
||||
:key="note.id" />
|
||||
:is="getComponentName(note)"
|
||||
:note="getComponentData(note)"
|
||||
:key="note.id"
|
||||
/>
|
||||
</ul>
|
||||
<issue-comment-form v-if="!isLoading" />
|
||||
</div>
|
||||
|
|
|
@ -21,7 +21,8 @@ export default {
|
|||
<a :href="currentUser.path">
|
||||
<img
|
||||
:src="currentUser.avatar_url"
|
||||
class="avatar s40" />
|
||||
class="avatar s40"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
|
|
|
@ -138,8 +138,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
|
|||
export const poll = ({ commit, state, getters }) => {
|
||||
const { notesPath } = $('.js-notes-wrapper')[0].dataset;
|
||||
|
||||
return service
|
||||
.poll(`${notesPath}?full_data=1`, state.lastFetchedAt)
|
||||
return service.poll(`${notesPath}?full_data=1`, state.lastFetchedAt)
|
||||
.then(res => res.json())
|
||||
.then((res) => {
|
||||
if (res.notes.length) {
|
||||
|
@ -188,8 +187,8 @@ export const toggleAward = ({ commit, getters, dispatch }, data) => {
|
|||
});
|
||||
|
||||
if (amIAwarded) {
|
||||
Object.assign(data, { awardName: counterAward });
|
||||
Object.assign(data, { skipMutalityCheck: true });
|
||||
data.awardName = counterAward;
|
||||
data.skipMutalityCheck = true;
|
||||
|
||||
dispatch(types.TOGGLE_AWARD, data);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue