Initial commit

This commit is contained in:
Maksim Eltyshev
2019-08-31 04:07:25 +05:00
commit 5ffef61fe7
613 changed files with 91659 additions and 0 deletions

22
client/src/selectors/all.js Executable file
View File

@@ -0,0 +1,22 @@
import { createSelector } from 'redux-orm';
import orm from '../orm';
import { dbSelector } from './common';
import { currentUserIdSelector } from './current';
export const allUsersSelector = createSelector(
orm,
dbSelector,
({ User }) => User.getOrderedUndeletedQuerySet().toRefArray(),
);
export const allUsersExceptCurrentSelector = createSelector(
orm,
dbSelector,
(state) => currentUserIdSelector(state),
({ User }, currentUserId) => User.getOrderedUndeletedQuerySet()
.exclude({
id: currentUserId,
})
.toRefArray(),
);

166
client/src/selectors/by-id.js Executable file
View File

@@ -0,0 +1,166 @@
import { createSelector } from 'redux-orm';
import orm from '../orm';
import { dbSelector } from './common';
import { isLocalId } from '../utils/local-id';
export const makeBoardByIdSelector = () => createSelector(
orm,
dbSelector,
(_, id) => id,
({ Board }, id) => {
const boardModel = Board.withId(id);
if (!boardModel) {
return boardModel;
}
return boardModel.ref;
},
);
export const makeListByIdSelector = () => createSelector(
orm,
dbSelector,
(_, id) => id,
({ List }, id) => {
const listModel = List.withId(id);
if (!listModel) {
return listModel;
}
return {
...listModel.ref,
isPersisted: !isLocalId(id),
};
},
);
export const makeCardIdsByListIdSelector = () => createSelector(
orm,
dbSelector,
(_, id) => id,
({ List }, id) => {
const listModel = List.withId(id);
if (!listModel) {
return listModel;
}
return listModel.getOrderedFilteredCardsModelArray().map((cardModel) => cardModel.id);
},
);
export const makeCardByIdSelector = () => createSelector(
orm,
dbSelector,
(_, id) => id,
({ Card }, id) => {
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return {
...cardModel.ref,
isPersisted: !isLocalId(id),
};
},
);
export const makeUsersByCardIdSelector = () => createSelector(
orm,
dbSelector,
(_, id) => id,
({ Card }, id) => {
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel.users.toRefArray();
},
);
export const makeLabelsByCardIdSelector = () => createSelector(
orm,
dbSelector,
(_, id) => id,
({ Card }, id) => {
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel.labels.toRefArray();
},
);
export const makeTasksByCardIdSelector = () => createSelector(
orm,
dbSelector,
(_, id) => id,
({ Card }, id) => {
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel.tasks.toRefArray();
},
);
export const makeLastActionIdByCardIdSelector = () => createSelector(
orm,
dbSelector,
(_, id) => id,
({ Card }, id) => {
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
const lastActionModel = cardModel.getOrderedInCardActionsQuerySet().last();
return lastActionModel && lastActionModel.id;
},
);
export const makeNotificationsTotalByCardIdSelector = () => createSelector(
orm,
dbSelector,
(_, id) => id,
({ Card }, id) => {
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel.getUnreadNotificationsQuerySet().count();
},
);
export const boardByIdSelector = makeBoardByIdSelector();
export const listByIdSelector = makeListByIdSelector();
export const cardIdsByListIdSelector = makeCardIdsByListIdSelector();
export const cardByIdSelector = makeCardByIdSelector();
export const usersByCardIdSelector = makeUsersByCardIdSelector();
export const labelsByCardIdSelector = makeLabelsByCardIdSelector();
export const tasksByCardIdSelector = makeTasksByCardIdSelector();
export const lastActionIdByCardIdSelector = makeLastActionIdByCardIdSelector();
export const notificationsTotalByCardIdSelector = makeNotificationsTotalByCardIdSelector();

7
client/src/selectors/common.js Executable file
View File

@@ -0,0 +1,7 @@
export const dbSelector = ({ db }) => db;
export const maxIdSelector = ({ db }, modelName) => db[modelName].meta.maxId;
export const accessTokenSelector = ({ auth: { accessToken } }) => accessToken;
export const isAppInitializingSelector = ({ app: { isInitializing } }) => isInitializing;

405
client/src/selectors/current.js Executable file
View File

