@dsh-workbench/shared 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/host-write.d.ts +1 -0
- package/dist/api/host-write.js +7 -1
- package/dist/components/CardHead.js +3 -3
- package/dist/host.d.ts +2 -0
- package/dist/host.js +2 -0
- package/dist/i18n/en.js +3 -3
- package/dist/i18n/index.d.ts +4 -4
- package/dist/i18n/zh.d.ts +3 -3
- package/dist/i18n/zh.js +3 -3
- package/dist/lib/ui.d.ts +0 -6
- package/dist/lib/ui.js +0 -6
- package/package.json +1 -1
- package/src/api/__tests__/host-write.test.ts +20 -0
- package/src/api/host-write.ts +17 -3
- package/src/components/CardHead.tsx +3 -3
- package/src/host.ts +2 -0
- package/src/i18n/en.ts +3 -3
- package/src/i18n/zh.ts +3 -3
- package/src/lib/ui.ts +0 -7
package/dist/api/host-write.d.ts
CHANGED
package/dist/api/host-write.js
CHANGED
|
@@ -11,7 +11,13 @@ export function writeOutcomeOf(response, networkText) {
|
|
|
11
11
|
const own = typeof box.error?.message === 'string' && box.error.message !== '' ? box.error.message : undefined;
|
|
12
12
|
const fallback = typeof box.text === 'string' && box.text !== '' ? box.text : networkText;
|
|
13
13
|
const detail = typeof box.error?.detail === 'string' ? box.error.detail : undefined;
|
|
14
|
-
|
|
14
|
+
const helpUrl = typeof box.error?.helpUrl === 'string' && box.error.helpUrl !== '' ? box.error.helpUrl : undefined;
|
|
15
|
+
return {
|
|
16
|
+
ok: false,
|
|
17
|
+
message: own ?? fallback,
|
|
18
|
+
...(detail === undefined ? {} : { detail }),
|
|
19
|
+
...(helpUrl === undefined ? {} : { helpUrl }),
|
|
20
|
+
};
|
|
15
21
|
}
|
|
16
22
|
return { ok: true, value: response };
|
|
17
23
|
}
|
|
@@ -6,11 +6,11 @@ export function CardHead({ t, title, meta, refreshing, onRefresh, gear, gearOpen
|
|
|
6
6
|
return (h("header", { className: "wb-cardHead" },
|
|
7
7
|
h("h2", { className: "wb-cardTitle" }, title),
|
|
8
8
|
meta === undefined ? null : h("span", { className: "wb-cardMeta" }, meta),
|
|
9
|
-
platformHref === undefined || platform === undefined ? null : (h(Tooltip, { label: platformTitle ?? platform },
|
|
9
|
+
platformHref === undefined || platform === undefined ? null : (h(Tooltip, { side: "bottom", align: "end", gap: 6, portal: true, label: platformTitle ?? platform },
|
|
10
10
|
h("a", { className: "wb-iconButton wb-cardOpen", href: platformHref, target: "_blank", rel: "noreferrer noopener", "aria-label": platform },
|
|
11
11
|
h(IconRightUpOutlineRegular, { size: 14 })))),
|
|
12
|
-
h(Tooltip, { label: refreshLabel },
|
|
12
|
+
h(Tooltip, { side: "bottom", align: "end", gap: 6, portal: true, label: refreshLabel },
|
|
13
13
|
h(Button, { type: "button", size: "sm", variant: "ghost", className: `wb-cardRefresh${refreshing ? ' wb-spinning' : ''}`, "aria-label": refreshLabel, disabled: refreshing, icon: h(IconRefreshOutlineRegular, { size: 14 }), onClick: onRefresh })),
|
|
14
|
-
gear === undefined || onToggleGear === undefined ? null : (h(Tooltip, { label: gear },
|
|
14
|
+
gear === undefined || onToggleGear === undefined ? null : (h(Tooltip, { side: "bottom", align: "end", gap: 6, portal: true, label: gear },
|
|
15
15
|
h(Button, { type: "button", size: "sm", variant: "ghost", className: `wb-cardGear${gearOpen === true ? ' wb-iconButtonActive' : ''}`, "aria-label": gear, "aria-expanded": gearOpen === true, icon: h(IconSettingsOutlineRegular, { size: 15 }), onClick: onToggleGear })))));
|
|
16
16
|
}
|
package/dist/host.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export * from './api/unit.js';
|
|
|
4
4
|
export * from './api/facts.js';
|
|
5
5
|
export * from './api/long-task.js';
|
|
6
6
|
export * from './lib/text.js';
|
|
7
|
+
export * from './lib/ui.js';
|
|
8
|
+
export * from './api/blocker-table.js';
|
|
7
9
|
export * from './host/cli-error.js';
|
|
8
10
|
export * from './host/data-root.js';
|
|
9
11
|
export * from './host/facts.js';
|
package/dist/host.js
CHANGED
|
@@ -4,6 +4,8 @@ export * from './api/unit.js';
|
|
|
4
4
|
export * from './api/facts.js';
|
|
5
5
|
export * from './api/long-task.js';
|
|
6
6
|
export * from './lib/text.js';
|
|
7
|
+
export * from './lib/ui.js';
|
|
8
|
+
export * from './api/blocker-table.js';
|
|
7
9
|
export * from './host/cli-error.js';
|
|
8
10
|
export * from './host/data-root.js';
|
|
9
11
|
export * from './host/facts.js';
|
package/dist/i18n/en.js
CHANGED
|
@@ -78,7 +78,8 @@ export const en = {
|
|
|
78
78
|
'panels.market.badSource': 'The install method is incomplete — install it yourself',
|
|
79
79
|
'panels.market.empty': 'No modules available',
|
|
80
80
|
'panels.market.installedSection': 'Installed',
|
|
81
|
-
'panels.market.
|
|
81
|
+
'panels.market.moduleOutdated': 'update available',
|
|
82
|
+
'panels.market.moduleRestartHint': 'it may need a restart after installing',
|
|
82
83
|
'panels.market.restartNeeded': 'The new version is installed — restart once to pick it up.',
|
|
83
84
|
'panels.market.foot': 'After installing, enable it in the panel page of that project.',
|
|
84
85
|
'panels.market.recheck': 'Check for updates',
|
|
@@ -175,11 +176,10 @@ export const en = {
|
|
|
175
176
|
'panels.market.add.doneRestart': 'Installed — restart once to pick it up.',
|
|
176
177
|
'panels.market.add.cancelled': 'Cancelled.',
|
|
177
178
|
'panels.market.add.failed': "Didn't work: {reason}",
|
|
178
|
-
'panels.market.add.
|
|
179
|
+
'panels.market.add.removed': 'It has been removed.',
|
|
179
180
|
'panels.market.add.supplyPending': 'Its plugins install after you restart.',
|
|
180
181
|
'panels.market.add.supplyFailed': "Its plugins didn't install: {reason}",
|
|
181
182
|
'panels.market.add.notModule': "This is not a workbench module (no dsh.workbench declaration), so it will not show up on the board.",
|
|
182
|
-
'panels.market.add.removed': 'Removed.',
|
|
183
183
|
'panels.market.add.removedRestart': 'Removed — restart once to finish.',
|
|
184
184
|
'panels.market.add.remove': 'Remove it',
|
|
185
185
|
'panels.market.add.problem.invalidSpec': "That is not a spec we accept: it cannot be empty or start with a dash.",
|
package/dist/i18n/index.d.ts
CHANGED
|
@@ -80,7 +80,8 @@ export declare const dictionaries: {
|
|
|
80
80
|
readonly 'panels.market.badSource': "安装方式没写全,只能自己动手";
|
|
81
81
|
readonly 'panels.market.empty': "暂无可用模块";
|
|
82
82
|
readonly 'panels.market.installedSection': "已装";
|
|
83
|
-
readonly 'panels.market.
|
|
83
|
+
readonly 'panels.market.moduleOutdated': "有新版";
|
|
84
|
+
readonly 'panels.market.moduleRestartHint': "安装完成后可能需要重启才生效";
|
|
84
85
|
readonly 'panels.market.restartNeeded': "新版装好了,重启一次才生效。";
|
|
85
86
|
readonly 'panels.market.foot': "装好后到那个项目的面板页勾选它,模块才会出现。";
|
|
86
87
|
readonly 'panels.market.recheck': "重新检查更新";
|
|
@@ -177,11 +178,10 @@ export declare const dictionaries: {
|
|
|
177
178
|
readonly 'panels.market.add.doneRestart': "装好了,重启一次才生效。";
|
|
178
179
|
readonly 'panels.market.add.cancelled': "已取消。";
|
|
179
180
|
readonly 'panels.market.add.failed': "没成功:{reason}";
|
|
180
|
-
readonly 'panels.market.add.
|
|
181
|
+
readonly 'panels.market.add.removed': "已经移除了。";
|
|
181
182
|
readonly 'panels.market.add.supplyPending': "它要的插件重启后再装。";
|
|
182
183
|
readonly 'panels.market.add.supplyFailed': "它要的插件没装上:{reason}";
|
|
183
184
|
readonly 'panels.market.add.notModule': "这不是工作台模块(没有 dsh.workbench 声明),不会出现在面板上。";
|
|
184
|
-
readonly 'panels.market.add.removed': "已经移除了。";
|
|
185
185
|
readonly 'panels.market.add.removedRestart': "卸掉了,重启一次才彻底生效。";
|
|
186
186
|
readonly 'panels.market.add.remove': "移除它";
|
|
187
187
|
readonly 'panels.market.add.problem.invalidSpec': "这个写法不认:不能是空的,也不能以横杠开头。";
|
|
@@ -287,7 +287,7 @@ export declare const dictionaries: {
|
|
|
287
287
|
readonly 'panel.conversation': "对话";
|
|
288
288
|
readonly 'panels.label': "全局面板";
|
|
289
289
|
};
|
|
290
|
-
en: Record<"time.now" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.fix.update" | "blocker.market.open" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "panels.title" | "panels.reset" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.failed" | "panels.hintEffect" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.outdated" | "panels.market.hasNew" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.installedSection" | "panels.market.
|
|
290
|
+
en: Record<"time.now" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.fix.update" | "blocker.market.open" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "panels.title" | "panels.reset" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.failed" | "panels.hintEffect" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.outdated" | "panels.market.hasNew" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.installedSection" | "panels.market.moduleOutdated" | "panels.market.moduleRestartHint" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.recheck" | "panels.market.checkUpdates" | "panels.market.checkedAt" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.problemNetwork" | "panels.market.add.problemUnknown" | "panels.market.add.failureNetwork" | "panels.market.add.failureNotFound" | "panels.market.add.failureNoMatchingVersion" | "panels.market.add.failureDiskFull" | "panels.market.add.failurePermission" | "panels.market.add.failureBuildBlocked" | "panels.market.add.failureIntegrity" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureGeneric" | "panels.market.add.approveTitle" | "panels.market.add.approveCaution" | "panels.market.add.approveRun" | "panels.market.add.restart" | "panels.market.add.tookEffect" | "panels.market.add.details" | "panels.market.add.open" | "panels.market.add.title" | "panels.market.add.intro" | "panels.market.add.specLabel" | "panels.market.add.specHint" | "panels.market.add.exampleTitle" | "panels.market.add.exampleFill" | "panels.market.add.registryLabel" | "panels.market.add.registryProfile" | "panels.market.add.registryPnpm" | "panels.market.add.check" | "panels.market.add.checking" | "panels.market.add.change" | "panels.market.add.previewTitle" | "panels.market.add.fieldName" | "panels.market.add.fieldVersion" | "panels.market.add.fieldDescription" | "panels.market.add.fieldSource" | "panels.market.add.install" | "panels.market.add.installing" | "panels.market.add.cancel" | "panels.market.add.close" | "panels.market.add.retry" | "panels.market.add.changeSource" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.daemon" | "env.bridge.extension" | "env.bridge.extensionLink" | "env.bridge.profile" | "env.bridge.stale" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.copyCommand" | "env.copied" | "env.step.opencli" | "env.step.codingPlugin" | "env.step.bridge" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "coding.notARepo.title" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label", string>;
|
|
291
291
|
};
|
|
292
292
|
export type { WorkbenchMessages };
|
|
293
293
|
export interface Dictionaries {
|
package/dist/i18n/zh.d.ts
CHANGED
|
@@ -78,7 +78,8 @@ export declare const zh: {
|
|
|
78
78
|
readonly 'panels.market.badSource': "安装方式没写全,只能自己动手";
|
|
79
79
|
readonly 'panels.market.empty': "暂无可用模块";
|
|
80
80
|
readonly 'panels.market.installedSection': "已装";
|
|
81
|
-
readonly 'panels.market.
|
|
81
|
+
readonly 'panels.market.moduleOutdated': "有新版";
|
|
82
|
+
readonly 'panels.market.moduleRestartHint': "安装完成后可能需要重启才生效";
|
|
82
83
|
readonly 'panels.market.restartNeeded': "新版装好了,重启一次才生效。";
|
|
83
84
|
readonly 'panels.market.foot': "装好后到那个项目的面板页勾选它,模块才会出现。";
|
|
84
85
|
readonly 'panels.market.recheck': "重新检查更新";
|
|
@@ -175,11 +176,10 @@ export declare const zh: {
|
|
|
175
176
|
readonly 'panels.market.add.doneRestart': "装好了,重启一次才生效。";
|
|
176
177
|
readonly 'panels.market.add.cancelled': "已取消。";
|
|
177
178
|
readonly 'panels.market.add.failed': "没成功:{reason}";
|
|
178
|
-
readonly 'panels.market.add.
|
|
179
|
+
readonly 'panels.market.add.removed': "已经移除了。";
|
|
179
180
|
readonly 'panels.market.add.supplyPending': "它要的插件重启后再装。";
|
|
180
181
|
readonly 'panels.market.add.supplyFailed': "它要的插件没装上:{reason}";
|
|
181
182
|
readonly 'panels.market.add.notModule': "这不是工作台模块(没有 dsh.workbench 声明),不会出现在面板上。";
|
|
182
|
-
readonly 'panels.market.add.removed': "已经移除了。";
|
|
183
183
|
readonly 'panels.market.add.removedRestart': "卸掉了,重启一次才彻底生效。";
|
|
184
184
|
readonly 'panels.market.add.remove': "移除它";
|
|
185
185
|
readonly 'panels.market.add.problem.invalidSpec': "这个写法不认:不能是空的,也不能以横杠开头。";
|
package/dist/i18n/zh.js
CHANGED
|
@@ -78,7 +78,8 @@ export const zh = {
|
|
|
78
78
|
'panels.market.badSource': '安装方式没写全,只能自己动手',
|
|
79
79
|
'panels.market.empty': '暂无可用模块',
|
|
80
80
|
'panels.market.installedSection': '已装',
|
|
81
|
-
'panels.market.
|
|
81
|
+
'panels.market.moduleOutdated': '有新版',
|
|
82
|
+
'panels.market.moduleRestartHint': '安装完成后可能需要重启才生效',
|
|
82
83
|
'panels.market.restartNeeded': '新版装好了,重启一次才生效。',
|
|
83
84
|
'panels.market.foot': '装好后到那个项目的面板页勾选它,模块才会出现。',
|
|
84
85
|
'panels.market.recheck': '重新检查更新',
|
|
@@ -175,11 +176,10 @@ export const zh = {
|
|
|
175
176
|
'panels.market.add.doneRestart': '装好了,重启一次才生效。',
|
|
176
177
|
'panels.market.add.cancelled': '已取消。',
|
|
177
178
|
'panels.market.add.failed': '没成功:{reason}',
|
|
178
|
-
'panels.market.add.
|
|
179
|
+
'panels.market.add.removed': '已经移除了。',
|
|
179
180
|
'panels.market.add.supplyPending': '它要的插件重启后再装。',
|
|
180
181
|
'panels.market.add.supplyFailed': '它要的插件没装上:{reason}',
|
|
181
182
|
'panels.market.add.notModule': '这不是工作台模块(没有 dsh.workbench 声明),不会出现在面板上。',
|
|
182
|
-
'panels.market.add.removed': '已经移除了。',
|
|
183
183
|
'panels.market.add.removedRestart': '卸掉了,重启一次才彻底生效。',
|
|
184
184
|
'panels.market.add.remove': '移除它',
|
|
185
185
|
'panels.market.add.problem.invalidSpec': '这个写法不认:不能是空的,也不能以横杠开头。',
|
package/dist/lib/ui.d.ts
CHANGED
|
@@ -2,10 +2,4 @@ export declare function cx(...parts: Array<string | false | null | undefined>):
|
|
|
2
2
|
export type TimeTranslate = (key: string, params?: Record<string, unknown>) => string;
|
|
3
3
|
export declare function relativeTime(epochMs: number, t: TimeTranslate): string;
|
|
4
4
|
export declare function shortenPath(path: unknown): string;
|
|
5
|
-
export declare const LINK_BUTTON_STYLE: {
|
|
6
|
-
readonly display: "inline-flex";
|
|
7
|
-
readonly alignItems: "center";
|
|
8
|
-
readonly gap: "var(--wb-gap-xs)";
|
|
9
|
-
readonly textDecoration: "none";
|
|
10
|
-
};
|
|
11
5
|
export declare function parseLocalTimestamp(text: string | null | undefined): number;
|
package/dist/lib/ui.js
CHANGED
|
@@ -22,12 +22,6 @@ export function shortenPath(path) {
|
|
|
22
22
|
const hit = path.match(/^\/Users\/[^/]+/);
|
|
23
23
|
return hit === null ? path : path.replace(hit[0], '~');
|
|
24
24
|
}
|
|
25
|
-
export const LINK_BUTTON_STYLE = {
|
|
26
|
-
display: 'inline-flex',
|
|
27
|
-
alignItems: 'center',
|
|
28
|
-
gap: 'var(--wb-gap-xs)',
|
|
29
|
-
textDecoration: 'none',
|
|
30
|
-
};
|
|
31
25
|
const LOCAL_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})$/;
|
|
32
26
|
export function parseLocalTimestamp(text) {
|
|
33
27
|
const raw = String(text ?? '').trim();
|
package/package.json
CHANGED
|
@@ -33,6 +33,26 @@ describe('writeOutcomeOf', () => {
|
|
|
33
33
|
expect(outcome).toEqual({ ok: false, message: '生产环境要先审批', detail: 'job 1234' });
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
it('★ 登录态失效那条错误带着 helpUrl → 一路带出去(卡片才能给「去登录 ↗」而不是"还没绑定")', () => {
|
|
37
|
+
const outcome = writeOutcomeOf(
|
|
38
|
+
{
|
|
39
|
+
ok: false,
|
|
40
|
+
error: {
|
|
41
|
+
code: 'cmdb/login-required',
|
|
42
|
+
message: 'CMDB 登录态失效了',
|
|
43
|
+
helpUrl: 'https://cmdb.example.test/login',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
'网络不通',
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
expect(outcome).toEqual({
|
|
50
|
+
ok: false,
|
|
51
|
+
message: 'CMDB 登录态失效了',
|
|
52
|
+
helpUrl: 'https://cmdb.example.test/login',
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
36
56
|
it('没有 detail 就不给那个字段(别塞一个 undefined 进类型里)', () => {
|
|
37
57
|
const outcome = writeOutcomeOf({ ok: false, error: { code: 'x', message: '不行' } }, '网络不通');
|
|
38
58
|
|
package/src/api/host-write.ts
CHANGED
|
@@ -9,19 +9,33 @@ export function writeRoute(channel: WriteChannel, resource: string): string {
|
|
|
9
9
|
|
|
10
10
|
export type WriteOutcome<T> =
|
|
11
11
|
| { readonly ok: true; readonly value: T }
|
|
12
|
-
| {
|
|
12
|
+
| {
|
|
13
|
+
readonly ok: false;
|
|
14
|
+
readonly message: string;
|
|
15
|
+
readonly detail?: string;
|
|
16
|
+
readonly helpUrl?: string;
|
|
17
|
+
};
|
|
13
18
|
|
|
14
19
|
export function writeOutcomeOf<T>(response: ApiResponse<T> | null, networkText: string): WriteOutcome<T> {
|
|
15
20
|
if (response === null) return { ok: false, message: networkText };
|
|
16
21
|
if (!response.ok) {
|
|
17
22
|
const box = response as {
|
|
18
|
-
readonly error?:
|
|
23
|
+
readonly error?:
|
|
24
|
+
| { readonly message?: unknown; readonly detail?: unknown; readonly helpUrl?: unknown }
|
|
25
|
+
| undefined;
|
|
19
26
|
readonly text?: unknown;
|
|
20
27
|
};
|
|
21
28
|
const own = typeof box.error?.message === 'string' && box.error.message !== '' ? box.error.message : undefined;
|
|
22
29
|
const fallback = typeof box.text === 'string' && box.text !== '' ? box.text : networkText;
|
|
23
30
|
const detail = typeof box.error?.detail === 'string' ? box.error.detail : undefined;
|
|
24
|
-
|
|
31
|
+
const helpUrl =
|
|
32
|
+
typeof box.error?.helpUrl === 'string' && box.error.helpUrl !== '' ? box.error.helpUrl : undefined;
|
|
33
|
+
return {
|
|
34
|
+
ok: false,
|
|
35
|
+
message: own ?? fallback,
|
|
36
|
+
...(detail === undefined ? {} : { detail }),
|
|
37
|
+
...(helpUrl === undefined ? {} : { helpUrl }),
|
|
38
|
+
};
|
|
25
39
|
}
|
|
26
40
|
return { ok: true, value: response };
|
|
27
41
|
}
|
|
@@ -43,7 +43,7 @@ export function CardHead({
|
|
|
43
43
|
<h2 className="wb-cardTitle">{title}</h2>
|
|
44
44
|
{meta === undefined ? null : <span className="wb-cardMeta">{meta}</span>}
|
|
45
45
|
{platformHref === undefined || platform === undefined ? null : (
|
|
46
|
-
<Tooltip label={platformTitle ?? platform}>
|
|
46
|
+
<Tooltip side="bottom" align="end" gap={6} portal label={platformTitle ?? platform}>
|
|
47
47
|
<a
|
|
48
48
|
className="wb-iconButton wb-cardOpen"
|
|
49
49
|
href={platformHref}
|
|
@@ -55,7 +55,7 @@ export function CardHead({
|
|
|
55
55
|
</a>
|
|
56
56
|
</Tooltip>
|
|
57
57
|
)}
|
|
58
|
-
<Tooltip label={refreshLabel}>
|
|
58
|
+
<Tooltip side="bottom" align="end" gap={6} portal label={refreshLabel}>
|
|
59
59
|
<Button
|
|
60
60
|
type="button"
|
|
61
61
|
size="sm"
|
|
@@ -68,7 +68,7 @@ export function CardHead({
|
|
|
68
68
|
/>
|
|
69
69
|
</Tooltip>
|
|
70
70
|
{gear === undefined || onToggleGear === undefined ? null : (
|
|
71
|
-
<Tooltip label={gear}>
|
|
71
|
+
<Tooltip side="bottom" align="end" gap={6} portal label={gear}>
|
|
72
72
|
<Button
|
|
73
73
|
type="button"
|
|
74
74
|
size="sm"
|
package/src/host.ts
CHANGED
|
@@ -4,6 +4,8 @@ export * from './api/unit.js';
|
|
|
4
4
|
export * from './api/facts.js';
|
|
5
5
|
export * from './api/long-task.js';
|
|
6
6
|
export * from './lib/text.js';
|
|
7
|
+
export * from './lib/ui.js';
|
|
8
|
+
export * from './api/blocker-table.js';
|
|
7
9
|
export * from './host/cli-error.js';
|
|
8
10
|
export * from './host/data-root.js';
|
|
9
11
|
export * from './host/facts.js';
|
package/src/i18n/en.ts
CHANGED
|
@@ -85,7 +85,8 @@ export const en: Record<keyof WorkbenchMessages, string> = {
|
|
|
85
85
|
'panels.market.badSource': 'The install method is incomplete — install it yourself',
|
|
86
86
|
'panels.market.empty': 'No modules available',
|
|
87
87
|
'panels.market.installedSection': 'Installed',
|
|
88
|
-
'panels.market.
|
|
88
|
+
'panels.market.moduleOutdated': 'update available',
|
|
89
|
+
'panels.market.moduleRestartHint': 'it may need a restart after installing',
|
|
89
90
|
'panels.market.restartNeeded': 'The new version is installed — restart once to pick it up.',
|
|
90
91
|
'panels.market.foot': 'After installing, enable it in the panel page of that project.',
|
|
91
92
|
'panels.market.recheck': 'Check for updates',
|
|
@@ -182,11 +183,10 @@ export const en: Record<keyof WorkbenchMessages, string> = {
|
|
|
182
183
|
'panels.market.add.doneRestart': 'Installed — restart once to pick it up.',
|
|
183
184
|
'panels.market.add.cancelled': 'Cancelled.',
|
|
184
185
|
'panels.market.add.failed': "Didn't work: {reason}",
|
|
185
|
-
'panels.market.add.
|
|
186
|
+
'panels.market.add.removed': 'It has been removed.',
|
|
186
187
|
'panels.market.add.supplyPending': 'Its plugins install after you restart.',
|
|
187
188
|
'panels.market.add.supplyFailed': "Its plugins didn't install: {reason}",
|
|
188
189
|
'panels.market.add.notModule': "This is not a workbench module (no dsh.workbench declaration), so it will not show up on the board.",
|
|
189
|
-
'panels.market.add.removed': 'Removed.',
|
|
190
190
|
'panels.market.add.removedRestart': 'Removed — restart once to finish.',
|
|
191
191
|
'panels.market.add.remove': 'Remove it',
|
|
192
192
|
'panels.market.add.problem.invalidSpec': "That is not a spec we accept: it cannot be empty or start with a dash.",
|
package/src/i18n/zh.ts
CHANGED
|
@@ -81,7 +81,8 @@ export const zh = {
|
|
|
81
81
|
'panels.market.badSource': '安装方式没写全,只能自己动手',
|
|
82
82
|
'panels.market.empty': '暂无可用模块',
|
|
83
83
|
'panels.market.installedSection': '已装',
|
|
84
|
-
'panels.market.
|
|
84
|
+
'panels.market.moduleOutdated': '有新版',
|
|
85
|
+
'panels.market.moduleRestartHint': '安装完成后可能需要重启才生效',
|
|
85
86
|
'panels.market.restartNeeded': '新版装好了,重启一次才生效。',
|
|
86
87
|
'panels.market.foot': '装好后到那个项目的面板页勾选它,模块才会出现。',
|
|
87
88
|
'panels.market.recheck': '重新检查更新',
|
|
@@ -178,11 +179,10 @@ export const zh = {
|
|
|
178
179
|
'panels.market.add.doneRestart': '装好了,重启一次才生效。',
|
|
179
180
|
'panels.market.add.cancelled': '已取消。',
|
|
180
181
|
'panels.market.add.failed': '没成功:{reason}',
|
|
181
|
-
'panels.market.add.
|
|
182
|
+
'panels.market.add.removed': '已经移除了。',
|
|
182
183
|
'panels.market.add.supplyPending': '它要的插件重启后再装。',
|
|
183
184
|
'panels.market.add.supplyFailed': '它要的插件没装上:{reason}',
|
|
184
185
|
'panels.market.add.notModule': '这不是工作台模块(没有 dsh.workbench 声明),不会出现在面板上。',
|
|
185
|
-
'panels.market.add.removed': '已经移除了。',
|
|
186
186
|
'panels.market.add.removedRestart': '卸掉了,重启一次才彻底生效。',
|
|
187
187
|
'panels.market.add.remove': '移除它',
|
|
188
188
|
'panels.market.add.problem.invalidSpec': '这个写法不认:不能是空的,也不能以横杠开头。',
|
package/src/lib/ui.ts
CHANGED
|
@@ -22,13 +22,6 @@ export function shortenPath(path: unknown): string {
|
|
|
22
22
|
return hit === null ? path : path.replace(hit[0], '~');
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export const LINK_BUTTON_STYLE = {
|
|
26
|
-
display: 'inline-flex',
|
|
27
|
-
alignItems: 'center',
|
|
28
|
-
gap: 'var(--wb-gap-xs)',
|
|
29
|
-
textDecoration: 'none',
|
|
30
|
-
} as const;
|
|
31
|
-
|
|
32
25
|
const LOCAL_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})$/;
|
|
33
26
|
|
|
34
27
|
export function parseLocalTimestamp(text: string | null | undefined): number {
|