refactor(ui): share channel config extras and hint types
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
export type UpdateAvailable = import("../../../src/infra/update-startup.js").UpdateAvailable;
|
||||
import type { ConfigUiHints } from "../../../src/shared/config-ui-hints-types.js";
|
||||
|
||||
export type ChannelsStatusSnapshot = {
|
||||
ts: number;
|
||||
@@ -283,20 +284,6 @@ export type ConfigSnapshot = {
|
||||
issues?: ConfigSnapshotIssue[] | null;
|
||||
};
|
||||
|
||||
export type ConfigUiHint = {
|
||||
label?: string;
|
||||
help?: string;
|
||||
tags?: string[];
|
||||
group?: string;
|
||||
order?: number;
|
||||
advanced?: boolean;
|
||||
sensitive?: boolean;
|
||||
placeholder?: string;
|
||||
itemTemplate?: unknown;
|
||||
};
|
||||
|
||||
export type ConfigUiHints = Record<string, ConfigUiHint>;
|
||||
|
||||
export type ConfigSchemaResponse = {
|
||||
schema: unknown;
|
||||
uiHints: ConfigUiHints;
|
||||
|
||||
@@ -15,6 +15,7 @@ import type {
|
||||
CronStatus,
|
||||
} from "../types.ts";
|
||||
import { formatBytes, type AgentContext } from "./agents-utils.ts";
|
||||
import { resolveChannelExtras as resolveChannelExtrasFromConfig } from "./channel-config-extras.ts";
|
||||
|
||||
function renderAgentContextCard(context: AgentContext, subtitle: string) {
|
||||
return html`
|
||||
@@ -100,55 +101,6 @@ function resolveChannelEntries(snapshot: ChannelsStatusSnapshot | null): Channel
|
||||
|
||||
const CHANNEL_EXTRA_FIELDS = ["groupPolicy", "streamMode", "dmPolicy"] as const;
|
||||
|
||||
function resolveChannelConfigValue(
|
||||
configForm: Record<string, unknown> | null,
|
||||
channelId: string,
|
||||
): Record<string, unknown> | null {
|
||||
if (!configForm) {
|
||||
return null;
|
||||
}
|
||||
const channels = (configForm.channels ?? {}) as Record<string, unknown>;
|
||||
const fromChannels = channels[channelId];
|
||||
if (fromChannels && typeof fromChannels === "object") {
|
||||
return fromChannels as Record<string, unknown>;
|
||||
}
|
||||
const fallback = configForm[channelId];
|
||||
if (fallback && typeof fallback === "object") {
|
||||
return fallback as Record<string, unknown>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function formatChannelExtraValue(raw: unknown): string {
|
||||
if (raw == null) {
|
||||
return "n/a";
|
||||
}
|
||||
if (typeof raw === "string" || typeof raw === "number" || typeof raw === "boolean") {
|
||||
return String(raw);
|
||||
}
|
||||
try {
|
||||
return JSON.stringify(raw);
|
||||
} catch {
|
||||
return "n/a";
|
||||
}
|
||||
}
|
||||
|
||||
function resolveChannelExtras(
|
||||
configForm: Record<string, unknown> | null,
|
||||
channelId: string,
|
||||
): Array<{ label: string; value: string }> {
|
||||
const value = resolveChannelConfigValue(configForm, channelId);
|
||||
if (!value) {
|
||||
return [];
|
||||
}
|
||||
return CHANNEL_EXTRA_FIELDS.flatMap((field) => {
|
||||
if (!(field in value)) {
|
||||
return [];
|
||||
}
|
||||
return [{ label: field, value: formatChannelExtraValue(value[field]) }];
|
||||
});
|
||||
}
|
||||
|
||||
function summarizeChannelAccounts(accounts: ChannelAccountSnapshot[]) {
|
||||
let connected = 0;
|
||||
let configured = 0;
|
||||
@@ -234,7 +186,11 @@ export function renderAgentChannels(params: {
|
||||
? `${summary.configured} configured`
|
||||
: "not configured";
|
||||
const enabled = summary.total ? `${summary.enabled} enabled` : "disabled";
|
||||
const extras = resolveChannelExtras(params.configForm, entry.id);
|
||||
const extras = resolveChannelExtrasFromConfig({
|
||||
configForm: params.configForm,
|
||||
channelId: entry.id,
|
||||
fields: CHANNEL_EXTRA_FIELDS,
|
||||
});
|
||||
return html`
|
||||
<div class="list-item">
|
||||
<div class="list-main">
|
||||
|
||||
49
ui/src/ui/views/channel-config-extras.ts
Normal file
49
ui/src/ui/views/channel-config-extras.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
export function resolveChannelConfigValue(
|
||||
configForm: Record<string, unknown> | null | undefined,
|
||||
channelId: string,
|
||||
): Record<string, unknown> | null {
|
||||
if (!configForm) {
|
||||
return null;
|
||||
}
|
||||
const channels = (configForm.channels ?? {}) as Record<string, unknown>;
|
||||
const fromChannels = channels[channelId];
|
||||
if (fromChannels && typeof fromChannels === "object") {
|
||||
return fromChannels as Record<string, unknown>;
|
||||
}
|
||||
const fallback = configForm[channelId];
|
||||
if (fallback && typeof fallback === "object") {
|
||||
return fallback as Record<string, unknown>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function formatChannelExtraValue(raw: unknown): string {
|
||||
if (raw == null) {
|
||||
return "n/a";
|
||||
}
|
||||
if (typeof raw === "string" || typeof raw === "number" || typeof raw === "boolean") {
|
||||
return String(raw);
|
||||
}
|
||||
try {
|
||||
return JSON.stringify(raw);
|
||||
} catch {
|
||||
return "n/a";
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveChannelExtras(params: {
|
||||
configForm: Record<string, unknown> | null | undefined;
|
||||
channelId: string;
|
||||
fields: readonly string[];
|
||||
}): Array<{ label: string; value: string }> {
|
||||
const value = resolveChannelConfigValue(params.configForm, params.channelId);
|
||||
if (!value) {
|
||||
return [];
|
||||
}
|
||||
return params.fields.flatMap((field) => {
|
||||
if (!(field in value)) {
|
||||
return [];
|
||||
}
|
||||
return [{ label: field, value: formatChannelExtraValue(value[field]) }];
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { html } from "lit";
|
||||
import type { ConfigUiHints } from "../types.ts";
|
||||
import { formatChannelExtraValue, resolveChannelConfigValue } from "./channel-config-extras.ts";
|
||||
import type { ChannelsProps } from "./channels.types.ts";
|
||||
import { analyzeConfigSchema, renderNode, schemaType, type JsonSchema } from "./config-form.ts";
|
||||
|
||||
@@ -52,33 +53,11 @@ function resolveChannelValue(
|
||||
config: Record<string, unknown>,
|
||||
channelId: string,
|
||||
): Record<string, unknown> {
|
||||
const channels = (config.channels ?? {}) as Record<string, unknown>;
|
||||
const fromChannels = channels[channelId];
|
||||
const fallback = config[channelId];
|
||||
const resolved =
|
||||
(fromChannels && typeof fromChannels === "object"
|
||||
? (fromChannels as Record<string, unknown>)
|
||||
: null) ??
|
||||
(fallback && typeof fallback === "object" ? (fallback as Record<string, unknown>) : null);
|
||||
return resolved ?? {};
|
||||
return resolveChannelConfigValue(config, channelId) ?? {};
|
||||
}
|
||||
|
||||
const EXTRA_CHANNEL_FIELDS = ["groupPolicy", "streamMode", "dmPolicy"] as const;
|
||||
|
||||
function formatExtraValue(raw: unknown): string {
|
||||
if (raw == null) {
|
||||
return "n/a";
|
||||
}
|
||||
if (typeof raw === "string" || typeof raw === "number" || typeof raw === "boolean") {
|
||||
return String(raw);
|
||||
}
|
||||
try {
|
||||
return JSON.stringify(raw);
|
||||
} catch {
|
||||
return "n/a";
|
||||
}
|
||||
}
|
||||
|
||||
function renderExtraChannelFields(value: Record<string, unknown>) {
|
||||
const entries = EXTRA_CHANNEL_FIELDS.flatMap((field) => {
|
||||
if (!(field in value)) {
|
||||
@@ -95,7 +74,7 @@ function renderExtraChannelFields(value: Record<string, unknown>) {
|
||||
([field, raw]) => html`
|
||||
<div>
|
||||
<span class="label">${field}</span>
|
||||
<span>${formatExtraValue(raw)}</span>
|
||||
<span>${formatChannelExtraValue(raw)}</span>
|
||||
</div>
|
||||
`,
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user