/*! * Copyright (c) 2024 PLANKA Software GmbH * Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md */ import { createSelector } from 'redux-orm'; import orm from '../orm'; import { selectIsFavoritesEnabled, selectIsHiddenProjectsVisible, selectProjectsOrder, selectProjectsSearch, } from './core'; import { isLocalId } from '../utils/local-id'; import { isUserAdminOrProjectOwner } from '../utils/record-helpers'; import { STATIC_USER_BY_ID } from '../constants/StaticUsers'; import { BoardMembershipRoles, ProjectGroups, ProjectOrders } from '../constants/Enums'; const ORDER_BY_ARGS_BY_PROJECTS_ORDER = { [ProjectOrders.ALPHABETICALLY]: [['name', 'id.length', 'id']], [ProjectOrders.BY_CREATION_TIME]: [['id', 'id.length']], }; export const selectCurrentUserId = ({ auth: { userId } }) => userId; export const makeSelectUserById = () => createSelector( orm, (_, id) => id, ({ User }, id) => { if (STATIC_USER_BY_ID[id]) { return STATIC_USER_BY_ID[id]; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel.ref; }, ); export const selectUserById = makeSelectUserById(); export const selectUsers = createSelector(orm, ({ User }) => User.getAllQuerySet().toRefArray()); export const selectActiveUsers = createSelector(orm, ({ User }) => User.getActiveQuerySet().toRefArray(), ); export const selectActiveUsersTotal = createSelector(orm, ({ User }) => User.getActiveQuerySet().count(), ); export const selectActiveAdminOrProjectOwnerUsers = createSelector(orm, ({ User }) => User.getActiveQuerySet() .filter((user) => isUserAdminOrProjectOwner(user)) .toRefArray(), ); export const selectCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), ({ User }, id) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel.ref; }, ); export const selectProjectIdsForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), ({ User }, id) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel.getProjectsModelArray().map((projectModel) => projectModel.id); }, ); export const selectFilteredProjectIdsForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), (state) => selectProjectsSearch(state), (state) => selectIsHiddenProjectsVisible(state), (state) => selectProjectsOrder(state), ({ User }, id, projectsSearch, isHiddenProjectsVisible, projectsOrder) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel .getFilteredProjectsModelArray( projectsSearch, isHiddenProjectsVisible, ORDER_BY_ARGS_BY_PROJECTS_ORDER[projectsOrder], ) .map((projectModel) => projectModel.id); }, ); export const selectFilteredProjctIdsByGroupForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), (state) => selectProjectsSearch(state), (state) => selectIsHiddenProjectsVisible(state), (state) => selectProjectsOrder(state), ({ User }, id, projectsSearch, isHiddenProjectsVisible, projectsOrder) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } const { managerProjectModels, membershipProjectModels, adminProjectModels } = userModel.getFilteredSeparatedProjectsModelArray( projectsSearch, isHiddenProjectsVisible, ORDER_BY_ARGS_BY_PROJECTS_ORDER[projectsOrder], ); return managerProjectModels.reduce( (result, projectModel) => { const group = projectModel.ownerProjectManager ? ProjectGroups.MY_OWN : ProjectGroups.TEAM; result[group].push(projectModel.id); return result; }, { [ProjectGroups.MY_OWN]: [], [ProjectGroups.TEAM]: [], [ProjectGroups.SHARED_WITH_ME]: membershipProjectModels.map( (projectModel) => projectModel.id, ), [ProjectGroups.OTHERS]: adminProjectModels.map((projectModel) => projectModel.id), }, ); }, ); export const selectFavoriteProjectIdsForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), (state) => selectProjectsOrder(state), ({ User }, id, projectsOrder) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel .getFavoriteProjectsModelArray(ORDER_BY_ARGS_BY_PROJECTS_ORDER[projectsOrder]) .map((projectModel) => projectModel.id); }, ); export const selectProjectsToBoardsWithEditorRightsForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), ({ User }, id) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel.getMembershipProjectsModelArray().map((projectModel) => ({ ...projectModel.ref, boards: projectModel.getBoardsModelArrayForUserWithId(id).flatMap((boardModel) => { const boardMembersipModel = boardModel.getMembershipModelByUserId(id); if (boardMembersipModel.role !== BoardMembershipRoles.EDITOR) { return []; } return boardModel.ref; }), })); }, ); export const selectProjectsToListsWithEditorRightsForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), ({ User }, id) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel.getMembershipProjectsModelArray().map((projectModel) => ({ ...projectModel.ref, boards: projectModel.getBoardsModelArrayForUserWithId(id).flatMap((boardModel) => { const boardMembersipModel = boardModel.getMembershipModelByUserId(id); if (boardMembersipModel.role !== BoardMembershipRoles.EDITOR) { return []; } return { ...boardModel.ref, lists: boardModel .getListsQuerySet() .toRefArray() .map((list) => ({ ...list, isPersisted: !isLocalId(list.id), })), }; }), })); }, ); export const selectBoardIdsForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), ({ User }, id) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel .getProjectsModelArray() .flatMap((projectModel) => projectModel .getBoardsModelArrayAvailableForUser(userModel) .map((boardModel) => boardModel.id), ); }, ); export const selectNotificationIdsForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), ({ User }, id) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel .getUnreadNotificationsQuerySet() .toRefArray() .map((notification) => notification.id); }, ); export const selectNotificationServiceIdsForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), ({ User }, id) => { if (!id) { return id; } const userModel = User.withId(id); if (!userModel) { return userModel; } return userModel .getNotificationServicesQuerySet() .toRefArray() .map((notificationService) => notificationService.id); }, ); export const selectIsFavoritesActiveForCurrentUser = createSelector( orm, (state) => selectCurrentUserId(state), (state) => selectIsFavoritesEnabled(state), ({ User }, id, isFavoritesEnabled) => { if (!id) { return false; } const userModel = User.withId(id); if (!userModel) { return false; } // TODO: use selectFavoriteProjectIdsForCurrentUser instead return isFavoritesEnabled && userModel.getFavoriteProjectsModelArray().length > 0; }, ); export default { makeSelectUserById, selectUserById, selectCurrentUserId, selectUsers, selectActiveUsers, selectActiveUsersTotal, selectActiveAdminOrProjectOwnerUsers, selectCurrentUser, selectProjectIdsForCurrentUser, selectFilteredProjectIdsForCurrentUser, selectFilteredProjctIdsByGroupForCurrentUser, selectFavoriteProjectIdsForCurrentUser, selectProjectsToBoardsWithEditorRightsForCurrentUser, selectProjectsToListsWithEditorRightsForCurrentUser, selectBoardIdsForCurrentUser, selectNotificationIdsForCurrentUser, selectNotificationServiceIdsForCurrentUser, selectIsFavoritesActiveForCurrentUser, };