issue_notes_app.vue 4.2 KB
Newer Older
1
<script>
2
  /* global Flash */
3

4 5 6 7 8 9 10 11 12 13 14 15
  import Vue from 'vue';
  import { mapGetters, mapActions, mapMutations } from 'vuex';
  import store from '../stores/';
  import * as constants from '../constants'
  import eventHub from '../event_hub';
  import issueNote from './issue_note.vue';
  import issueDiscussion from './issue_discussion.vue';
  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 loadingIcon from '../../vue_shared/components/loading_icon.vue';
16

17 18
  export default {
    name: 'IssueNotes',
19 20 21 22 23 24 25 26 27
    props: {
      issueData: {
        type: Object,
        required: true,
      },
      notesData: {
        type: Object,
        required: true,
      },
28 29 30 31
      userData: {
        type: Object,
        required: true,
      },
32
    },
33 34 35 36 37
    store,
    data() {
      return {
        isLoading: true,
      };
38
    },
39 40 41 42 43 44 45 46
    components: {
      issueNote,
      issueDiscussion,
      issueSystemNote,
      issueCommentForm,
      loadingIcon,
      placeholderNote,
      placeholderSystemNote,
F
Fatih Acet 已提交
47
    },
48 49
    computed: {
      ...mapGetters([
50
        'notes',
51
        'notesById',
52
        'getNotesDataByProp',
53 54 55 56 57
      ]),
    },
    methods: {
      ...mapActions({
        actionFetchNotes: 'fetchNotes',
58
        poll: 'poll',
59
        actionToggleAward: 'toggleAward',
60
        scrollToNoteIfNeeded: 'scrollToNoteIfNeeded',
61 62 63
        setNotesData: 'setNotesData',
        setIssueData: 'setIssueData',
        setUserData: 'setUserData',
64
        setLastFetchedAt: 'setLastFetchedAt'
65 66 67 68 69 70 71 72 73 74
      }),
      getComponentName(note) {
        if (note.isPlaceholderNote) {
          if (note.placeholderType === constants.SYSTEM_NOTE) {
            return placeholderSystemNote;
          }
          return placeholderNote;
        } else if (note.individual_note) {
          return note.notes[0].system ? issueSystemNote : issueNote;
        }
75

76 77 78 79 80 81
        return issueDiscussion;
      },
      getComponentData(note) {
        return note.individual_note ? note.notes[0] : note;
      },
      fetchNotes() {
82
        this.actionFetchNotes(this.getNotesDataByProp('discussionsPath'))
83 84
          .then(() => {
            this.isLoading = false;
85

86 87 88 89
            // Scroll to note if we have hash fragment in the page URL
            Vue.nextTick(() => {
              this.checkLocationHash();
            });
90
          })
91
          .catch((error) => Flash('Something went wrong while fetching issue comments. Please try again.'));
92 93
      },
      initPolling() {
94
        this.setLastFetchedAt(this.getNotesDataByProp('lastFetchedAt'));
95

96
        this.poll();
97 98
      },
      bindEventHubListeners() {
99 100
        this.$el.parentElement.addEventListener('toggleAward', (event) => {
          const { awardName, noteId } = event.detail;
101
          const endpoint = this.notesById[noteId].toggle_award_path;
102

103 104
          this.actionToggleAward({ endpoint, awardName, noteId })
            .catch((error) => Flash('Something went wrong on our end.'));
105
        });
106

107
        // JQuery is needed here because it is a custom event being dispatched with jQuery.
108 109 110 111 112 113 114 115 116 117 118 119 120 121
        $(document).on('issuable:change', (e, isClosed) => {
          eventHub.$emit('issueStateChanged', isClosed);
        });
      },
      checkLocationHash() {
        const hash = gl.utils.getLocationHash();
        const $el = $(`#${hash}`);

        if (hash && $el) {
          this.setTargetNoteHash(hash);
          this.scrollToNoteIfNeeded($el);
        }
      },
    },
122 123 124
    created() {
      this.setNotesData(this.notesData);
      this.setIssueData(this.issueData);
125
      this.setUserData(this.userData)
126
    },
127 128 129 130
    mounted() {
      this.fetchNotes();
      this.initPolling();
      this.bindEventHubListeners();
131
    },
132
  };
133 134 135 136 137 138 139
</script>

<template>
  <div id="notes">
    <div
      v-if="isLoading"
      class="loading">
140
      <loading-icon />
141
    </div>
142

143
    <ul
144 145 146
      v-if="!isLoading"
      id="notes-list"
      class="notes main-notes-list timeline">
147

148
      <component
149
        v-for="note in notes"
150 151 152 153
        :is="getComponentName(note)"
        :note="getComponentData(note)"
        :key="note.id"
        />
154
    </ul>
155 156

    <issue-comment-form />
157 158
  </div>
</template>