134 lines
4.6 KiB
TypeScript
134 lines
4.6 KiB
TypeScript
import { html, nothing } from "lit";
|
|
|
|
import { formatAgo } from "../format";
|
|
import type { ChannelAccountSnapshot, TelegramStatus } from "../types";
|
|
import type { ChannelsProps } from "./channels.types";
|
|
import { renderChannelConfigSection } from "./channels.config";
|
|
|
|
export function renderTelegramCard(params: {
|
|
props: ChannelsProps;
|
|
telegram?: TelegramStatus;
|
|
telegramAccounts: ChannelAccountSnapshot[];
|
|
accountCountLabel: unknown;
|
|
}) {
|
|
const { props, telegram, telegramAccounts, accountCountLabel } = params;
|
|
const hasMultipleAccounts = telegramAccounts.length > 1;
|
|
const configDisabled = props.configSaving || props.configSchemaLoading;
|
|
|
|
const renderAccountCard = (account: ChannelAccountSnapshot) => {
|
|
const probe = account.probe as { bot?: { username?: string } } | undefined;
|
|
const botUsername = probe?.bot?.username;
|
|
const label = account.name || account.accountId;
|
|
return html`
|
|
<div class="account-card">
|
|
<div class="account-card-header">
|
|
<div class="account-card-title">
|
|
${botUsername ? `@${botUsername}` : label}
|
|
</div>
|
|
<div class="account-card-id">${account.accountId}</div>
|
|
</div>
|
|
<div class="status-list account-card-status">
|
|
<div>
|
|
<span class="label">Running</span>
|
|
<span>${account.running ? "Yes" : "No"}</span>
|
|
</div>
|
|
<div>
|
|
<span class="label">Configured</span>
|
|
<span>${account.configured ? "Yes" : "No"}</span>
|
|
</div>
|
|
<div>
|
|
<span class="label">Last inbound</span>
|
|
<span>${account.lastInboundAt ? formatAgo(account.lastInboundAt) : "n/a"}</span>
|
|
</div>
|
|
${account.lastError
|
|
? html`
|
|
<div class="account-card-error">
|
|
${account.lastError}
|
|
</div>
|
|
`
|
|
: nothing}
|
|
</div>
|
|
</div>
|
|
`;
|
|
};
|
|
|
|
return html`
|
|
<div class="card card--channel">
|
|
<div class="card-content">
|
|
<div class="card-title">Telegram</div>
|
|
<div class="card-sub">Bot status and channel configuration.</div>
|
|
${accountCountLabel}
|
|
|
|
${hasMultipleAccounts
|
|
? html`
|
|
<div class="account-card-list">
|
|
${telegramAccounts.map((account) => renderAccountCard(account))}
|
|
</div>
|
|
`
|
|
: html`
|
|
<div class="status-list" style="margin-top: 16px;">
|
|
<div>
|
|
<span class="label">Configured</span>
|
|
<span>${telegram?.configured ? "Yes" : "No"}</span>
|
|
</div>
|
|
<div>
|
|
<span class="label">Running</span>
|
|
<span>${telegram?.running ? "Yes" : "No"}</span>
|
|
</div>
|
|
<div>
|
|
<span class="label">Mode</span>
|
|
<span>${telegram?.mode ?? "n/a"}</span>
|
|
</div>
|
|
<div>
|
|
<span class="label">Last start</span>
|
|
<span>${telegram?.lastStartAt ? formatAgo(telegram.lastStartAt) : "n/a"}</span>
|
|
</div>
|
|
<div>
|
|
<span class="label">Last probe</span>
|
|
<span>${telegram?.lastProbeAt ? formatAgo(telegram.lastProbeAt) : "n/a"}</span>
|
|
</div>
|
|
</div>
|
|
`}
|
|
|
|
${telegram?.probe
|
|
? html`<div class="callout" style="margin-top: 12px;">
|
|
Probe ${telegram.probe.ok ? "ok" : "failed"} ·
|
|
${telegram.probe.status ?? ""} ${telegram.probe.error ?? ""}
|
|
</div>`
|
|
: nothing}
|
|
|
|
${renderChannelConfigSection({ channelId: "telegram", props })}
|
|
</div>
|
|
|
|
<div class="card-footer">
|
|
${telegram?.lastError
|
|
? html`<div class="callout danger" style="margin-bottom: 12px;">
|
|
${telegram.lastError}
|
|
</div>`
|
|
: nothing}
|
|
|
|
<div class="row" style="gap: 8px; align-items: center; flex-wrap: wrap;">
|
|
<ui-button @click=${() => props.onRefresh(true)}>
|
|
Probe
|
|
</ui-button>
|
|
<div style="margin-left: auto; display: flex; gap: 8px;">
|
|
<ui-button
|
|
variant="primary"
|
|
?disabled=${configDisabled || !props.configFormDirty}
|
|
@click=${() => props.onConfigSave()}
|
|
>
|
|
${props.configSaving ? "Saving…" : "Save Config"}
|
|
</ui-button>
|
|
<ui-button
|
|
?disabled=${configDisabled}
|
|
@click=${() => props.onConfigReload()}
|
|
>
|
|
Reload
|
|
</ui-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|