feat: add onboarding with oldmarr import (#1606)
This commit is contained in:
59
packages/old-import/src/prepare/prepare-apps.ts
Normal file
59
packages/old-import/src/prepare/prepare-apps.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import type { InferSelectModel } from "@homarr/db";
|
||||
import type { apps } from "@homarr/db/schema/sqlite";
|
||||
import type { OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
import type { ValidAnalyseConfig } from "../analyse/types";
|
||||
import { mapOldmarrApp, mapOldmarrBookmarkApp } from "../mappers/map-app";
|
||||
import type { OldmarrBookmarkDefinition } from "../widgets/definitions/bookmark";
|
||||
|
||||
export type PreparedApp = Omit<InferSelectModel<typeof apps>, "id"> & { ids: string[]; existingId?: string };
|
||||
|
||||
export const prepareApps = (analyseConfigs: ValidAnalyseConfig[]) => {
|
||||
const preparedApps: PreparedApp[] = [];
|
||||
|
||||
analyseConfigs.forEach(({ config }) => {
|
||||
const appsFromConfig = extractAppsFromConfig(config).concat(extractBookmarkAppsFromConfig(config));
|
||||
addAppsToPreparedApps(preparedApps, appsFromConfig);
|
||||
});
|
||||
|
||||
return preparedApps;
|
||||
};
|
||||
|
||||
const extractAppsFromConfig = (config: OldmarrConfig) => {
|
||||
return config.apps.map(mapOldmarrApp);
|
||||
};
|
||||
|
||||
const extractBookmarkAppsFromConfig = (config: OldmarrConfig) => {
|
||||
const bookmarkWidgets = config.widgets.filter((widget) => widget.type === "bookmark");
|
||||
return bookmarkWidgets.flatMap((widget) =>
|
||||
(widget.properties as OldmarrBookmarkDefinition["options"]).items.map(mapOldmarrBookmarkApp),
|
||||
);
|
||||
};
|
||||
|
||||
const addAppsToPreparedApps = (preparedApps: PreparedApp[], configApps: InferSelectModel<typeof apps>[]) => {
|
||||
configApps.forEach(({ id, ...app }) => {
|
||||
const existingApp = preparedApps.find((preparedApp) => doAppsMatch(preparedApp, app));
|
||||
|
||||
if (existingApp) {
|
||||
existingApp.ids.push(id);
|
||||
return;
|
||||
}
|
||||
|
||||
preparedApps.push({
|
||||
...app,
|
||||
ids: [id],
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const doAppsMatch = (
|
||||
app1: Omit<InferSelectModel<typeof apps>, "id">,
|
||||
app2: Omit<InferSelectModel<typeof apps>, "id">,
|
||||
) => {
|
||||
return (
|
||||
app1.name === app2.name &&
|
||||
app1.iconUrl === app2.iconUrl &&
|
||||
app1.description === app2.description &&
|
||||
app1.href === app2.href
|
||||
);
|
||||
};
|
||||
34
packages/old-import/src/prepare/prepare-boards.ts
Normal file
34
packages/old-import/src/prepare/prepare-boards.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { objectEntries } from "@homarr/common";
|
||||
import type { BoardSize } from "@homarr/old-schema";
|
||||
|
||||
import type { ValidAnalyseConfig } from "../analyse/types";
|
||||
import type { BoardSelectionMap } from "../components/initial/board-selection-card";
|
||||
|
||||
const boardSizeSuffix: Record<BoardSize, string> = {
|
||||
lg: "large",
|
||||
md: "medium",
|
||||
sm: "small",
|
||||
};
|
||||
|
||||
export const createBoardName = (fileName: string, boardSize: BoardSize) => {
|
||||
return `${fileName.replace(".json", "")}-${boardSizeSuffix[boardSize]}`;
|
||||
};
|
||||
|
||||
export const prepareBoards = (analyseConfigs: ValidAnalyseConfig[], selections: BoardSelectionMap) => {
|
||||
return analyseConfigs.flatMap(({ name, config }) => {
|
||||
const selectedSizes = selections.get(name);
|
||||
if (!selectedSizes) return [];
|
||||
|
||||
return objectEntries(selectedSizes)
|
||||
.map(([size, selected]) => {
|
||||
if (!selected) return null;
|
||||
|
||||
return {
|
||||
name: createBoardName(name, size),
|
||||
size,
|
||||
config,
|
||||
};
|
||||
})
|
||||
.filter((board) => board !== null);
|
||||
});
|
||||
};
|
||||
19
packages/old-import/src/prepare/prepare-integrations.ts
Normal file
19
packages/old-import/src/prepare/prepare-integrations.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { ValidAnalyseConfig } from "../analyse/types";
|
||||
|
||||
export type PreparedIntegration = ReturnType<typeof prepareIntegrations>[number];
|
||||
|
||||
export const prepareIntegrations = (analyseConfigs: ValidAnalyseConfig[]) => {
|
||||
return analyseConfigs.flatMap(({ config }) => {
|
||||
return config.apps
|
||||
.map((app) =>
|
||||
app.integration?.type
|
||||
? {
|
||||
...app.integration,
|
||||
name: app.name,
|
||||
url: app.url,
|
||||
}
|
||||
: null,
|
||||
)
|
||||
.filter((integration) => integration !== null);
|
||||
});
|
||||
};
|
||||
14
packages/old-import/src/prepare/prepare-items.ts
Normal file
14
packages/old-import/src/prepare/prepare-items.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { BoardSize, OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
import { mapApp, mapWidget } from "../mappers/map-item";
|
||||
|
||||
export const prepareItems = (
|
||||
{ apps, widgets }: Pick<OldmarrConfig, "apps" | "widgets">,
|
||||
boardSize: BoardSize,
|
||||
appsMap: Map<string, { id: string }>,
|
||||
sectionMap: Map<string, { id: string }>,
|
||||
) =>
|
||||
widgets
|
||||
.map((widget) => mapWidget(widget, boardSize, appsMap, sectionMap))
|
||||
.filter((widget) => widget !== null)
|
||||
.concat(apps.map((app) => mapApp(app, boardSize, appsMap, sectionMap)));
|
||||
25
packages/old-import/src/prepare/prepare-multiple.ts
Normal file
25
packages/old-import/src/prepare/prepare-multiple.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { AnalyseConfig, ValidAnalyseConfig } from "../analyse/types";
|
||||
import type { BoardSelectionMap } from "../components/initial/board-selection-card";
|
||||
import type { InitialOldmarrImportSettings } from "../settings";
|
||||
import { prepareApps } from "./prepare-apps";
|
||||
import { prepareBoards } from "./prepare-boards";
|
||||
import { prepareIntegrations } from "./prepare-integrations";
|
||||
|
||||
export const prepareMultipleImports = (
|
||||
analyseConfigs: AnalyseConfig[],
|
||||
settings: InitialOldmarrImportSettings,
|
||||
selections: BoardSelectionMap,
|
||||
) => {
|
||||
const invalidConfigs = analyseConfigs.filter((item) => item.config === null);
|
||||
invalidConfigs.forEach(({ name }) => {
|
||||
console.warn(`Skipping import of ${name} due to error in configuration. See logs of container for more details.`);
|
||||
});
|
||||
|
||||
const filteredConfigs = analyseConfigs.filter((item): item is ValidAnalyseConfig => item.config !== null);
|
||||
|
||||
return {
|
||||
preparedApps: prepareApps(filteredConfigs),
|
||||
preparedBoards: settings.onlyImportApps ? [] : prepareBoards(filteredConfigs, selections),
|
||||
preparedIntegrations: prepareIntegrations(filteredConfigs),
|
||||
};
|
||||
};
|
||||
13
packages/old-import/src/prepare/prepare-sections.ts
Normal file
13
packages/old-import/src/prepare/prepare-sections.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
import { mapCategorySection, mapEmptySection } from "../mappers/map-section";
|
||||
|
||||
export const prepareSections = (
|
||||
boardId: string,
|
||||
{ categories, wrappers }: Pick<OldmarrConfig, "categories" | "wrappers">,
|
||||
) =>
|
||||
new Map(
|
||||
categories
|
||||
.map((category) => [category.id, mapCategorySection(boardId, category)] as const)
|
||||
.concat(wrappers.map((wrapper) => [wrapper.id, mapEmptySection(boardId, wrapper)] as const)),
|
||||
);
|
||||
21
packages/old-import/src/prepare/prepare-single.ts
Normal file
21
packages/old-import/src/prepare/prepare-single.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import type { OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
import type { OldmarrImportConfiguration } from "../settings";
|
||||
import { prepareApps } from "./prepare-apps";
|
||||
|
||||
export const prepareSingleImport = (config: OldmarrConfig, settings: OldmarrImportConfiguration) => {
|
||||
const validAnalyseConfigs = [{ name: settings.name, config, isError: false }];
|
||||
|
||||
return {
|
||||
preparedApps: prepareApps(validAnalyseConfigs),
|
||||
preparedBoards: settings.onlyImportApps
|
||||
? []
|
||||
: [
|
||||
{
|
||||
name: settings.name,
|
||||
size: settings.screenSize,
|
||||
config,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user