Fix widgets
This commit is contained in:
parent
1bd300e497
commit
20e0d655fb
10
Dockerfile
10
Dockerfile
@ -8,9 +8,11 @@ WORKDIR /app
|
|||||||
COPY --link package.json pnpm-lock.yaml* ./
|
COPY --link package.json pnpm-lock.yaml* ./
|
||||||
|
|
||||||
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
|
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
|
||||||
|
RUN nslookup www.google.com
|
||||||
|
RUN sed -i 's/https/http/' /etc/apk/repositories
|
||||||
RUN apk add --no-cache libc6-compat \
|
RUN apk add --no-cache libc6-compat \
|
||||||
&& apk add --no-cache --virtual .gyp python3 make g++ \
|
&& apk add --no-cache --virtual .gyp python3 make g++ \
|
||||||
&& npm install -g pnpm
|
&& npm install -g pnpm
|
||||||
|
|
||||||
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm fetch | grep -v "cross-device link not permitted\|Falling back to copying packages from store"
|
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm fetch | grep -v "cross-device link not permitted\|Falling back to copying packages from store"
|
||||||
|
|
||||||
@ -29,8 +31,8 @@ COPY . .
|
|||||||
|
|
||||||
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
|
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
|
||||||
RUN npm run telemetry \
|
RUN npm run telemetry \
|
||||||
&& mkdir config \
|
&& mkdir config \
|
||||||
&& NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
|
&& NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
|
||||||
|
|
||||||
# Production image, copy all the files and run next
|
# Production image, copy all the files and run next
|
||||||
FROM docker.io/node:18-alpine AS runner
|
FROM docker.io/node:18-alpine AS runner
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export default function List({ group, services, layout, isGroup = false }) {
|
|||||||
service.type === "grouped-service" ? (
|
service.type === "grouped-service" ? (
|
||||||
<List
|
<List
|
||||||
key={service.name}
|
key={service.name}
|
||||||
group={service.name}
|
group={group}
|
||||||
services={service.services}
|
services={service.services}
|
||||||
layout={{ columns: parseInt(service.name, 10) || service.services.length, style: "row" }}
|
layout={{ columns: parseInt(service.name, 10) || service.services.length, style: "row" }}
|
||||||
isGroup
|
isGroup
|
||||||
|
|||||||
@ -177,7 +177,14 @@ function Home({ initialSettings }) {
|
|||||||
const { data: bookmarks } = useSWR("/api/bookmarks");
|
const { data: bookmarks } = useSWR("/api/bookmarks");
|
||||||
const { data: widgets } = useSWR("/api/widgets");
|
const { data: widgets } = useSWR("/api/widgets");
|
||||||
|
|
||||||
const servicesAndBookmarks = [...services.map(sg => sg.services).flat(), ...bookmarks.map(bg => bg.bookmarks).flat()]
|
const servicesAndBookmarks = [
|
||||||
|
...services
|
||||||
|
.map((sg) => sg.services)
|
||||||
|
.flat(1)
|
||||||
|
.map((service) => (service.type === "grouped-service" ? service.services : service))
|
||||||
|
.flat(1),
|
||||||
|
...bookmarks.map((bg) => bg.bookmarks).flat(),
|
||||||
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (settings.language) {
|
if (settings.language) {
|
||||||
@ -196,15 +203,15 @@ function Home({ initialSettings }) {
|
|||||||
const [searching, setSearching] = useState(false);
|
const [searching, setSearching] = useState(false);
|
||||||
const [searchString, setSearchString] = useState("");
|
const [searchString, setSearchString] = useState("");
|
||||||
let searchProvider = null;
|
let searchProvider = null;
|
||||||
const searchWidget = Object.values(widgets).find(w => w.type === "search");
|
const searchWidget = Object.values(widgets).find((w) => w.type === "search");
|
||||||
if (searchWidget) {
|
if (searchWidget) {
|
||||||
if (Array.isArray(searchWidget.options?.provider)) {
|
if (Array.isArray(searchWidget.options?.provider)) {
|
||||||
// if search provider is a list, try to retrieve from localstorage, fall back to the first
|
// if search provider is a list, try to retrieve from localstorage, fall back to the first
|
||||||
searchProvider = getStoredProvider() ?? searchProviders[searchWidget.options.provider[0]];
|
searchProvider = getStoredProvider() ?? searchProviders[searchWidget.options.provider[0]];
|
||||||
} else if (searchWidget.options?.provider === 'custom') {
|
} else if (searchWidget.options?.provider === "custom") {
|
||||||
searchProvider = {
|
searchProvider = {
|
||||||
url: searchWidget.options.url
|
url: searchWidget.options.url,
|
||||||
}
|
};
|
||||||
} else {
|
} else {
|
||||||
searchProvider = searchProviders[searchWidget.options?.provider];
|
searchProvider = searchProviders[searchWidget.options?.provider];
|
||||||
}
|
}
|
||||||
@ -223,12 +230,12 @@ function Home({ initialSettings }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('keydown', handleKeyDown);
|
document.addEventListener("keydown", handleKeyDown);
|
||||||
|
|
||||||
return function cleanup() {
|
return function cleanup() {
|
||||||
document.removeEventListener('keydown', handleKeyDown);
|
document.removeEventListener("keydown", handleKeyDown);
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -255,12 +262,7 @@ function Home({ initialSettings }) {
|
|||||||
<meta name="theme-color" content={themes[initialSettings.color || "slate"][initialSettings.theme || "dark"]} />
|
<meta name="theme-color" content={themes[initialSettings.color || "slate"][initialSettings.theme || "dark"]} />
|
||||||
</Head>
|
</Head>
|
||||||
<div className="relative container m-auto flex flex-col justify-start z-10 h-full">
|
<div className="relative container m-auto flex flex-col justify-start z-10 h-full">
|
||||||
<div
|
<div className={classNames("flex flex-row flex-wrap justify-between", headerStyles[headerStyle])}>
|
||||||
className={classNames(
|
|
||||||
"flex flex-row flex-wrap justify-between",
|
|
||||||
headerStyles[headerStyle]
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<QuickLaunch
|
<QuickLaunch
|
||||||
servicesAndBookmarks={servicesAndBookmarks}
|
servicesAndBookmarks={servicesAndBookmarks}
|
||||||
searchString={searchString}
|
searchString={searchString}
|
||||||
@ -274,17 +276,19 @@ function Home({ initialSettings }) {
|
|||||||
{widgets
|
{widgets
|
||||||
.filter((widget) => !rightAlignedWidgets.includes(widget.type))
|
.filter((widget) => !rightAlignedWidgets.includes(widget.type))
|
||||||
.map((widget, i) => (
|
.map((widget, i) => (
|
||||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: false}} />
|
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: false }} />
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div className={classNames(
|
<div
|
||||||
"m-auto flex flex-wrap grow sm:basis-auto justify-between md:justify-end",
|
className={classNames(
|
||||||
headerStyle === "boxedWidgets" ? "sm:ml-4" : "sm:ml-2"
|
"m-auto flex flex-wrap grow sm:basis-auto justify-between md:justify-end",
|
||||||
)}>
|
headerStyle === "boxedWidgets" ? "sm:ml-4" : "sm:ml-2"
|
||||||
|
)}
|
||||||
|
>
|
||||||
{widgets
|
{widgets
|
||||||
.filter((widget) => rightAlignedWidgets.includes(widget.type))
|
.filter((widget) => rightAlignedWidgets.includes(widget.type))
|
||||||
.map((widget, i) => (
|
.map((widget, i) => (
|
||||||
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: true}} />
|
<Widget key={i} widget={widget} style={{ header: headerStyle, isRightAligned: true }} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -294,24 +298,27 @@ function Home({ initialSettings }) {
|
|||||||
{services?.length > 0 && (
|
{services?.length > 0 && (
|
||||||
<div className="flex flex-wrap p-4 sm:p-8 sm:pt-4 items-start pb-2">
|
<div className="flex flex-wrap p-4 sm:p-8 sm:pt-4 items-start pb-2">
|
||||||
{services.map((group) => (
|
{services.map((group) => (
|
||||||
<ServicesGroup
|
<ServicesGroup
|
||||||
key={group.name}
|
key={group.name}
|
||||||
group={group.name}
|
group={group.name}
|
||||||
services={group}
|
services={group}
|
||||||
layout={initialSettings.layout?.[group.name]}
|
layout={initialSettings.layout?.[group.name]}
|
||||||
fiveColumns={settings.fiveColumns}
|
fiveColumns={settings.fiveColumns}
|
||||||
disableCollapse={settings.disableCollapse} />
|
disableCollapse={settings.disableCollapse}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{bookmarks?.length > 0 && (
|
{bookmarks?.length > 0 && (
|
||||||
<div className={`grow flex flex-wrap pt-0 p-4 sm:p-8 gap-2 grid-cols-1 lg:grid-cols-2 lg:grid-cols-${Math.min(6, bookmarks.length)}`}>
|
<div
|
||||||
|
className={`grow flex flex-wrap pt-0 p-4 sm:p-8 gap-2 grid-cols-1 lg:grid-cols-2 lg:grid-cols-${Math.min(
|
||||||
|
6,
|
||||||
|
bookmarks.length
|
||||||
|
)}`}
|
||||||
|
>
|
||||||
{bookmarks.map((group) => (
|
{bookmarks.map((group) => (
|
||||||
<BookmarksGroup
|
<BookmarksGroup key={group.name} group={group} disableCollapse={settings.disableCollapse} />
|
||||||
key={group.name}
|
|
||||||
group={group}
|
|
||||||
disableCollapse={settings.disableCollapse} />
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -323,9 +330,7 @@ function Home({ initialSettings }) {
|
|||||||
{!initialSettings?.theme && <ThemeToggle />}
|
{!initialSettings?.theme && <ThemeToggle />}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex mt-4 w-full justify-end">
|
<div className="flex mt-4 w-full justify-end">{!initialSettings?.hideVersion && <Version />}</div>
|
||||||
{!initialSettings?.hideVersion && <Version />}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -340,7 +345,7 @@ export default function Wrapper({ initialSettings, fallback }) {
|
|||||||
if (initialSettings && initialSettings.background) {
|
if (initialSettings && initialSettings.background) {
|
||||||
let opacity = initialSettings.backgroundOpacity ?? 1;
|
let opacity = initialSettings.backgroundOpacity ?? 1;
|
||||||
let backgroundImage = initialSettings.background;
|
let backgroundImage = initialSettings.background;
|
||||||
if (typeof initialSettings.background === 'object') {
|
if (typeof initialSettings.background === "object") {
|
||||||
backgroundImage = initialSettings.background.image;
|
backgroundImage = initialSettings.background.image;
|
||||||
backgroundBlur = initialSettings.background.blur !== undefined;
|
backgroundBlur = initialSettings.background.blur !== undefined;
|
||||||
backgroundSaturate = initialSettings.background.saturate !== undefined;
|
backgroundSaturate = initialSettings.background.saturate !== undefined;
|
||||||
@ -373,13 +378,15 @@ export default function Wrapper({ initialSettings, fallback }) {
|
|||||||
style={wrappedStyle}
|
style={wrappedStyle}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
id="inner_wrapper"
|
id="inner_wrapper"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'fixed overflow-auto w-full h-full',
|
"fixed overflow-auto w-full h-full",
|
||||||
backgroundBlur && `backdrop-blur${initialSettings.background.blur.length ? '-' : ""}${initialSettings.background.blur}`,
|
backgroundBlur &&
|
||||||
backgroundSaturate && `backdrop-saturate-${initialSettings.background.saturate}`,
|
`backdrop-blur${initialSettings.background.blur.length ? "-" : ""}${initialSettings.background.blur}`,
|
||||||
backgroundBrightness && `backdrop-brightness-${initialSettings.background.brightness}`,
|
backgroundSaturate && `backdrop-saturate-${initialSettings.background.saturate}`,
|
||||||
)}>
|
backgroundBrightness && `backdrop-brightness-${initialSettings.background.brightness}`
|
||||||
|
)}
|
||||||
|
>
|
||||||
<Index initialSettings={initialSettings} fallback={fallback} />
|
<Index initialSettings={initialSettings} fallback={fallback} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -25,35 +25,34 @@ export async function servicesFromConfig() {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
// map easy to write YAML objects into easy to consume JS arrays
|
// map easy to write YAML objects into easy to consume JS arrays
|
||||||
|
|
||||||
const servicesArray = services.map((servicesGroup) => ({
|
const servicesArray = services.map((servicesGroup) => ({
|
||||||
name: Object.keys(servicesGroup)[0],
|
name: Object.keys(servicesGroup)[0],
|
||||||
services: servicesGroup[Object.keys(servicesGroup)[0]].map((entries) => {
|
services: servicesGroup[Object.keys(servicesGroup)[0]].map((entries) =>
|
||||||
if (Array.isArray(entries[Object.keys(entries)[0]]))
|
Array.isArray(entries[Object.keys(entries)[0]])
|
||||||
return {
|
? {
|
||||||
name: Object.keys(entries)[0],
|
name: Object.keys(entries)[0],
|
||||||
services: entries[Object.keys(entries)[0]].map((entry) => ({
|
services: entries[Object.keys(entries)[0]].map((entry) => ({
|
||||||
name: Object.keys(entry)[0],
|
name: Object.keys(entry)[0],
|
||||||
...entry[Object.keys(entry)[0]],
|
...entry[Object.keys(entry)[0]],
|
||||||
|
type: "service",
|
||||||
|
})),
|
||||||
|
type: "grouped-service",
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
name: Object.keys(entries)[0],
|
||||||
|
...entries[Object.keys(entries)[0]],
|
||||||
type: "service",
|
type: "service",
|
||||||
})),
|
}
|
||||||
type: "grouped-service",
|
),
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: Object.keys(entries)[0],
|
|
||||||
...entries[Object.keys(entries)[0]],
|
|
||||||
type: "service",
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// add default weight to services based on their position in the configuration
|
// add default weight to services based on their position in the configuration
|
||||||
servicesArray.forEach((group, groupIndex) => {
|
servicesArray.forEach((group, groupIndex) => {
|
||||||
group.services.forEach((service, serviceIndex) => {
|
group.services.forEach((service, serviceIndex) => {
|
||||||
if (!service.weight && service.type !== "grouped-service") {
|
if (!service.weight) servicesArray[groupIndex].services[serviceIndex].weight = (serviceIndex + 1) * 100;
|
||||||
servicesArray[groupIndex].services[serviceIndex].weight = (serviceIndex + 1) * 100;
|
|
||||||
}
|
|
||||||
if (service.type === "grouped-service") {
|
if (service.type === "grouped-service") {
|
||||||
servicesArray[groupIndex].services[serviceIndex].weight = (serviceIndex + 1) * 100;
|
|
||||||
service.services.forEach((groupedService, groupedServiceIndex) => {
|
service.services.forEach((groupedService, groupedServiceIndex) => {
|
||||||
if (!groupedService.weight) {
|
if (!groupedService.weight) {
|
||||||
servicesArray[groupIndex].services[serviceIndex].services[groupedServiceIndex].weight =
|
servicesArray[groupIndex].services[serviceIndex].services[groupedServiceIndex].weight =
|
||||||
@ -297,97 +296,102 @@ export async function servicesFromKubernetes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function cleanService(service, serviceGroup) {
|
||||||
|
const cleanedService =
|
||||||
|
service.type === "grouped-service"
|
||||||
|
? { ...service, services: service.services.map((s) => cleanService(s, serviceGroup)) }
|
||||||
|
: { ...service };
|
||||||
|
if (cleanedService.showStats !== undefined) cleanedService.showStats = JSON.parse(cleanedService.showStats);
|
||||||
|
if (typeof service.weight === "string") {
|
||||||
|
const weight = parseInt(service.weight, 10);
|
||||||
|
if (Number.isNaN(weight)) {
|
||||||
|
cleanedService.weight = 0;
|
||||||
|
} else {
|
||||||
|
cleanedService.weight = weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof cleanedService.weight !== "number") {
|
||||||
|
cleanedService.weight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanedService.widget) {
|
||||||
|
// whitelisted set of keys to pass to the frontend
|
||||||
|
const {
|
||||||
|
type, // all widgets
|
||||||
|
fields,
|
||||||
|
hideErrors,
|
||||||
|
server, // docker widget
|
||||||
|
container,
|
||||||
|
currency, // coinmarketcap widget
|
||||||
|
symbols,
|
||||||
|
defaultinterval,
|
||||||
|
site, // unifi widget
|
||||||
|
namespace, // kubernetes widget
|
||||||
|
app,
|
||||||
|
podSelector,
|
||||||
|
wan, // opnsense widget, pfsense widget
|
||||||
|
enableBlocks, // emby/jellyfin
|
||||||
|
enableNowPlaying,
|
||||||
|
volume, // diskstation widget,
|
||||||
|
enableQueue, // sonarr/radarr
|
||||||
|
} = cleanedService.widget;
|
||||||
|
|
||||||
|
let fieldsList = fields;
|
||||||
|
if (typeof fields === "string") {
|
||||||
|
try {
|
||||||
|
JSON.parse(fields);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("Invalid fields list detected in config for service '%s'", service.name);
|
||||||
|
fieldsList = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanedService.widget = {
|
||||||
|
type,
|
||||||
|
fields: fieldsList || null,
|
||||||
|
hide_errors: hideErrors || false,
|
||||||
|
service_name: service.name,
|
||||||
|
service_group: serviceGroup.name,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (currency) cleanedService.widget.currency = currency;
|
||||||
|
if (symbols) cleanedService.widget.symbols = symbols;
|
||||||
|
if (defaultinterval) cleanedService.widget.defaultinterval = defaultinterval;
|
||||||
|
|
||||||
|
if (type === "docker") {
|
||||||
|
if (server) cleanedService.widget.server = server;
|
||||||
|
if (container) cleanedService.widget.container = container;
|
||||||
|
}
|
||||||
|
if (type === "unifi") {
|
||||||
|
if (site) cleanedService.widget.site = site;
|
||||||
|
}
|
||||||
|
if (type === "kubernetes") {
|
||||||
|
if (namespace) cleanedService.widget.namespace = namespace;
|
||||||
|
if (app) cleanedService.widget.app = app;
|
||||||
|
if (podSelector) cleanedService.widget.podSelector = podSelector;
|
||||||
|
}
|
||||||
|
if (["opnsense", "pfsense"].includes(type)) {
|
||||||
|
if (wan) cleanedService.widget.wan = wan;
|
||||||
|
}
|
||||||
|
if (["emby", "jellyfin"].includes(type)) {
|
||||||
|
if (enableBlocks !== undefined) cleanedService.widget.enableBlocks = JSON.parse(enableBlocks);
|
||||||
|
if (enableNowPlaying !== undefined) cleanedService.widget.enableNowPlaying = JSON.parse(enableNowPlaying);
|
||||||
|
}
|
||||||
|
if (["sonarr", "radarr"].includes(type)) {
|
||||||
|
if (enableQueue !== undefined) cleanedService.widget.enableQueue = JSON.parse(enableQueue);
|
||||||
|
}
|
||||||
|
if (["diskstation", "qnap"].includes(type)) {
|
||||||
|
if (volume) cleanedService.widget.volume = volume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cleanedService;
|
||||||
|
}
|
||||||
|
|
||||||
export function cleanServiceGroups(groups) {
|
export function cleanServiceGroups(groups) {
|
||||||
return groups.map((serviceGroup) => ({
|
return groups.map((serviceGroup) => ({
|
||||||
name: serviceGroup.name,
|
name: serviceGroup.name,
|
||||||
services: serviceGroup.services.map((service) => {
|
services: serviceGroup.services.map((service) => cleanService(service, serviceGroup)),
|
||||||
const cleanedService = { ...service };
|
|
||||||
if (cleanedService.showStats !== undefined) cleanedService.showStats = JSON.parse(cleanedService.showStats);
|
|
||||||
if (typeof service.weight === "string") {
|
|
||||||
const weight = parseInt(service.weight, 10);
|
|
||||||
if (Number.isNaN(weight)) {
|
|
||||||
cleanedService.weight = 0;
|
|
||||||
} else {
|
|
||||||
cleanedService.weight = weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (typeof cleanedService.weight !== "number") {
|
|
||||||
cleanedService.weight = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cleanedService.widget) {
|
|
||||||
// whitelisted set of keys to pass to the frontend
|
|
||||||
const {
|
|
||||||
type, // all widgets
|
|
||||||
fields,
|
|
||||||
hideErrors,
|
|
||||||
server, // docker widget
|
|
||||||
container,
|
|
||||||
currency, // coinmarketcap widget
|
|
||||||
symbols,
|
|
||||||
defaultinterval,
|
|
||||||
site, // unifi widget
|
|
||||||
namespace, // kubernetes widget
|
|
||||||
app,
|
|
||||||
podSelector,
|
|
||||||
wan, // opnsense widget, pfsense widget
|
|
||||||
enableBlocks, // emby/jellyfin
|
|
||||||
enableNowPlaying,
|
|
||||||
volume, // diskstation widget,
|
|
||||||
enableQueue, // sonarr/radarr
|
|
||||||
} = cleanedService.widget;
|
|
||||||
|
|
||||||
let fieldsList = fields;
|
|
||||||
if (typeof fields === "string") {
|
|
||||||
try {
|
|
||||||
JSON.parse(fields);
|
|
||||||
} catch (e) {
|
|
||||||
logger.error("Invalid fields list detected in config for service '%s'", service.name);
|
|
||||||
fieldsList = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanedService.widget = {
|
|
||||||
type,
|
|
||||||
fields: fieldsList || null,
|
|
||||||
hide_errors: hideErrors || false,
|
|
||||||
service_name: service.name,
|
|
||||||
service_group: serviceGroup.name,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (currency) cleanedService.widget.currency = currency;
|
|
||||||
if (symbols) cleanedService.widget.symbols = symbols;
|
|
||||||
if (defaultinterval) cleanedService.widget.defaultinterval = defaultinterval;
|
|
||||||
|
|
||||||
if (type === "docker") {
|
|
||||||
if (server) cleanedService.widget.server = server;
|
|
||||||
if (container) cleanedService.widget.container = container;
|
|
||||||
}
|
|
||||||
if (type === "unifi") {
|
|
||||||
if (site) cleanedService.widget.site = site;
|
|
||||||
}
|
|
||||||
if (type === "kubernetes") {
|
|
||||||
if (namespace) cleanedService.widget.namespace = namespace;
|
|
||||||
if (app) cleanedService.widget.app = app;
|
|
||||||
if (podSelector) cleanedService.widget.podSelector = podSelector;
|
|
||||||
}
|
|
||||||
if (["opnsense", "pfsense"].includes(type)) {
|
|
||||||
if (wan) cleanedService.widget.wan = wan;
|
|
||||||
}
|
|
||||||
if (["emby", "jellyfin"].includes(type)) {
|
|
||||||
if (enableBlocks !== undefined) cleanedService.widget.enableBlocks = JSON.parse(enableBlocks);
|
|
||||||
if (enableNowPlaying !== undefined) cleanedService.widget.enableNowPlaying = JSON.parse(enableNowPlaying);
|
|
||||||
}
|
|
||||||
if (["sonarr", "radarr"].includes(type)) {
|
|
||||||
if (enableQueue !== undefined) cleanedService.widget.enableQueue = JSON.parse(enableQueue);
|
|
||||||
}
|
|
||||||
if (["diskstation", "qnap"].includes(type)) {
|
|
||||||
if (volume) cleanedService.widget.volume = volume;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cleanedService;
|
|
||||||
}),
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,7 +400,10 @@ export async function getServiceItem(group, service) {
|
|||||||
|
|
||||||
const serviceGroup = configuredServices.find((g) => g.name === group);
|
const serviceGroup = configuredServices.find((g) => g.name === group);
|
||||||
if (serviceGroup) {
|
if (serviceGroup) {
|
||||||
const serviceEntry = serviceGroup.services.find((s) => s.name === service);
|
const serviceEntry = serviceGroup.services
|
||||||
|
.map((s) => (s.type === "grouped-service" ? s.services : s))
|
||||||
|
.flat(1)
|
||||||
|
.find((s) => s.name === service);
|
||||||
if (serviceEntry) return serviceEntry;
|
if (serviceEntry) return serviceEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user