@@ -0,0 +1,405 @@
import { createSelector } from 'redux-orm';
import orm from '../orm';
import { dbSelector } from './common';
import { pathSelector } from './path';
import { isLocalId } from '../utils/local-id';
export const currentModalSelector = ({ app: { currentModal } }) => currentModal;
export const currentUserIdSelector = ({ auth: { userId } }) => userId;
export const currentUserSelector = createSelector(
orm,
dbSelector,
(state) => currentUserIdSelector(state),
({ User }, id) => {
if (!id) {
return id;
}
const userModel = User.withId(id);
if (!userModel) {
return userModel;
}
return userModel.ref;
},
);
export const projectsForCurrentUserSelector = createSelector(
orm,
dbSelector,
(state) => currentUserIdSelector(state),
({ User }, id) => {
if (!id) {
return id;
}
const userModel = User.withId(id);
if (!userModel) {
return userModel;
}
return userModel
.getOrderedProjectMembershipsQuerySet()
.toModelArray()
.map(({ project: projectModel }) => {
let notificationsTotal = 0;
projectModel.boards.toModelArray().forEach((boardModel) => {
boardModel.cards.toModelArray().forEach((cardModel) => {
notificationsTotal += cardModel.getUnreadNotificationsQuerySet().count();
});
});
const firstBoard = projectModel.boards.first();
const firstBoardId = firstBoard && firstBoard.id;
return {
...projectModel.ref,
notificationsTotal,
firstBoardId,
};
});
},
);
export const notificationsForCurrentUserSelector = createSelector(
orm,
dbSelector,
(state) => currentUserIdSelector(state),
({ User }, id) => {
if (!id) {
return id;
}
const userModel = User.withId(id);
if (!userModel) {
return userModel;
}
return userModel
.getOrderedUnreadNotificationsQuerySet()
.toModelArray()
.map((notificationModel) => ({
...notificationModel.ref,
action: notificationModel.action && {
...notificationModel.action.ref,
user: notificationModel.action.user.ref,
},
card: notificationModel.card && notificationModel.card.ref,
}));
},
);
export const currentProjectSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).projectId,
({ Project }, id) => {
if (!id) {
return id;
}
const projectModel = Project.withId(id);
if (!projectModel) {
return projectModel;
}
return projectModel.ref;
},
);
export const membershipsForCurrentProjectSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).projectId,
(state) => currentUserIdSelector(state),
({ Project }, id, currentUserId) => {
if (!id) {
return id;
}
const projectModel = Project.withId(id);
if (!projectModel) {
return projectModel;
}
return projectModel
.getOrderedMembershipsQuerySet()
.toModelArray()
.map((projectMembershipModel) => ({
...projectMembershipModel.ref,
isPersisted: !isLocalId(projectMembershipModel.id),
user: {
...projectMembershipModel.user.ref,
isCurrent: projectMembershipModel.user.id === currentUserId,
},
}));
},
);
export const boardsForCurrentProjectSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).projectId,
({ Project }, id) => {
if (!id) {
return id;
}
const projectModel = Project.withId(id);
if (!projectModel) {
return projectModel;
}
return projectModel
.getOrderedBoardsQuerySet()
.toRefArray()
.map((board) => ({
...board,
isPersisted: !isLocalId(board.id),
}));
},
);
export const currentBoardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).boardId,
({ Board }, id) => {
if (!id) {
return id;
}
const boardModel = Board.withId(id);
if (!boardModel) {
return boardModel;
}
return boardModel.ref;
},
);
export const listIdsForCurrentBoardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).boardId,
({ Board }, id) => {
if (!id) {
return id;
}
const boardModel = Board.withId(id);
if (!boardModel) {
return boardModel;
}
return boardModel
.getOrderedListsQuerySet()
.toRefArray()
.map((list) => list.id);
},
);
export const labelsForCurrentBoardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).boardId,
({ Board }, id) => {
if (!id) {
return id;
}
const boardModel = Board.withId(id);
if (!boardModel) {
return boardModel;
}
return boardModel.labels.toRefArray().map((label) => ({
...label,
isPersisted: !isLocalId(label.id),
}));
},
);
export const filterUsersForCurrentBoardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).boardId,
({ Board }, id) => {
if (!id) {
return id;
}
const boardModel = Board.withId(id);
if (!boardModel) {
return boardModel;
}
return boardModel.filterUsers.toRefArray();
},
);
export const filterLabelsForCurrentBoardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).boardId,
({ Board }, id) => {
if (!id) {
return id;
}
const boardModel = Board.withId(id);
if (!boardModel) {
return boardModel;
}
return boardModel.filterLabels.toRefArray();
},
);
export const currentCardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).cardId,
({ Card }, id) => {
if (!id) {
return id;
}
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel.ref;
},
);
export const usersForCurrentCardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).cardId,
({ Card }, id) => {
if (!id) {
return id;
}
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel.users.toRefArray();
},
);
export const labelsForCurrentCardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).cardId,
({ Card }, id) => {
if (!id) {
return id;
}
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel.labels.toRefArray();
},
);
export const tasksForCurrentCardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).cardId,
({ Card }, id) => {
if (!id) {
return id;
}
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel
.getOrderedTasksQuerySet()
.toRefArray()
.map((task) => ({
...task,
isPersisted: !isLocalId(task.id),
}));
},
);
export const actionsForCurrentCardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).cardId,
(state) => currentUserIdSelector(state),
({ Card }, id, currentUserId) => {
if (!id) {
return id;
}
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel
.getOrderedInCardActionsQuerySet()
.toModelArray()
.map((actionModel) => ({
...actionModel.ref,
isPersisted: !isLocalId(actionModel.id),
user: {
...actionModel.user.ref,
isCurrent: actionModel.user.id === currentUserId,
},
}));
},
);
export const notificationIdsForCurrentCardSelector = createSelector(
orm,
dbSelector,
(state) => pathSelector(state).cardId,
({ Card }, id) => {
if (!id) {
return id;
}
const cardModel = Card.withId(id);
if (!cardModel) {
return cardModel;
}
return cardModel
.getUnreadNotificationsQuerySet()
.toRefArray()
.map((notification) => notification.id);
},
);

