@chengxianglibra/dsh-data-analysis 0.1.1 → 0.1.2
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/README.md +83 -34
- package/lib/bin/environment.js +1 -1
- package/lib/bin/presentation-lint.js +21 -0
- package/lib/bridges.js +2 -2
- package/lib/client/credentials/create-datasource.js +67 -0
- package/lib/client/credentials/install.js +191 -0
- package/lib/client/credentials/model.js +494 -0
- package/lib/client/credentials/styles.js +17 -0
- package/lib/client/workspace-header-action.js +11 -0
- package/lib/client.js +1133 -736
- package/lib/compatibility.js +1 -1
- package/lib/datasource/authoring.js +70 -0
- package/lib/datasource/bridge-programs.js +30 -18
- package/lib/datasource/bridge.js +100 -8
- package/lib/datasource/index.js +3 -2
- package/lib/datasource/python.js +115 -0
- package/lib/datasource/resolver-program.js +112 -0
- package/lib/datasource/rpc.js +88 -0
- package/lib/datasource/service.js +687 -0
- package/lib/datasource/shell-env.js +2 -333
- package/lib/datasource/test.js +24 -51
- package/lib/environment/binding.js +54 -9
- package/lib/environment/runtime.js +89 -78
- package/lib/environment/subprocess.js +6 -1
- package/lib/environment/summary.js +3 -3
- package/lib/environment/workspace.js +5 -0
- package/lib/index.js +1 -1
- package/lib/plugin.js +168 -51
- package/lib/presentation/assets/portable.js +606 -0
- package/lib/presentation/assets/static.js +945 -0
- package/lib/presentation/build/index.js +71 -0
- package/lib/presentation/commit.js +156 -0
- package/lib/presentation/contracts/charts.js +476 -0
- package/lib/presentation/contracts/editing.js +58 -0
- package/lib/presentation/contracts/index.js +651 -0
- package/lib/presentation/contracts/interaction.js +62 -0
- package/lib/presentation/contracts/types.js +15 -0
- package/lib/presentation/contracts/values.js +28 -0
- package/lib/presentation/delivery.js +56 -0
- package/lib/presentation/files.js +83 -0
- package/lib/presentation/index.js +6 -0
- package/lib/presentation/lint.js +46 -0
- package/lib/presentation/projection/files.js +85 -0
- package/lib/presentation/projection/index.js +195 -0
- package/lib/presentation/projection/program.js +144 -0
- package/lib/presentation/projection/sql-code.js +79 -0
- package/lib/presentation/receipt.js +34 -0
- package/lib/presentation/reports.js +122 -0
- package/lib/presentation/rpc.js +148 -0
- package/lib/presentation/tool.js +122 -0
- package/lib/python-execution-contracts.js +1 -0
- package/lib/python-execution.js +232 -0
- package/lib/semantic-browser/contracts.js +80 -0
- package/lib/semantic-browser/definition.js +64 -0
- package/lib/semantic-browser/program.js +119 -0
- package/lib/semantic-browser/service.js +72 -0
- package/lib/semantic-reference/bridge.js +118 -0
- package/lib/semantic-reference/contracts.js +113 -0
- package/lib/semantic-reference/index.js +3 -0
- package/lib/semantic-reference/rpc.js +122 -0
- package/lib/semantic-reference/search.js +94 -0
- package/lib/semantic-reference/usage.js +143 -0
- package/lib/types/bridges.d.ts +2 -2
- package/lib/types/client/credentials/create-datasource.d.ts +5 -0
- package/lib/types/client/credentials/install.d.ts +1 -0
- package/lib/types/client/credentials/model.d.ts +59 -0
- package/lib/types/client/credentials/styles.d.ts +1 -0
- package/lib/types/client/presentation/ask-dsh.d.ts +9 -0
- package/lib/types/client/presentation/chart-explorer.d.ts +12 -0
- package/lib/types/client/presentation/chart-geometry.d.ts +30 -0
- package/lib/types/client/presentation/chart-renderer.d.ts +10 -0
- package/lib/types/client/presentation/chart-specials.d.ts +10 -0
- package/lib/types/client/presentation/chart-styles.d.ts +1 -0
- package/lib/types/client/presentation/chart-tooltip.d.ts +13 -0
- package/lib/types/client/presentation/chart-view.d.ts +23 -0
- package/lib/types/client/presentation/copy-context.d.ts +5 -0
- package/lib/types/client/presentation/delivery-model.d.ts +54 -0
- package/lib/types/client/presentation/delivery.d.ts +77 -0
- package/lib/types/client/presentation/editor-controls.d.ts +12 -0
- package/lib/types/client/presentation/global-filters.d.ts +6 -0
- package/lib/types/client/presentation/host-entry.d.ts +12 -0
- package/lib/types/client/presentation/icons.d.ts +4 -0
- package/lib/types/client/presentation/install.d.ts +15 -0
- package/lib/types/client/presentation/markdown.d.ts +5 -0
- package/lib/types/client/presentation/model.d.ts +62 -0
- package/lib/types/client/presentation/reader.d.ts +11 -0
- package/lib/types/client/presentation/source-code-model.d.ts +16 -0
- package/lib/types/client/presentation/source-code.d.ts +11 -0
- package/lib/types/client/presentation/source-dialog.d.ts +13 -0
- package/lib/types/client/presentation/source-facts.d.ts +20 -0
- package/lib/types/client/presentation/source-format.d.ts +5 -0
- package/lib/types/client/presentation/source-highlight.d.ts +7 -0
- package/lib/types/client/presentation/sources.d.ts +13 -0
- package/lib/types/client/presentation/styles.d.ts +1 -0
- package/lib/types/client/presentation/table.d.ts +12 -0
- package/lib/types/client/presentation/use-element-width.d.ts +5 -0
- package/lib/types/client/workspace-header-action.d.ts +7 -0
- package/lib/types/client.d.ts +4 -122
- package/lib/types/compatibility.d.ts +2 -2
- package/lib/types/datasource/authoring.d.ts +25 -0
- package/lib/types/datasource/bridge.d.ts +21 -3
- package/lib/types/datasource/index.d.ts +3 -5
- package/lib/types/datasource/python.d.ts +4 -0
- package/lib/types/datasource/resolver-program.d.ts +6 -0
- package/lib/types/datasource/rpc.d.ts +4 -0
- package/lib/types/datasource/service.d.ts +112 -0
- package/lib/types/datasource/shell-env.d.ts +0 -29
- package/lib/types/datasource/test.d.ts +6 -29
- package/lib/types/environment/binding.d.ts +5 -1
- package/lib/types/environment/errors.d.ts +1 -1
- package/lib/types/environment/runtime.d.ts +5 -5
- package/lib/types/environment/types.d.ts +13 -2
- package/lib/types/index.d.ts +1 -1
- package/lib/types/plugin.d.ts +11 -5
- package/lib/types/presentation/build/index.d.ts +11 -0
- package/lib/types/presentation/commit.d.ts +4 -0
- package/lib/types/presentation/contracts/charts.d.ts +13 -0
- package/lib/types/presentation/contracts/editing.d.ts +8 -0
- package/lib/types/presentation/contracts/index.d.ts +11 -0
- package/lib/types/presentation/contracts/interaction.d.ts +8 -0
- package/lib/types/presentation/contracts/types.d.ts +252 -0
- package/lib/types/presentation/contracts/values.d.ts +9 -0
- package/lib/types/presentation/delivery.d.ts +3 -0
- package/lib/types/presentation/files.d.ts +7 -0
- package/lib/types/presentation/index.d.ts +6 -0
- package/lib/types/presentation/lint.d.ts +13 -0
- package/lib/types/presentation/projection/files.d.ts +2 -0
- package/lib/types/presentation/projection/index.d.ts +20 -0
- package/lib/types/presentation/projection/program.d.ts +2 -0
- package/lib/types/presentation/projection/sql-code.d.ts +2 -0
- package/lib/types/presentation/receipt.d.ts +14 -0
- package/lib/types/presentation/reports.d.ts +5 -0
- package/lib/types/presentation/rpc.d.ts +24 -0
- package/lib/types/presentation/tool.d.ts +12 -0
- package/lib/types/python-execution-contracts.d.ts +10 -0
- package/lib/types/python-execution.d.ts +10 -0
- package/lib/types/semantic-browser/contracts.d.ts +40 -0
- package/lib/types/semantic-browser/definition.d.ts +20 -0
- package/lib/types/semantic-browser/program.d.ts +2 -0
- package/lib/types/semantic-browser/service.d.ts +20 -0
- package/lib/types/semantic-reference/bridge.d.ts +11 -0
- package/lib/types/semantic-reference/contracts.d.ts +51 -0
- package/lib/types/semantic-reference/index.d.ts +3 -0
- package/lib/types/semantic-reference/rpc.d.ts +15 -0
- package/lib/types/semantic-reference/search.d.ts +10 -0
- package/lib/types/semantic-reference/usage.d.ts +43 -0
- package/package.json +43 -19
- package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
- package/skills/dsh-data-analysis-presentation/SKILL.md +24 -0
- package/skills/dsh-data-analysis-presentation/references/chart-examples.md +18 -0
- package/skills/dsh-data-analysis-presentation/references/charts.md +55 -0
- package/skills/dsh-data-analysis-presentation/references/examples/artifact.draft.json +27 -0
- package/skills/dsh-data-analysis-presentation/references/examples/charts-bins.dataset.json +33 -0
- package/skills/dsh-data-analysis-presentation/references/examples/charts-boxes.dataset.json +45 -0
- package/skills/dsh-data-analysis-presentation/references/examples/charts-composition.dataset.json +33 -0
- package/skills/dsh-data-analysis-presentation/references/examples/charts-funnel.dataset.json +27 -0
- package/skills/dsh-data-analysis-presentation/references/examples/charts-precision.dataset.json +21 -0
- package/skills/dsh-data-analysis-presentation/references/examples/charts-series.dataset.json +58 -0
- package/skills/dsh-data-analysis-presentation/references/examples/charts-shares.dataset.json +33 -0
- package/skills/dsh-data-analysis-presentation/references/examples/charts-waterfall.dataset.json +44 -0
- package/skills/dsh-data-analysis-presentation/references/examples/charts.draft.json +392 -0
- package/skills/dsh-data-analysis-presentation/references/examples/comparison-selected.dataset.json +24 -0
- package/skills/dsh-data-analysis-presentation/references/examples/comparison-summary.dataset.json +22 -0
- package/skills/dsh-data-analysis-presentation/references/examples/comparison.dataset.json +18 -0
- package/skills/dsh-data-analysis-presentation/references/examples/comparison.draft.json +79 -0
- package/skills/dsh-data-analysis-presentation/references/examples/computed-sources.draft.json +35 -0
- package/skills/dsh-data-analysis-presentation/references/examples/computed.dataset.json +12 -0
- package/skills/dsh-data-analysis-presentation/references/examples/computed.draft.json +57 -0
- package/skills/dsh-data-analysis-presentation/references/examples/interaction-detail.dataset.json +30 -0
- package/skills/dsh-data-analysis-presentation/references/examples/interaction-summary.dataset.json +22 -0
- package/skills/dsh-data-analysis-presentation/references/examples/interaction.draft.json +278 -0
- package/skills/dsh-data-analysis-presentation/references/examples/source-only.draft.json +19 -0
- package/skills/dsh-data-analysis-presentation/references/examples/write-charts.py +73 -0
- package/skills/dsh-data-analysis-presentation/references/examples/write-comparison.py +42 -0
- package/skills/dsh-data-analysis-presentation/references/examples/write-computed.py +21 -0
- package/skills/dsh-data-analysis-presentation/references/examples/write-interaction.py +33 -0
- package/skills/dsh-data-analysis-presentation/references/examples.md +42 -0
- package/skills/dsh-data-analysis-presentation/references/interaction.md +56 -0
- package/skills/dsh-data-analysis-presentation/references/narrative.md +37 -0
- package/skills/dsh-data-analysis-presentation/references/schema.md +138 -0
- package/lib/datasource/access.js +0 -60
- package/lib/datasource/credentials.js +0 -24
- package/lib/evidence/bridge-program.js +0 -153
- package/lib/evidence/bridge.js +0 -166
- package/lib/evidence/index.js +0 -2
- package/lib/evidence/sources.js +0 -263
- package/lib/types/datasource/access.d.ts +0 -27
- package/lib/types/evidence/bridge.d.ts +0 -40
- package/lib/types/evidence/index.d.ts +0 -4
- package/lib/types/evidence/sources.d.ts +0 -57
- package/python/report-kit/dist/dsh_data_analysis_report_kit-3.0.0-py3-none-any.whl +0 -0
- package/skills/dsh-data-analysis-report/SKILL.md +0 -57
- package/skills/dsh-data-analysis-report/assets/marivo-artifact.js +0 -113
- package/skills/dsh-data-analysis-report/assets/marivo-session-dag.js +0 -1201
- package/skills/dsh-data-analysis-report/assets/report-data.js +0 -449
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
const CHANNEL = '/dsh-data-analysis-credentials';
|
|
2
|
+
const STORAGE_KEY = 'marivo-credential-operation';
|
|
3
|
+
const messages = {
|
|
4
|
+
'context-changed': 'Workspace 或数据源定义已变化,请重新读取后操作。',
|
|
5
|
+
'credentials-changed': '凭证配置已变化,请重新读取后验证。',
|
|
6
|
+
'call-ended': '原调用已结束,已保存的值仍保留;请重新发起任务。',
|
|
7
|
+
'credential-missing': '凭证尚未配齐,请补填后验证。',
|
|
8
|
+
'credential-save-failed': '部分凭证保存失败;已成功保存的项目保留。',
|
|
9
|
+
'operation-busy': '该操作正在进行,请等待结果。',
|
|
10
|
+
'credential-state-unavailable': '暂时无法读取凭证状态,请稍后重试。',
|
|
11
|
+
'capacity-exceeded': '当前操作数量达到上限,请稍后重试。',
|
|
12
|
+
'datasource-already-exists': '该数据源已存在,请使用其他名称。',
|
|
13
|
+
'datasource-definition-invalid': '数据源定义无效,请检查名称、字段类型和凭证引用。',
|
|
14
|
+
'datasource-credential-ref-invalid': '凭证引用名称无效。*_env 字段填写引用名(如 MY_DB_PASSWORD),仅可使用字母、数字和下划线,且不能以数字开头;不能使用 MARIVO_、DSH_DATA_ANALYSIS_ 前缀或 Host 保留名称。实际用户名和密码请在创建后的“新增凭证”中填写。',
|
|
15
|
+
'datasource-authoring-unavailable': '当前 Runtime 不支持新增数据源。',
|
|
16
|
+
};
|
|
17
|
+
export function credentialMessage(code) {
|
|
18
|
+
return messages[code] ?? '凭证操作失败,请检查配置后重试。';
|
|
19
|
+
}
|
|
20
|
+
class CredentialResponseError extends Error {
|
|
21
|
+
code;
|
|
22
|
+
constructor(code) {
|
|
23
|
+
super(credentialMessage(code));
|
|
24
|
+
this.code = code;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function delay(ms, signal) {
|
|
28
|
+
return new Promise((resolve) => {
|
|
29
|
+
const done = () => {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
signal.removeEventListener('abort', done);
|
|
32
|
+
resolve();
|
|
33
|
+
};
|
|
34
|
+
const timer = setTimeout(done, ms);
|
|
35
|
+
signal.addEventListener('abort', done, { once: true });
|
|
36
|
+
if (signal.aborted)
|
|
37
|
+
done();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export class CredentialClientModel {
|
|
41
|
+
#state = {
|
|
42
|
+
open: false,
|
|
43
|
+
workspaceId: '',
|
|
44
|
+
sessionId: '',
|
|
45
|
+
generation: '',
|
|
46
|
+
datasources: [],
|
|
47
|
+
requests: [],
|
|
48
|
+
requestId: '',
|
|
49
|
+
selected: '',
|
|
50
|
+
loading: false,
|
|
51
|
+
error: '',
|
|
52
|
+
operations: [],
|
|
53
|
+
outcomes: {},
|
|
54
|
+
};
|
|
55
|
+
#rpc;
|
|
56
|
+
#storage;
|
|
57
|
+
#listeners = new Set();
|
|
58
|
+
#lifetime = new AbortController();
|
|
59
|
+
#watch;
|
|
60
|
+
#read;
|
|
61
|
+
#refresh;
|
|
62
|
+
#polls = new Map();
|
|
63
|
+
#operations = new Map();
|
|
64
|
+
#opened = new Set();
|
|
65
|
+
constructor(rpc, storage) {
|
|
66
|
+
this.#rpc = rpc;
|
|
67
|
+
this.#storage = storage;
|
|
68
|
+
}
|
|
69
|
+
getSnapshot = () => this.#state;
|
|
70
|
+
subscribe = (listener) => {
|
|
71
|
+
this.#listeners.add(listener);
|
|
72
|
+
return () => {
|
|
73
|
+
this.#listeners.delete(listener);
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
#patch(change) {
|
|
77
|
+
if (this.#lifetime.signal.aborted)
|
|
78
|
+
return;
|
|
79
|
+
this.#state = { ...this.#state, ...change };
|
|
80
|
+
for (const listener of this.#listeners)
|
|
81
|
+
listener();
|
|
82
|
+
}
|
|
83
|
+
async #call(endpoint, payload, signal = this.#lifetime.signal) {
|
|
84
|
+
const result = (await this.#rpc.call(CHANNEL, endpoint, payload, signal));
|
|
85
|
+
if (!result.ok)
|
|
86
|
+
throw new CredentialResponseError(result.error?.message ?? '');
|
|
87
|
+
return result.value;
|
|
88
|
+
}
|
|
89
|
+
show(workspaceId) {
|
|
90
|
+
this.#patch({ open: true, requestId: '' });
|
|
91
|
+
void this.selectWorkspace(workspaceId);
|
|
92
|
+
}
|
|
93
|
+
async authoring(workspaceId, signal) {
|
|
94
|
+
return (await this.#call('authoring', { workspaceId }, signal));
|
|
95
|
+
}
|
|
96
|
+
async createDatasource(workspaceId, schema, input) {
|
|
97
|
+
let result;
|
|
98
|
+
try {
|
|
99
|
+
result = (await this.#call('create-datasource', {
|
|
100
|
+
workspaceId,
|
|
101
|
+
generation: schema.generation,
|
|
102
|
+
fingerprint: schema.fingerprint,
|
|
103
|
+
...input,
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (error instanceof CredentialResponseError &&
|
|
108
|
+
[
|
|
109
|
+
'datasource-credential-ref-invalid',
|
|
110
|
+
'datasource-already-exists',
|
|
111
|
+
'context-changed',
|
|
112
|
+
].includes(error.code))
|
|
113
|
+
throw error;
|
|
114
|
+
throw new Error(`${error instanceof Error ? error.message : '新增数据源失败。'} 如提交结果未确认,请刷新列表核对后再操作。`);
|
|
115
|
+
}
|
|
116
|
+
if (!this.#state.open || this.#state.workspaceId !== workspaceId)
|
|
117
|
+
return;
|
|
118
|
+
await this.selectWorkspace(workspaceId);
|
|
119
|
+
if (this.#state.workspaceId !== workspaceId)
|
|
120
|
+
return;
|
|
121
|
+
const created = this.#state.datasources.find((item) => item.name === result.name);
|
|
122
|
+
if (created)
|
|
123
|
+
this.select(created.token);
|
|
124
|
+
}
|
|
125
|
+
close() {
|
|
126
|
+
this.#read?.abort();
|
|
127
|
+
this.#refresh?.abort();
|
|
128
|
+
this.#patch({ open: false, loading: false });
|
|
129
|
+
}
|
|
130
|
+
openRequest(id) {
|
|
131
|
+
this.#read?.abort();
|
|
132
|
+
this.#refresh?.abort();
|
|
133
|
+
this.#patch({ open: true, requestId: id, loading: false });
|
|
134
|
+
}
|
|
135
|
+
select(token) {
|
|
136
|
+
this.#patch({ selected: token, requestId: '', error: '' });
|
|
137
|
+
}
|
|
138
|
+
async selectWorkspace(workspaceId) {
|
|
139
|
+
this.#read?.abort();
|
|
140
|
+
this.#refresh?.abort();
|
|
141
|
+
const flight = new AbortController();
|
|
142
|
+
this.#read = flight;
|
|
143
|
+
const selected = this.#state.workspaceId === workspaceId ? this.#state.selected : '';
|
|
144
|
+
const activity = new Map([...Object.values(this.#state.outcomes), ...this.#operations.values()].map((entry) => [
|
|
145
|
+
entry.handle.scope,
|
|
146
|
+
entry.handle.id,
|
|
147
|
+
]));
|
|
148
|
+
this.#patch({
|
|
149
|
+
workspaceId,
|
|
150
|
+
datasources: [],
|
|
151
|
+
selected: '',
|
|
152
|
+
requestId: '',
|
|
153
|
+
loading: !!workspaceId,
|
|
154
|
+
error: '',
|
|
155
|
+
});
|
|
156
|
+
if (!workspaceId)
|
|
157
|
+
return;
|
|
158
|
+
try {
|
|
159
|
+
const value = (await this.#call('overview', { workspaceId }, flight.signal));
|
|
160
|
+
if (flight.signal.aborted)
|
|
161
|
+
return;
|
|
162
|
+
this.#patch({
|
|
163
|
+
generation: value.generation,
|
|
164
|
+
datasources: value.datasources,
|
|
165
|
+
outcomes: this.#currentOutcomes(workspaceId, value.generation, value.datasources, activity),
|
|
166
|
+
selected: value.datasources.some((item) => item.token === selected)
|
|
167
|
+
? selected
|
|
168
|
+
: (value.datasources[0]?.token ?? ''),
|
|
169
|
+
loading: false,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
if (!flight.signal.aborted)
|
|
174
|
+
this.#patch({
|
|
175
|
+
loading: false,
|
|
176
|
+
error: error instanceof Error ? error.message : '无法读取凭证状态。',
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
session(sessionId) {
|
|
181
|
+
if (sessionId === this.#state.sessionId && this.#watch)
|
|
182
|
+
return;
|
|
183
|
+
this.#watch?.abort();
|
|
184
|
+
this.#read?.abort();
|
|
185
|
+
this.#refresh?.abort();
|
|
186
|
+
const controller = new AbortController();
|
|
187
|
+
this.#watch = controller;
|
|
188
|
+
this.#patch({ sessionId, requests: [], requestId: '', open: false });
|
|
189
|
+
if (sessionId)
|
|
190
|
+
void this.#watchSession(sessionId, controller.signal);
|
|
191
|
+
}
|
|
192
|
+
async #watchSession(sessionId, signal) {
|
|
193
|
+
let cursor, attempt = 0;
|
|
194
|
+
while (!signal.aborted && !this.#lifetime.signal.aborted) {
|
|
195
|
+
try {
|
|
196
|
+
const value = (await this.#call('watch', { sessionId, ...(cursor ? { cursor } : {}) }, signal));
|
|
197
|
+
if (signal.aborted)
|
|
198
|
+
return;
|
|
199
|
+
cursor = value.cursor;
|
|
200
|
+
attempt = 0;
|
|
201
|
+
this.#patch({ generation: value.generation, requests: value.requests });
|
|
202
|
+
const request = value.requests.find((r) => r.endedAt === undefined && !this.#opened.has(r.id));
|
|
203
|
+
if (request) {
|
|
204
|
+
this.#opened.add(request.id);
|
|
205
|
+
this.openRequest(request.id);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
if (!signal.aborted) {
|
|
210
|
+
this.#patch({ error: '凭证待办连接中断,正在重连;Host 中的等待仍受原调用期限限制。' });
|
|
211
|
+
await delay([1000, 2000, 5000][Math.min(attempt++, 2)], signal);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
#persist() {
|
|
217
|
+
try {
|
|
218
|
+
const pending = [...this.#operations.values()]
|
|
219
|
+
.filter((entry) => !entry.error && (!entry.operation || entry.operation.status === 'running'))
|
|
220
|
+
.map(({ handle, name, workspaceId }) => ({ handle, name, workspaceId }));
|
|
221
|
+
if (pending.length)
|
|
222
|
+
this.#storage?.setItem(STORAGE_KEY, JSON.stringify(pending));
|
|
223
|
+
else
|
|
224
|
+
this.#storage?.removeItem(STORAGE_KEY);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
/* in-memory queries still work */
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
#visible(scope) {
|
|
231
|
+
const selected = this.#state.requestId
|
|
232
|
+
? this.#state.requests.find((request) => request.id === this.#state.requestId)?.context.token
|
|
233
|
+
: this.#state.selected;
|
|
234
|
+
return selected === scope;
|
|
235
|
+
}
|
|
236
|
+
#currentOutcomes(workspaceId, generation, datasources, activity) {
|
|
237
|
+
const scopes = new Set(datasources.map((context) => context.token));
|
|
238
|
+
return Object.fromEntries(Object.entries(this.#state.outcomes)
|
|
239
|
+
.filter(([scope, entry]) => entry.handle.generation === generation &&
|
|
240
|
+
(entry.workspaceId !== workspaceId || scopes.has(scope)))
|
|
241
|
+
.map(([scope, entry]) => [
|
|
242
|
+
scope,
|
|
243
|
+
scopes.has(scope) && activity.get(scope) === entry.handle.id
|
|
244
|
+
? { ...entry, overviewUpdated: true }
|
|
245
|
+
: entry,
|
|
246
|
+
]));
|
|
247
|
+
}
|
|
248
|
+
#activity(scope) {
|
|
249
|
+
return ([...this.#operations.values()].find((entry) => entry.handle.scope === scope)?.handle.id ??
|
|
250
|
+
this.#state.outcomes[scope]?.handle.id);
|
|
251
|
+
}
|
|
252
|
+
async #refreshOverview(handle) {
|
|
253
|
+
const { workspaceId, generation, datasources, open, requestId } = this.#state;
|
|
254
|
+
if (!open ||
|
|
255
|
+
requestId ||
|
|
256
|
+
handle.generation !== generation ||
|
|
257
|
+
!datasources.some((context) => context.token === handle.scope))
|
|
258
|
+
return;
|
|
259
|
+
this.#refresh?.abort();
|
|
260
|
+
const flight = new AbortController(), read = this.#read, activity = new Map(datasources.map((context) => [context.token, this.#activity(context.token)]));
|
|
261
|
+
this.#refresh = flight;
|
|
262
|
+
try {
|
|
263
|
+
const value = (await this.#call('overview', { workspaceId }, flight.signal));
|
|
264
|
+
if (flight.signal.aborted ||
|
|
265
|
+
read !== this.#read ||
|
|
266
|
+
workspaceId !== this.#state.workspaceId ||
|
|
267
|
+
generation !== this.#state.generation ||
|
|
268
|
+
value.generation !== generation)
|
|
269
|
+
return;
|
|
270
|
+
const current = new Map(this.#state.datasources.map((context) => [context.token, context]));
|
|
271
|
+
const updated = value.datasources.map((context) => current.has(context.token) && activity.get(context.token) !== this.#activity(context.token)
|
|
272
|
+
? current.get(context.token)
|
|
273
|
+
: context);
|
|
274
|
+
this.#patch({
|
|
275
|
+
datasources: updated,
|
|
276
|
+
outcomes: this.#currentOutcomes(workspaceId, generation, updated, activity),
|
|
277
|
+
selected: updated.some((context) => context.token === this.#state.selected)
|
|
278
|
+
? this.#state.selected
|
|
279
|
+
: (updated[0]?.token ?? ''),
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
// Keep the last authoritative overview and scoped outcome if a passive refresh fails.
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
#publish(handle, operation) {
|
|
287
|
+
const entry = this.#operations.get(handle.id);
|
|
288
|
+
if (!entry)
|
|
289
|
+
return;
|
|
290
|
+
if (operation.status !== 'running') {
|
|
291
|
+
this.#settle({ ...entry, operation });
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
this.#operations.set(handle.id, { ...entry, operation });
|
|
295
|
+
this.#patch({
|
|
296
|
+
operations: [...this.#operations.values()],
|
|
297
|
+
...(this.#state.handle?.id === handle.id
|
|
298
|
+
? { operation, ...(this.#visible(handle.scope) ? { error: '' } : {}) }
|
|
299
|
+
: {}),
|
|
300
|
+
});
|
|
301
|
+
this.#persist();
|
|
302
|
+
}
|
|
303
|
+
#settle(entry) {
|
|
304
|
+
this.#operations.delete(entry.handle.id);
|
|
305
|
+
this.#patch({
|
|
306
|
+
operations: [...this.#operations.values()],
|
|
307
|
+
outcomes: { ...this.#state.outcomes, [entry.handle.scope]: entry },
|
|
308
|
+
...(this.#state.handle?.id === entry.handle.id
|
|
309
|
+
? {
|
|
310
|
+
handle: undefined,
|
|
311
|
+
operation: undefined,
|
|
312
|
+
...(this.#visible(entry.handle.scope) ? { error: entry.error ?? '' } : {}),
|
|
313
|
+
}
|
|
314
|
+
: {}),
|
|
315
|
+
});
|
|
316
|
+
this.#persist();
|
|
317
|
+
}
|
|
318
|
+
selectOperation(id) {
|
|
319
|
+
const entry = this.#operations.get(id);
|
|
320
|
+
if (entry)
|
|
321
|
+
this.#patch({ handle: entry.handle, operation: entry.operation, error: entry.error ?? '' });
|
|
322
|
+
}
|
|
323
|
+
async start(context, action, changes = {}, reference) {
|
|
324
|
+
if ([...this.#operations.values()].some((entry) => entry.handle.scope === context.token &&
|
|
325
|
+
!entry.error &&
|
|
326
|
+
(!entry.operation || entry.operation.status === 'running'))) {
|
|
327
|
+
for (const ref of Object.keys(changes))
|
|
328
|
+
delete changes[ref];
|
|
329
|
+
this.#patch({ error: credentialMessage('operation-busy') });
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const outcomes = { ...this.#state.outcomes };
|
|
333
|
+
delete outcomes[context.token];
|
|
334
|
+
const handle = {
|
|
335
|
+
generation: this.#state.generation,
|
|
336
|
+
id: crypto.randomUUID(),
|
|
337
|
+
scope: context.token,
|
|
338
|
+
};
|
|
339
|
+
const requestId = action === 'submit' || action === 'diagnose' ? this.#state.requestId : undefined;
|
|
340
|
+
const operation = {
|
|
341
|
+
id: handle.id,
|
|
342
|
+
scope: handle.scope,
|
|
343
|
+
action,
|
|
344
|
+
status: 'running',
|
|
345
|
+
phase: 'saving',
|
|
346
|
+
saved: [],
|
|
347
|
+
errors: [],
|
|
348
|
+
};
|
|
349
|
+
this.#operations.set(handle.id, {
|
|
350
|
+
handle,
|
|
351
|
+
name: context.name,
|
|
352
|
+
workspaceId: context.workspaceId,
|
|
353
|
+
operation,
|
|
354
|
+
});
|
|
355
|
+
this.#patch({
|
|
356
|
+
handle,
|
|
357
|
+
operation,
|
|
358
|
+
operations: [...this.#operations.values()],
|
|
359
|
+
outcomes,
|
|
360
|
+
error: '',
|
|
361
|
+
});
|
|
362
|
+
this.#persist();
|
|
363
|
+
try {
|
|
364
|
+
// Only operation queries publish authoritative progress. A late submit reply cannot
|
|
365
|
+
// overwrite another operation or an already newer query result for this ID.
|
|
366
|
+
await this.#call('start', {
|
|
367
|
+
...handle,
|
|
368
|
+
action,
|
|
369
|
+
version: context.version,
|
|
370
|
+
...(requestId ? { requestId } : {}),
|
|
371
|
+
changes,
|
|
372
|
+
...(reference ? { reference } : {}),
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
if (this.#state.handle?.id === handle.id && this.#visible(handle.scope))
|
|
377
|
+
this.#patch({ error: '提交响应未确认,正在查询操作状态;不会重新发送秘密值。' });
|
|
378
|
+
}
|
|
379
|
+
finally {
|
|
380
|
+
for (const ref of Object.keys(changes))
|
|
381
|
+
delete changes[ref];
|
|
382
|
+
}
|
|
383
|
+
await this.#query(handle);
|
|
384
|
+
}
|
|
385
|
+
async #query(handle) {
|
|
386
|
+
const entry = this.#operations.get(handle.id);
|
|
387
|
+
if (!entry ||
|
|
388
|
+
entry.error ||
|
|
389
|
+
this.#polls.has(handle.id) ||
|
|
390
|
+
(entry.operation && entry.operation.status !== 'running'))
|
|
391
|
+
return;
|
|
392
|
+
const controller = new AbortController();
|
|
393
|
+
this.#polls.set(handle.id, controller);
|
|
394
|
+
const signal = AbortSignal.any([controller.signal, this.#lifetime.signal]);
|
|
395
|
+
try {
|
|
396
|
+
while (!signal.aborted) {
|
|
397
|
+
try {
|
|
398
|
+
const operation = (await this.#call('operation', handle, signal));
|
|
399
|
+
if (signal.aborted)
|
|
400
|
+
return;
|
|
401
|
+
if (!operation) {
|
|
402
|
+
const error = '操作状态不可恢复。保存可能已经发生,请重新读取实际配置后决定下一步。';
|
|
403
|
+
this.#settle({ ...entry, operation: undefined, error });
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
this.#publish(handle, operation);
|
|
407
|
+
if (operation.status !== 'running') {
|
|
408
|
+
await this.#refreshOverview(handle);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
catch {
|
|
413
|
+
if (!signal.aborted &&
|
|
414
|
+
this.#state.handle?.id === handle.id &&
|
|
415
|
+
this.#visible(handle.scope))
|
|
416
|
+
this.#patch({ error: '正在恢复操作结果;已提交的保存不会自动重发。' });
|
|
417
|
+
}
|
|
418
|
+
await delay(1000, signal);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
finally {
|
|
422
|
+
if (this.#polls.get(handle.id) === controller)
|
|
423
|
+
this.#polls.delete(handle.id);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
recover() {
|
|
427
|
+
try {
|
|
428
|
+
const raw = this.#storage?.getItem(STORAGE_KEY);
|
|
429
|
+
if (!raw)
|
|
430
|
+
return;
|
|
431
|
+
const entries = JSON.parse(raw);
|
|
432
|
+
if (!Array.isArray(entries))
|
|
433
|
+
return;
|
|
434
|
+
for (const entry of entries) {
|
|
435
|
+
const handle = entry?.handle;
|
|
436
|
+
if (!handle ||
|
|
437
|
+
![handle.generation, handle.id, handle.scope].every((v) => typeof v === 'string' && /^[a-f0-9-]{36}$/i.test(v)) ||
|
|
438
|
+
typeof entry.name !== 'string')
|
|
439
|
+
continue;
|
|
440
|
+
if (!this.#operations.has(handle.id))
|
|
441
|
+
this.#operations.set(handle.id, {
|
|
442
|
+
handle,
|
|
443
|
+
name: entry.name,
|
|
444
|
+
...(typeof entry.workspaceId === 'string' ? { workspaceId: entry.workspaceId } : {}),
|
|
445
|
+
});
|
|
446
|
+
if (!this.#state.handle)
|
|
447
|
+
this.selectOperation(handle.id);
|
|
448
|
+
void this.#query(handle);
|
|
449
|
+
}
|
|
450
|
+
this.#patch({ operations: [...this.#operations.values()] });
|
|
451
|
+
}
|
|
452
|
+
catch {
|
|
453
|
+
/* invalid or unavailable local handles are not replayed */
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
async cancelRequest(id) {
|
|
457
|
+
try {
|
|
458
|
+
await this.#call('cancel-request', { requestId: id });
|
|
459
|
+
}
|
|
460
|
+
catch (error) {
|
|
461
|
+
this.#patch({ error: error instanceof Error ? error.message : '调用已结束。' });
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
async cancelOperation(scope) {
|
|
465
|
+
const handle = scope
|
|
466
|
+
? [...this.#operations.values()].find((entry) => entry.handle.scope === scope &&
|
|
467
|
+
!entry.error &&
|
|
468
|
+
(!entry.operation || entry.operation.status === 'running'))?.handle
|
|
469
|
+
: this.#state.handle;
|
|
470
|
+
if (!handle)
|
|
471
|
+
return;
|
|
472
|
+
try {
|
|
473
|
+
await this.#call('cancel-operation', handle);
|
|
474
|
+
}
|
|
475
|
+
catch {
|
|
476
|
+
this.#patch({ error: '无法确认取消结果,请继续查询。' });
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
reset() {
|
|
480
|
+
this.#watch?.abort();
|
|
481
|
+
this.#watch = undefined;
|
|
482
|
+
this.session(this.#state.sessionId);
|
|
483
|
+
this.recover();
|
|
484
|
+
}
|
|
485
|
+
dispose() {
|
|
486
|
+
this.#lifetime.abort();
|
|
487
|
+
this.#watch?.abort();
|
|
488
|
+
this.#read?.abort();
|
|
489
|
+
this.#refresh?.abort();
|
|
490
|
+
for (const controller of this.#polls.values())
|
|
491
|
+
controller.abort();
|
|
492
|
+
this.#listeners.clear();
|
|
493
|
+
}
|
|
494
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const credentialStyles = `
|
|
2
|
+
.mc-input-heading{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 12px;min-width:0}.mc-input-name{font-weight:500;color:var(--mc-text);overflow-wrap:anywhere}.mc-input-description{flex:1 1 200px;min-width:0;font-size:11px;line-height:1.6;color:var(--mc-muted);overflow-wrap:anywhere}
|
|
3
|
+
.mc-dialog{--mc-bg:var(--dsw-alias-surface-primary,#fff);--mc-soft:var(--dsw-alias-interactive-bg-hover,#f5f7f9);--mc-text:var(--dsw-alias-label-primary,#182a33);--mc-muted:var(--dsw-alias-label-secondary,#627580);--mc-border:var(--dsw-alias-border-l2,#dce4e8);--mc-accent:#087b70;--mc-tint:#eaf6f2;--mc-danger:#b04436;--mc-warning:#886217;color:var(--mc-text);background:var(--mc-bg);border:1px solid var(--mc-border);border-radius:16px;width:calc(100vw - 48px);max-width:1060px;height:min(760px,calc(100dvh - 64px));max-height:calc(100dvh - 32px);padding:0;box-shadow:0 28px 100px #0003;pointer-events:auto;font:14px/1.55 system-ui,sans-serif;overflow:hidden}
|
|
4
|
+
.mc-dialog::backdrop{background:#102a3a66;backdrop-filter:blur(4px)}
|
|
5
|
+
.mc-dialog *{box-sizing:border-box}.mc-shell{height:100%;display:flex;flex-direction:column}.mc-dialog button,.mc-dialog input,.mc-dialog select{font:inherit;color:inherit}.mc-dialog button{cursor:pointer;border:1px solid var(--mc-border);border-radius:8px;padding:7px 12px;background:var(--mc-bg);line-height:1.5}.mc-dialog button:hover{background:var(--mc-soft)}.mc-dialog button:disabled{cursor:default;opacity:.5}.mc-dialog :focus-visible{outline:2px solid var(--mc-accent);outline-offset:3px}.mc-dialog select,.mc-dialog input{border:1px solid var(--mc-border);border-radius:8px;background:var(--mc-bg);padding:9px 10px;max-width:100%;min-width:0}.mc-dialog select{width:100%}.mc-dialog button.mc-primary{color:#fff;background:var(--mc-accent);border-color:var(--mc-accent)}.mc-dialog button.mc-primary:hover{filter:brightness(.93)}.mc-dialog button.mc-danger{color:var(--mc-danger)}.mc-dialog button.mc-quiet{border-color:transparent;background:transparent;color:var(--mc-muted)}.mc-dialog button.mc-quiet:hover{background:var(--mc-soft)}
|
|
6
|
+
.mc-header{display:flex;align-items:center;gap:14px;padding:22px 26px;border-bottom:1px solid var(--mc-border);flex:none}.mc-header-mark{display:grid;place-items:center;width:42px;height:42px;border:1px solid var(--mc-border);border-radius:12px;background:var(--mc-soft);color:var(--mc-accent);flex:none}.mc-header-copy{flex:1;min-width:0}.mc-header h2{font-size:20px;line-height:1.4;margin:0 0 4px;font-weight:650}.mc-header p{margin:0;font-size:12px;color:var(--mc-muted)}.mc-dialog .mc-close{display:grid;place-items:center;padding:8px;border:0;background:transparent;color:var(--mc-muted)}
|
|
7
|
+
.mc-columns{display:grid;grid-template-columns:244px minmax(0,1fr);flex:1;min-height:0}.mc-nav{display:flex;flex-direction:column;gap:24px;padding:22px 16px;background:var(--mc-soft);border-right:1px solid var(--mc-border);overflow:auto}.mc-workspace-label{display:block;font-size:12px;font-weight:600;color:var(--mc-muted);margin-bottom:8px}.mc-nav-heading{display:flex;align-items:center;justify-content:space-between;margin:0 0 10px;padding:0 4px;font-size:12px;color:var(--mc-muted)}.mc-nav-heading h3{font-size:inherit;font-weight:600;margin:0}.mc-nav-heading button{padding:4px}.mc-datasources{list-style:none;padding:0;margin:0;display:grid;gap:6px}.mc-dialog .mc-datasource{display:flex;align-items:start;gap:10px;width:100%;padding:12px 10px;border:1px solid transparent;background:transparent;text-align:left}.mc-dialog .mc-datasource[aria-pressed=true]{border-color:var(--mc-border);background:var(--mc-bg);box-shadow:0 2px 5px #102a3a05}.mc-datasource>svg{margin-top:2px;flex:none;color:var(--mc-muted)}.mc-datasource[aria-pressed=true]>svg{color:var(--mc-accent)}.mc-datasource-copy{min-width:0;display:grid;gap:4px}.mc-datasource-name{font-size:13px;font-weight:600;overflow-wrap:anywhere}.mc-datasource-status{font-size:11px;color:var(--mc-muted);display:flex;align-items:center;gap:5px}.mc-dot{width:6px;height:6px;background:var(--mc-muted);border-radius:50%;flex:none}.mc-dot[data-ready=true]{background:var(--mc-accent)}.mc-dot[data-ready=false]{background:#c58a26}
|
|
8
|
+
.mc-main{min-width:0;overflow:auto;display:flex;flex-direction:column}.mc-form{display:flex;flex-direction:column;flex:1;min-width:0}.mc-form-body{padding:26px 30px;flex:1}.mc-detail-heading{display:flex;align-items:start;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:22px}.mc-eyebrow{font-size:11px;color:var(--mc-muted);margin:0 0 5px}.mc-detail-heading h3{font-size:22px;font-weight:650;line-height:1.4;margin:0;overflow-wrap:anywhere}.mc-badge{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--mc-border);border-radius:6px;padding:3px 7px;font-size:11px;white-space:nowrap;color:var(--mc-muted)}.mc-badge[data-ready=true]{color:var(--mc-accent);background:var(--mc-tint);border-color:transparent}.mc-badge[data-ready=false]{color:var(--mc-warning)}
|
|
9
|
+
.mc-section-heading{font-size:13px;font-weight:600;margin:0 0 12px}.mc-properties{margin:0 0 24px;min-width:0}.mc-property-list{margin:0;border:1px solid var(--mc-border);border-radius:12px;overflow:hidden}.mc-property{display:grid;grid-template-columns:minmax(0,140px) minmax(0,1fr);gap:16px;padding:12px 18px;align-items:start}.mc-property+.mc-property{border-top:1px solid var(--mc-border)}.mc-property dt{font-size:12px;color:var(--mc-muted);overflow-wrap:anywhere}.mc-property dd{margin:0;min-width:0;font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.mc-property pre{font:12px/1.6 ui-monospace,monospace;white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.mc-property-json{max-height:240px;overflow:auto}
|
|
10
|
+
.mc-fields{border:1px solid var(--mc-border);border-radius:12px;overflow:hidden;margin:0 0 14px}.mc-field{min-width:0;border:0;padding:18px;margin:0}.mc-field+.mc-field{border-top:1px solid var(--mc-border)}.mc-field-header{display:flex;align-items:start;gap:12px;justify-content:space-between}.mc-field-title{min-width:0}.mc-field-title h4{font-size:13px;margin:0 0 4px;font-weight:600;overflow-wrap:anywhere}.mc-field-title p{margin:0;font-size:11px;color:var(--mc-muted);overflow-wrap:anywhere}.mc-field-actions{display:flex;align-items:center;gap:6px;flex-wrap:wrap;flex:none}.mc-dialog .mc-field-actions button{font-size:12px;padding:5px 9px}.mc-secret-input{display:grid;gap:7px;margin-top:14px;font-size:12px;color:var(--mc-muted)}.mc-secret-input input{width:100%;color:var(--mc-text)}.mc-field-note{font-size:11px;color:var(--mc-muted);margin:10px 0 0;overflow-wrap:anywhere}.mc-confirm{margin-top:12px;padding:12px;border:1px solid var(--mc-border);border-radius:8px;background:var(--mc-soft);display:flex;align-items:center;flex-wrap:wrap;gap:8px;font-size:12px}.mc-confirm p{flex-basis:100%;margin:0}.mc-note{font-size:12px;color:var(--mc-muted);margin:12px 0;overflow-wrap:anywhere}
|
|
11
|
+
.mc-test{margin-top:24px;padding-top:20px;border-top:1px solid var(--mc-border)}.mc-test-heading{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:12px}.mc-test-heading h4{margin:0;font-size:13px}.mc-test-heading time{font-size:11px;color:var(--mc-muted)}.mc-result{border-radius:9px;padding:12px 14px;background:var(--mc-tint);color:var(--mc-accent);font-size:12px}.mc-result[data-tone=error]{background:var(--mc-soft);color:var(--mc-danger)}.mc-result[data-tone=stale]{background:var(--mc-soft);color:var(--mc-muted)}.mc-result-title{display:flex;align-items:center;gap:7px;font-weight:600;font-size:13px}.mc-result p{margin:6px 0 0}.mc-result details{margin-top:9px}.mc-result summary{cursor:pointer}.mc-result pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:180px;overflow:auto;font:12px/1.6 ui-monospace,monospace}.mc-empty-test{font-size:12px;color:var(--mc-muted);margin:0}
|
|
12
|
+
.mc-form-footer{padding:16px 30px;border-top:1px solid var(--mc-border);background:var(--mc-bg);position:sticky;bottom:0;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.mc-form-footer button{font-size:13px}.mc-form-footer .mc-cancel{margin-left:auto}.mc-alert{margin:16px 30px 0;padding:12px 14px;border-radius:8px;font-size:12px;background:var(--mc-soft);color:var(--mc-danger);white-space:pre-wrap;overflow-wrap:anywhere}.mc-request-status{margin:0 0 18px;padding:12px 14px;border-radius:9px;background:var(--mc-soft);font-size:12px}.mc-request-status p{margin:4px 0 0;color:var(--mc-muted)}.mc-requests{padding:12px 20px;border-bottom:1px solid var(--mc-border);display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px}.mc-requests button{font-size:12px}.mc-pending-entry{font:inherit;font-size:12px;cursor:pointer;border:1px solid currentColor;border-radius:7px;padding:5px 9px;background:transparent;color:inherit}
|
|
13
|
+
.mc-activity{padding:14px 30px;background:var(--mc-soft);border-top:1px solid var(--mc-border)}.mc-activity-heading{font-size:12px;color:var(--mc-muted);margin:0 0 8px}.mc-activity-list{display:flex;gap:6px;flex-wrap:wrap}.mc-activity-list button{font-size:12px}.mc-activity-list button[aria-pressed=true]{border-color:var(--mc-accent);color:var(--mc-accent)}.mc-progress{font-size:12px;margin-top:10px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}.mc-progress p{margin:0}.mc-progress button{font-size:12px;margin-left:auto}.mc-operation-note{font-size:12px;margin-top:12px;color:var(--mc-muted)}.mc-operation-note p{margin:6px 0}.mc-operation-note[data-error=true]{color:var(--mc-danger)}.mc-empty{padding:64px 28px;text-align:center;color:var(--mc-muted);margin:auto}.mc-empty>svg{margin-bottom:10px;opacity:.65}.mc-empty h3{font-size:15px;color:var(--mc-text);margin:0 0 8px}.mc-empty p{font-size:12px;margin:0}.mc-loading{padding:18px 30px;font-size:12px;color:var(--mc-muted)}
|
|
14
|
+
@media(prefers-color-scheme:dark){.mc-dialog{--mc-bg:var(--dsw-alias-surface-primary,#182127);--mc-soft:var(--dsw-alias-interactive-bg-hover,#202d34);--mc-text:var(--dsw-alias-label-primary,#e4edf1);--mc-muted:var(--dsw-alias-label-secondary,#9baeb9);--mc-border:var(--dsw-alias-border-l2,#35464f);--mc-accent:#39b8a8;--mc-tint:#153d39;--mc-danger:#ef998b;--mc-warning:#d6b778}.mc-dialog button.mc-primary{color:#102a29}}
|
|
15
|
+
@media(max-width:700px){.mc-property{grid-template-columns:minmax(0,1fr);gap:5px;padding:12px 14px}}
|
|
16
|
+
@media(max-width:700px){.mc-dialog{width:calc(100vw - 16px);height:calc(100dvh - 16px);max-height:calc(100dvh - 16px);border-radius:12px}.mc-header{padding:16px;gap:10px}.mc-header-mark{display:none}.mc-header h2{font-size:18px}.mc-columns{display:flex;flex-direction:column;overflow:auto}.mc-nav{flex:none;padding:14px 16px;gap:14px;overflow:visible;border-right:0;border-bottom:1px solid var(--mc-border)}.mc-workspace-label{font-size:11px;margin-bottom:5px}.mc-nav select{padding:7px 10px}.mc-nav-heading{margin-bottom:5px}.mc-datasources{display:flex;overflow-x:auto;padding:2px;gap:6px}.mc-datasources li{flex:0 0 auto;max-width:240px}.mc-dialog .mc-datasource{padding:9px 10px}.mc-datasource-name{font-size:12px}.mc-main{overflow:visible;flex:1;flex-shrink:0}.mc-form-body{padding:22px 18px}.mc-detail-heading h3{font-size:20px}.mc-field{padding:14px}.mc-field-header{flex-wrap:wrap;gap:10px}.mc-field-actions{margin-left:auto}.mc-form-footer{padding:14px 18px;position:static}.mc-form-footer .mc-cancel{margin-left:0}.mc-alert{margin:14px 18px 0}.mc-activity{padding:14px 18px}.mc-test-heading{align-items:start;flex-wrap:wrap}.mc-close{align-self:start}.mc-empty{padding:32px 18px}.mc-requests{padding:12px 16px}}
|
|
17
|
+
`;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const styles = `
|
|
3
|
+
.marivo-workspace-header-action{display:inline-flex;flex:none;align-items:center;justify-content:center;gap:5px;height:32px;padding:6px 8px;border:0;border-radius:8px;background:transparent;color:inherit;font:inherit;font-size:12px;line-height:20px;white-space:nowrap;cursor:pointer}
|
|
4
|
+
.marivo-workspace-header-action:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#7b899414)}
|
|
5
|
+
.marivo-workspace-header-action:focus-visible{outline:2px solid var(--dsw-alias-label-primary,#087b70);outline-offset:2px}
|
|
6
|
+
.marivo-workspace-header-action:disabled{opacity:.45;cursor:default}
|
|
7
|
+
@media(max-width:640px){.marivo-workspace-header-action{width:32px;padding:8px}.marivo-workspace-header-action span{display:none}}
|
|
8
|
+
`;
|
|
9
|
+
export function WorkspaceHeaderAction({ label, icon, disabled, title, onClick, }) {
|
|
10
|
+
return (_jsxs(_Fragment, { children: [_jsx("style", { children: styles }), _jsxs("button", { className: "marivo-workspace-header-action", type: "button", title: title ?? label, "aria-label": `打开${label}`, disabled: disabled, onClick: onClick, children: [_jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: icon === 'semantic' ? (_jsx("path", { d: "m12 3 9 5-9 5-9-5 9-5Zm-9 9 9 5 9-5M3 16l9 5 9-5" })) : (_jsxs(_Fragment, { children: [_jsx("rect", { x: "4", y: "10", width: "16", height: "11", rx: "2" }), _jsx("path", { d: "M8 10V7a4 4 0 0 1 8 0v3m-4 5v2" })] })) }), _jsx("span", { children: label })] })] }));
|
|
11
|
+
}
|