2024-04-05 22:40:35 +02:00
|
|
|
import pick from 'lodash/pick';
|
2022-12-26 21:10:50 +01:00
|
|
|
import { attr, fk, many, oneToOne } 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';
|
|
|
|
import Config from '../constants/Config';
|
2022-08-04 13:31:14 +02:00
|
|
|
import { ActivityTypes } from '../constants/Enums';
|
2019-08-31 04:07:25 +05:00
|
|
|
|
2022-12-26 21:10:50 +01:00
|
|
|
export default class extends BaseModel {
|
2019-08-31 04:07:25 +05:00
|
|
|
static modelName = 'Card';
|
|
|
|
|
|
|
|
static fields = {
|
|
|
|
id: attr(),
|
|
|
|
position: attr(),
|
|
|
|
name: attr(),
|
|
|
|
description: attr(),
|
2019-10-05 06:12:36 +05:00
|
|
|
dueDate: attr(),
|
2023-02-27 19:09:51 +01:00
|
|
|
stopwatch: attr(),
|
2019-08-31 04:07:25 +05:00
|
|
|
isSubscribed: attr({
|
|
|
|
getDefault: () => false,
|
|
|
|
}),
|
2022-08-04 13:31:14 +02:00
|
|
|
isActivitiesFetching: attr({
|
2019-08-31 04:07:25 +05:00
|
|
|
getDefault: () => false,
|
|
|
|
}),
|
2022-08-04 13:31:14 +02:00
|
|
|
isAllActivitiesFetched: attr({
|
2019-08-31 04:07:25 +05:00
|
|
|
getDefault: () => false,
|
|
|
|
}),
|
2022-08-04 13:31:14 +02:00
|
|
|
isActivitiesDetailsVisible: attr({
|
2022-07-29 17:40:18 +02:00
|
|
|
getDefault: () => false,
|
|
|
|
}),
|
2022-08-04 13:31:14 +02:00
|
|
|
isActivitiesDetailsFetching: attr({
|
2022-07-29 17:40:18 +02:00
|
|
|
getDefault: () => false,
|
|
|
|
}),
|
2019-08-31 04:07:25 +05:00
|
|
|
boardId: fk({
|
|
|
|
to: 'Board',
|
|
|
|
as: 'board',
|
|
|
|
relatedName: 'cards',
|
|
|
|
}),
|
2020-08-04 01:32:46 +05:00
|
|
|
listId: fk({
|
|
|
|
to: 'List',
|
|
|
|
as: 'list',
|
|
|
|
relatedName: 'cards',
|
|
|
|
}),
|
2020-04-23 03:02:53 +05:00
|
|
|
coverAttachmentId: oneToOne({
|
|
|
|
to: 'Attachment',
|
|
|
|
as: 'coverAttachment',
|
|
|
|
relatedName: 'coveredCard',
|
|
|
|
}),
|
2019-08-31 04:07:25 +05:00
|
|
|
users: many('User', 'cards'),
|
|
|
|
labels: many('Label', 'cards'),
|
|
|
|
};
|
|
|
|
|
|
|
|
static reducer({ type, payload }, Card) {
|
|
|
|
switch (type) {
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.LOCATION_CHANGE_HANDLE:
|
|
|
|
case ActionTypes.CORE_INITIALIZE:
|
|
|
|
case ActionTypes.PROJECT_MANAGER_CREATE_HANDLE:
|
|
|
|
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
|
|
|
if (payload.cards) {
|
|
|
|
payload.cards.forEach((card) => {
|
|
|
|
Card.upsert(card);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (payload.cardMemberships) {
|
|
|
|
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
|
|
|
Card.withId(cardId).users.add(userId);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (payload.cardLabels) {
|
|
|
|
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
|
|
|
Card.withId(cardId).labels.add(labelId);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ActionTypes.SOCKET_RECONNECT_HANDLE:
|
2022-12-26 21:10:50 +01:00
|
|
|
Card.all()
|
|
|
|
.toModelArray()
|
|
|
|
.forEach((cardModel) => {
|
|
|
|
cardModel.deleteWithClearable();
|
|
|
|
});
|
2021-06-24 01:05:22 +05:00
|
|
|
|
|
|
|
if (payload.cards) {
|
|
|
|
payload.cards.forEach((card) => {
|
|
|
|
Card.upsert(card);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (payload.cardMemberships) {
|
|
|
|
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
|
|
|
Card.withId(cardId).users.add(userId);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (payload.cardLabels) {
|
|
|
|
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
|
|
|
Card.withId(cardId).labels.add(labelId);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2019-08-31 04:07:25 +05:00
|
|
|
case ActionTypes.USER_TO_CARD_ADD: {
|
|
|
|
const cardModel = Card.withId(payload.cardId);
|
|
|
|
cardModel.users.add(payload.id);
|
|
|
|
|
|
|
|
if (payload.isCurrent) {
|
|
|
|
cardModel.isSubscribed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.USER_TO_CARD_ADD__SUCCESS:
|
|
|
|
case ActionTypes.USER_TO_CARD_ADD_HANDLE:
|
|
|
|
try {
|
|
|
|
Card.withId(payload.cardMembership.cardId).users.add(payload.cardMembership.userId);
|
|
|
|
} catch {} // eslint-disable-line no-empty
|
|
|
|
|
|
|
|
break;
|
2019-08-31 04:07:25 +05:00
|
|
|
case ActionTypes.USER_FROM_CARD_REMOVE:
|
|
|
|
Card.withId(payload.cardId).users.remove(payload.id);
|
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.USER_FROM_CARD_REMOVE__SUCCESS:
|
|
|
|
case ActionTypes.USER_FROM_CARD_REMOVE_HANDLE:
|
|
|
|
try {
|
|
|
|
Card.withId(payload.cardMembership.cardId).users.remove(payload.cardMembership.userId);
|
|
|
|
} catch {} // eslint-disable-line no-empty
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ActionTypes.BOARD_FETCH__SUCCESS:
|
2020-03-25 00:15:47 +05:00
|
|
|
payload.cards.forEach((card) => {
|
2019-08-31 04:07:25 +05:00
|
|
|
Card.upsert(card);
|
|
|
|
});
|
|
|
|
|
|
|
|
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
|
|
|
Card.withId(cardId).users.add(userId);
|
|
|
|
});
|
|
|
|
|
|
|
|
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
|
|
|
Card.withId(cardId).labels.add(labelId);
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
case ActionTypes.LABEL_TO_CARD_ADD:
|
|
|
|
Card.withId(payload.cardId).labels.add(payload.id);
|
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.LABEL_TO_CARD_ADD__SUCCESS:
|
|
|
|
case ActionTypes.LABEL_TO_CARD_ADD_HANDLE:
|
|
|
|
try {
|
|
|
|
Card.withId(payload.cardLabel.cardId).labels.add(payload.cardLabel.labelId);
|
|
|
|
} catch {} // eslint-disable-line no-empty
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.LABEL_FROM_CARD_REMOVE:
|
|
|
|
Card.withId(payload.cardId).labels.remove(payload.id);
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.LABEL_FROM_CARD_REMOVE__SUCCESS:
|
|
|
|
case ActionTypes.LABEL_FROM_CARD_REMOVE_HANDLE:
|
|
|
|
try {
|
|
|
|
Card.withId(payload.cardLabel.cardId).labels.remove(payload.cardLabel.labelId);
|
|
|
|
} catch {} // eslint-disable-line no-empty
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.CARD_CREATE:
|
|
|
|
case ActionTypes.CARD_UPDATE__SUCCESS:
|
|
|
|
case ActionTypes.CARD_UPDATE_HANDLE:
|
|
|
|
Card.upsert(payload.card);
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.CARD_CREATE__SUCCESS:
|
2019-08-31 04:07:25 +05:00
|
|
|
Card.withId(payload.localId).delete();
|
|
|
|
Card.upsert(payload.card);
|
|
|
|
|
|
|
|
break;
|
2024-04-05 22:40:35 +02:00
|
|
|
case ActionTypes.CARD_CREATE_HANDLE: {
|
|
|
|
const cardModel = Card.upsert(payload.card);
|
|
|
|
|
|
|
|
payload.cardMemberships.forEach(({ userId }) => {
|
|
|
|
cardModel.users.add(userId);
|
|
|
|
});
|
|
|
|
|
|
|
|
payload.cardLabels.forEach(({ labelId }) => {
|
|
|
|
cardModel.labels.add(labelId);
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.CARD_UPDATE:
|
|
|
|
Card.withId(payload.id).update(payload.data);
|
2020-05-09 05:30:52 +05:00
|
|
|
|
2021-06-24 01:05:22 +05:00
|
|
|
break;
|
2024-04-05 22:40:35 +02:00
|
|
|
case ActionTypes.CARD_DUPLICATE: {
|
|
|
|
const cardModel = Card.withId(payload.id);
|
|
|
|
|
|
|
|
const nextCardModel = Card.upsert({
|
|
|
|
...pick(cardModel.ref, [
|
|
|
|
'boardId',
|
|
|
|
'listId',
|
|
|
|
'position',
|
|
|
|
'name',
|
|
|
|
'description',
|
|
|
|
'dueDate',
|
|
|
|
'stopwatch',
|
|
|
|
]),
|
|
|
|
...payload.card,
|
|
|
|
});
|
|
|
|
|
|
|
|
cardModel.users.toRefArray().forEach(({ id }) => {
|
|
|
|
nextCardModel.users.add(id);
|
|
|
|
});
|
|
|
|
|
|
|
|
cardModel.labels.toRefArray().forEach(({ id }) => {
|
|
|
|
nextCardModel.labels.add(id);
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ActionTypes.CARD_DUPLICATE__SUCCESS: {
|
|
|
|
Card.withId(payload.localId).deleteWithRelated();
|
|
|
|
const cardModel = Card.upsert(payload.card);
|
|
|
|
|
|
|
|
payload.cardMemberships.forEach(({ userId }) => {
|
|
|
|
cardModel.users.add(userId);
|
|
|
|
});
|
|
|
|
|
|
|
|
payload.cardLabels.forEach(({ labelId }) => {
|
|
|
|
cardModel.labels.add(labelId);
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.CARD_DELETE:
|
2022-12-26 21:10:50 +01:00
|
|
|
Card.withId(payload.id).deleteWithRelated();
|
2019-08-31 04:07:25 +05:00
|
|
|
|
|
|
|
break;
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.CARD_DELETE__SUCCESS:
|
|
|
|
case ActionTypes.CARD_DELETE_HANDLE: {
|
|
|
|
const cardModel = Card.withId(payload.card.id);
|
2020-05-09 05:30:52 +05:00
|
|
|
|
2021-06-24 01:05:22 +05:00
|
|
|
if (cardModel) {
|
|
|
|
cardModel.deleteWithRelated();
|
2020-05-09 05:30:52 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2022-08-04 13:31:14 +02:00
|
|
|
case ActionTypes.ACTIVITIES_FETCH:
|
2019-08-31 04:07:25 +05:00
|
|
|
Card.withId(payload.cardId).update({
|
2022-08-04 13:31:14 +02:00
|
|
|
isActivitiesFetching: true,
|
2019-08-31 04:07:25 +05:00
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
2022-08-04 13:31:14 +02:00
|
|
|
case ActionTypes.ACTIVITIES_FETCH__SUCCESS:
|
2019-08-31 04:07:25 +05:00
|
|
|
Card.withId(payload.cardId).update({
|
2022-08-04 13:31:14 +02:00
|
|
|
isActivitiesFetching: false,
|
|
|
|
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
|
2019-08-31 04:07:25 +05:00
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
2022-08-04 13:31:14 +02:00
|
|
|
case ActionTypes.ACTIVITIES_DETAILS_TOGGLE: {
|
2022-07-29 17:40:18 +02:00
|
|
|
const cardModel = Card.withId(payload.cardId);
|
2022-08-04 13:31:14 +02:00
|
|
|
cardModel.isActivitiesDetailsVisible = payload.isVisible;
|
2022-07-29 17:40:18 +02:00
|
|
|
|
|
|
|
if (payload.isVisible) {
|
2022-08-04 13:31:14 +02:00
|
|
|
cardModel.isActivitiesDetailsFetching = true;
|
2022-07-29 17:40:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2022-08-04 13:31:14 +02:00
|
|
|
case ActionTypes.ACTIVITIES_DETAILS_TOGGLE__SUCCESS: {
|
2022-07-29 17:40:18 +02:00
|
|
|
const cardModel = Card.withId(payload.cardId);
|
|
|
|
|
|
|
|
cardModel.update({
|
2022-08-04 13:31:14 +02:00
|
|
|
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
|
|
|
|
isActivitiesDetailsFetching: false,
|
2022-07-29 17:40:18 +02:00
|
|
|
});
|
|
|
|
|
2022-12-26 21:10:50 +01:00
|
|
|
cardModel.deleteActivities();
|
2022-07-29 17:40:18 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2021-06-24 01:05:22 +05:00
|
|
|
case ActionTypes.NOTIFICATION_CREATE_HANDLE:
|
2020-03-25 00:15:47 +05:00
|
|
|
payload.cards.forEach((card) => {
|
2019-08-31 04:07:25 +05:00
|
|
|
Card.upsert(card);
|
|
|
|
});
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
getOrderedTasksQuerySet() {
|
2022-07-21 11:31:05 +02:00
|
|
|
return this.tasks.orderBy('position');
|
2019-08-31 04:07:25 +05:00
|
|
|
}
|
|
|
|
|
2020-04-21 05:04:34 +05:00
|
|
|
getOrderedAttachmentsQuerySet() {
|
2023-06-13 00:19:17 +02:00
|
|
|
return this.attachments.orderBy('createdAt', false);
|
2020-04-21 05:04:34 +05:00
|
|
|
}
|
|
|
|
|
2022-08-04 13:31:14 +02:00
|
|
|
getFilteredOrderedInCardActivitiesQuerySet() {
|
2022-07-29 17:40:18 +02:00
|
|
|
const filter = {
|
|
|
|
isInCard: true,
|
|
|
|
};
|
|
|
|
|
2022-08-04 13:31:14 +02:00
|
|
|
if (!this.isActivitiesDetailsVisible) {
|
|
|
|
filter.type = ActivityTypes.COMMENT_CARD;
|
2022-07-29 17:40:18 +02:00
|
|
|
}
|
|
|
|
|
2023-06-13 00:19:17 +02:00
|
|
|
return this.activities.filter(filter).orderBy('createdAt', false);
|
2019-08-31 04:07:25 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
getUnreadNotificationsQuerySet() {
|
|
|
|
return this.notifications.filter({
|
|
|
|
isRead: false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-12-26 21:10:50 +01:00
|
|
|
isAvailableForUser(userId) {
|
|
|
|
return this.board && this.board.isAvailableForUser(userId);
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteClearable() {
|
|
|
|
this.users.clear();
|
|
|
|
this.labels.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteActivities() {
|
|
|
|
this.activities.toModelArray().forEach((activityModel) => {
|
|
|
|
if (activityModel.notification) {
|
|
|
|
activityModel.update({
|
|
|
|
isInCard: false,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
activityModel.delete();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-06-24 01:05:22 +05:00
|
|
|
deleteRelated() {
|
2022-12-26 21:10:50 +01:00
|
|
|
this.deleteClearable();
|
2019-08-31 04:07:25 +05:00
|
|
|
this.tasks.delete();
|
2020-05-09 05:30:52 +05:00
|
|
|
this.attachments.delete();
|
2022-12-26 21:10:50 +01:00
|
|
|
this.deleteActivities();
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteWithClearable() {
|
|
|
|
this.deleteClearable();
|
|
|
|
this.delete();
|
2021-06-24 01:05:22 +05:00
|
|
|
}
|
2019-08-31 04:07:25 +05:00
|
|
|
|
2021-06-24 01:05:22 +05:00
|
|
|
deleteWithRelated() {
|
|
|
|
this.deleteRelated();
|
2019-08-31 04:07:25 +05:00
|
|
|
this.delete();
|
|
|
|
}
|
|
|
|
}
|