getters.js 6.7 KB
Newer Older
1
import _ from 'underscore';
F
Felipe Artur 已提交
2
import * as constants from '../constants';
J
Jose Ivan Vargas 已提交
3 4
import { collapseSystemNotes } from './collapse_utils';

F
Felipe Artur 已提交
5
export const discussions = state => collapseSystemNotes(state.discussions);
6

7
export const targetNoteHash = state => state.targetNoteHash;
8 9

export const getNotesData = state => state.notesData;
F
Felipe Artur 已提交
10

11 12
export const isNotesFetched = state => state.isNotesFetched;

13 14
export const isLoading = state => state.isLoading;

15
export const getNotesDataByProp = state => prop => state.notesData[prop];
16

S
Simon Knox 已提交
17
export const getNoteableData = state => state.noteableData;
F
Felipe Artur 已提交
18

S
Simon Knox 已提交
19
export const getNoteableDataByProp = state => prop => state.noteableData[prop];
F
Felipe Artur 已提交
20

21
export const openState = state => state.noteableData.state;
22

23
export const getUserData = state => state.userData || {};
F
Felipe Artur 已提交
24 25

export const getUserDataByProp = state => prop => state.userData && state.userData[prop];
26

F
Fatih Acet 已提交
27
export const notesById = state =>
F
Felipe Artur 已提交
28
  state.discussions.reduce((acc, note) => {
F
Fatih Acet 已提交
29 30 31
    note.notes.every(n => Object.assign(acc, { [n.id]: n }));
    return acc;
  }, {});
32

F
Felipe Artur 已提交
33 34 35 36 37 38 39 40 41 42
export const noteableType = state => {
  const { ISSUE_NOTEABLE_TYPE, MERGE_REQUEST_NOTEABLE_TYPE, EPIC_NOTEABLE_TYPE } = constants;

  if (state.noteableData.noteableType === EPIC_NOTEABLE_TYPE) {
    return EPIC_NOTEABLE_TYPE;
  }

  return state.noteableData.merge_params ? MERGE_REQUEST_NOTEABLE_TYPE : ISSUE_NOTEABLE_TYPE;
};

43
const reverseNotes = array => array.slice(0).reverse();
F
Felipe Artur 已提交
44

F
Fatih Acet 已提交
45
const isLastNote = (note, state) =>
F
Felipe Artur 已提交
46
  !note.system && state.userData && note.author && note.author.id === state.userData.id;
F
Filipa Lacerda 已提交
47

F
Fatih Acet 已提交
48
export const getCurrentUserLastNote = state =>
F
Felipe Artur 已提交
49 50 51
  _.flatten(reverseNotes(state.discussions).map(note => reverseNotes(note.notes))).find(el =>
    isLastNote(el, state),
  );
52

F
Fatih Acet 已提交
53 54
export const getDiscussionLastNote = state => discussion =>
  reverseNotes(discussion.notes).find(el => isLastNote(el, state));
55

56 57 58
export const unresolvedDiscussionsCount = state => state.unresolvedDiscussionsCount;
export const resolvableDiscussionsCount = state => state.resolvableDiscussionsCount;
export const hasUnresolvedDiscussions = state => state.hasUnresolvedDiscussions;
59

60 61 62 63 64 65 66 67 68 69 70
export const showJumpToNextDiscussion = (state, getters) => (discussionId, mode = 'discussion') => {
  const orderedDiffs =
    mode !== 'discussion'
      ? getters.unresolvedDiscussionsIdsByDiff
      : getters.unresolvedDiscussionsIdsByDate;

  const indexOf = orderedDiffs.indexOf(discussionId);

  return indexOf !== -1 && indexOf < orderedDiffs.length - 1;
};

71 72 73
export const isDiscussionResolved = (state, getters) => discussionId =>
  getters.resolvedDiscussionsById[discussionId] !== undefined;

74 75
export const allResolvableDiscussions = state =>
  state.discussions.filter(d => !d.individual_note && d.resolvable);
76

