Files
ThreadNet-Web/modules/banner/element-web/src/Univention/navigation.ts
T
2025-11-12 12:16:31 +00:00

87 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { z } from "zod/mini";
import { type StaticConfig } from "../config";
/**
* Univention Central Navigation API
* https://docs.software-univention.de/nubus-kubernetes-customization/1.x/en/api/central-navigation.html
*/
const UniventionCentralNavigation = z.object({
categories: z.array(
z.object({
identifier: z.string(),
display_name: z.string(),
entries: z.array(
z.object({
/**
* A unique identifier for the navigation item.
*/
identifier: z.string(),
/**
* The URL to the icon in SVG format.
*/
icon_url: z.string(),
/**
* The label of the link.
*/
display_name: z.string(),
/**
* The destination URL of the link.
*/
link: z.string(),
/**
* The browsing context in which the browser opens the link.
* Corresponds to the `target` property of `<a>` tags in HTML.
*/
target: z.string(),
/**
* Its usually empty.
*/
keywords: z.optional(z.object({})),
}),
),
}),
),
});
type UniventionCentralNavigation = z.infer<typeof UniventionCentralNavigation>;
function navigationToConfig(navigation: UniventionCentralNavigation): StaticConfig {
return {
type: "static",
categories: navigation.categories.map((category) => ({
name: category.display_name,
links: category.entries.map((entry) => ({
icon_uri: entry.icon_url,
name: entry.display_name,
link_url: entry.link,
target: entry.target,
})),
})),
};
}
export async function fetchNavigation(icsUrl: string, language: string): Promise<StaticConfig> {
const url = new URL("navigation.json", icsUrl);
url.search = `?language=${language}`;
const response = await fetch(url, {
credentials: "include",
});
if (!response.ok) {
throw new Error(`Failed to fetch navigation: ${response.status}`);
}
const data = await response.json();
const config = await UniventionCentralNavigation.parseAsync(data);
return navigationToConfig(config);
}