notes_app.vue 4.77 KB
Newer Older
1
<script>
Fatih Acet's avatar
Fatih Acet committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15
import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
import { getLocationHash } from '../../lib/utils/url_utility';
import Flash from '../../flash';
import store from '../stores/';
import * as constants from '../constants';
import noteableNote from './noteable_note.vue';
import noteableDiscussion from './noteable_discussion.vue';
import systemNote from '../../vue_shared/components/notes/system_note.vue';
import commentForm from './comment_form.vue';
import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
import placeholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
import skeletonLoadingContainer from '../../vue_shared/components/notes/skeleton_note.vue';
16

Fatih Acet's avatar
Fatih Acet committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
export default {
  name: 'NotesApp',
  components: {
    noteableNote,
    noteableDiscussion,
    systemNote,
    commentForm,
    loadingIcon,
    placeholderNote,
    placeholderSystemNote,
  },
  props: {
    noteableData: {
      type: Object,
      required: true,
Filipa Lacerda's avatar
Filipa Lacerda committed
32
    },
Fatih Acet's avatar
Fatih Acet committed
33 34 35
    notesData: {
      type: Object,
      required: true,
36
    },
Fatih Acet's avatar
Fatih Acet committed
37 38 39 40
    userData: {
      type: Object,
      required: false,
      default: () => ({}),
41
    },
Fatih Acet's avatar
Fatih Acet committed
42 43 44 45 46 47 48 49 50 51 52 53
  },
  store,
  data() {
    return {
      isLoading: true,
    };
  },
  computed: {
    ...mapGetters(['notes', 'getNotesDataByProp', 'discussionCount']),
    noteableType() {
      // FIXME -- @fatihacet Get this from JSON data.
      const { ISSUE_NOTEABLE_TYPE, MERGE_REQUEST_NOTEABLE_TYPE } = constants;
54

Fatih Acet's avatar
Fatih Acet committed
55 56 57
      return this.noteableData.merge_params
        ? MERGE_REQUEST_NOTEABLE_TYPE
        : ISSUE_NOTEABLE_TYPE;
Filipa Lacerda's avatar
Filipa Lacerda committed
58
    },
Fatih Acet's avatar
Fatih Acet committed
59 60 61
    allNotes() {
      if (this.isLoading) {
        const totalNotes = parseInt(this.notesData.totalNotes, 10) || 0;
Filipa Lacerda's avatar
Filipa Lacerda committed
62

Fatih Acet's avatar
Fatih Acet committed
63 64
        return new Array(totalNotes).fill({
          isSkeletonNote: true,
Filipa Lacerda's avatar
Filipa Lacerda committed
65 66
        });
      }
Fatih Acet's avatar
Fatih Acet committed
67
      return this.notes;
Filipa Lacerda's avatar
Filipa Lacerda committed
68
    },
Fatih Acet's avatar
Fatih Acet committed
69 70 71 72 73 74 75 76 77 78
  },
  created() {
    this.setNotesData(this.notesData);
    this.setNoteableData(this.noteableData);
    this.setUserData(this.userData);
  },
  mounted() {
    this.fetchNotes();

    const parentElement = this.$el.parentElement;
79

Fatih Acet's avatar
Fatih Acet committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    if (
      parentElement &&
      parentElement.classList.contains('js-vue-notes-event')
    ) {
      parentElement.addEventListener('toggleAward', event => {
        const { awardName, noteId } = event.detail;
        this.actionToggleAward({ awardName, noteId });
      });
    }
    document.addEventListener('refreshVueNotes', this.fetchNotes);
  },
  beforeDestroy() {
    document.removeEventListener('refreshVueNotes', this.fetchNotes);
  },
  methods: {
    ...mapActions({
      actionFetchNotes: 'fetchNotes',
      poll: 'poll',
      actionToggleAward: 'toggleAward',
      scrollToNoteIfNeeded: 'scrollToNoteIfNeeded',
      setNotesData: 'setNotesData',
      setNoteableData: 'setNoteableData',
      setUserData: 'setUserData',
      setLastFetchedAt: 'setLastFetchedAt',
      setTargetNoteHash: 'setTargetNoteHash',
    }),
    getComponentName(note) {
      if (note.isSkeletonNote) {
        return skeletonLoadingContainer;
      }
      if (note.isPlaceholderNote) {
        if (note.placeholderType === constants.SYSTEM_NOTE) {
          return placeholderSystemNote;
113
        }
Fatih Acet's avatar
Fatih Acet committed
114 115 116 117
        return placeholderNote;
      } else if (note.individual_note) {
        return note.notes[0].system ? systemNote : noteableNote;
      }
118

Fatih Acet's avatar
Fatih Acet committed
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
      return noteableDiscussion;
    },
    getComponentData(note) {
      return note.individual_note ? note.notes[0] : note;
    },
    fetchNotes() {
      return this.actionFetchNotes(this.getNotesDataByProp('discussionsPath'))
        .then(() => this.initPolling())
        .then(() => {
          this.isLoading = false;
        })
        .then(() => this.$nextTick())
        .then(() => this.checkLocationHash())
        .catch(() => {
          this.isLoading = false;
          Flash(
            'Something went wrong while fetching comments. Please try again.',
          );
        });
    },
    initPolling() {
      if (this.isPollingInitialized) {
        return;
      }
143

Fatih Acet's avatar
Fatih Acet committed
144
      this.setLastFetchedAt(this.getNotesDataByProp('lastFetchedAt'));
145

Fatih Acet's avatar
Fatih Acet committed
146 147 148 149 150 151 152 153 154 155 156
      this.poll();
      this.isPollingInitialized = true;
    },
    checkLocationHash() {
      const hash = getLocationHash();
      const element = document.getElementById(hash);

      if (hash && element) {
        this.setTargetNoteHash(hash);
        this.scrollToNoteIfNeeded($(element));
      }
157
    },
Fatih Acet's avatar
Fatih Acet committed
158 159
  },
};
160 161 162 163
</script>

<template>
  <div id="notes">
164
    <ul
165 166
      id="notes-list"
      class="notes main-notes-list timeline">
167

168
      <component
169
        v-for="note in allNotes"
170 171 172
        :is="getComponentName(note)"
        :note="getComponentData(note)"
        :key="note.id"
Filipa Lacerda's avatar
Filipa Lacerda committed
173
      />
174
    </ul>
175

176 177 178
    <comment-form
      :noteable-type="noteableType"
    />
179 180
  </div>
</template>