feat(boards): add responsive layout system (#2271)
This commit is contained in:
@@ -1,20 +1,31 @@
|
||||
import { createId } from "@homarr/db";
|
||||
import { createDbInsertCollectionForTransaction } from "@homarr/db/collection";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { BoardSize } from "@homarr/old-schema";
|
||||
import { boardSizes, getBoardSizeName } from "@homarr/old-schema";
|
||||
|
||||
import { fixSectionIssues } from "../../fix-section-issues";
|
||||
import { mapBoard } from "../../mappers/map-board";
|
||||
import { mapBreakpoint } from "../../mappers/map-breakpoint";
|
||||
import { mapColumnCount } from "../../mappers/map-column-count";
|
||||
import { moveWidgetsAndAppsIfMerge } from "../../move-widgets-and-apps-merge";
|
||||
import { prepareItems } from "../../prepare/prepare-items";
|
||||
import type { prepareMultipleImports } from "../../prepare/prepare-multiple";
|
||||
import { prepareSections } from "../../prepare/prepare-sections";
|
||||
import type { InitialOldmarrImportSettings } from "../../settings";
|
||||
import { createDbInsertCollection } from "./common";
|
||||
|
||||
export const createBoardInsertCollection = (
|
||||
{ preparedApps, preparedBoards }: Omit<ReturnType<typeof prepareMultipleImports>, "preparedIntegrations">,
|
||||
settings: InitialOldmarrImportSettings,
|
||||
) => {
|
||||
const insertCollection = createDbInsertCollection(["apps", "boards", "sections", "items"]);
|
||||
const insertCollection = createDbInsertCollectionForTransaction([
|
||||
"apps",
|
||||
"boards",
|
||||
"layouts",
|
||||
"sections",
|
||||
"items",
|
||||
"itemLayouts",
|
||||
]);
|
||||
logger.info("Preparing boards for insert collection");
|
||||
|
||||
const appsMap = new Map(
|
||||
@@ -49,7 +60,6 @@ export const createBoardInsertCollection = (
|
||||
const { wrappers, categories, wrapperIdsToMerge } = fixSectionIssues(board.config);
|
||||
const { apps, widgets } = moveWidgetsAndAppsIfMerge(board.config, wrapperIdsToMerge, {
|
||||
...settings,
|
||||
screenSize: board.size,
|
||||
name: board.name,
|
||||
});
|
||||
|
||||
@@ -58,6 +68,25 @@ export const createBoardInsertCollection = (
|
||||
const mappedBoard = mapBoard(board);
|
||||
logger.debug(`Mapped board fileName=${board.name} boardId=${mappedBoard.id}`);
|
||||
insertCollection.boards.push(mappedBoard);
|
||||
|
||||
const layoutMapping = boardSizes.reduce(
|
||||
(acc, size) => {
|
||||
acc[size] = createId();
|
||||
return acc;
|
||||
},
|
||||
{} as Record<BoardSize, string>,
|
||||
);
|
||||
|
||||
insertCollection.layouts.push(
|
||||
...boardSizes.map((size) => ({
|
||||
id: layoutMapping[size],
|
||||
boardId: mappedBoard.id,
|
||||
columnCount: mapColumnCount(board.config, size),
|
||||
breakpoint: mapBreakpoint(size),
|
||||
name: getBoardSizeName(size),
|
||||
})),
|
||||
);
|
||||
|
||||
const preparedSections = prepareSections(mappedBoard.id, { wrappers, categories });
|
||||
|
||||
for (const section of preparedSections.values()) {
|
||||
@@ -65,8 +94,11 @@ export const createBoardInsertCollection = (
|
||||
}
|
||||
logger.debug(`Added sections to board insert collection count=${insertCollection.sections.length}`);
|
||||
|
||||
const preparedItems = prepareItems({ apps, widgets }, board.size, appsMap, preparedSections);
|
||||
preparedItems.forEach((item) => insertCollection.items.push(item));
|
||||
const preparedItems = prepareItems({ apps, widgets }, appsMap, preparedSections, layoutMapping, mappedBoard.id);
|
||||
preparedItems.forEach(({ layouts, ...item }) => {
|
||||
insertCollection.items.push(item);
|
||||
insertCollection.itemLayouts.push(...layouts);
|
||||
});
|
||||
logger.debug(`Added items to board insert collection count=${insertCollection.items.length}`);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import { objectEntries } from "@homarr/common";
|
||||
import type { Database, HomarrDatabaseMysql, InferInsertModel } from "@homarr/db";
|
||||
import * as schema from "@homarr/db/schema";
|
||||
|
||||
type TableKey = {
|
||||
[K in keyof typeof schema]: (typeof schema)[K] extends { _: { brand: "Table" } } ? K : never;
|
||||
}[keyof typeof schema];
|
||||
|
||||
export const createDbInsertCollection = <TTableKey extends TableKey>(tablesInInsertOrder: TTableKey[]) => {
|
||||
const context = tablesInInsertOrder.reduce(
|
||||
(acc, key) => {
|
||||
acc[key] = [];
|
||||
return acc;
|
||||
},
|
||||
{} as { [K in TTableKey]: InferInsertModel<(typeof schema)[K]>[] },
|
||||
);
|
||||
|
||||
return {
|
||||
...context,
|
||||
insertAll: (db: Database) => {
|
||||
db.transaction((transaction) => {
|
||||
for (const [key, values] of objectEntries(context)) {
|
||||
if (values.length >= 1) {
|
||||
transaction
|
||||
.insert(schema[key])
|
||||
.values(values as never)
|
||||
.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
insertAllAsync: async (db: HomarrDatabaseMysql) => {
|
||||
await db.transaction(async (transaction) => {
|
||||
for (const [key, values] of objectEntries(context)) {
|
||||
if (values.length >= 1) {
|
||||
// Below is actually the mysqlSchema when the driver is mysql
|
||||
await transaction.insert(schema[key] as never).values(values as never);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,15 +1,15 @@
|
||||
import { encryptSecret } from "@homarr/common/server";
|
||||
import { createDbInsertCollectionForTransaction } from "@homarr/db/collection";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
import { mapAndDecryptIntegrations } from "../../mappers/map-integration";
|
||||
import type { PreparedIntegration } from "../../prepare/prepare-integrations";
|
||||
import { createDbInsertCollection } from "./common";
|
||||
|
||||
export const createIntegrationInsertCollection = (
|
||||
preparedIntegrations: PreparedIntegration[],
|
||||
encryptionToken: string | null | undefined,
|
||||
) => {
|
||||
const insertCollection = createDbInsertCollection(["integrations", "integrationSecrets"]);
|
||||
const insertCollection = createDbInsertCollectionForTransaction(["integrations", "integrationSecrets"]);
|
||||
|
||||
if (preparedIntegrations.length === 0) {
|
||||
return insertCollection;
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
import { createId } from "@homarr/db";
|
||||
import { createDbInsertCollectionForTransaction } from "@homarr/db/collection";
|
||||
import { credentialsAdminGroup } from "@homarr/definitions";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
import { mapAndDecryptUsers } from "../../mappers/map-user";
|
||||
import type { OldmarrImportUser } from "../../user-schema";
|
||||
import { createDbInsertCollection } from "./common";
|
||||
|
||||
export const createUserInsertCollection = (
|
||||
importUsers: OldmarrImportUser[],
|
||||
encryptionToken: string | null | undefined,
|
||||
) => {
|
||||
const insertCollection = createDbInsertCollection(["users", "groups", "groupMembers", "groupPermissions"]);
|
||||
const insertCollection = createDbInsertCollectionForTransaction([
|
||||
"users",
|
||||
"groups",
|
||||
"groupMembers",
|
||||
"groupPermissions",
|
||||
]);
|
||||
|
||||
if (importUsers.length === 0) {
|
||||
return insertCollection;
|
||||
|
||||
@@ -4,14 +4,7 @@ import { zfd } from "zod-form-data";
|
||||
|
||||
import { initialOldmarrImportSettings } from "../settings";
|
||||
|
||||
const boardSelectionMapSchema = z.map(
|
||||
z.string(),
|
||||
z.object({
|
||||
sm: z.boolean().nullable(),
|
||||
md: z.boolean().nullable(),
|
||||
lg: z.boolean().nullable(),
|
||||
}),
|
||||
);
|
||||
const boardSelectionMapSchema = z.map(z.string(), z.boolean());
|
||||
|
||||
export const importInitialOldmarrInputSchema = zfd.formData({
|
||||
file: zfd.file(),
|
||||
|
||||
Reference in New Issue
Block a user