feature/IO-3291-Tasks-Notifications: Checkpoint
This commit is contained in:
@@ -16,11 +16,6 @@ import { useMutation } from "@apollo/client";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||||
import { INITIAL_NOTIFICATIONS, SocketContext } from "./useSocket.js";
|
import { INITIAL_NOTIFICATIONS, SocketContext } from "./useSocket.js";
|
||||||
import {
|
|
||||||
QUERY_MY_TASKS_COUNT,
|
|
||||||
QUERY_TASKS_NO_DUE_DATE_PAGINATED,
|
|
||||||
QUERY_TASKS_WITH_DUE_DATES
|
|
||||||
} from "../../graphql/tasks.queries";
|
|
||||||
|
|
||||||
const LIMIT = INITIAL_NOTIFICATIONS;
|
const LIMIT = INITIAL_NOTIFICATIONS;
|
||||||
|
|
||||||
@@ -193,123 +188,61 @@ const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => {
|
|||||||
limit: LIMIT,
|
limit: LIMIT,
|
||||||
offset: 0
|
offset: 0
|
||||||
};
|
};
|
||||||
const countVars = {
|
|
||||||
assigned_to: assignedToId,
|
|
||||||
bodyshopid: bodyshop?.id
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper to update a list in cache locally
|
const whereBase = {
|
||||||
const updateListCache = (query, vars, action) => {
|
bodyshopid: { _eq: bodyshop?.id },
|
||||||
// action: 'add' or 'remove'
|
assigned_to: { _eq: assignedToId },
|
||||||
|
deleted: { _eq: false },
|
||||||
|
completed: { _eq: false }
|
||||||
|
};
|
||||||
|
const whereDue = { ...whereBase, due_date: { _is_null: false } };
|
||||||
|
const whereNoDue = { ...whereBase, due_date: { _is_null: true } };
|
||||||
|
|
||||||
|
// Helper to invalidate a cache entry
|
||||||
|
const invalidateCache = (fieldName, args) => {
|
||||||
try {
|
try {
|
||||||
const current = client.readQuery({ query, variables: vars });
|
client.cache.evict({
|
||||||
if (!current) return; // List not loaded yet, skip
|
id: "ROOT_QUERY",
|
||||||
|
fieldName,
|
||||||
let updatedTasks = [...current.tasks];
|
args
|
||||||
let delta = 0;
|
});
|
||||||
|
|
||||||
if (action === "remove") {
|
|
||||||
const prevLength = updatedTasks.length;
|
|
||||||
updatedTasks = updatedTasks.filter((task) => task.id !== payload.id);
|
|
||||||
if (updatedTasks.length < prevLength) delta -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action === "add") {
|
|
||||||
const exists = updatedTasks.some((task) => task.id === payload.id);
|
|
||||||
if (!exists) {
|
|
||||||
const newTask = { ...payload, __typename: "tasks" };
|
|
||||||
updatedTasks.push(newTask);
|
|
||||||
delta += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort the array based on the query type if delta !== 0
|
|
||||||
if (delta !== 0) {
|
|
||||||
if (query === QUERY_TASKS_WITH_DUE_DATES) {
|
|
||||||
updatedTasks.sort((a, b) => {
|
|
||||||
const da = new Date(a.due_date);
|
|
||||||
const db = new Date(b.due_date);
|
|
||||||
if (da < db) return -1;
|
|
||||||
if (da > db) return 1;
|
|
||||||
const ca = new Date(a.created_at);
|
|
||||||
const cb = new Date(b.created_at);
|
|
||||||
return cb - ca; // desc
|
|
||||||
});
|
|
||||||
} else if (query === QUERY_TASKS_NO_DUE_DATE_PAGINATED) {
|
|
||||||
updatedTasks.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = { ...current, tasks: updatedTasks };
|
|
||||||
|
|
||||||
// Adjust aggregate count for no due date query
|
|
||||||
if (query === QUERY_TASKS_NO_DUE_DATE_PAGINATED && delta !== 0 && current.tasks_aggregate) {
|
|
||||||
const newCount = Math.max(0, current.tasks_aggregate.aggregate.count + delta);
|
|
||||||
data = {
|
|
||||||
...data,
|
|
||||||
tasks_aggregate: {
|
|
||||||
...current.tasks_aggregate,
|
|
||||||
aggregate: {
|
|
||||||
...current.tasks_aggregate.aggregate,
|
|
||||||
count: newCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
client.writeQuery({ query, variables: vars, data });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error updating task list cache:", error);
|
console.error("Error invalidating cache:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update lists based on event type
|
// Invalidate lists and aggregates based on event type
|
||||||
if (message.type === "task-deleted") {
|
if (message.type === "task-deleted" || message.type === "task-updated") {
|
||||||
updateListCache(QUERY_TASKS_WITH_DUE_DATES, dueVars, "remove");
|
// Invalidate both lists and no due aggregate for deletes and updates
|
||||||
updateListCache(QUERY_TASKS_NO_DUE_DATE_PAGINATED, noDueVars, "remove");
|
invalidateCache("tasks", { where: whereDue, order_by: dueVars.order });
|
||||||
} else {
|
invalidateCache("tasks", {
|
||||||
const targetQuery = payload.due_date ? QUERY_TASKS_WITH_DUE_DATES : QUERY_TASKS_NO_DUE_DATE_PAGINATED;
|
where: whereNoDue,
|
||||||
const targetVars = payload.due_date ? dueVars : noDueVars;
|
order_by: noDueVars.order,
|
||||||
|
limit: noDueVars.limit,
|
||||||
if (message.type === "task-updated") {
|
offset: noDueVars.offset
|
||||||
// Remove from both in case of due_date change
|
});
|
||||||
updateListCache(QUERY_TASKS_WITH_DUE_DATES, dueVars, "remove");
|
invalidateCache("tasks_aggregate", { where: whereNoDue });
|
||||||
updateListCache(QUERY_TASKS_NO_DUE_DATE_PAGINATED, noDueVars, "remove");
|
} else if (message.type === "task-created") {
|
||||||
|
// For creates, invalidate the target list and no due aggregate if applicable
|
||||||
|
const hasDue = !!payload.due_date;
|
||||||
|
if (hasDue) {
|
||||||
|
invalidateCache("tasks", { where: whereDue, order_by: dueVars.order });
|
||||||
|
} else {
|
||||||
|
invalidateCache("tasks", {
|
||||||
|
where: whereNoDue,
|
||||||
|
order_by: noDueVars.order,
|
||||||
|
limit: noDueVars.limit,
|
||||||
|
offset: noDueVars.offset
|
||||||
|
});
|
||||||
|
invalidateCache("tasks_aggregate", { where: whereNoDue });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to the target list
|
|
||||||
updateListCache(targetQuery, targetVars, "add");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locally update the total count (no network call)
|
// Always invalidate the total count for all events (handles creates, deletes, updates including completions)
|
||||||
try {
|
invalidateCache("tasks_aggregate", { where: whereBase });
|
||||||
const currentCountQuery = client.readQuery({ query: QUERY_MY_TASKS_COUNT, variables: countVars });
|
|
||||||
if (currentCountQuery) {
|
|
||||||
let countDelta = 0;
|
|
||||||
if (message.type === "task-created") countDelta = 1;
|
|
||||||
else if (message.type === "task-deleted") countDelta = -1;
|
|
||||||
// For "task-updated", assume no change to count unless specific logic (e.g., completion)
|
|
||||||
|
|
||||||
if (countDelta !== 0) {
|
// Garbage collect after evictions
|
||||||
const newCount = Math.max(0, currentCountQuery.tasks_aggregate.aggregate.count + countDelta);
|
client.cache.gc();
|
||||||
client.writeQuery({
|
|
||||||
query: QUERY_MY_TASKS_COUNT,
|
|
||||||
variables: countVars,
|
|
||||||
data: {
|
|
||||||
tasks_aggregate: {
|
|
||||||
__typename: "tasks_aggregate",
|
|
||||||
aggregate: {
|
|
||||||
__typename: "tasks_aggregate_fields",
|
|
||||||
count: newCount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error updating task count cache:", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user