255 lines
6.6 KiB
JavaScript
Executable File
255 lines
6.6 KiB
JavaScript
Executable File
/*!
|
|
* Copyright (c) 2024 PLANKA Software GmbH
|
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
|
*/
|
|
|
|
import { attr, many, oneToOne } from 'redux-orm';
|
|
|
|
import BaseModel from './BaseModel';
|
|
import ActionTypes from '../constants/ActionTypes';
|
|
import { UserRoles } from '../constants/Enums';
|
|
|
|
export default class extends BaseModel {
|
|
static modelName = 'Project';
|
|
|
|
static fields = {
|
|
id: attr(),
|
|
name: attr(),
|
|
description: attr(),
|
|
backgroundType: attr(),
|
|
backgroundGradient: attr(),
|
|
isHidden: attr(),
|
|
isFavorite: attr({
|
|
getDefault: () => false,
|
|
}),
|
|
ownerProjectManagerId: oneToOne({
|
|
to: 'ProjectManager',
|
|
as: 'ownerProjectManager',
|
|
relatedName: 'ownedProject',
|
|
}),
|
|
backgroundImageId: oneToOne({
|
|
to: 'BackgroundImage',
|
|
as: 'backgroundImage',
|
|
relatedName: 'backgroundedProject', // TODO: rename?
|
|
}),
|
|
managerUsers: many({
|
|
to: 'User',
|
|
through: 'ProjectManager',
|
|
relatedName: 'managerProjects',
|
|
}),
|
|
};
|
|
|
|
static reducer({ type, payload }, Project) {
|
|
switch (type) {
|
|
case ActionTypes.LOCATION_CHANGE_HANDLE:
|
|
if (payload.projects) {
|
|
payload.projects.forEach((project) => {
|
|
Project.upsert(project);
|
|
});
|
|
}
|
|
|
|
break;
|
|
case ActionTypes.SOCKET_RECONNECT_HANDLE:
|
|
Project.all().delete();
|
|
|
|
payload.projects.forEach((project) => {
|
|
Project.upsert(project);
|
|
});
|
|
|
|
break;
|
|
case ActionTypes.CORE_INITIALIZE:
|
|
case ActionTypes.BOARD_FETCH__SUCCESS:
|
|
payload.projects.forEach((project) => {
|
|
Project.upsert(project);
|
|
});
|
|
|
|
break;
|
|
case ActionTypes.USER_UPDATE_HANDLE:
|
|
Project.all()
|
|
.toModelArray()
|
|
.forEach((projectModel) => {
|
|
if (!payload.projectIds.includes(projectModel.id)) {
|
|
projectModel.deleteWithRelated(true);
|
|
}
|
|
});
|
|
|
|
if (payload.projects) {
|
|
payload.projects.forEach((project) => {
|
|
Project.upsert(project);
|
|
});
|
|
}
|
|
|
|
break;
|
|
case ActionTypes.PROJECT_CREATE__SUCCESS:
|
|
case ActionTypes.PROJECT_CREATE_HANDLE:
|
|
case ActionTypes.PROJECT_UPDATE__SUCCESS:
|
|
Project.upsert(payload.project);
|
|
|
|
break;
|
|
case ActionTypes.PROJECT_UPDATE:
|
|
Project.withId(payload.id).update(payload.data);
|
|
|
|
break;
|
|
case ActionTypes.PROJECT_UPDATE_HANDLE: {
|
|
const projectModel = Project.withId(payload.project.id);
|
|
|
|
if (projectModel) {
|
|
if (payload.isAvailable) {
|
|
projectModel.boards.toModelArray().forEach((boardModel) => {
|
|
if (!payload.boardIds.includes(boardModel.id)) {
|
|
boardModel.deleteWithRelated(true);
|
|
}
|
|
});
|
|
} else {
|
|
projectModel.deleteWithRelated(true);
|
|
}
|
|
}
|
|
|
|
Project.upsert(payload.project);
|
|
|
|
break;
|
|
}
|
|
case ActionTypes.PROJECT_DELETE:
|
|
Project.withId(payload.id).deleteWithRelated();
|
|
|
|
break;
|
|
case ActionTypes.PROJECT_DELETE__SUCCESS:
|
|
case ActionTypes.PROJECT_DELETE_HANDLE: {
|
|
const projectModel = Project.withId(payload.project.id);
|
|
|
|
if (projectModel) {
|
|
projectModel.deleteWithRelated();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ActionTypes.PROJECT_MANAGER_CREATE_HANDLE: {
|
|
const projectModel = Project.withId(payload.projectManager.projectId);
|
|
|
|
if (projectModel) {
|
|
if (payload.isProjectAvailable) {
|
|
projectModel.boards.toModelArray().forEach((boardModel) => {
|
|
if (payload.boardIds.includes(boardModel.id)) {
|
|
if (payload.isCurrentUser) {
|
|
boardModel.notificationServices.delete();
|
|
}
|
|
} else {
|
|
boardModel.deleteWithRelated(true);
|
|
}
|
|
});
|
|
} else {
|
|
projectModel.deleteWithRelated(true);
|
|
}
|
|
}
|
|
|
|
if (payload.project) {
|
|
Project.upsert(payload.project);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
|
if (!payload.isProjectAvailable) {
|
|
const projectModel = Project.withId(payload.boardMembership.projectId);
|
|
|
|
if (projectModel) {
|
|
projectModel.deleteWithRelated(true);
|
|
}
|
|
}
|
|
|
|
if (payload.project) {
|
|
Project.upsert(payload.project);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
}
|
|
}
|
|
|
|
static getSharedQuerySet() {
|
|
return this.filter({
|
|
ownerProjectManagerId: null,
|
|
}).orderBy(['id.length', 'id']);
|
|
}
|
|
|
|
getManagersQuerySet() {
|
|
return this.managers.orderBy(['id.length', 'id']);
|
|
}
|
|
|
|
getBackgroundImagesQuerySet() {
|
|
return this.backgroundImages.orderBy(['id.length', 'id']);
|
|
}
|
|
|
|
getBaseCustomFieldGroupsQuerySet() {
|
|
return this.baseCustomFieldGroups.orderBy(['id.length', 'id']);
|
|
}
|
|
|
|
getBoardsQuerySet() {
|
|
return this.boards.orderBy(['position', 'id.length', 'id']);
|
|
}
|
|
|
|
getBoardsModelArrayForUserWithId(userId) {
|
|
return this.getBoardsQuerySet()
|
|
.toModelArray()
|
|
.filter((boardModel) => boardModel.hasMembershipWithUserId(userId));
|
|
}
|
|
|
|
getBoardsModelArrayAvailableForUser(userModel) {
|
|
if (this.isExternalAccessibleForUser(userModel)) {
|
|
return this.getBoardsQuerySet().toModelArray();
|
|
}
|
|
|
|
return this.getBoardsModelArrayForUserWithId(userModel.id);
|
|
}
|
|
|
|
hasManagerWithUserId(userId) {
|
|
return this.managers
|
|
.filter({
|
|
userId,
|
|
})
|
|
.exists();
|
|
}
|
|
|
|
hasMembershipWithUserIdInAnyBoard(userId) {
|
|
return this.boards
|
|
.toModelArray()
|
|
.some((boardModel) => boardModel.hasMembershipWithUserId(userId));
|
|
}
|
|
|
|
isExternalAccessibleForUser(userModel) {
|
|
if (!this.ownerProjectManagerId && userModel.role === UserRoles.ADMIN) {
|
|
return true;
|
|
}
|
|
|
|
return this.hasManagerWithUserId(userModel.id);
|
|
}
|
|
|
|
isAvailableForUser(userModel) {
|
|
return (
|
|
this.isExternalAccessibleForUser(userModel) ||
|
|
this.hasMembershipWithUserIdInAnyBoard(userModel.id)
|
|
);
|
|
}
|
|
|
|
deleteRelated(soft) {
|
|
this.managers.delete();
|
|
|
|
this.backgroundImages.toModelArray().forEach((backgroundImageModel) => {
|
|
backgroundImageModel.deleteWithRelated();
|
|
});
|
|
|
|
this.baseCustomFieldGroups.toModelArray().forEach((baseCustomFieldGroupModel) => {
|
|
baseCustomFieldGroupModel.deleteWithRelated();
|
|
});
|
|
|
|
this.boards.toModelArray().forEach((boardModel) => {
|
|
boardModel.deleteWithRelated(soft);
|
|
});
|
|
}
|
|
|
|
deleteWithRelated(soft) {
|
|
this.deleteRelated(soft);
|
|
this.delete();
|
|
}
|
|
}
|