mirror of
https://github.com/linkwarden/linkwarden.git
synced 2026-07-01 08:16:26 +00:00
189 lines
4.6 KiB
TypeScript
189 lines
4.6 KiB
TypeScript
import {
|
|
UpdateDashboardLayoutSchema,
|
|
UpdateDashboardLayoutSchemaType,
|
|
} from "@linkwarden/lib/schemaValidation";
|
|
import { prisma } from "@linkwarden/prisma";
|
|
import { DashboardSection } from "@linkwarden/prisma/client";
|
|
import getDashboardData from "./getDashboardDataV2";
|
|
|
|
export default async function updateDashboardLayout(
|
|
userId: number,
|
|
body: UpdateDashboardLayoutSchemaType[]
|
|
) {
|
|
const dataValidation = UpdateDashboardLayoutSchema.safeParse(body);
|
|
|
|
if (!dataValidation.success) {
|
|
console.log(dataValidation.error.issues[0].message);
|
|
return {
|
|
response: `Error: ${
|
|
dataValidation.error.issues[0].message
|
|
} [${dataValidation.error.issues[0].path.join(", ")}]`,
|
|
status: 400,
|
|
};
|
|
}
|
|
|
|
const data = dataValidation.data;
|
|
|
|
let collectionIds = data
|
|
.map((section) => section.collectionId)
|
|
.filter((id) => id !== undefined);
|
|
|
|
if (collectionIds && collectionIds.length > 0) {
|
|
collectionIds = (
|
|
await prisma.collection.findMany({
|
|
where: {
|
|
id: {
|
|
in: collectionIds as number[],
|
|
},
|
|
OR: [{ ownerId: userId }, { members: { some: { userId } } }],
|
|
},
|
|
})
|
|
).map((collection) => collection.id);
|
|
}
|
|
|
|
let parsedData = data.filter((section) =>
|
|
section.collectionId ? collectionIds.includes(section.collectionId) : true
|
|
);
|
|
|
|
const existingSections = await prisma.dashboardSection.findMany({
|
|
where: {
|
|
userId: userId,
|
|
},
|
|
});
|
|
|
|
const existingSectionsMap = new Map(
|
|
existingSections.map((section) => [
|
|
`${section.type}-${section.collectionId || "default"}`,
|
|
section,
|
|
])
|
|
);
|
|
|
|
const sectionsToCreate: Pick<
|
|
DashboardSection,
|
|
"userId" | "type" | "collectionId" | "order"
|
|
>[] = [];
|
|
const sectionsToUpdate: Array<{
|
|
id: number;
|
|
newOrder: number;
|
|
oldOrder: number;
|
|
}> = [];
|
|
const sectionsToDelete: Array<{
|
|
id: number;
|
|
order: number;
|
|
}> = [];
|
|
|
|
for (const section of parsedData) {
|
|
const key = `${section.type}-${section.collectionId || "default"}`;
|
|
const existingSection = existingSectionsMap.get(key);
|
|
|
|
if (existingSection && !section.enabled) {
|
|
sectionsToDelete.push({
|
|
id: existingSection.id,
|
|
order: existingSection.order,
|
|
});
|
|
} else if (existingSection && section.enabled) {
|
|
if (existingSection.order !== section.order) {
|
|
sectionsToUpdate.push({
|
|
id: existingSection.id,
|
|
newOrder: section.order!,
|
|
oldOrder: existingSection.order,
|
|
});
|
|
}
|
|
} else if (section.enabled) {
|
|
sectionsToCreate.push({
|
|
userId: userId,
|
|
type: section.type,
|
|
collectionId: section.collectionId || null,
|
|
order: section.order!,
|
|
});
|
|
}
|
|
}
|
|
|
|
await prisma.$transaction(async (tx) => {
|
|
for (const sectionToDelete of sectionsToDelete) {
|
|
await tx.dashboardSection.delete({
|
|
where: {
|
|
id: sectionToDelete.id,
|
|
},
|
|
});
|
|
|
|
// Decrement order for all sections with order greater than deleted section
|
|
await tx.dashboardSection.updateMany({
|
|
where: {
|
|
userId,
|
|
order: {
|
|
gt: sectionToDelete.order,
|
|
},
|
|
},
|
|
data: {
|
|
order: {
|
|
decrement: 1,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
// Handle order updates - need to be careful about conflicts
|
|
for (const sectionToUpdate of sectionsToUpdate) {
|
|
const { id, newOrder, oldOrder } = sectionToUpdate;
|
|
|
|
if (newOrder > oldOrder) {
|
|
// Moving down: decrement order for sections between oldOrder and newOrder
|
|
await tx.dashboardSection.updateMany({
|
|
where: {
|
|
userId,
|
|
order: {
|
|
gt: oldOrder,
|
|
lte: newOrder,
|
|
},
|
|
id: {
|
|
not: id,
|
|
},
|
|
},
|
|
data: {
|
|
order: {
|
|
decrement: 1,
|
|
},
|
|
},
|
|
});
|
|
} else if (newOrder < oldOrder) {
|
|
await tx.dashboardSection.updateMany({
|
|
where: {
|
|
userId,
|
|
order: {
|
|
gte: newOrder,
|
|
lt: oldOrder,
|
|
},
|
|
id: {
|
|
not: id,
|
|
},
|
|
},
|
|
data: {
|
|
order: {
|
|
increment: 1,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
await tx.dashboardSection.update({
|
|
where: { id },
|
|
data: { order: newOrder },
|
|
});
|
|
}
|
|
|
|
if (sectionsToCreate.length > 0) {
|
|
await tx.dashboardSection.createMany({
|
|
data: sectionsToCreate,
|
|
});
|
|
}
|
|
});
|
|
|
|
const getData = await getDashboardData(userId);
|
|
|
|
return {
|
|
status: 200,
|
|
response: getData,
|
|
};
|
|
}
|