6
client/src/selectors/index.js Executable file
View File

@@ -0,0 +1,6 @@
export * from './common';
export * from './all';
export * from './path';
export * from './current';
export * from './by-id';
export * from './next-position';

View File

@@ -0,0 +1,80 @@
import { createSelector } from 'redux-orm';
import isUndefined from 'lodash/isUndefined';
import orm from '../orm';
import { dbSelector } from './common';
import Config from '../constants/Config';
const nextPosition = (items, index, excludedId) => {
const filteredItems = isUndefined(excludedId)
? items
: items.filter((item) => item.id !== excludedId);
if (isUndefined(index)) {
const lastItem = filteredItems[filteredItems.length - 1];
return (lastItem ? lastItem.position : 0) + Config.POSITION_GAP;
}
const prevItem = filteredItems[index - 1];
const nextItem = filteredItems[index];
const prevPosition = prevItem ? prevItem.position : 0;
if (!nextItem) {
return prevPosition + Config.POSITION_GAP;
}
return prevPosition + (nextItem.position - prevPosition) / 2;
};
export const nextBoardPositionSelector = createSelector(
orm,
dbSelector,
(_, projectId) => projectId,
(_, __, index) => index,
(_, __, ___, excludedId) => excludedId,
({ Project }, projectId, index, excludedId) => {
const projectModel = Project.withId(projectId);
if (!projectModel) {
return projectModel;
}
return nextPosition(projectModel.getOrderedBoardsQuerySet().toRefArray(), index, excludedId);
},
);
export const nextListPositionSelector = createSelector(
orm,
dbSelector,
(_, boardId) => boardId,
(_, __, index) => index,
(_, __, ___, excludedId) => excludedId,
({ Board }, boardId, index, excludedId) => {
const boardModel = Board.withId(boardId);
if (!boardModel) {
return boardModel;
}
return nextPosition(boardModel.getOrderedListsQuerySet().toRefArray(), index, excludedId);
},
);
export const nextCardPositionSelector = createSelector(
orm,
dbSelector,
(_, listId) => listId,
(_, __, index) => index,
(_, __, ___, excludedId) => excludedId,
({ List }, listId, index, excludedId) => {
const listModel = List.withId(listId);
if (!listModel) {
return listModel;
}
return nextPosition(listModel.getOrderedFilteredCardsModelArray(), index, excludedId);
},
);

73
client/src/selectors/path.js Executable file
View File

@@ -0,0 +1,73 @@
import { createSelector as createReselectSelector } from 'reselect';
import { createSelector as createReduxOrmSelector } from 'redux-orm';
import orm from '../orm';
import { dbSelector } from './common';
import matchPaths from '../utils/match-paths';
import Paths from '../constants/Paths';
export const pathnameSelector = ({
router: {
location: { pathname },
},
}) => pathname;
// eslint-disable-next-line max-len
export const pathsMatchSelector = createReselectSelector(pathnameSelector, (pathname) => matchPaths(pathname, Object.values(Paths)));
export const pathSelector = createReduxOrmSelector(
orm,
dbSelector,
pathsMatchSelector,
({ Project, Board, Card }, pathsMatch) => {
if (pathsMatch) {
switch (pathsMatch.path) {
case Paths.PROJECTS: {
const projectModel = Project.withId(pathsMatch.params.id);
return {
projectId: projectModel && projectModel.id,
};
}
case Paths.BOARDS: {
const boardModel = Board.withId(pathsMatch.params.id);
const projectModel = boardModel && boardModel.project;
if (!projectModel) {
return {
boardId: null,
projectId: null,
};
}
return {
boardId: boardModel.id,
projectId: projectModel.id,
};
}
case Paths.CARDS: {
const cardModel = Card.withId(pathsMatch.params.id);
const boardModel = cardModel && cardModel.board;
const projectModel = boardModel && boardModel.project;
if (!projectModel) {
return {
cardId: null,
boardId: null,
projectId: null,
};
}
return {
cardId: cardModel.id,
boardId: boardModel.id,
projectId: projectModel.id,
};
}
default:
}
}
return {};
},
);