2022-12-26 21:10:50 +01:00
|
|
|
import { attr, fk, many } from 'redux-orm';
|
2019-08-31 04:07:25 +05:00
|
|
|
|
2022-12-26 21:10:50 +01:00
|
|
|
import BaseModel from './BaseModel';
|
2019-08-31 04:07:25 +05:00
|
|
|
import ActionTypes from '../constants/ActionTypes';
|
|
|
|
|
2024-04-22 23:15:31 +02:00
|
|
|
import User from './User';
|
|
|
|
import Label from './Label';
|
|
|
|
|
2022-12-26 21:10:50 +01:00
|
|
|
export default class extends BaseModel {
|
2019-08-31 04:07:25 +05:00
|
|
|
static modelName = 'Board';
|
|
|
|
|
|
|
|
static fields = {
|
|
|
|
id: attr(),
|
|
|
|
position: attr(),
|
|
|
|
name: attr(),
|
|
|
|
isFetching: attr({
|
|
|
|
getDefault: () => null,
|
|
|
|
}),
|
|
|
|
projectId: fk({
|
|
|
|
to: 'Project',
|
|
|
|
as: 'project',
|
|
|
|
relatedName: 'boards',
|
|
|
|
}),
|
2021-06-24 01:05:22 +05:00
|
|
|
memberUsers: many({
|
|
|
|
to: 'User',
|
|
|
|
through: 'BoardMembership',
|
|
|
|
relatedName: 'boards',
|
|
|
|
}),
|
2019-08-31 04:07:25 +05:00
|
|
|
filterUsers: many('User', 'filterBoards'),
|
|
|
|
filterLabels: many('Label', 'filterBoards'),
|
2024-04-22 23:15:31 +02:00
|
|
|
filterText: attr({
|
|
|
|
getDefault: () => '',
|
|
|
|
}),
|
2019-08-31 04:07:25 +05:00
|
|
|
};
|
|
|
|
|
|
|
|
static reducer({ type, payload }, Board) {
|
|
|
|
switch (type) {
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.LOCATION_CHANGE_HANDLE:
|
2022-12-16 17:05:03 +01:00
|
|
|
if (payload.board) {
|
|
|
|
Board.upsert({
|
|
|
|
...payload.board,
|
|
|
|
isFetching: false,
|
|
|
|
});
|
|
|
|
}
|
2021-06-24 01:05:22 +05:00
|
|
|
|
|
|
|
break;
|
|
|
|
case ActionTypes.LOCATION_CHANGE_HANDLE__BOARD_FETCH:
|
|
|
|
case ActionTypes.BOARD_FETCH:
|
|
|
|
Board.withId(payload.id).update({
|
|
|
|
isFetching: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ActionTypes.SOCKET_RECONNECT_HANDLE:
|
|
|
|
Board.all().delete();
|
|
|
|
|
|
|
|
if (payload.board) {
|
|
|
|
Board.upsert({
|
|
|
|
...payload.board,
|
|
|
|
isFetching: false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
payload.boards.forEach((board) => {
|
|
|
|
Board.upsert(board);
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ActionTypes.SOCKET_RECONNECT_HANDLE__CORE_FETCH:
|
|
|
|
Board.all()
|
|
|
|
.toModelArray()
|
|
|
|
.forEach((boardModel) => {
|
|
|
|
if (boardModel.id !== payload.currentBoardId) {
|
|
|
|
boardModel.update({
|
|
|
|
isFetching: null,
|
|
|
|
});
|
|
|
|
|
|
|
|
boardModel.deleteRelated(payload.currentUserId);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ActionTypes.CORE_INITIALIZE:
|
|
|
|
if (payload.board) {
|
|
|
|
Board.upsert({
|
|
|
|
...payload.board,
|
|
|
|
isFetching: false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
payload.boards.forEach((board) => {
|
|
|
|
Board.upsert(board);
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
2019-08-31 04:07:25 +05:00
|
|
|
case ActionTypes.USER_TO_BOARD_FILTER_ADD:
|
|
|
|
Board.withId(payload.boardId).filterUsers.add(payload.id);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ActionTypes.USER_FROM_BOARD_FILTER_REMOVE:
|
|
|
|
Board.withId(payload.boardId).filterUsers.remove(payload.id);
|
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.PROJECT_CREATE_HANDLE:
|
2020-03-25 00:15:47 +05:00
|
|
|
payload.boards.forEach((board) => {
|
2019-08-31 04:07:25 +05:00
|
|
|
Board.upsert(board);
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.PROJECT_MANAGER_CREATE_HANDLE:
|
|
|
|
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
|
|
|
if (payload.boards) {
|
|
|
|
payload.boards.forEach((board) => {
|
|
|
|
Board.upsert({
|
|
|
|
...board,
|
|
|
|
...(payload.board &&
|
|
|
|
payload.board.id === board.id && {
|
|
|
|
isFetching: false,
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.BOARD_CREATE:
|
|
|
|
case ActionTypes.BOARD_CREATE_HANDLE:
|
|
|
|
case ActionTypes.BOARD_UPDATE__SUCCESS:
|
|
|
|
case ActionTypes.BOARD_UPDATE_HANDLE:
|
|
|
|
Board.upsert(payload.board);
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.BOARD_CREATE__SUCCESS:
|
2019-08-31 04:07:25 +05:00
|
|
|
Board.withId(payload.localId).delete();
|
2022-12-16 23:48:06 +01:00
|
|
|
Board.upsert(payload.board);
|
2019-08-31 04:07:25 +05:00
|
|
|
|
2022-12-16 17:05:03 +01:00
|
|
|
break;
|
|
|
|
case ActionTypes.BOARD_FETCH__SUCCESS:
|
|
|
|
Board.upsert({
|
|
|
|
...payload.board,
|
|
|
|
isFetching: false,
|
|
|
|
});
|
|
|
|
|
2019-08-31 04:07:25 +05:00
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.BOARD_FETCH__FAILURE:
|
2019-08-31 04:07:25 +05:00
|
|
|
Board.withId(payload.id).update({
|
2021-06-24 01:05:22 +05:00
|
|
|
isFetching: null,
|
2019-08-31 04:07:25 +05:00
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.BOARD_UPDATE:
|
|
|
|
Board.withId(payload.id).update(payload.data);
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.BOARD_DELETE:
|
|
|
|
Board.withId(payload.id).deleteWithRelated();
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.BOARD_DELETE__SUCCESS:
|
|
|
|
case ActionTypes.BOARD_DELETE_HANDLE: {
|
|
|
|
const boardModel = Board.withId(payload.board.id);
|
|
|
|
|
|
|
|
if (boardModel) {
|
|
|
|
boardModel.deleteWithRelated();
|
|
|
|
}
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
}
|
2019-08-31 04:07:25 +05:00
|
|
|
case ActionTypes.LABEL_TO_BOARD_FILTER_ADD:
|
|
|
|
Board.withId(payload.boardId).filterLabels.add(payload.id);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ActionTypes.LABEL_FROM_BOARD_FILTER_REMOVE:
|
|
|
|
Board.withId(payload.boardId).filterLabels.remove(payload.id);
|
|
|
|
|
|
|
|
break;
|
2024-04-22 23:15:31 +02:00
|
|
|
case ActionTypes.TEXT_FILTER_IN_CURRENT_BOARD: {
|
|
|
|
const board = Board.withId(payload.boardId);
|
|
|
|
let filterText = payload.text;
|
|
|
|
const posSpace = filterText.indexOf(' ');
|
|
|
|
|
|
|
|
// Shortcut to user filters
|
|
|
|
const posAT = filterText.indexOf('@');
|
|
|
|
if (posAT >= 0 && posSpace > 0 && posAT < posSpace) {
|
|
|
|
const userId = User.findUsersFromText(
|
|
|
|
filterText.substring(posAT + 1, posSpace),
|
|
|
|
board.memberships.toModelArray().map((membership) => membership.user),
|
|
|
|
);
|
|
|
|
if (
|
|
|
|
userId &&
|
|
|
|
board.filterUsers.toModelArray().filter((user) => user.id === userId).length === 0
|
|
|
|
) {
|
|
|
|
board.filterUsers.add(userId);
|
|
|
|
filterText = filterText.substring(0, posAT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Shortcut to label filters
|
|
|
|
const posSharp = filterText.indexOf('#');
|
|
|
|
if (posSharp >= 0 && posSpace > 0 && posSharp < posSpace) {
|
|
|
|
const labelId = Label.findLabelsFromText(
|
|
|
|
filterText.substring(posSharp + 1, posSpace),
|
|
|
|
board.labels.toModelArray(),
|
|
|
|
);
|
|
|
|
if (
|
|
|
|
labelId &&
|
|
|
|
board.filterLabels.toModelArray().filter((label) => label.id === labelId).length === 0
|
|
|
|
) {
|
|
|
|
board.filterLabels.add(labelId);
|
|
|
|
filterText = filterText.substring(0, posSharp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
board.update({ filterText });
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2019-08-31 04:07:25 +05:00
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-24 01:05:22 +05:00
|
|
|
getOrderedMembershipsQuerySet() {
|
2023-06-13 00:19:17 +02:00
|
|
|
return this.memberships.orderBy('createdAt');
|
2021-06-24 01:05:22 +05:00
|
|
|
}
|
|
|
|
|
2023-01-09 12:17:06 +01:00
|
|
|
getOrderedLabelsQuerySet() {
|
|
|
|
return this.labels.orderBy('position');
|
|
|
|
}
|
|
|
|
|
2019-08-31 04:07:25 +05:00
|
|
|
getOrderedListsQuerySet() {
|
|
|
|
return this.lists.orderBy('position');
|
|
|
|
}
|
|
|
|
|
2022-12-26 21:10:50 +01:00
|
|
|
getMembershipModelForUser(userId) {
|
2022-08-19 14:00:40 +02:00
|
|
|
return this.memberships
|
|
|
|
.filter({
|
|
|
|
userId,
|
|
|
|
})
|
|
|
|
.first();
|
|
|
|
}
|
|
|
|
|
2022-12-26 21:10:50 +01:00
|
|
|
hasMembershipForUser(userId) {
|
2021-06-24 01:05:22 +05:00
|
|
|
return this.memberships
|
|
|
|
.filter({
|
|
|
|
userId,
|
|
|
|
})
|
|
|
|
.exists();
|
|
|
|
}
|
|
|
|
|
2022-12-26 21:10:50 +01:00
|
|
|
isAvailableForUser(userId) {
|
|
|
|
return (
|
|
|
|
this.project && (this.project.hasManagerForUser(userId) || this.hasMembershipForUser(userId))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-06-24 01:05:22 +05:00
|
|
|
deleteRelated(exceptMemberUserId) {
|
|
|
|
this.memberships.toModelArray().forEach((boardMembershipModel) => {
|
|
|
|
if (boardMembershipModel.userId !== exceptMemberUserId) {
|
|
|
|
boardMembershipModel.deleteWithRelated();
|
|
|
|
}
|
2019-08-31 04:07:25 +05:00
|
|
|
});
|
|
|
|
|
2021-06-24 01:05:22 +05:00
|
|
|
this.labels.delete();
|
|
|
|
|
|
|
|
this.lists.toModelArray().forEach((listModel) => {
|
|
|
|
listModel.deleteWithRelated();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteWithRelated() {
|
|
|
|
this.deleteRelated();
|
2019-08-31 04:07:25 +05:00
|
|
|
this.delete();
|
|
|
|
}
|
|
|
|
}
|