F
Fatih Acet 已提交
77
export const resolvedDiscussionsById = state => {
78 79
  const map = {};

M
Mike Greiling 已提交
80 81 82 83 84 85 86 87 88
  state.discussions
    .filter(d => d.resolvable)
    .forEach(n => {
      if (n.notes) {
        const resolved = n.notes.filter(note => note.resolvable).every(note => note.resolved);

        if (resolved) {
          map[n.id] = n;
        }
89
      }
M
Mike Greiling 已提交
90
    });
91 92 93 94

  return map;
};

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
// Gets Discussions IDs ordered by the date of their initial note
export const unresolvedDiscussionsIdsByDate = (state, getters) =>
  getters.allResolvableDiscussions
    .filter(d => !d.resolved)
    .sort((a, b) => {
      const aDate = new Date(a.notes[0].created_at);
      const bDate = new Date(b.notes[0].created_at);

      if (aDate < bDate) {
        return -1;
      }

      return aDate === bDate ? 0 : 1;
    })
    .map(d => d.id);

// Gets Discussions IDs ordered by their position in the diff
//
// Sorts the array of resolvable yet unresolved discussions by
// comparing file names first. If file names are the same, compares
// line numbers.
export const unresolvedDiscussionsIdsByDiff = (state, getters) =>
  getters.allResolvableDiscussions
118
    .filter(d => !d.resolved && d.active)
119 120 121 122 123 124 125 126 127
    .sort((a, b) => {
      if (!a.diff_file || !b.diff_file) {
        return 0;
      }

      // Get file names comparison result
      const filenameComparison = a.diff_file.file_path.localeCompare(b.diff_file.file_path);

      // Get the line numbers, to compare within the same file
M
Mark Chao 已提交
128 129
      const aLines = [a.position.new_line, a.position.old_line];
      const bLines = [b.position.new_line, b.position.old_line];
130 131 132 133 134 135 136 137 138 139

      return filenameComparison < 0 ||
        (filenameComparison === 0 &&
          // .max() because one of them might be zero (if removed/added)
          Math.max(aLines[0], aLines[1]) < Math.max(bLines[0], bLines[1]))
        ? -1
        : 1;
    })
    .map(d => d.id);

140 141 142 143 144
export const resolvedDiscussionCount = (state, getters) => {
  const resolvedMap = getters.resolvedDiscussionsById;

  return Object.keys(resolvedMap).length;
};
145

146 147 148 149 150 151
export const discussionTabCounter = state =>
  state.discussions.reduce(
    (acc, discussion) =>
      acc + discussion.notes.filter(note => !note.system && !note.placeholder).length,
    0,
  );
F
Felipe Artur 已提交
152

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
// Returns the list of discussion IDs ordered according to given parameter
// @param {Boolean} diffOrder - is ordered by diff?
export const unresolvedDiscussionsIdsOrdered = (state, getters) => diffOrder => {
  if (diffOrder) {
    return getters.unresolvedDiscussionsIdsByDiff;
  }
  return getters.unresolvedDiscussionsIdsByDate;
};

// Checks if a given discussion is the last in the current order (diff or date)
// @param {Boolean} discussionId - id of the discussion
// @param {Boolean} diffOrder - is ordered by diff?
export const isLastUnresolvedDiscussion = (state, getters) => (discussionId, diffOrder) => {
  const idsOrdered = getters.unresolvedDiscussionsIdsOrdered(diffOrder);
  const lastDiscussionId = idsOrdered[idsOrdered.length - 1];

  return lastDiscussionId === discussionId;
};

// Gets the ID of the discussion following the one provided, respecting order (diff or date)
// @param {Boolean} discussionId - id of the current discussion
// @param {Boolean} diffOrder - is ordered by diff?
export const nextUnresolvedDiscussionId = (state, getters) => (discussionId, diffOrder) => {
  const idsOrdered = getters.unresolvedDiscussionsIdsOrdered(diffOrder);
  const currentIndex = idsOrdered.indexOf(discussionId);
178
  const slicedIds = idsOrdered.slice(currentIndex + 1, currentIndex + 2);
179

180 181
  // Get the first ID if there is none after the currentIndex
  return slicedIds.length ? idsOrdered.slice(currentIndex + 1, currentIndex + 2)[0] : idsOrdered[0];
182 183 184 185 186 187 188 189 190 191
};

// @param {Boolean} diffOrder - is ordered by diff?
export const firstUnresolvedDiscussionId = (state, getters) => diffOrder => {
  if (diffOrder) {
    return getters.unresolvedDiscussionsIdsByDiff[0];
  }
  return getters.unresolvedDiscussionsIdsByDate[0];
};

192 193
export const commentsDisabled = state => state.commentsDisabled;

194 195
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};