Add migrator for modules to widgets

This commit is contained in:
Manuel Ruwe
2023-01-07 20:18:53 +01:00
parent 44c3e68042
commit dad89e2862
4 changed files with 276 additions and 19 deletions

View File

@@ -1,8 +1,16 @@
import Consola from 'consola';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { AppType } from '../../types/app'; import { AppIntegrationType, AppType, IntegrationType } from '../../types/app';
import { AreaType } from '../../types/area'; import { AreaType } from '../../types/area';
import { CategoryType } from '../../types/category'; import { CategoryType } from '../../types/category';
import { ConfigType } from '../../types/config'; import { ConfigType } from '../../types/config';
import widgets from '../../widgets';
import { IBitTorrent } from '../../widgets/bitTorrent/BitTorrentTile';
import { IDashDotTile } from '../../widgets/dashDot/DashDotTile';
import { IDateWidget } from '../../widgets/date/DateTile';
import { ITorrentNetworkTraffic } from '../../widgets/torrentNetworkTraffic/TorrentNetworkTrafficTile';
import { IWeatherWidget } from '../../widgets/weather/WeatherTile';
import { IWidget } from '../../widgets/widgets';
import { Config, serviceItem } from '../types'; import { Config, serviceItem } from '../types';
export function migrateConfig(config: Config): ConfigType { export function migrateConfig(config: Config): ConfigType {
@@ -12,7 +20,7 @@ export function migrateConfig(config: Config): ConfigType {
name: config.name ?? 'default', name: config.name ?? 'default',
}, },
categories: [], categories: [],
widgets: [], widgets: migrateModules(config),
apps: [], apps: [],
settings: { settings: {
common: { common: {
@@ -26,13 +34,17 @@ export function migrateConfig(config: Config): ConfigType {
defaultConfig: 'default', defaultConfig: 'default',
}, },
customization: { customization: {
colors: {}, colors: {
primary: config.settings.primaryColor,
secondary: config.settings.secondaryColor,
shade: config.settings.primaryShade,
},
layout: { layout: {
enabledDocker: false, enabledDocker: config.modules.docker?.enabled ?? false,
enabledLeftSidebar: false, enabledLeftSidebar: false,
enabledPing: false, enabledPing: config.modules.ping?.enabled ?? false,
enabledRightSidebar: false, enabledRightSidebar: false,
enabledSearchbar: true, enabledSearchbar: config.modules.search?.enabled ?? true,
}, },
}, },
}, },
@@ -122,10 +134,7 @@ const migrateService = (
appearance: { appearance: {
iconUrl: migrateIcon(oldService.icon), iconUrl: migrateIcon(oldService.icon),
}, },
integration: { integration: migrateIntegration(oldService),
type: null,
properties: [],
},
area: areaType, area: areaType,
shape: { shape: {
lg: getShapeForColumnCount(serviceIndex, 12), lg: getShapeForColumnCount(serviceIndex, 12),
@@ -134,13 +143,259 @@ const migrateService = (
}, },
}); });
const migrateModules = (config: Config): IWidget<string, any>[] => {
const moduleKeys = Object.keys(config.modules);
return moduleKeys
.map((moduleKey): IWidget<string, any> | null => {
const oldModule = config.modules[moduleKey];
if (!oldModule.enabled) {
return null;
}
switch (moduleKey.toLowerCase()) {
case 'torrent-status':
case 'Torrent':
return {
id: uuidv4(),
properties: {
refreshInterval: 10,
displayCompletedTorrents: oldModule.options?.hideComplete?.value ?? false,
displayStaleTorrents: true,
},
area: {
type: 'wrapper',
properties: {
id: 'default',
},
},
} as IBitTorrent;
case 'weather':
return {
id: uuidv4(),
properties: {
displayInFahrenheit: oldModule.options?.freedomunit?.value ?? false,
location: oldModule.options?.location?.value ?? 'Paris',
},
} as IWeatherWidget;
case 'dashdot':
case 'Dash.':
return {
id: uuidv4(),
properties: {
url: oldModule.options?.url?.value ?? '',
cpuMultiView: oldModule.options?.cpuMultiView?.value ?? false,
storageMultiView: oldModule.options?.storageMultiView?.value ?? false,
useCompactView: oldModule.options?.useCompactView?.value ?? false,
graphs: oldModule.options?.graphs?.value ?? ['cpu', 'ram'],
},
} as IDashDotTile;
case 'date':
return {
id: uuidv4(),
properties: {
display24HourFormat: oldModule.options?.full?.value ?? true,
},
} as IDateWidget;
case 'Download Speed':
case 'dlspeed':
return {
id: uuidv4(),
properties: {},
} as ITorrentNetworkTraffic;
default:
Consola.error(`Failed to map unknown module type ${moduleKey} to new type definitions.`);
return null;
}
})
.filter((x) => x !== null) as IWidget<string, any>[];
};
const migrateIcon = (iconUrl: string) => { const migrateIcon = (iconUrl: string) => {
if (iconUrl.startsWith('https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/')) { if (iconUrl.startsWith('https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/')) {
console.log('migrating icon:');
const icon = iconUrl.split('/').at(-1); const icon = iconUrl.split('/').at(-1);
console.log(`${iconUrl} -> ${icon}`); Consola.warn(
`Detected legacy icon repository. Upgrading to replacement repository: ${iconUrl} -> ${icon}`
);
return `https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${icon}`; return `https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${icon}`;
} }
return iconUrl; return iconUrl;
}; };
const migrateIntegration = (oldService: serviceItem): AppIntegrationType => {
const logInformation = (newType: IntegrationType) => {
Consola.info(`Migrated integration ${oldService.type} to the new type ${newType}`);
};
switch (oldService.type) {
case 'Deluge':
logInformation('deluge');
return {
type: 'deluge',
properties: [
{
field: 'password',
isDefined: oldService.password !== undefined,
type: 'private',
value: oldService.password,
},
],
};
case 'Jellyseerr':
logInformation('jellyseerr');
return {
type: 'jellyseerr',
properties: [
{
field: 'apiKey',
isDefined: oldService.apiKey !== undefined,
type: 'private',
value: oldService.apiKey,
},
],
};
case 'Overseerr':
logInformation('overseerr');
return {
type: 'overseerr',
properties: [
{
field: 'apiKey',
isDefined: oldService.apiKey !== undefined,
type: 'private',
value: oldService.apiKey,
},
],
};
case 'Lidarr':
logInformation('lidarr');
return {
type: 'lidarr',
properties: [
{
field: 'apiKey',
isDefined: oldService.apiKey !== undefined,
type: 'private',
value: oldService.apiKey,
},
],
};
case 'Radarr':
logInformation('radarr');
return {
type: 'radarr',
properties: [
{
field: 'apiKey',
isDefined: oldService.apiKey !== undefined,
type: 'private',
value: oldService.apiKey,
},
],
};
case 'Readarr':
logInformation('readarr');
return {
type: 'readarr',
properties: [
{
field: 'apiKey',
isDefined: oldService.apiKey !== undefined,
type: 'private',
value: oldService.apiKey,
},
],
};
case 'Sabnzbd':
logInformation('sabnzbd');
return {
type: 'sabnzbd',
properties: [
{
field: 'apiKey',
isDefined: oldService.apiKey !== undefined,
type: 'private',
value: oldService.apiKey,
},
],
};
case 'Sonarr':
logInformation('sonarr');
return {
type: 'sonarr',
properties: [
{
field: 'apiKey',
isDefined: oldService.apiKey !== undefined,
type: 'private',
value: oldService.apiKey,
},
],
};
case 'NZBGet':
logInformation('nzbGet');
return {
type: 'nzbGet',
properties: [
{
field: 'username',
isDefined: oldService.username !== undefined,
type: 'private',
value: oldService.username,
},
{
field: 'password',
isDefined: oldService.password !== undefined,
type: 'private',
value: oldService.password,
},
],
};
case 'qBittorrent':
logInformation('qBittorrent');
return {
type: 'qBittorrent',
properties: [
{
field: 'username',
isDefined: oldService.username !== undefined,
type: 'private',
value: oldService.username,
},
{
field: 'password',
isDefined: oldService.password !== undefined,
type: 'private',
value: oldService.password,
},
],
};
case 'Transmission':
logInformation('transmission');
return {
type: 'transmission',
properties: [
{
field: 'username',
isDefined: oldService.username !== undefined,
type: 'private',
value: oldService.username,
},
{
field: 'password',
isDefined: oldService.password !== undefined,
type: 'private',
value: oldService.password,
},
],
};
default:
Consola.warn(
`Integration type of service ${oldService.name} could not be mapped to new integration type definition`
);
return {
type: null,
properties: [],
};
}
};

