feat: Add board activity log

This commit is contained in:
Maksim Eltyshev
2025-05-22 23:14:46 +02:00
parent 777ff467f3
commit 86cfd155f2
72 changed files with 833 additions and 169 deletions

View File

@@ -18,6 +18,11 @@ export default class extends BaseModel {
createdAt: attr({
getDefault: () => new Date(),
}),
boardId: fk({
to: 'Board',
as: 'board',
relatedName: 'activities',
}),
cardId: fk({
to: 'Card',
as: 'card',
@@ -37,7 +42,8 @@ export default class extends BaseModel {
break;
case ActionTypes.LIST_CARDS_MOVE__SUCCESS:
case ActionTypes.ACTIVITIES_FETCH__SUCCESS:
case ActionTypes.ACTIVITIES_IN_BOARD_FETCH__SUCCESS:
case ActionTypes.ACTIVITIES_IN_CARD_FETCH__SUCCESS:
payload.activities.forEach((activity) => {
Activity.upsert(activity);
});

View File

@@ -9,6 +9,7 @@ import BaseModel from './BaseModel';
import buildSearchParts from '../utils/build-search-parts';
import { isListFinite } from '../utils/record-helpers';
import ActionTypes from '../constants/ActionTypes';
import Config from '../constants/Config';
import { BoardContexts, BoardViews } from '../constants/Enums';
const prepareFetchedBoard = (board) => ({
@@ -39,6 +40,15 @@ export default class extends BaseModel {
isFetching: attr({
getDefault: () => null,
}),
lastActivityId: attr({
getDefault: () => null,
}),
isActivitiesFetching: attr({
getDefault: () => false,
}),
isAllActivitiesFetched: attr({
getDefault: () => null,
}),
projectId: fk({
to: 'Project',
as: 'project',
@@ -241,6 +251,22 @@ export default class extends BaseModel {
case ActionTypes.LABEL_FROM_BOARD_FILTER_REMOVE:
Board.withId(payload.boardId).filterLabels.remove(payload.id);
break;
case ActionTypes.ACTIVITIES_IN_BOARD_FETCH:
Board.withId(payload.boardId).update({
isActivitiesFetching: true,
});
break;
case ActionTypes.ACTIVITIES_IN_BOARD_FETCH__SUCCESS:
Board.withId(payload.boardId).update({
isActivitiesFetching: false,
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
...(payload.activities.length > 0 && {
lastActivityId: payload.activities[payload.activities.length - 1].id,
}),
});
break;
default:
}
@@ -266,6 +292,10 @@ export default class extends BaseModel {
return this.customFieldGroups.orderBy(['position', 'id.length', 'id']);
}
getActivitiesQuerySet() {
return this.activities.orderBy(['id.length', 'id'], ['desc', 'desc']);
}
getUnreadNotificationsQuerySet() {
return this.notifications.filter({
isRead: false,
@@ -347,6 +377,30 @@ export default class extends BaseModel {
return cardModels;
}
getActivitiesModelArray() {
if (this.isAllActivitiesFetched === null) {
return [];
}
const activityModels = this.getActivitiesQuerySet().toModelArray();
if (this.lastActivityId && this.isAllActivitiesFetched === false) {
return activityModels.filter((activityModel) => {
if (activityModel.id.length > this.lastActivityId.length) {
return true;
}
if (activityModel.id.length < this.lastActivityId.length) {
return false;
}
return activityModel.id >= this.lastActivityId;
});
}
return activityModels;
}
hasMembershipWithUserId(userId) {
return this.memberships
.filter({

View File

@@ -402,13 +402,13 @@ export default class extends BaseModel {
});
break;
case ActionTypes.ACTIVITIES_FETCH:
case ActionTypes.ACTIVITIES_IN_CARD_FETCH:
Card.withId(payload.cardId).update({
isActivitiesFetching: true,
});
break;
case ActionTypes.ACTIVITIES_FETCH__SUCCESS:
case ActionTypes.ACTIVITIES_IN_CARD_FETCH__SUCCESS:
Card.withId(payload.cardId).update({
isActivitiesFetching: false,
isAllActivitiesFetched: payload.activities.length < Config.ACTIVITIES_LIMIT,
@@ -607,7 +607,6 @@ export default class extends BaseModel {
this.customFieldValues.delete();
this.comments.delete();
this.activities.delete();
}
deleteWithClearable() {

View File

@@ -295,7 +295,8 @@ export default class extends BaseModel {
case ActionTypes.CARD_CREATE_HANDLE:
case ActionTypes.COMMENTS_FETCH__SUCCESS:
case ActionTypes.COMMENT_CREATE_HANDLE:
case ActionTypes.ACTIVITIES_FETCH__SUCCESS:
case ActionTypes.ACTIVITIES_IN_BOARD_FETCH__SUCCESS:
case ActionTypes.ACTIVITIES_IN_CARD_FETCH__SUCCESS:
case ActionTypes.NOTIFICATION_CREATE_HANDLE:
payload.users.forEach((user) => {
User.upsert(user);