debian-mirror-gitlab/app/assets/javascripts/notes/stores/getters.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

310 lines
10 KiB
JavaScript
Raw Normal View History

2020-04-22 19:07:51 +05:30
import { flattenDeep, clone } from 'lodash';
2022-07-16 23:28:13 +05:30
import { match } from '~/diffs/utils/diff_file';
import { badgeState } from '~/issuable/components/status_box.vue';
2021-06-08 01:23:25 +05:30
import { isInMRPage } from '~/lib/utils/common_utils';
2018-11-08 19:23:39 +05:30
import * as constants from '../constants';
import { collapseSystemNotes } from './collapse_utils';
2021-04-29 21:17:54 +05:30
const getDraftComments = (state) => {
if (!state.batchComments) {
return [];
}
return state.batchComments.drafts
.filter((draft) => !draft.file_path && !draft.discussion_id)
.map((x) => ({
...x,
// Treat a top-level draft note as individual_note so it's not included in
// expand/collapse threads
individual_note: true,
}))
.sort((a, b) => a.id - b.id);
};
export const discussions = (state, getters, rootState) => {
2020-04-22 19:07:51 +05:30
let discussionsInState = clone(state.discussions);
// NOTE: not testing bc will be removed when backend is finished.
2021-01-03 14:25:43 +05:30
if (state.isTimelineEnabled) {
discussionsInState = discussionsInState
.reduce((acc, discussion) => {
2021-03-08 18:12:59 +05:30
const transformedToIndividualNotes = discussion.notes.map((note) => ({
2021-01-03 14:25:43 +05:30
...discussion,
id: note.id,
created_at: note.created_at,
individual_note: true,
notes: [note],
}));
return acc.concat(transformedToIndividualNotes);
}, [])
.sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
}
2021-04-29 21:17:54 +05:30
discussionsInState = collapseSystemNotes(discussionsInState);
discussionsInState = discussionsInState.concat(getDraftComments(rootState));
2020-04-22 19:07:51 +05:30
if (state.discussionSortOrder === constants.DESC) {
discussionsInState = discussionsInState.reverse();
}
2021-04-29 21:17:54 +05:30
return discussionsInState;
2020-04-22 19:07:51 +05:30
};
2018-03-17 18:26:18 +05:30
2021-03-08 18:12:59 +05:30
export const convertedDisscussionIds = (state) => state.convertedDisscussionIds;
2019-07-07 11:18:12 +05:30
2021-03-08 18:12:59 +05:30
export const targetNoteHash = (state) => state.targetNoteHash;
2018-03-17 18:26:18 +05:30
2021-03-08 18:12:59 +05:30
export const getNotesData = (state) => state.notesData;
2018-11-08 19:23:39 +05:30
2021-03-08 18:12:59 +05:30
export const isNotesFetched = (state) => state.isNotesFetched;
2018-11-08 19:23:39 +05:30
2020-04-22 19:07:51 +05:30
/*
* WARNING: This is an example of an "unnecessary" getter
* more info found here: https://gitlab.com/groups/gitlab-org/-/epics/2913.
*/
2021-03-08 18:12:59 +05:30
export const sortDirection = (state) => state.discussionSortOrder;
2020-04-22 19:07:51 +05:30
2021-03-08 18:12:59 +05:30
export const persistSortOrder = (state) => state.persistSortOrder;
2021-01-03 14:25:43 +05:30
2021-03-08 18:12:59 +05:30
export const timelineEnabled = (state) => state.isTimelineEnabled;
2021-01-03 14:25:43 +05:30
2021-03-11 19:13:27 +05:30
export const isFetching = (state) => state.isFetching;
2021-03-08 18:12:59 +05:30
export const isLoading = (state) => state.isLoading;
2018-12-13 13:39:08 +05:30
2021-03-08 18:12:59 +05:30
export const getNotesDataByProp = (state) => (prop) => state.notesData[prop];
2018-03-17 18:26:18 +05:30
2021-03-08 18:12:59 +05:30
export const getNoteableData = (state) => state.noteableData;
2018-11-08 19:23:39 +05:30
2021-03-08 18:12:59 +05:30
export const getNoteableDataByProp = (state) => (prop) => state.noteableData[prop];
2018-11-08 19:23:39 +05:30
2021-03-08 18:12:59 +05:30
export const getBlockedByIssues = (state) => state.noteableData.blocked_by_issues;
2020-05-24 23:13:21 +05:30
2021-03-08 18:12:59 +05:30
export const userCanReply = (state) => Boolean(state.noteableData.current_user.can_create_note);
2019-07-31 22:56:46 +05:30
2022-07-16 23:28:13 +05:30
export const openState = (state) => (isInMRPage() ? badgeState.state : state.noteableData.state);
2018-03-17 18:26:18 +05:30
2021-03-08 18:12:59 +05:30
export const getUserData = (state) => state.userData || {};
2018-11-08 19:23:39 +05:30
2021-03-08 18:12:59 +05:30
export const getUserDataByProp = (state) => (prop) => state.userData && state.userData[prop];
2018-03-17 18:26:18 +05:30
2021-03-08 18:12:59 +05:30
export const descriptionVersions = (state) => state.descriptionVersions;
2020-04-08 14:13:33 +05:30
2021-03-08 18:12:59 +05:30
export const notesById = (state) =>
2018-11-08 19:23:39 +05:30
state.discussions.reduce((acc, note) => {
2021-03-08 18:12:59 +05:30
note.notes.every((n) => Object.assign(acc, { [n.id]: n }));
2018-05-09 12:01:36 +05:30
return acc;
}, {});
2018-03-17 18:26:18 +05:30
2021-03-08 18:12:59 +05:30
export const noteableType = (state) => {
2018-11-08 19:23:39 +05:30
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;
};
2021-03-08 18:12:59 +05:30
const reverseNotes = (array) => array.slice(0).reverse();
2018-11-08 19:23:39 +05:30
2018-05-09 12:01:36 +05:30
const isLastNote = (note, state) =>
2018-11-08 19:23:39 +05:30
!note.system && state.userData && note.author && note.author.id === state.userData.id;
2018-03-17 18:26:18 +05:30
2021-03-08 18:12:59 +05:30
export const getCurrentUserLastNote = (state) =>
flattenDeep(reverseNotes(state.discussions).map((note) => reverseNotes(note.notes))).find((el) =>
2018-11-08 19:23:39 +05:30
isLastNote(el, state),
);
2018-03-17 18:26:18 +05:30
2021-03-08 18:12:59 +05:30
export const getDiscussionLastNote = (state) => (discussion) =>
reverseNotes(discussion.notes).find((el) => isLastNote(el, state));
2018-03-27 19:54:05 +05:30
2021-03-08 18:12:59 +05:30
export const unresolvedDiscussionsCount = (state) => state.unresolvedDiscussionsCount;
export const resolvableDiscussionsCount = (state) => state.resolvableDiscussionsCount;
2018-03-27 19:54:05 +05:30
2019-09-30 21:07:59 +05:30
export const showJumpToNextDiscussion = (state, getters) => (mode = 'discussion') => {
2019-02-15 15:39:39 +05:30
const orderedDiffs =
mode !== 'discussion'
? getters.unresolvedDiscussionsIdsByDiff
: getters.unresolvedDiscussionsIdsByDate;
2018-11-08 19:23:39 +05:30
2019-09-30 21:07:59 +05:30
return orderedDiffs.length > 1;
2018-03-27 19:54:05 +05:30
};
2021-03-08 18:12:59 +05:30
export const isDiscussionResolved = (state, getters) => (discussionId) =>
2018-12-05 23:21:45 +05:30
getters.resolvedDiscussionsById[discussionId] !== undefined;
2021-03-08 18:12:59 +05:30
export const allResolvableDiscussions = (state) =>
state.discussions.filter((d) => !d.individual_note && d.resolvable);
2018-11-18 11:00:15 +05:30
2021-03-08 18:12:59 +05:30
export const resolvedDiscussionsById = (state) => {
2018-03-27 19:54:05 +05:30
const map = {};
2019-02-15 15:39:39 +05:30
state.discussions
2021-03-08 18:12:59 +05:30
.filter((d) => d.resolvable)
.forEach((n) => {
2019-02-15 15:39:39 +05:30
if (n.notes) {
2021-03-08 18:12:59 +05:30
const resolved = n.notes.filter((note) => note.resolvable).every((note) => note.resolved);
2018-03-27 19:54:05 +05:30
2019-02-15 15:39:39 +05:30
if (resolved) {
map[n.id] = n;
}
2018-03-27 19:54:05 +05:30
}
2019-02-15 15:39:39 +05:30
});
2018-03-27 19:54:05 +05:30
return map;
};
2018-11-18 11:00:15 +05:30
// Gets Discussions IDs ordered by the date of their initial note
export const unresolvedDiscussionsIdsByDate = (state, getters) =>
getters.allResolvableDiscussions
2021-03-08 18:12:59 +05:30
.filter((d) => !d.resolved)
2018-11-18 11:00:15 +05:30
.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;
})
2021-03-08 18:12:59 +05:30
.map((d) => d.id);
2018-11-18 11:00:15 +05:30
// 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.
2022-07-16 23:28:13 +05:30
export const unresolvedDiscussionsIdsByDiff = (state, getters, allState) => {
const authoritativeFiles = allState.diffs.diffFiles;
return getters.allResolvableDiscussions
2021-03-08 18:12:59 +05:30
.filter((d) => !d.resolved && d.active)
2018-11-18 11:00:15 +05:30
.sort((a, b) => {
2022-07-16 23:28:13 +05:30
let order = 0;
2018-11-18 11:00:15 +05:30
if (!a.diff_file || !b.diff_file) {
2022-07-16 23:28:13 +05:30
return order;
2018-11-18 11:00:15 +05:30
}
2022-07-16 23:28:13 +05:30
const authoritativeA = authoritativeFiles.find((source) =>
match({ fileA: source, fileB: a.diff_file, mode: 'mr' }),
);
const authoritativeB = authoritativeFiles.find((source) =>
match({ fileA: source, fileB: b.diff_file, mode: 'mr' }),
);
if (authoritativeA && authoritativeB) {
order = authoritativeA.order - authoritativeB.order;
}
2018-11-18 11:00:15 +05:30
// Get the line numbers, to compare within the same file
2018-11-20 20:47:30 +05:30
const aLines = [a.position.new_line, a.position.old_line];
const bLines = [b.position.new_line, b.position.old_line];
2018-11-18 11:00:15 +05:30
2022-07-16 23:28:13 +05:30
return order < 0 ||
(order === 0 &&
2018-11-18 11:00:15 +05:30
// .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;
})
2021-03-08 18:12:59 +05:30
.map((d) => d.id);
2022-07-16 23:28:13 +05:30
};
2018-11-18 11:00:15 +05:30
2018-03-27 19:54:05 +05:30
export const resolvedDiscussionCount = (state, getters) => {
const resolvedMap = getters.resolvedDiscussionsById;
return Object.keys(resolvedMap).length;
};
2018-10-15 14:42:47 +05:30
2021-03-08 18:12:59 +05:30
export const discussionTabCounter = (state) =>
2019-02-15 15:39:39 +05:30
state.discussions.reduce(
(acc, discussion) =>
2021-03-08 18:12:59 +05:30
acc + discussion.notes.filter((note) => !note.system && !note.placeholder).length,
2019-02-15 15:39:39 +05:30
0,
);
2018-11-08 19:23:39 +05:30
2018-11-18 11:00:15 +05:30
// Returns the list of discussion IDs ordered according to given parameter
// @param {Boolean} diffOrder - is ordered by diff?
2021-03-08 18:12:59 +05:30
export const unresolvedDiscussionsIdsOrdered = (state, getters) => (diffOrder) => {
2018-11-18 11:00:15 +05:30
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;
};
2019-12-04 20:38:33 +05:30
export const findUnresolvedDiscussionIdNeighbor = (state, getters) => ({
discussionId,
diffOrder,
step,
}) => {
2020-10-24 23:57:45 +05:30
const diffIds = getters.unresolvedDiscussionsIdsOrdered(diffOrder);
const dateIds = getters.unresolvedDiscussionsIdsOrdered(false);
const ids = diffIds.length ? diffIds : dateIds;
2019-12-04 20:38:33 +05:30
const index = ids.indexOf(discussionId) + step;
if (index < 0 && step < 0) {
return ids[ids.length - 1];
}
if (index === ids.length && step > 0) {
return ids[0];
}
2018-11-18 11:00:15 +05:30
2019-12-04 20:38:33 +05:30
return ids[index];
2018-11-18 11:00:15 +05:30
};
2019-12-04 20:38:33 +05:30
// 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) =>
getters.findUnresolvedDiscussionIdNeighbor({ discussionId, diffOrder, step: 1 });
2019-10-12 21:52:04 +05:30
2019-12-04 20:38:33 +05:30
export const previousUnresolvedDiscussionId = (state, getters) => (discussionId, diffOrder) =>
getters.findUnresolvedDiscussionIdNeighbor({ discussionId, diffOrder, step: -1 });
2019-10-12 21:52:04 +05:30
2018-11-18 11:00:15 +05:30
// @param {Boolean} diffOrder - is ordered by diff?
2021-03-08 18:12:59 +05:30
export const firstUnresolvedDiscussionId = (state, getters) => (diffOrder) => {
2018-11-18 11:00:15 +05:30
if (diffOrder) {
return getters.unresolvedDiscussionsIdsByDiff[0];
}
return getters.unresolvedDiscussionsIdsByDate[0];
};
2021-03-08 18:12:59 +05:30
export const getDiscussion = (state) => (discussionId) =>
state.discussions.find((discussion) => discussion.id === discussionId);
2019-07-07 11:18:12 +05:30
2021-03-08 18:12:59 +05:30
export const commentsDisabled = (state) => state.commentsDisabled;
2021-01-03 14:25:43 +05:30
export const suggestionsCount = (state, getters) =>
2021-09-30 23:02:18 +05:30
Object.values(getters.notesById).filter((n) => n.suggestions?.length).length;
2021-04-29 21:17:54 +05:30
export const hasDrafts = (state, getters, rootState, rootGetters) =>
Boolean(rootGetters['batchComments/hasDrafts']);
2021-11-18 22:05:49 +05:30
export const getSuggestionsFilePaths = (state) => () =>
state.batchSuggestionsInfo.reduce((acc, suggestion) => {
const discussion = state.discussions.find((d) => d.id === suggestion.discussionId);
if (acc.indexOf(discussion?.diff_file?.file_path) === -1) {
acc.push(discussion.diff_file.file_path);
}
return acc;
}, []);