@chengxianglibra/dsh-data-analysis 0.1.2 → 0.2.0
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 +136 -99
- package/cordis.patch.yml +1 -1
- package/lib/bin/environment.js +8 -6
- package/lib/client/credentials/changes.js +74 -0
- package/lib/client/credentials/create-datasource.js +126 -22
- package/lib/client/credentials/credential-draft.js +42 -0
- package/lib/client/credentials/defaults.js +11 -0
- package/lib/client/credentials/descriptions.js +46 -0
- package/lib/client/credentials/install.js +209 -81
- package/lib/client/credentials/model.js +323 -51
- package/lib/client/credentials/report-publishing.js +96 -0
- package/lib/client/credentials/styles.js +13 -9
- package/lib/client/i18n/context.js +22 -0
- package/lib/client/i18n/copy.js +57 -0
- package/lib/client/i18n/credentials.js +475 -0
- package/lib/client/i18n/host.js +27 -0
- package/lib/client/i18n/navigation.js +41 -0
- package/lib/client/i18n/presentation.js +577 -0
- package/lib/client/i18n/python.js +36 -0
- package/lib/client/i18n/semantic.js +441 -0
- package/lib/client/input-context.js +21 -0
- package/lib/client/python-tool/card.js +35 -0
- package/lib/client/python-tool/execution-error.js +35 -0
- package/lib/client/python-tool/install.js +9 -0
- package/lib/client/python-tool/model.js +101 -0
- package/lib/client/right-tabs/install.js +535 -0
- package/lib/client/right-tabs/live-delivery.js +58 -0
- package/lib/client/right-tabs/navigation.js +47 -0
- package/lib/client/right-tabs/page.js +178 -0
- package/lib/client/right-tabs/styles.js +11 -0
- package/lib/client/rpc.js +5 -0
- package/lib/client/semantic-reference.js +10 -0
- package/lib/client/workspace-header-action.js +14 -1
- package/lib/client/workspace-shortcuts.js +26 -0
- package/lib/client.js +365 -242
- package/lib/compatibility.js +1 -1
- package/lib/datasource/authoring.js +43 -4
- package/lib/datasource/bridge-programs.js +23 -20
- package/lib/datasource/bridge.js +46 -3
- package/lib/datasource/changes-contract.js +41 -0
- package/lib/datasource/changes.js +49 -0
- package/lib/datasource/configure.js +39 -0
- package/lib/datasource/defaults.js +25 -0
- package/lib/datasource/index.js +2 -1
- package/lib/datasource/python-options.js +21 -0
- package/lib/datasource/python.js +116 -25
- package/lib/datasource/rpc.js +75 -13
- package/lib/datasource/service.js +286 -11
- package/lib/datasource/test.js +2 -1
- package/lib/disclosure/activation.js +19 -7
- package/lib/disclosure/execution-guidance.js +52 -0
- package/lib/disclosure/help.js +4 -1
- package/lib/environment/runtime.js +35 -34
- package/lib/environment/workspace.js +18 -1
- package/lib/lifecycle.js +33 -0
- package/lib/plugin-agents.js +154 -0
- package/lib/plugin.js +94 -172
- package/lib/presentation/asset.js +34 -0
- package/lib/presentation/assets/portable.js +14 -14
- package/lib/presentation/assets/static.js +344 -73
- package/lib/presentation/build/index.js +3 -2
- package/lib/presentation/commit.js +19 -12
- package/lib/presentation/contracts/asset-path.js +9 -0
- package/lib/presentation/contracts/catalog.js +62 -0
- package/lib/presentation/contracts/charts.js +0 -23
- package/lib/presentation/contracts/index.js +17 -5
- package/lib/presentation/contracts/types.js +1 -1
- package/lib/presentation/delivery.js +45 -30
- package/lib/presentation/export-html.js +214 -0
- package/lib/presentation/files.js +4 -5
- package/lib/presentation/projection/index.js +2 -1
- package/lib/presentation/projection/program.js +2 -9
- package/lib/presentation/projection/sql-code.js +13 -13
- package/lib/presentation/reports.js +114 -17
- package/lib/presentation/rpc.js +96 -58
- package/lib/presentation/tool.js +6 -10
- package/lib/report-publishing/adapters.js +111 -0
- package/lib/report-publishing/config.js +69 -0
- package/lib/report-publishing/service.js +180 -0
- package/lib/rpc.js +49 -0
- package/lib/semantic-browser/contracts.js +17 -0
- package/lib/semantic-browser/program.js +10 -0
- package/lib/semantic-browser/service.js +40 -6
- package/lib/semantic-reference/bridge.js +10 -1
- package/lib/semantic-reference/contracts.js +20 -6
- package/lib/semantic-reference/environment.js +56 -0
- package/lib/semantic-reference/labels.js +16 -0
- package/lib/semantic-reference/rpc.js +39 -18
- package/lib/semantic-reference/search.js +5 -4
- package/lib/semantic-reference/usage.js +12 -3
- package/lib/tool-lifecycle.js +22 -0
- package/lib/types/client/credentials/changes.d.ts +9 -0
- package/lib/types/client/credentials/create-datasource.d.ts +3 -1
- package/lib/types/client/credentials/credential-draft.d.ts +14 -0
- package/lib/types/client/credentials/defaults.d.ts +2 -0
- package/lib/types/client/credentials/descriptions.d.ts +1 -0
- package/lib/types/client/credentials/install.d.ts +19 -1
- package/lib/types/client/credentials/model.d.ts +31 -11
- package/lib/types/client/credentials/report-publishing.d.ts +5 -0
- package/lib/types/client/credentials/styles.d.ts +1 -1
- package/lib/types/client/i18n/context.d.ts +17 -0
- package/lib/types/client/i18n/copy.d.ts +806 -0
- package/lib/types/client/i18n/credentials.d.ts +475 -0
- package/lib/types/client/i18n/host.d.ts +16 -0
- package/lib/types/client/i18n/navigation.d.ts +41 -0
- package/lib/types/client/i18n/presentation.d.ts +577 -0
- package/lib/types/client/i18n/python.d.ts +19 -0
- package/lib/types/client/i18n/semantic.d.ts +441 -0
- package/lib/types/client/input-context.d.ts +19 -0
- package/lib/types/client/presentation/ask-dsh.d.ts +4 -8
- package/lib/types/client/presentation/catalog-model.d.ts +24 -0
- package/lib/types/client/presentation/catalog.d.ts +20 -0
- package/lib/types/client/presentation/chart-tooltip.d.ts +2 -2
- package/lib/types/client/presentation/context-reference.d.ts +12 -0
- package/lib/types/client/presentation/copy-context.d.ts +2 -2
- package/lib/types/client/presentation/delivery-model.d.ts +27 -6
- package/lib/types/client/presentation/delivery.d.ts +8 -7
- package/lib/types/client/presentation/download.d.ts +2 -0
- package/lib/types/client/presentation/export-menu.d.ts +26 -0
- package/lib/types/client/presentation/export-view.d.ts +63 -0
- package/lib/types/client/presentation/host-entry.d.ts +8 -2
- package/lib/types/client/presentation/icons.d.ts +1 -1
- package/lib/types/client/presentation/model.d.ts +14 -15
- package/lib/types/client/presentation/reader.d.ts +15 -2
- package/lib/types/client/presentation/reference-source.d.ts +9 -0
- package/lib/types/client/presentation/source-code-model.d.ts +2 -1
- package/lib/types/client/presentation/source-code.d.ts +0 -5
- package/lib/types/client/presentation/source-dialog.d.ts +1 -2
- package/lib/types/client/presentation/sources.d.ts +5 -5
- package/lib/types/client/presentation/styles.d.ts +1 -1
- package/lib/types/client/presentation/table.d.ts +5 -1
- package/lib/types/client/python-tool/card.d.ts +2 -0
- package/lib/types/client/python-tool/execution-error.d.ts +3 -0
- package/lib/types/client/python-tool/install.d.ts +2 -0
- package/lib/types/client/python-tool/model.d.ts +20 -0
- package/lib/types/client/right-tabs/install.d.ts +18 -0
- package/lib/types/client/right-tabs/live-delivery.d.ts +8 -0
- package/lib/types/client/right-tabs/navigation.d.ts +17 -0
- package/lib/types/client/right-tabs/page.d.ts +36 -0
- package/lib/types/client/right-tabs/styles.d.ts +2 -0
- package/lib/types/client/rpc.d.ts +3 -0
- package/lib/types/client/semantic-reference.d.ts +4 -0
- package/lib/types/client/workspace-header-action.d.ts +1 -1
- package/lib/types/client/workspace-shortcuts.d.ts +15 -0
- package/lib/types/client.d.ts +6 -3
- package/lib/types/compatibility.d.ts +1 -1
- package/lib/types/datasource/authoring.d.ts +10 -0
- package/lib/types/datasource/bridge.d.ts +23 -2
- package/lib/types/datasource/changes-contract.d.ts +18 -0
- package/lib/types/datasource/changes.d.ts +15 -0
- package/lib/types/datasource/configure.d.ts +7 -0
- package/lib/types/datasource/defaults.d.ts +7 -0
- package/lib/types/datasource/index.d.ts +6 -1
- package/lib/types/datasource/python-options.d.ts +9 -0
- package/lib/types/datasource/python.d.ts +17 -2
- package/lib/types/datasource/rpc.d.ts +2 -1
- package/lib/types/datasource/service.d.ts +48 -5
- package/lib/types/datasource/test.d.ts +1 -1
- package/lib/types/disclosure/activation.d.ts +2 -1
- package/lib/types/disclosure/execution-guidance.d.ts +6 -0
- package/lib/types/disclosure/help.d.ts +1 -1
- package/lib/types/environment/types.d.ts +2 -1
- package/lib/types/environment/workspace.d.ts +1 -0
- package/lib/types/lifecycle.d.ts +8 -0
- package/lib/types/plugin-agents.d.ts +27 -0
- package/lib/types/plugin.d.ts +12 -28
- package/lib/types/presentation/asset.d.ts +6 -0
- package/lib/types/presentation/build/index.d.ts +7 -2
- package/lib/types/presentation/commit.d.ts +1 -1
- package/lib/types/presentation/contracts/asset-path.d.ts +2 -0
- package/lib/types/presentation/contracts/catalog.d.ts +27 -0
- package/lib/types/presentation/contracts/charts.d.ts +0 -2
- package/lib/types/presentation/contracts/types.d.ts +7 -4
- package/lib/types/presentation/delivery.d.ts +1 -1
- package/lib/types/presentation/export-html.d.ts +13 -0
- package/lib/types/presentation/reports.d.ts +6 -1
- package/lib/types/presentation/rpc.d.ts +3 -2
- package/lib/types/presentation/tool.d.ts +2 -2
- package/lib/types/report-publishing/adapters.d.ts +6 -0
- package/lib/types/report-publishing/config.d.ts +22 -0
- package/lib/types/report-publishing/service.d.ts +68 -0
- package/lib/types/rpc.d.ts +3 -0
- package/lib/types/semantic-browser/contracts.d.ts +7 -0
- package/lib/types/semantic-browser/service.d.ts +7 -1
- package/lib/types/semantic-reference/bridge.d.ts +1 -0
- package/lib/types/semantic-reference/contracts.d.ts +5 -2
- package/lib/types/semantic-reference/environment.d.ts +22 -0
- package/lib/types/semantic-reference/labels.d.ts +16 -0
- package/lib/types/semantic-reference/rpc.d.ts +1 -1
- package/lib/types/semantic-reference/search.d.ts +1 -1
- package/lib/types/tool-lifecycle.d.ts +4 -0
- package/lib/types/workspace-identity.d.ts +6 -0
- package/lib/workspace-identity.js +9 -0
- package/package.json +83 -61
- package/python/presentation-kit/dist/dsh_data_analysis_presentation_kit-1.1.0-py3-none-any.whl +0 -0
- package/skills/dsh-data-analysis-files/SKILL.md +32 -0
- package/skills/dsh-data-analysis-files/references/examples.md +93 -0
- package/skills/dsh-data-analysis-presentation/SKILL.md +10 -6
- package/skills/dsh-data-analysis-presentation/references/examples/artifact.draft.json +13 -4
- package/skills/dsh-data-analysis-presentation/references/examples/charts.draft.json +3 -2
- package/skills/dsh-data-analysis-presentation/references/examples/comparison.draft.json +3 -2
- package/skills/dsh-data-analysis-presentation/references/examples/computed-sources.draft.json +12 -5
- package/skills/dsh-data-analysis-presentation/references/examples/computed.draft.json +3 -2
- package/skills/dsh-data-analysis-presentation/references/examples/interaction.draft.json +3 -2
- package/skills/dsh-data-analysis-presentation/references/examples/source-only.draft.json +12 -4
- package/skills/dsh-data-analysis-presentation/references/examples.md +3 -1
- package/skills/dsh-data-analysis-presentation/references/export-html.md +7 -0
- package/skills/dsh-data-analysis-presentation/references/interaction.md +1 -1
- package/skills/dsh-data-analysis-presentation/references/narrative.md +1 -1
- package/skills/dsh-data-analysis-presentation/references/publishing.md +3 -0
- package/skills/dsh-data-analysis-presentation/references/schema.md +25 -1
- package/lib/types/client/presentation/install.d.ts +0 -15
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function credentialReference(name, draft) {
|
|
2
|
+
if (draft.reference !== undefined)
|
|
3
|
+
return draft.reference.trim();
|
|
4
|
+
if (!draft.value)
|
|
5
|
+
return draft.existing ?? '';
|
|
6
|
+
const part = (value) => value
|
|
7
|
+
.toUpperCase()
|
|
8
|
+
.replace(/[^A-Z0-9_]/g, '_')
|
|
9
|
+
.slice(0, 40);
|
|
10
|
+
return `DS_${part(name) || 'CONNECTION'}_${part(draft.key ?? draft.field.replace(/_env$/, ''))}_${draft.id.replace(/-/g, '').toUpperCase()}`;
|
|
11
|
+
}
|
|
12
|
+
/** Values are kept separate from the public configuration, then handed to the credential operation. */
|
|
13
|
+
export function prepareCredentials(name, drafts) {
|
|
14
|
+
const fields = {};
|
|
15
|
+
const changes = Object.create(null);
|
|
16
|
+
for (const draft of drafts) {
|
|
17
|
+
const ref = credentialReference(name, draft);
|
|
18
|
+
if (!ref && !draft.value)
|
|
19
|
+
continue;
|
|
20
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(ref) ||
|
|
21
|
+
ref.length > 256 ||
|
|
22
|
+
/^(MARIVO_|DSH_DATA_ANALYSIS_|DSH_HOME$|DSH_SESSION_ID$|DSH_SESSION_JSONL$|DSH_SHELL$)/i.test(ref))
|
|
23
|
+
throw new Error('marivo.credentials.credential-references-may-contain-only-letters-numbers-and-underscores');
|
|
24
|
+
if (draft.key !== undefined) {
|
|
25
|
+
if (!draft.key.trim())
|
|
26
|
+
throw new Error('marivo.credentials.enter-the-header-name-for-this-credential');
|
|
27
|
+
fields[draft.field] ??= Object.create(null);
|
|
28
|
+
const mapping = fields[draft.field];
|
|
29
|
+
if (Object.hasOwn(mapping, draft.key))
|
|
30
|
+
throw new Error('marivo.credentials.header-names-must-be-unique');
|
|
31
|
+
mapping[draft.key] = ref;
|
|
32
|
+
}
|
|
33
|
+
else
|
|
34
|
+
fields[draft.field] = ref;
|
|
35
|
+
if (draft.value) {
|
|
36
|
+
if (changes[ref] !== undefined && changes[ref] !== draft.value)
|
|
37
|
+
throw new Error('marivo.credentials.the-same-credential-reference-cannot-have-different-values');
|
|
38
|
+
changes[ref] = draft.value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { fields, changes };
|
|
42
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function creationFieldValues(schema, backend) {
|
|
2
|
+
const defaults = schema.creationDefaults?.[backend] ?? {};
|
|
3
|
+
return Object.fromEntries((schema.backends.find((item) => item.name === backend)?.fields ?? [])
|
|
4
|
+
.filter((field) => !field.name.endsWith('_env') && Object.hasOwn(defaults, field.name))
|
|
5
|
+
.map((field) => [
|
|
6
|
+
field.name,
|
|
7
|
+
field.type === 'string'
|
|
8
|
+
? defaults[field.name]
|
|
9
|
+
: JSON.stringify(defaults[field.name]),
|
|
10
|
+
]));
|
|
11
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Presentation-only translations of public Runtime descriptions, not a field schema.
|
|
2
|
+
// Match the complete source text so changed or newly added descriptions retain their meaning.
|
|
3
|
+
const descriptions = {
|
|
4
|
+
'Global datasource name; letters, digits, underscores, and hyphens only.': 'marivo.credentials.global-datasource-name-use-only-letters-numbers-underscores-and',
|
|
5
|
+
'Rare JSON-safe ibis keyword arguments not modeled by the typed class.': 'marivo.credentials.additional-connection-parameters-for-ibis-options-not-listed-in',
|
|
6
|
+
'DuckDB database path; defaults to in-memory.': 'marivo.credentials.duckdb-database-file-path-defaults-to-an-in-memory',
|
|
7
|
+
'SQLite database path; defaults to in-memory.': 'marivo.credentials.sqlite-database-file-path-defaults-to-an-in-memory',
|
|
8
|
+
'Open the DuckDB database in read-only mode.': 'marivo.credentials.open-the-duckdb-database-in-read-only-mode',
|
|
9
|
+
'Open the SQLite database in query-only mode.': 'marivo.credentials.open-the-sqlite-database-in-query-only-mode',
|
|
10
|
+
'Optional mapping from declared SQLite type names to Ibis type strings.': 'marivo.credentials.optional-mapping-from-sqlite-declared-type-names-to-ibis',
|
|
11
|
+
'Optional HTTP(S) URL prefix for scoped remote JSON auth.': 'marivo.credentials.optional-http-s-url-prefix-where-remote-json-requests',
|
|
12
|
+
'Environment variable for a scoped HTTP bearer token.': 'marivo.credentials.credential-reference-for-the-http-bearer-token-within-the',
|
|
13
|
+
'Optional custom HTTP header names mapped to secret environment variables.': 'marivo.credentials.optional-mapping-from-custom-http-header-names-to-credential',
|
|
14
|
+
'Trino coordinator host.': 'marivo.credentials.trino-coordinator-host-address',
|
|
15
|
+
'Trino catalog; mapped to ibis database at connect time.': 'marivo.credentials.trino-catalog-name-mapped-to-the-ibis-database-parameter',
|
|
16
|
+
'Required environment variable for the Trino user.': 'marivo.credentials.required-credential-reference-for-the-trino-username',
|
|
17
|
+
'Trino port; ibis default is 8080.': 'marivo.credentials.trino-port-ibis-defaults-to-8080',
|
|
18
|
+
'Optional default schema.': 'marivo.credentials.optional-default-schema-name',
|
|
19
|
+
'Optional client application/source tag.': 'marivo.credentials.optional-client-application-or-request-source-identifier',
|
|
20
|
+
'Optional engine session timezone.': 'marivo.credentials.optional-database-session-timezone',
|
|
21
|
+
"Set to 'https' for TLS.": 'marivo.credentials.enter-https-to-enable-tls-encryption',
|
|
22
|
+
'Optional Trino client tags.': 'marivo.credentials.optional-trino-client-tags-as-a-json-array',
|
|
23
|
+
'Optional Trino session properties.': 'marivo.credentials.optional-trino-session-properties-as-a-json-object',
|
|
24
|
+
'Environment variable for Trino auth token or password.': 'marivo.credentials.credential-reference-for-the-trino-token-or-password',
|
|
25
|
+
'MySQL host.': 'marivo.credentials.mysql-server-host-address',
|
|
26
|
+
'MySQL database name.': 'marivo.credentials.mysql-database-name',
|
|
27
|
+
'MySQL port; ibis default is 3306.': 'marivo.credentials.mysql-port-ibis-defaults-to-3306',
|
|
28
|
+
'Optional autocommit override.': 'marivo.credentials.optional-setting-for-automatic-transaction-commits',
|
|
29
|
+
'Environment variable for MySQL user.': 'marivo.credentials.credential-reference-for-the-mysql-username',
|
|
30
|
+
'Environment variable for MySQL password.': 'marivo.credentials.credential-reference-for-the-mysql-password',
|
|
31
|
+
'Postgres host.': 'marivo.credentials.postgresql-server-host-address',
|
|
32
|
+
'Postgres database name.': 'marivo.credentials.postgresql-database-name',
|
|
33
|
+
'Postgres port; ibis default is 5432.': 'marivo.credentials.postgresql-port-ibis-defaults-to-5432',
|
|
34
|
+
'Environment variable for Postgres user.': 'marivo.credentials.credential-reference-for-the-postgresql-username',
|
|
35
|
+
'Environment variable for Postgres password.': 'marivo.credentials.credential-reference-for-the-postgresql-password',
|
|
36
|
+
'ClickHouse host.': 'marivo.credentials.clickhouse-server-host-address',
|
|
37
|
+
'ClickHouse port; native default is 9000, secure default is 9440.': 'marivo.credentials.clickhouse-port-native-connections-default-to-9000-secure-connections',
|
|
38
|
+
"ClickHouse database; ibis default is 'default'.": 'marivo.credentials.clickhouse-database-name-ibis-defaults-to-default',
|
|
39
|
+
'Enable TLS for ClickHouse.': 'marivo.credentials.enable-tls-encryption-for-clickhouse',
|
|
40
|
+
'Optional ClickHouse settings map.': 'marivo.credentials.optional-clickhouse-settings-as-a-json-object',
|
|
41
|
+
'Environment variable for ClickHouse user.': 'marivo.credentials.credential-reference-for-the-clickhouse-username',
|
|
42
|
+
'Environment variable for ClickHouse password.': 'marivo.credentials.credential-reference-for-the-clickhouse-password',
|
|
43
|
+
};
|
|
44
|
+
export function datasourceDescription(description) {
|
|
45
|
+
return descriptions[description] ?? description;
|
|
46
|
+
}
|
|
@@ -1,47 +1,68 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState, useSyncExternalStore } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { useCopy } from "./../i18n/context.js";
|
|
4
|
+
import { localized } from "../i18n/host.js";
|
|
4
5
|
import { CreateDatasource } from "./create-datasource.js";
|
|
5
6
|
import { CredentialClientModel, credentialMessage } from "./model.js";
|
|
7
|
+
import { ReportPublishingCredentials } from "./report-publishing.js";
|
|
6
8
|
import { credentialStyles } from "./styles.js";
|
|
7
9
|
const statusLabels = {
|
|
8
|
-
'awaiting-input': '
|
|
9
|
-
executing: '
|
|
10
|
-
'awaiting-decision': '
|
|
11
|
-
succeeded: '
|
|
12
|
-
'handed-off': '
|
|
13
|
-
'call-ended': '
|
|
14
|
-
|
|
10
|
+
'awaiting-input': 'marivo.credentials.awaiting-input',
|
|
11
|
+
executing: 'marivo.credentials.saving-or-validating-77',
|
|
12
|
+
'awaiting-decision': 'marivo.credentials.connection-validation-failed-action-needed',
|
|
13
|
+
succeeded: 'marivo.credentials.validated-original-call-continues',
|
|
14
|
+
'handed-off': 'marivo.credentials.handed-to-the-assistant-for-investigation',
|
|
15
|
+
'call-ended': 'marivo.credentials.original-call-ended',
|
|
16
|
+
cancelled: 'marivo.credentials.configuration-request-cancelled',
|
|
17
|
+
'context-changed': 'marivo.credentials.context-changed',
|
|
15
18
|
};
|
|
16
|
-
function
|
|
17
|
-
return (_jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [name === 'database' && (_jsxs(_Fragment, { children: [_jsx("ellipse", { cx: "12", cy: "5", rx: "8", ry: "3" }), _jsx("path", { d: "M4 5v14c0 4 16 4 16 0V5M4 12c0 4 16 4 16 0" })] })), name === '
|
|
19
|
+
export function CredentialIcon({ name, size = 18 }) {
|
|
20
|
+
return (_jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [name === 'database' && (_jsxs(_Fragment, { children: [_jsx("ellipse", { cx: "12", cy: "5", rx: "8", ry: "3" }), _jsx("path", { d: "M4 5v14c0 4 16 4 16 0V5M4 12c0 4 16 4 16 0" })] })), name === 'refresh' && (_jsx("path", { d: "M20 7v5h-5M4 17v-5h5M6.1 6a8 8 0 0 1 13.4 3M4.5 15a8 8 0 0 0 13.4 3" })), name === 'add' && _jsx("path", { d: "M12 5v14M5 12h14" }), name === 'edit' && _jsx("path", { d: "m16 3 5 5L9 20l-6 1 1-6L16 3ZM13 6l5 5" }), name === 'delete' && _jsx("path", { d: "M3 6h18M9 6V3h6v3M5 6l1 15h12l1-15M10 10v7m4-7v7" }), name === 'test' && (_jsx("path", { d: "M9 3h6M10 3v6l-6 10a1.3 1.3 0 0 0 1 2h14a1.3 1.3 0 0 0 1-2L14 9V3M7 15h10" })), name === 'check' && _jsx("path", { d: "m5 12 4 4L19 6" }), name === 'info' && (_jsxs(_Fragment, { children: [_jsx("circle", { cx: "12", cy: "12", r: "9" }), _jsx("path", { d: "M12 11v6m0-10v.01" })] }))] }));
|
|
18
21
|
}
|
|
19
|
-
function TestResult({ result, stale = false }) {
|
|
22
|
+
export function TestResult({ result, stale = false }) {
|
|
23
|
+
const t = useCopy();
|
|
20
24
|
if (!result)
|
|
21
25
|
return null;
|
|
22
|
-
return (_jsxs("div", { className: "mc-result", "data-tone": stale ? 'stale' : result.ok ? 'success' : 'error', role: "status", children: [_jsxs("div", { className: "mc-result-title", children: [_jsx(
|
|
26
|
+
return (_jsxs("div", { className: "mc-result", "data-tone": t(stale ? 'stale' : result.ok ? 'success' : 'error'), role: "status", children: [_jsxs("div", { className: "mc-result-title", children: [_jsx(CredentialIcon, { name: stale || !result.ok ? 'info' : 'check', size: 16 }), stale
|
|
27
|
+
? t('marivo.credentials.configuration-changed-test-again')
|
|
28
|
+
: result.ok
|
|
29
|
+
? t('marivo.credentials.connection-test-succeeded')
|
|
30
|
+
: t('marivo.credentials.connection-test-failed')] }), !result.ok && !stale && (_jsxs(_Fragment, { children: [_jsx("p", { children: t(result.failure?.message) }), result.repair?.action && _jsx("p", { children: result.repair.action }), result.failure?.code && (_jsxs("details", { children: [_jsx("summary", { children: t('marivo.credentials.show-error-code') }), _jsx("pre", { children: result.failure.code })] }))] }))] }));
|
|
23
31
|
}
|
|
24
32
|
function OperationOutcome({ entry }) {
|
|
33
|
+
const t = useCopy();
|
|
25
34
|
if (!entry)
|
|
26
35
|
return null;
|
|
27
36
|
const operation = entry.operation;
|
|
28
37
|
const errors = operation?.errors ?? [];
|
|
38
|
+
if (operation?.action === 'delete-datasource')
|
|
39
|
+
return (_jsxs("div", { className: "mc-operation-note", "data-error": operation.status !== 'succeeded', role: "status", children: [_jsx("p", { children: operation.datasourceRemoved
|
|
40
|
+
? t('marivo.credentials.datasource-value-was-deleted', { p0: entry.name })
|
|
41
|
+
: t('marivo.credentials.deletion-of-datasource-value-is-unconfirmed-refresh-the-list', {
|
|
42
|
+
p0: entry.name,
|
|
43
|
+
}) }), operation.datasourceRemoved && !operation.deleteCredentials && (_jsx("p", { children: t('marivo.credentials.associated-saved-credentials-were-retained') })), operation.deletedCredentials?.length > 0 && (_jsxs("p", { children: [t('marivo.credentials.deleted-credentials'), operation.deletedCredentials.join('、'), "\u3002"] })), operation.credentialDeleteFailures?.length > 0 && (_jsxs("p", { children: [t('marivo.credentials.credentials-that-could-not-be-deleted'), operation.credentialDeleteFailures.join('、'), "\u3002"] })), operation.status === 'cancelled' && (_jsx("p", { children: t('marivo.credentials.operation-cancelled-completed-deletions-remain-other-credentials-may-still') })), errors.length > 0 && _jsx("p", { children: errors.map(credentialMessage).join(' ') })] }));
|
|
29
44
|
const unsuccessful = entry.error ||
|
|
30
45
|
operation?.status === 'cancelled' ||
|
|
31
46
|
operation?.status === 'failed' ||
|
|
32
47
|
operation?.result?.ok === false;
|
|
33
48
|
if (!unsuccessful && operation?.action !== 'delete')
|
|
34
49
|
return null;
|
|
35
|
-
return (_jsxs("div", { className: "mc-operation-note", "data-error": Boolean(entry.error || errors.length), role: "status", children: [entry.error && _jsx("p", { children: entry.error }), operation?.status === 'cancelled' && _jsx("p", { children:
|
|
50
|
+
return (_jsxs("div", { className: "mc-operation-note", "data-error": t(Boolean(entry.error || errors.length)), role: "status", children: [entry.error && _jsx("p", { children: t(entry.error) }), operation?.status === 'cancelled' && (_jsx("p", { children: t('marivo.credentials.this-operation-was-cancelled') })), operation?.status === 'succeeded' && operation.action === 'delete' && (_jsx("p", { children: t('marivo.credentials.saved-value-deleted-configuration-status-updated') })), errors.length > 0 && _jsx("p", { children: errors.map(credentialMessage).join(' ') }), operation?.status === 'failed' && errors.length === 0 && !operation.result && (_jsx("p", { children: t('marivo.credentials.operation-incomplete-please-retry') })), unsuccessful && operation?.saved.length > 0 && (_jsxs("p", { children: [t('marivo.credentials.saved'), operation.saved.join('、'), "\u3002"] }))] }));
|
|
36
51
|
}
|
|
37
|
-
function DatasourceProperties({ context }) {
|
|
52
|
+
export function DatasourceProperties({ context }) {
|
|
53
|
+
const t = useCopy();
|
|
38
54
|
const properties = Object.entries(context.properties ?? {});
|
|
39
|
-
return (_jsxs("section", { className: "mc-properties", "aria-label":
|
|
55
|
+
return (_jsxs("section", { className: "mc-properties", "aria-label": t('marivo.credentials.datasource-properties'), children: [_jsx("h4", { className: "mc-section-heading", children: t('marivo.credentials.datasource-properties') }), _jsxs("dl", { className: "mc-property-list", children: [_jsxs("div", { className: "mc-property", children: [_jsx("dt", { children: t('marivo.credentials.engine') }), _jsx("dd", { children: context.backend || t('marivo.credentials.not-provided') })] }), properties.map(([field, value]) => (_jsxs("div", { className: "mc-property", children: [_jsx("dt", { children: field }), _jsx("dd", { children: value !== null && typeof value === 'object' ? (_jsx("section", { className: "mc-property-json",
|
|
56
|
+
// biome-ignore lint/a11y/noNoninteractiveTabindex: Keyboard users must be able to scroll long JSON values.
|
|
57
|
+
tabIndex: 0, "aria-label": t('marivo.credentials.value-configuration-value', { p0: field }), children: _jsx("pre", { children: JSON.stringify(value, null, 2) }) })) : (_jsx("span", { children: typeof value === 'string' && value !== '' ? value : JSON.stringify(value) })) })] }, field)))] })] }));
|
|
40
58
|
}
|
|
41
|
-
function CredentialForm({ context, request, state, model, workspaceId }) {
|
|
59
|
+
function CredentialForm({ context, request, state, model, workspaceId, onEdit }) {
|
|
60
|
+
const t = useCopy();
|
|
42
61
|
const [values, setValues] = useState({});
|
|
43
62
|
const [editing, setEditing] = useState({});
|
|
44
63
|
const [deleting, setDeleting] = useState('');
|
|
64
|
+
const [removingDatasource, setRemovingDatasource] = useState(false);
|
|
65
|
+
const [removeCredentials, setRemoveCredentials] = useState(false);
|
|
45
66
|
const busy = request?.status === 'executing' ||
|
|
46
67
|
state.operations.some((entry) => entry.handle.scope === context.token);
|
|
47
68
|
const ended = request?.endedAt !== undefined;
|
|
@@ -57,6 +78,8 @@ function CredentialForm({ context, request, state, model, workspaceId }) {
|
|
|
57
78
|
setValues({});
|
|
58
79
|
setEditing({});
|
|
59
80
|
setDeleting('');
|
|
81
|
+
setRemovingDatasource(false);
|
|
82
|
+
setRemoveCredentials(false);
|
|
60
83
|
}, [context.token, context.version]);
|
|
61
84
|
const saveReference = (ref) => {
|
|
62
85
|
const changes = { [ref]: values[ref] };
|
|
@@ -70,91 +93,183 @@ function CredentialForm({ context, request, state, model, workspaceId }) {
|
|
|
70
93
|
setEditing({});
|
|
71
94
|
void model.start(context, request ? 'submit' : 'update', changes);
|
|
72
95
|
};
|
|
73
|
-
return (_jsxs("section", { className: "mc-form", "aria-label":
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
96
|
+
return (_jsxs("section", { className: "mc-form", "aria-label": t('marivo.credentials.value-credential-configuration', { p0: context.name }), children: [_jsxs("div", { className: "mc-form-body", children: [_jsxs("div", { className: "mc-detail-heading mc-datasource-heading", children: [_jsx("p", { className: "mc-eyebrow", children: t('marivo.credentials.datasource-configuration') }), _jsxs("div", { className: "mc-name-row", children: [_jsx("h3", { children: context.name }), _jsxs("div", { className: "mc-heading-actions", children: [_jsxs("span", { className: "mc-badge", "data-ready": ready, children: [ready && _jsx(CredentialIcon, { name: "check", size: 13 }), context.refs.length === 0
|
|
97
|
+
? t('marivo.credentials.no-credentials-required')
|
|
98
|
+
: ready
|
|
99
|
+
? t('marivo.credentials.all-credentials-configured')
|
|
100
|
+
: t('marivo.credentials.value-value-configured', {
|
|
101
|
+
p0: configured,
|
|
102
|
+
p1: context.refs.length,
|
|
103
|
+
})] }), !ended && (_jsx("button", { className: "mc-icon-button", type: "button", title: t('marivo.credentials.edit-configuration'), "aria-label": t('marivo.credentials.edit-configuration'), disabled: busy, onClick: onEdit, children: _jsx(CredentialIcon, { name: "edit" }) })), !request && (_jsx("button", { className: "mc-icon-button mc-danger", type: "button", title: t('marivo.credentials.delete-datasource'), "aria-label": t('marivo.credentials.delete-datasource'), disabled: busy || state.loading, onClick: () => setRemovingDatasource(true), children: _jsx(CredentialIcon, { name: "delete" }) }))] })] })] }), removingDatasource && (_jsxs("fieldset", { className: "mc-confirm", "aria-label": t('marivo.credentials.confirm-datasource-deletion'), children: [_jsxs("p", { children: [t('marivo.credentials.confirm-datasource-deletion'), context.name, t('marivo.credentials.this-removes-the-datasource-definition-from-this-workspace-not')] }), context.refs.length > 0 && (_jsxs(_Fragment, { children: [_jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: removeCredentials, disabled: busy, onChange: (event) => setRemoveCredentials(event.target.checked) }), ' ', t('marivo.credentials.also-delete-associated-saved-credentials')] }), _jsxs("p", { children: [t('marivo.credentials.credential-references'), context.refs.join('、'), t('marivo.credentials.other-datasources-or-workspaces-may-share-these-credentials-and')] })] })), _jsx("button", { className: "mc-danger", type: "button", disabled: busy || state.loading, onClick: () => {
|
|
104
|
+
setRemovingDatasource(false);
|
|
105
|
+
void model.start(context, 'delete-datasource', {}, undefined, removeCredentials);
|
|
106
|
+
}, children: t('marivo.credentials.confirm-datasource-deletion') }), _jsx("button", { type: "button", disabled: busy, onClick: () => {
|
|
107
|
+
setRemovingDatasource(false);
|
|
108
|
+
setRemoveCredentials(false);
|
|
109
|
+
}, children: t('marivo.credentials.cancel') })] })), request && (_jsxs("div", { className: "mc-request-status", role: "status", children: [_jsx("strong", { children: t(statusLabels[request.status]) }), !ended && (_jsx("p", { children: t('marivo.credentials.continue-the-current-task-after-successful-validation') })), (request.status === 'call-ended' || request.status === 'context-changed') && (_jsx("p", { children: t('marivo.credentials.start-the-task-again') }))] })), _jsx(DatasourceProperties, { context: context }), _jsx("h4", { className: "mc-section-heading", children: t('marivo.credentials.credentials') }), context.refs.length === 0 && (_jsx("p", { className: "mc-note", children: t('marivo.credentials.this-datasource-has-no-credential-references-you-can-test') })), context.refs.length > 0 && (_jsx("div", { className: "mc-fields", children: context.refs.map((ref) => {
|
|
78
110
|
const info = context.credentials[ref];
|
|
79
111
|
const shared = state.datasources
|
|
80
112
|
.filter((item) => item.refs.includes(ref))
|
|
81
113
|
.map((item) => item.name);
|
|
82
|
-
return (_jsxs("fieldset", { className: "mc-field", disabled: busy || ended, "aria-label": ref, children: [_jsxs("div", { className: "mc-field-header", children: [_jsxs("div", { className: "mc-field-title", children: [_jsx("h4", { children: ref }), _jsxs("p", { children: [
|
|
114
|
+
return (_jsxs("fieldset", { className: "mc-field", disabled: busy || ended, "aria-label": ref, children: [_jsxs("div", { className: "mc-field-header", children: [_jsxs("div", { className: "mc-field-title", children: [_jsx("h4", { children: ref }), _jsxs("p", { children: [t('marivo.credentials.field'), Object.entries(context.fields)
|
|
83
115
|
.filter(([, value]) => value === ref)
|
|
84
116
|
.map(([field]) => field)
|
|
85
|
-
.join('、'), ' ',
|
|
117
|
+
.join('、'), ' ', t('marivo.credentials.source'), info?.source ?? t('marivo.credentials.none'), !info?.writable && t('marivo.credentials.read-only-source')] })] }), _jsxs("div", { className: "mc-field-actions", children: [_jsx("span", { className: "mc-badge", "data-ready": Boolean(info?.configured), children: info?.configured
|
|
118
|
+
? t('marivo.credentials.configured')
|
|
119
|
+
: t('marivo.credentials.not-configured') }), info?.writable && info.configured && !editing[ref] && (_jsx("button", { type: "button", onClick: () => setEditing({ ...editing, [ref]: true }), children: t('marivo.credentials.replace') })), info?.writable && info.configured && editing[ref] && (_jsx("button", { type: "button", onClick: () => {
|
|
86
120
|
setValues({ ...values, [ref]: '' });
|
|
87
121
|
setEditing({ ...editing, [ref]: false });
|
|
88
|
-
}, children:
|
|
122
|
+
}, children: t('marivo.credentials.cancel-replacement') })), info?.writable && !request && info.configured && (_jsx("button", { className: "mc-danger", type: "button", onClick: () => setDeleting(ref), children: t('marivo.credentials.delete-saved-value') }))] })] }), info?.writable && (!info.configured || editing[ref]) && (_jsxs("label", { className: "mc-secret-input", children: [t('marivo.credentials.new-value'), _jsx("input", { type: "password", autoComplete: "new-password", placeholder: t('marivo.credentials.enter-credential-value-127'), value: values[ref] ?? '', onChange: (event) => setValues({ ...values, [ref]: event.target.value }) }), !request && (_jsx("button", { type: "button", className: "mc-primary", disabled: !values[ref], onClick: () => saveReference(ref), children: info.configured
|
|
123
|
+
? t('marivo.credentials.confirm-replacement')
|
|
124
|
+
: t('marivo.credentials.add-credential') }))] })), shared.length > 1 && (_jsxs("p", { className: "mc-field-note", children: [t('marivo.credentials.and'), shared.filter((name) => name !== context.name).join('、'), ' ', t('marivo.credentials.share-this-reference')] })), deleting === ref && (_jsxs("div", { className: "mc-confirm", children: [_jsxs("p", { children: [t('marivo.credentials.confirm-deletion-of'), ref, " ", t('marivo.credentials.the-saved-value')] }), _jsx("button", { className: "mc-danger", type: "button", onClick: () => {
|
|
89
125
|
setDeleting('');
|
|
90
126
|
void model.start(context, 'delete', {}, ref);
|
|
91
|
-
}, children:
|
|
92
|
-
}) })), _jsxs("div", { className: "mc-test", children: [_jsxs("div", { className: "mc-test-heading", children: [_jsx("h4", { children:
|
|
127
|
+
}, children: t('marivo.credentials.confirm-saved-value-deletion') }), _jsx("button", { type: "button", onClick: () => setDeleting(''), children: t('marivo.credentials.keep') })] }))] }, ref));
|
|
128
|
+
}) })), _jsxs("div", { className: "mc-test", children: [_jsxs("div", { className: "mc-test-heading", children: [_jsx("h4", { children: t('marivo.credentials.connection-status') }), _jsxs("div", { className: "mc-heading-actions", children: [latestTest?.at !== undefined && (_jsxs("time", { dateTime: new Date(latestTest.at).toISOString(), children: [t('marivo.credentials.last-test'), new Date(latestTest.at).toLocaleString()] })), !request && (_jsx("button", { className: "mc-icon-button", type: "button", title: t('marivo.credentials.test-connection'), "aria-label": t('marivo.credentials.test-connection'), disabled: busy, onClick: () => void model.start(context, 'test'), children: _jsx(CredentialIcon, { name: "test" }) }))] })] }), latestResult ? (_jsx(TestResult, { result: latestResult, stale: !request?.failure && latestTest?.stale })) : (_jsx("p", { className: "mc-empty-test", children: t('marivo.credentials.connection-has-not-been-tested') })), outcome?.operation?.action !== 'delete-datasource' && (_jsx(OperationOutcome, { entry: outcome }))] })] }), !ended && (request || busy) && (_jsxs("div", { className: "mc-form-footer", children: [request && (_jsx("button", { className: "mc-primary", type: "button", disabled: busy, onClick: submit, children: t('marivo.credentials.submit-credentials-and-continue') })), request && (_jsx("button", { type: "button", disabled: busy, onClick: () => void model.start(context, 'submit'), children: t('marivo.credentials.validate-existing-configuration-and-continue') })), request?.failure && (_jsx("button", { type: "button", disabled: busy, onClick: () => void model.start(context, 'diagnose'), children: t('marivo.credentials.ask-the-assistant-to-investigate') })), request ? (_jsx("button", { className: "mc-quiet mc-cancel", type: "button", onClick: () => void model.cancelRequest(request.id), children: t('marivo.credentials.cancel-this-round') })) : (busy && (_jsx("button", { className: "mc-quiet mc-cancel", type: "button", onClick: () => void model.cancelOperation(context.token), children: t('marivo.credentials.cancel-operation') })))] })), ended && (_jsx("div", { className: "mc-form-footer", children: _jsx("button", { type: "button", onClick: () => model.show(workspaceId), children: t('marivo.credentials.back-to-datasource-management') }) }))] }));
|
|
93
129
|
}
|
|
94
|
-
function CredentialPanel({ model, workspaces }) {
|
|
130
|
+
export function CredentialPanel({ model, workspaces, onRefresh }) {
|
|
131
|
+
const t = useCopy();
|
|
95
132
|
const state = useSyncExternalStore(model.subscribe, model.getSnapshot);
|
|
96
|
-
const dialog = useRef(null);
|
|
97
133
|
const columns = useRef(null);
|
|
134
|
+
const navigation = useRef(null);
|
|
98
135
|
const main = useRef(null);
|
|
99
136
|
const [creating, setCreating] = useState(false);
|
|
137
|
+
const [editingName, setEditingName] = useState('');
|
|
138
|
+
const [requestError, setRequestError] = useState('');
|
|
139
|
+
const [requestChoice, setRequestChoice] = useState('create');
|
|
100
140
|
// biome-ignore lint/correctness/useExhaustiveDependencies: Switching context discards the creation form.
|
|
101
|
-
useEffect(() => setCreating(false), [state.open, state.workspaceId, state.requestId]);
|
|
102
141
|
useEffect(() => {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}, [state.open]);
|
|
142
|
+
setCreating(false);
|
|
143
|
+
setEditingName('');
|
|
144
|
+
setRequestError('');
|
|
145
|
+
setRequestChoice('create');
|
|
146
|
+
}, [state.open, state.workspaceId, state.requestId]);
|
|
108
147
|
const request = state.requests.find((item) => item.id === state.requestId);
|
|
148
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: Open the initial form once per request occurrence; live watch updates must preserve user navigation.
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
if (!request?.configuration || request.context || request.endedAt !== undefined)
|
|
151
|
+
return;
|
|
152
|
+
setCreating(true);
|
|
153
|
+
setEditingName(request.configuration.mode === 'edit' ? request.configuration.name : '');
|
|
154
|
+
}, [request?.id, state.open]);
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
if (request?.endedAt === undefined)
|
|
157
|
+
return;
|
|
158
|
+
setCreating(false);
|
|
159
|
+
setEditingName('');
|
|
160
|
+
}, [request?.endedAt]);
|
|
109
161
|
const pending = state.requests.filter((item) => item.endedAt === undefined && item.sessionId === state.sessionId);
|
|
110
|
-
const context = request
|
|
162
|
+
const context = request
|
|
163
|
+
? request.context
|
|
164
|
+
: state.datasources.find((item) => item.token === state.selected);
|
|
111
165
|
// biome-ignore lint/correctness/useExhaustiveDependencies: A different detail or creation page starts at the top of its content.
|
|
112
166
|
useEffect(() => {
|
|
113
|
-
if (main.current)
|
|
167
|
+
if (main.current) {
|
|
114
168
|
main.current.scrollTop = 0;
|
|
169
|
+
const page = main.current.closest('.rt-page');
|
|
170
|
+
if (page)
|
|
171
|
+
page.scrollTop = 0;
|
|
172
|
+
}
|
|
115
173
|
if (columns.current)
|
|
116
174
|
columns.current.scrollTop = 0;
|
|
175
|
+
const list = navigation.current;
|
|
176
|
+
const selected = list?.querySelector('[aria-pressed="true"]');
|
|
177
|
+
if (selected) {
|
|
178
|
+
const bounds = selected.getBoundingClientRect();
|
|
179
|
+
const viewport = list.getBoundingClientRect();
|
|
180
|
+
if (bounds.left < viewport.left)
|
|
181
|
+
list.scrollLeft += bounds.left - viewport.left;
|
|
182
|
+
else if (bounds.right > viewport.right)
|
|
183
|
+
list.scrollLeft += bounds.right - viewport.right;
|
|
184
|
+
}
|
|
117
185
|
}, [creating, context?.token]);
|
|
118
186
|
const workspaceId = request
|
|
119
187
|
? (workspaces.find((item) => item.sessionIds.includes(request.sessionId))?.workspaceId ?? '')
|
|
120
188
|
: state.workspaceId;
|
|
121
|
-
const datasources = request ? [request.context] : state.datasources;
|
|
189
|
+
const datasources = request ? (request.context ? [request.context] : []) : state.datasources;
|
|
122
190
|
const operations = state.operations.filter((entry) => entry.workspaceId === workspaceId);
|
|
123
191
|
const activeOperation = operations.find((entry) => entry.handle.id === state.handle?.id)?.operation;
|
|
124
192
|
if (!state.open)
|
|
125
193
|
return null;
|
|
126
|
-
return (_jsxs("
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
194
|
+
return (_jsxs("section", { className: "mc-panel", "aria-label": t('marivo.credentials.datasources-and-credentials'), children: [_jsx("style", { children: credentialStyles }), _jsxs("div", { className: "rt-heading-row", children: [_jsx("h2", { className: "rt-heading", children: t('marivo.credentials.datasources-and-credentials') }), _jsxs("div", { className: "mc-heading-actions", children: [!request && (_jsx("button", { className: "mc-icon-button", type: "button", title: t('marivo.credentials.add-datasource'), "aria-label": t('marivo.credentials.add-datasource'), disabled: !workspaceId || state.loading, onClick: () => {
|
|
195
|
+
setEditingName('');
|
|
196
|
+
setCreating(true);
|
|
197
|
+
}, children: _jsx(CredentialIcon, { name: "add" }) })), _jsx("button", { className: "mc-icon-button", type: "button", title: t('marivo.credentials.refresh-datasources'), "aria-label": t('marivo.credentials.refresh-datasources'), disabled: state.loading, onClick: onRefresh ?? (() => void model.refreshDatasources()), children: _jsx(CredentialIcon, { name: "refresh" }) })] })] }), _jsx("p", { className: "rt-caption", children: workspaces.find((item) => item.workspaceId === workspaceId)?.title ?? workspaceId }), _jsxs("div", { className: "mc-shell", children: [(pending.length > 0 || request) && (_jsxs("div", { className: "mc-requests", children: [_jsx("span", { children: pending.length
|
|
198
|
+
? t('marivo.credentials.requests-in-this-session')
|
|
199
|
+
: t('marivo.credentials.configuration-result') }), pending.map((item) => (_jsxs("button", { type: "button", onClick: () => model.openRequest(item.id), children: [item.context?.name ??
|
|
200
|
+
item.configuration?.name ??
|
|
201
|
+
t('marivo.credentials.add-datasource'), ' ', "\u00B7 ", t(statusLabels[item.status])] }, item.id))), request && (_jsx("button", { className: "mc-quiet", type: "button", onClick: () => model.show(workspaceId), children: t('marivo.credentials.datasource-management') }))] })), _jsxs("div", { className: "mc-columns", ref: columns, children: [!request && (_jsx("aside", { className: "mc-nav", "aria-label": t('marivo.credentials.datasource-navigation'), children: _jsxs("div", { children: [_jsx("div", { className: "mc-nav-heading", children: _jsx("h3", { children: request
|
|
202
|
+
? t('marivo.credentials.requested-datasource')
|
|
203
|
+
: t('marivo.credentials.datasource-value', { p0: datasources.length }) }) }), _jsx("ul", { className: "mc-datasources", ref: navigation, children: datasources.map((item) => {
|
|
204
|
+
const count = item.refs.filter((ref) => item.credentials[ref]?.configured).length;
|
|
205
|
+
const ready = count === item.refs.length;
|
|
206
|
+
const running = state.operations.some((entry) => entry.handle.scope === item.token);
|
|
207
|
+
return (_jsx("li", { children: _jsxs("button", { className: "mc-datasource", type: "button", "aria-label": t('marivo.credentials.select-datasource-value', {
|
|
208
|
+
p0: item.name,
|
|
209
|
+
}), "aria-pressed": !creating && context?.token === item.token, onClick: () => {
|
|
210
|
+
if (request)
|
|
211
|
+
model.openRequest(request.id);
|
|
212
|
+
else {
|
|
213
|
+
setCreating(false);
|
|
214
|
+
model.select(item.token);
|
|
215
|
+
}
|
|
216
|
+
}, children: [_jsx(CredentialIcon, { name: "database" }), _jsxs("span", { className: "mc-datasource-copy", children: [_jsx("span", { className: "mc-datasource-name", children: item.name }), _jsxs("span", { className: "mc-datasource-status", children: [_jsx("span", { className: "mc-dot", "data-ready": ready }), running
|
|
217
|
+
? t('marivo.credentials.processing')
|
|
218
|
+
: item.refs.length === 0
|
|
219
|
+
? t('marivo.credentials.no-credentials-required')
|
|
220
|
+
: ready
|
|
221
|
+
? t('marivo.credentials.all-credentials-configured')
|
|
222
|
+
: t('marivo.credentials.value-value-configured', {
|
|
223
|
+
p0: count,
|
|
224
|
+
p1: item.refs.length,
|
|
225
|
+
})] })] })] }) }, item.token));
|
|
226
|
+
}) })] }) })), _jsxs("main", { className: "mc-main", ref: main, children: [Object.values(state.outcomes)
|
|
227
|
+
.filter((entry) => entry.workspaceId === workspaceId &&
|
|
228
|
+
entry.operation?.action === 'delete-datasource')
|
|
229
|
+
.map((entry) => (_jsxs("div", { className: "mc-request-status", children: [_jsx(OperationOutcome, { entry: entry }), _jsx("button", { type: "button", onClick: () => model.dismissOutcome(entry.handle.scope), children: t('marivo.credentials.dismiss-deletion-result') })] }, entry.handle.id))), state.error && (_jsx("p", { role: "alert", className: "mc-alert", children: t(state.error) })), state.loading && (_jsx("p", { className: "mc-loading", role: "status", children: t('marivo.credentials.loading-datasources-and-credential-status') })), !request && !creating && !state.loading && !context && !state.error && (_jsxs("div", { className: "mc-empty", children: [_jsx(CredentialIcon, { name: "database", size: 32 }), _jsx("h3", { children: !state.workspaceId
|
|
230
|
+
? t('marivo.credentials.this-session-is-not-bound-to-a-workspace')
|
|
149
231
|
: state.datasources.length === 0
|
|
150
|
-
? '
|
|
151
|
-
: '
|
|
152
|
-
? '
|
|
232
|
+
? t('marivo.credentials.no-datasources')
|
|
233
|
+
: t('marivo.credentials.select-a-datasource') }), _jsx("p", { children: !state.workspaceId
|
|
234
|
+
? t('marivo.credentials.return-to-the-session-and-retry')
|
|
153
235
|
: state.datasources.length === 0
|
|
154
|
-
? '
|
|
155
|
-
: '
|
|
236
|
+
? t('marivo.credentials.this-workspace-has-no-defined-datasources')
|
|
237
|
+
: t('marivo.credentials.view-credential-configuration-and-the-latest-connection-test') })] })), request?.configuration && (_jsxs("section", { className: "mc-request-status", "aria-label": t('marivo.credentials.configuration-request'), children: [_jsxs("div", { className: "mc-request-heading", children: [_jsx("h3", { children: t('marivo.credentials.configure-a-datasource-to-continue') }), _jsx("span", { className: "mc-badge", role: "status", children: t(statusLabels[request.status]) }), request.endedAt === undefined && (_jsx("button", { className: "mc-quiet", type: "button", onClick: () => void model.cancelRequest(request.id), children: t('marivo.credentials.cancel-configuration-request') }))] }), _jsxs("details", { className: "mc-request-reason", children: [_jsx("summary", { children: t('marivo.credentials.show-assistant-request-details') }), _jsx("p", { children: t(request.configuration.reason) })] }), requestError && _jsx("p", { role: "alert", children: t(requestError) }), request.endedAt === undefined && request.status !== 'executing' && (_jsxs(_Fragment, { children: [request.configuration.mode === 'create' && !context && (_jsxs(_Fragment, { children: [_jsxs("fieldset", { className: "mc-request-choice", "aria-label": t('marivo.credentials.configuration-method'), children: [_jsx("button", { type: "button", "aria-pressed": requestChoice === 'create', onClick: () => {
|
|
238
|
+
setRequestChoice('create');
|
|
239
|
+
setCreating(true);
|
|
240
|
+
setEditingName('');
|
|
241
|
+
setRequestError('');
|
|
242
|
+
}, children: t('marivo.credentials.add-datasource') }), _jsx("button", { type: "button", "aria-pressed": requestChoice === 'existing', onClick: () => {
|
|
243
|
+
setRequestChoice('existing');
|
|
244
|
+
setCreating(false);
|
|
245
|
+
setEditingName('');
|
|
246
|
+
setRequestError('');
|
|
247
|
+
}, children: t('marivo.credentials.use-an-existing-datasource') })] }), requestChoice === 'existing' && (_jsxs("div", { className: "mc-existing-source", children: [_jsx("p", { children: t('marivo.credentials.if-an-existing-connection-can-access-the-target-table') }), _jsxs("label", { className: "mc-secret-input", children: [t('marivo.credentials.select-an-existing-datasource'), _jsxs("select", { "aria-label": t('marivo.credentials.select-an-existing-datasource'), value: "", onChange: async (event) => {
|
|
248
|
+
if (!event.target.value)
|
|
249
|
+
return;
|
|
250
|
+
try {
|
|
251
|
+
await model.selectConfiguration(workspaceId, request.id, event.target.value);
|
|
252
|
+
setCreating(false);
|
|
253
|
+
setEditingName('');
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
setRequestError(error.message);
|
|
257
|
+
}
|
|
258
|
+
}, children: [_jsx("option", { value: "", children: t('marivo.credentials.please-select') }), state.datasources.map((item) => (_jsx("option", { value: item.name, children: item.name }, item.name)))] })] }), state.datasources.length === 0 && (_jsx("p", { children: t('marivo.credentials.no-reusable-datasource-is-available-switch-to-add-datasource') }))] }))] })), !creating &&
|
|
259
|
+
!context &&
|
|
260
|
+
(request.configuration.mode === 'edit' || requestChoice === 'create') && (_jsx("button", { type: "button", onClick: () => {
|
|
261
|
+
setCreating(true);
|
|
262
|
+
setEditingName(request.configuration.name ?? '');
|
|
263
|
+
}, children: t('marivo.credentials.open-configuration-form') }))] }))] })), creating && request?.endedAt === undefined && (_jsx(CreateDatasource, { name: editingName || undefined, requestId: request?.configuration ? request.id : undefined, model: model, workspaceId: workspaceId, close: () => setCreating(false) }, `${workspaceId}/${editingName}/${request?.id ?? ''}`)), !creating && context && (_jsx(CredentialForm, { context: context, request: request, state: state, model: model, workspaceId: workspaceId, onEdit: () => {
|
|
264
|
+
setEditingName(context.name);
|
|
265
|
+
setCreating(true);
|
|
266
|
+
} }, context.token)), operations.length > 0 && (_jsxs("section", { className: "mc-activity", "aria-label": t('marivo.credentials.credential-operations-in-progress'), children: [_jsxs("p", { className: "mc-activity-heading", children: [t('marivo.credentials.in-progress'), operations.length] }), _jsx("div", { className: "mc-activity-list", children: operations.map((entry) => (_jsxs("button", { type: "button", "aria-pressed": state.handle?.id === entry.handle.id, onClick: () => model.selectOperation(entry.handle.id), children: [entry.name, " ", t('marivo.credentials.processing-177')] }, entry.handle.id))) }), activeOperation?.status === 'running' && (_jsxs("div", { className: "mc-progress", children: [_jsxs("p", { children: [state.operations.find((entry) => entry.handle.id === state.handle?.id)?.name, ' ', "\u00B7", ' ', activeOperation.phase === 'removing'
|
|
267
|
+
? t('marivo.credentials.deleting')
|
|
268
|
+
: activeOperation.phase === 'saving'
|
|
269
|
+
? t('marivo.credentials.saving')
|
|
270
|
+
: t('marivo.credentials.validating-connection')] }), _jsx("button", { type: "button", onClick: () => void model.cancelOperation(), children: t('marivo.credentials.cancel-this-operation') }), activeOperation.saved.length > 0 && (_jsxs("p", { children: [t('marivo.credentials.saved'), activeOperation.saved.join('、'), "\u3002"] }))] }))] }))] })] })] }), !request && workspaceId && (_jsx(ReportPublishingCredentials, { model: model, workspaceId: workspaceId }, workspaceId))] }));
|
|
156
271
|
}
|
|
157
|
-
export function installCredentials(ctx, rpc) {
|
|
272
|
+
export function installCredentials(ctx, rpc, changes) {
|
|
158
273
|
let storage;
|
|
159
274
|
try {
|
|
160
275
|
storage = window.sessionStorage;
|
|
@@ -162,30 +277,43 @@ export function installCredentials(ctx, rpc) {
|
|
|
162
277
|
catch {
|
|
163
278
|
/* optional query-handle persistence */
|
|
164
279
|
}
|
|
165
|
-
const model = new CredentialClientModel(rpc, storage);
|
|
280
|
+
const model = new CredentialClientModel(rpc, storage, changes);
|
|
166
281
|
model.recover();
|
|
167
282
|
ctx.effect(() => () => model.dispose(), 'dsh-data-analysis: credential client lifecycle');
|
|
168
283
|
ctx.on('connection/reset', () => model.reset());
|
|
169
|
-
ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}));
|
|
177
|
-
ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({ name: 'conversation.session.header.actions', id: 'marivo-credential-requests', order: 120 }, function Pending({ sessionId }) {
|
|
284
|
+
ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register({
|
|
285
|
+
locale: 'marivo.navigation',
|
|
286
|
+
name: 'conversation.session.header.actions',
|
|
287
|
+
id: 'marivo-credential-requests',
|
|
288
|
+
order: 120,
|
|
289
|
+
}, localized(ctx, function Pending({ sessionId }) {
|
|
290
|
+
const t = useCopy();
|
|
178
291
|
const state = useSyncExternalStore(model.subscribe, model.getSnapshot);
|
|
179
292
|
const request = state.requests.find((item) => item.sessionId === sessionId && item.endedAt === undefined);
|
|
180
|
-
return request ? (_jsx("button", { className: "mc-pending-entry",
|
|
181
|
-
|
|
182
|
-
|
|
293
|
+
return request ? (_jsx("button", { className: "mc-pending-entry", style: {
|
|
294
|
+
flex: 'none',
|
|
295
|
+
whiteSpace: 'nowrap',
|
|
296
|
+
fontSize: 12,
|
|
297
|
+
padding: '4px 6px',
|
|
298
|
+
border: '1px solid currentColor',
|
|
299
|
+
borderRadius: 7,
|
|
300
|
+
background: 'transparent',
|
|
301
|
+
color: 'inherit',
|
|
302
|
+
cursor: 'pointer',
|
|
303
|
+
}, "aria-label": request.configuration
|
|
304
|
+
? t('marivo.credentials.awaiting-datasource-configuration')
|
|
305
|
+
: t('marivo.credentials.awaiting-credentials'), title: request.configuration
|
|
306
|
+
? t('marivo.credentials.awaiting-datasource-configuration')
|
|
307
|
+
: t('marivo.credentials.awaiting-credentials'), type: "button", onClick: () => model.openRequest(request.id), children: t('marivo.credentials.configuration-needed') })) : null;
|
|
308
|
+
})));
|
|
309
|
+
ctx.slots.inject('shell.overlay', () => ctx.slots.register({ locale: 'marivo.navigation', name: 'shell.overlay', id: 'marivo-credential-observer' }, localized(ctx, function Observer({ useSessions, useWorkspaces }) {
|
|
183
310
|
const sessionId = useSessions((state) => state.current) ?? '';
|
|
184
311
|
const workspaces = useWorkspaces((state) => state.items);
|
|
185
312
|
const currentWorkspace = workspaces.find((item) => item.sessionIds.includes(sessionId))?.workspaceId ?? '';
|
|
186
313
|
useEffect(() => model.session(sessionId), [sessionId]);
|
|
187
314
|
// biome-ignore lint/correctness/useExhaustiveDependencies: Workspace reassignment must dismiss old content.
|
|
188
315
|
useEffect(() => model.close(), [currentWorkspace]);
|
|
189
|
-
return
|
|
190
|
-
}));
|
|
316
|
+
return null;
|
|
317
|
+
})));
|
|
318
|
+
return model;
|
|
191
319
|
}
|