View File

@@ -44,7 +44,7 @@ const definition = defineWidget({
}, },
refreshInterval: { refreshInterval: {
type: 'slider', type: 'slider',
defaultValue: 1, defaultValue: 10,
min: 1, min: 1,
max: 60, max: 60,
step: 1, step: 1,

View File

@@ -60,13 +60,13 @@ function DashDotTile({ widget }: DashDotTileProps) {
dashDotUrl, dashDotUrl,
}); });
const graphs = widget?.properties.graphs.map((g) => ({ const graphs = widget?.properties.graphs.map((graph) => ({
id: g, id: graph,
name: t(`card.graphs.${g}.title`), name: t(`card.graphs.${graph}.title`),
twoSpan: ['network', 'gpu'].includes(g), twoSpan: ['network', 'gpu'].includes(graph),
isMultiView: isMultiView:
(g === 'cpu' && widget.properties.cpuMultiView) || (graph === 'cpu' && widget.properties.cpuMultiView) ||
(g === 'storage' && widget.properties.storageMultiView), (graph === 'storage' && widget.properties.storageMultiView),
})); }));
const heading = ( const heading = (

View File

@@ -1,5 +1,7 @@
import { TablerIcon } from '@tabler/icons'; import { TablerIcon } from '@tabler/icons';
import React from 'react'; import React from 'react';
import { AreaType } from '../types/area';
import { ShapeType } from '../types/shape';
// Type of widgets which are safed to config // Type of widgets which are safed to config
export type IWidget<TKey extends string, TDefinition extends IWidgetDefinition> = { export type IWidget<TKey extends string, TDefinition extends IWidgetDefinition> = {