fix(boards): preview container contents

This commit is contained in:
Thomas Camlong authored and ajnart committed 2026-08-14 11:32:13 +02:00
1 parent e55def9b60
commit a11c53ebf7
5 files changed
+134 -24

No files matched your search

+66 -14
View File
@@ -283,7 +283,7 @@ export const boardRouter = createTRPCRouter({
const previewLayoutIds = dbBoards.flatMap((board) => board.layouts.map((layout) => layout.id));
const rootSectionIds = dbBoards.flatMap((board) => board.sections.map((section) => section.id));
const [previewItemLayouts, previewSectionLayouts] =
const [rootPreviewItemLayouts, previewSectionLayouts] =
previewLayoutIds.length > 0 && rootSectionIds.length > 0
? await Promise.all([
ctx.db.query.itemLayouts.findMany({
@@ -339,6 +339,43 @@ export const boardRouter = createTRPCRouter({
])
: [[], []];
const previewContainerSectionIds = [
...new Set(
previewSectionLayouts
.filter((layout) => layout.section.kind === "container")
.map((layout) => layout.sectionId),
),
];
const nestedPreviewItemLayouts =
previewLayoutIds.length > 0 && previewContainerSectionIds.length > 0
? await ctx.db.query.itemLayouts.findMany({
columns: {
itemId: true,
layoutId: true,
sectionId: true,
xOffset: true,
yOffset: true,
width: true,
height: true,
},
with: {
item: {
columns: { kind: true, options: true },
},
},
where: and(
inArray(itemLayouts.layoutId, previewLayoutIds),
inArray(itemLayouts.sectionId, previewContainerSectionIds),
gte(itemLayouts.xOffset, 0),
gte(itemLayouts.yOffset, 0),
lt(itemLayouts.yOffset, maxManageOverviewPreviewRows),
gt(itemLayouts.width, 0),
gt(itemLayouts.height, 0),
),
})
: [];
const previewItemLayouts = [...rootPreviewItemLayouts, ...nestedPreviewItemLayouts];
const appIdByItemId = new Map(
previewItemLayouts.flatMap((layout) => {
if (layout.item.kind !== "app") return [];
@@ -389,19 +426,6 @@ export const boardRouter = createTRPCRouter({
return columnCount !== undefined && columnCount > 0 && layout.xOffset < columnCount;
};
const itemPreview = previewLayout
? previewItemLayouts
.filter((layout) => layout.layoutId === previewLayout.id && isInsideRootLane(layout))
.map((layout) => {
const appId = appIdByItemId.get(layout.itemId);
return {
id: layout.itemId,
kind: layout.item.kind,
iconUrl: appId ? appIconUrlById.get(appId) : undefined,
layouts: [layout],
};
})
: [];
const containerPreview = previewLayout
? previewSectionLayouts
.filter(
@@ -417,6 +441,34 @@ export const boardRouter = createTRPCRouter({
layouts: [layout],
}))
: [];
const visibleContainerSizeById = new Map(
containerPreview.map((section) => [section.id, section.layouts[0]] as const),
);
const isInsideVisibleContainer = (layout: { sectionId: string; xOffset: number; yOffset: number }) => {
const containerLayout = visibleContainerSizeById.get(layout.sectionId);
return (
containerLayout !== undefined &&
layout.xOffset < containerLayout.width &&
layout.yOffset < containerLayout.height
);
};
const itemPreview = previewLayout
? previewItemLayouts
.filter(
(layout) =>
layout.layoutId === previewLayout.id &&
(isInsideRootLane(layout) || isInsideVisibleContainer(layout)),
)
.map((layout) => {
const appId = appIdByItemId.get(layout.itemId);
return {
id: layout.itemId,
kind: layout.item.kind,
iconUrl: appId ? appIconUrlById.get(appId) : undefined,
layouts: [layout],
};
})
: [];
return {
...board,
+14 -2
View File
@@ -350,6 +350,7 @@ describe("getManageOverview", () => {
const mobileItemId = createId();
const offscreenItemId = createId();
const nestedItemId = createId();
const nestedAppId = createId();
await db.insert(users).values({ id: defaultCreatorId });
await db.insert(boards).values([
@@ -400,11 +401,16 @@ describe("getManageOverview", () => {
width: 6,
height: 3,
});
await db.insert(apps).values({
id: nestedAppId,
name: "Nested app",
iconUrl: "https://example.com/nested.svg",
});
await db.insert(items).values([
{ id: itemId, boardId, kind: "clock" },
{ id: mobileItemId, boardId, kind: "clock" },
{ id: offscreenItemId, boardId, kind: "clock" },
{ id: nestedItemId, boardId, kind: "clock" },
{ id: nestedItemId, boardId, kind: "app", options: SuperJSON.stringify({ appId: nestedAppId }) },
]);
await db.insert(itemLayouts).values([
{
@@ -461,6 +467,12 @@ describe("getManageOverview", () => {
kind: "clock",
layouts: [{ layoutId: baseLayoutId, sectionId: rootSectionId, width: 4, height: 2 }],
},
{
id: nestedItemId,
kind: "app",
iconUrl: "https://example.com/nested.svg",
layouts: [{ layoutId: baseLayoutId, sectionId: containerSectionId, width: 2, height: 1 }],
},
],
sections: [
{ id: rootSectionId, kind: "empty" },
@@ -473,7 +485,7 @@ describe("getManageOverview", () => {
},
});
expect(result[0]?.preview?.layouts).toHaveLength(1);
expect(result[0]?.preview?.items.map((item) => item.id)).toEqual([itemId]);
expect(result[0]?.preview?.items.map((item) => item.id)).toEqual([itemId, nestedItemId]);
expect(result[0]?.preview?.sections).toHaveLength(2);
});