feat(web): prioritize SMS operations workspace
This commit is contained in:
@@ -28,10 +28,10 @@ export interface InstanceDetailProps {
|
||||
}
|
||||
|
||||
export const INSTANCE_MODULE_LABELS: Readonly<Record<InstanceModule, string>> = {
|
||||
overview: '概览',
|
||||
overview: '设备信息',
|
||||
cellular: '蜂窝网络',
|
||||
'device-network': '设备网络',
|
||||
messages: '消息',
|
||||
messages: '短信',
|
||||
calls: '通话',
|
||||
esim: 'eSIM',
|
||||
notifications: '通知',
|
||||
@@ -39,7 +39,7 @@ export const INSTANCE_MODULE_LABELS: Readonly<Record<InstanceModule, string>> =
|
||||
ota: 'OTA',
|
||||
};
|
||||
|
||||
const MODULES = Object.keys(INSTANCE_MODULE_LABELS) as readonly InstanceModule[];
|
||||
const PRIMARY_MODULES = ['messages', 'overview'] as const satisfies readonly InstanceModule[];
|
||||
|
||||
const DEFAULT_EXPLANATIONS: Readonly<Record<Exclude<CapabilityState, 'supported'>, string>> = {
|
||||
degraded: '此模块可用,但功能受限。',
|
||||
@@ -47,20 +47,18 @@ const DEFAULT_EXPLANATIONS: Readonly<Record<Exclude<CapabilityState, 'supported'
|
||||
unknown: '能力状态未知。',
|
||||
};
|
||||
|
||||
function capabilityFor(map: InstanceCapabilityMap, module: InstanceModule): InstanceCapability {
|
||||
return map[module] ?? { state: 'unknown' };
|
||||
}
|
||||
|
||||
function canRender(capability: InstanceCapability): boolean {
|
||||
function canRender(capability: InstanceCapability | undefined): boolean {
|
||||
if (!capability) return true;
|
||||
return capability.state === 'supported' || capability.state === 'degraded';
|
||||
}
|
||||
|
||||
const CORE_MODULES = new Set<InstanceModule>(['overview', 'messages']);
|
||||
function canOpen(module: InstanceModule, capability: InstanceCapability): boolean {
|
||||
return CORE_MODULES.has(module) || canRender(capability);
|
||||
function canOpen(module: InstanceModule, capability: InstanceCapability | undefined): boolean {
|
||||
return capability ? canRender(capability) : CORE_MODULES.has(module);
|
||||
}
|
||||
|
||||
function explanation(capability: InstanceCapability): string | null {
|
||||
function explanation(capability: InstanceCapability | undefined): string | null {
|
||||
if (!capability) return null;
|
||||
if (capability.state === 'supported') return null;
|
||||
return capability.explanation?.trim() || DEFAULT_EXPLANATIONS[capability.state];
|
||||
}
|
||||
@@ -124,19 +122,21 @@ export function InstanceDetail({
|
||||
|
||||
const map = capabilities ?? loadedCapabilities ?? {};
|
||||
const origin = canonicalHttpOrigin(instance.origin);
|
||||
const activeCapability = capabilityFor(map, module);
|
||||
const activeCapability = map[module];
|
||||
|
||||
return (
|
||||
<section className="instance-detail">
|
||||
<aside className="instance-context" aria-label="当前实例">
|
||||
<strong>{instance.name}</strong>
|
||||
<code>{instance.id}</code>
|
||||
<dl>
|
||||
<div>
|
||||
<dt>状态</dt>
|
||||
<dd>{displayStatus(instance.status)}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{instance.status !== 'unknown' ? (
|
||||
<dl>
|
||||
<div>
|
||||
<dt>状态</dt>
|
||||
<dd>{displayStatus(instance.status)}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
) : null}
|
||||
{origin ? (
|
||||
<a href={origin} target="_blank" rel="noopener noreferrer">
|
||||
打开源站
|
||||
@@ -145,24 +145,15 @@ export function InstanceDetail({
|
||||
<a href={`/settings/instances/${encodeURIComponent(instanceId)}`}>编辑实例</a>
|
||||
<nav aria-label="实例模块">
|
||||
<ul>
|
||||
{MODULES.map((item) => {
|
||||
const capability = capabilityFor(map, item);
|
||||
const reason = explanation(capability);
|
||||
{PRIMARY_MODULES.map((item) => {
|
||||
return (
|
||||
<li key={item} data-capability-state={capability.state}>
|
||||
{canOpen(item, capability) ? (
|
||||
<a
|
||||
href={`/instances/${encodeURIComponent(instanceId)}/${item}`}
|
||||
aria-current={module === item ? 'page' : undefined}
|
||||
>
|
||||
{INSTANCE_MODULE_LABELS[item]}
|
||||
</a>
|
||||
) : (
|
||||
<>
|
||||
<span>{INSTANCE_MODULE_LABELS[item]}</span>
|
||||
<small>{reason}</small>
|
||||
</>
|
||||
)}
|
||||
<li key={item}>
|
||||
<a
|
||||
href={`/instances/${encodeURIComponent(instanceId)}/${item}`}
|
||||
aria-current={module === item ? 'page' : undefined}
|
||||
>
|
||||
{INSTANCE_MODULE_LABELS[item]}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
@@ -175,14 +166,14 @@ export function InstanceDetail({
|
||||
{loadError ? <p role="alert">能力不可用:{loadError}</p> : null}
|
||||
{!loading && canOpen(module, activeCapability) ? (
|
||||
<>
|
||||
{activeCapability.state === 'degraded' ? (
|
||||
{activeCapability?.state === 'degraded' ? (
|
||||
<p data-capability-state="degraded">{explanation(activeCapability)}</p>
|
||||
) : null}
|
||||
{moduleContent ?? <p>查看{INSTANCE_MODULE_LABELS[module]}数据和可用操作。</p>}
|
||||
</>
|
||||
) : null}
|
||||
{!loading && !canOpen(module, activeCapability) ? (
|
||||
<p data-capability-state={activeCapability.state}>{explanation(activeCapability)}</p>
|
||||
<p data-capability-state={activeCapability?.state}>{explanation(activeCapability)}</p>
|
||||
) : null}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user