@gooddata/sdk-ui-catalog 11.48.0-alpha.1 → 11.48.0-alpha.3
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/esm/AnalyticsCatalogDetail.d.ts.map +1 -1
- package/esm/AnalyticsCatalogDetail.js +3 -3
- package/esm/asCode/AsCodeCreateDialog.d.ts +17 -0
- package/esm/asCode/AsCodeCreateDialog.d.ts.map +1 -0
- package/esm/asCode/AsCodeCreateDialog.js +51 -0
- package/esm/asCode/AsCodeDeleteDialog.d.ts +17 -0
- package/esm/asCode/AsCodeDeleteDialog.d.ts.map +1 -0
- package/esm/asCode/AsCodeDeleteDialog.js +55 -0
- package/esm/asCode/AsCodeDetailActions.d.ts +27 -0
- package/esm/asCode/AsCodeDetailActions.d.ts.map +1 -0
- package/esm/asCode/AsCodeDetailActions.js +66 -0
- package/esm/asCode/AsCodeDialog.d.ts +24 -0
- package/esm/asCode/AsCodeDialog.d.ts.map +1 -0
- package/esm/asCode/AsCodeDialog.js +94 -0
- package/esm/asCode/AsCodeEditDialog.d.ts +18 -0
- package/esm/asCode/AsCodeEditDialog.d.ts.map +1 -0
- package/esm/asCode/AsCodeEditDialog.js +38 -0
- package/esm/asCode/AsCodeEditorBody.d.ts +16 -0
- package/esm/asCode/AsCodeEditorBody.d.ts.map +1 -0
- package/esm/asCode/AsCodeEditorBody.js +10 -0
- package/esm/asCode/AsCodeMutationContext.d.ts +24 -0
- package/esm/asCode/AsCodeMutationContext.d.ts.map +1 -0
- package/esm/asCode/AsCodeMutationContext.js +40 -0
- package/esm/asCode/copy.d.ts +18 -0
- package/esm/asCode/copy.d.ts.map +1 -0
- package/esm/asCode/copy.js +58 -0
- package/esm/asCode/descriptor.d.ts +160 -0
- package/esm/asCode/descriptor.d.ts.map +1 -0
- package/esm/asCode/descriptor.js +8 -0
- package/esm/asCode/gate.d.ts +7 -0
- package/esm/asCode/gate.d.ts.map +1 -0
- package/esm/asCode/gate.js +11 -0
- package/esm/asCode/useAsCodeBase.d.ts +18 -0
- package/esm/asCode/useAsCodeBase.d.ts.map +1 -0
- package/esm/asCode/useAsCodeBase.js +27 -0
- package/esm/asCode/validateYaml.d.ts +39 -0
- package/esm/asCode/validateYaml.d.ts.map +1 -0
- package/esm/asCode/validateYaml.js +28 -0
- package/esm/asCodeRegistry.d.ts +20 -0
- package/esm/asCodeRegistry.d.ts.map +1 -0
- package/esm/asCodeRegistry.js +36 -0
- package/esm/catalog/Catalog.d.ts.map +1 -1
- package/esm/catalog/Catalog.js +4 -4
- package/esm/catalogDetail/CatalogDetailActions.d.ts +4 -2
- package/esm/catalogDetail/CatalogDetailActions.d.ts.map +1 -1
- package/esm/catalogDetail/CatalogDetailActions.js +22 -78
- package/esm/catalogDetail/CatalogDetailContent.d.ts.map +1 -1
- package/esm/catalogDetail/CatalogDetailContent.js +1 -3
- package/esm/catalogItem/query.d.ts +4 -2
- package/esm/catalogItem/query.d.ts.map +1 -1
- package/esm/catalogItem/query.js +6 -6
- package/esm/header/CreateObjectButton.d.ts.map +1 -1
- package/esm/header/CreateObjectButton.js +29 -28
- package/esm/localization/bundles/de-DE.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/de-DE.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/de-DE.localization-bundle.js +4 -6
- package/esm/localization/bundles/en-AU.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/en-AU.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/en-AU.localization-bundle.js +4 -6
- package/esm/localization/bundles/en-GB.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/en-GB.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/en-GB.localization-bundle.js +4 -6
- package/esm/localization/bundles/en-US.localization-bundle.d.ts +16 -24
- package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/en-US.localization-bundle.js +16 -24
- package/esm/localization/bundles/es-419.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/es-419.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/es-419.localization-bundle.js +4 -6
- package/esm/localization/bundles/es-ES.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/es-ES.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/es-ES.localization-bundle.js +4 -6
- package/esm/localization/bundles/fi-FI.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/fi-FI.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/fi-FI.localization-bundle.js +4 -6
- package/esm/localization/bundles/fr-CA.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/fr-CA.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/fr-CA.localization-bundle.js +4 -6
- package/esm/localization/bundles/fr-FR.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/fr-FR.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/fr-FR.localization-bundle.js +4 -6
- package/esm/localization/bundles/id-ID.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/id-ID.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/id-ID.localization-bundle.js +4 -6
- package/esm/localization/bundles/it-IT.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/it-IT.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/it-IT.localization-bundle.js +4 -6
- package/esm/localization/bundles/ja-JP.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/ja-JP.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/ja-JP.localization-bundle.js +4 -6
- package/esm/localization/bundles/ko-KR.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/ko-KR.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/ko-KR.localization-bundle.js +4 -6
- package/esm/localization/bundles/nl-NL.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/nl-NL.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/nl-NL.localization-bundle.js +4 -6
- package/esm/localization/bundles/pl-PL.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/pl-PL.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/pl-PL.localization-bundle.js +4 -6
- package/esm/localization/bundles/pt-BR.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/pt-BR.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/pt-BR.localization-bundle.js +4 -6
- package/esm/localization/bundles/pt-PT.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/pt-PT.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/pt-PT.localization-bundle.js +4 -6
- package/esm/localization/bundles/ru-RU.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/ru-RU.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/ru-RU.localization-bundle.js +4 -6
- package/esm/localization/bundles/sl-SI.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/sl-SI.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/sl-SI.localization-bundle.js +4 -6
- package/esm/localization/bundles/th-TH.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/th-TH.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/th-TH.localization-bundle.js +4 -6
- package/esm/localization/bundles/tr-TR.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/tr-TR.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/tr-TR.localization-bundle.js +4 -6
- package/esm/localization/bundles/uk-UA.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/uk-UA.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/uk-UA.localization-bundle.js +4 -6
- package/esm/localization/bundles/vi-VN.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/vi-VN.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/vi-VN.localization-bundle.js +4 -6
- package/esm/localization/bundles/zh-HK.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/zh-HK.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/zh-HK.localization-bundle.js +4 -6
- package/esm/localization/bundles/zh-Hans.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/zh-Hans.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/zh-Hans.localization-bundle.js +4 -6
- package/esm/localization/bundles/zh-Hant.localization-bundle.d.ts +4 -6
- package/esm/localization/bundles/zh-Hant.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/zh-Hant.localization-bundle.js +4 -6
- package/esm/metric/gate.d.ts +3 -4
- package/esm/metric/gate.d.ts.map +1 -1
- package/esm/metric/gate.js +5 -10
- package/esm/metric/metricCopy.d.ts +0 -1
- package/esm/metric/metricCopy.d.ts.map +1 -1
- package/esm/metric/metricCopy.js +3 -45
- package/esm/metric/metricDescriptor.d.ts +7 -0
- package/esm/metric/metricDescriptor.d.ts.map +1 -0
- package/esm/metric/metricDescriptor.js +74 -0
- package/esm/metric/metricMutationPort.d.ts +7 -10
- package/esm/metric/metricMutationPort.d.ts.map +1 -1
- package/esm/metric/metricMutationPort.js +15 -17
- package/esm/metric/metricValidation.d.ts.map +1 -1
- package/esm/metric/metricValidation.js +13 -32
- package/esm/metric/tests/metricMutationPort.test.utils.js +1 -1
- package/esm/parameter/gate.d.ts +3 -0
- package/esm/parameter/gate.d.ts.map +1 -1
- package/esm/parameter/gate.js +7 -5
- package/esm/parameter/parameterCopy.d.ts +0 -1
- package/esm/parameter/parameterCopy.d.ts.map +1 -1
- package/esm/parameter/parameterCopy.js +4 -41
- package/esm/parameter/parameterDescriptor.d.ts +7 -0
- package/esm/parameter/parameterDescriptor.d.ts.map +1 -0
- package/esm/parameter/parameterDescriptor.js +91 -0
- package/esm/parameter/parameterMutationPort.d.ts +5 -6
- package/esm/parameter/parameterMutationPort.d.ts.map +1 -1
- package/esm/parameter/parameterMutationPort.js +15 -2
- package/package.json +15 -15
- package/esm/metric/MetricCreateDialog.d.ts +0 -11
- package/esm/metric/MetricCreateDialog.d.ts.map +0 -1
- package/esm/metric/MetricCreateDialog.js +0 -55
- package/esm/metric/MetricDeleteDialog.d.ts +0 -9
- package/esm/metric/MetricDeleteDialog.d.ts.map +0 -1
- package/esm/metric/MetricDeleteDialog.js +0 -68
- package/esm/metric/MetricDetailActions.d.ts +0 -23
- package/esm/metric/MetricDetailActions.d.ts.map +0 -1
- package/esm/metric/MetricDetailActions.js +0 -101
- package/esm/metric/MetricDialog.d.ts +0 -14
- package/esm/metric/MetricDialog.d.ts.map +0 -1
- package/esm/metric/MetricDialog.js +0 -100
- package/esm/metric/MetricEditDialog.d.ts +0 -11
- package/esm/metric/MetricEditDialog.d.ts.map +0 -1
- package/esm/metric/MetricEditDialog.js +0 -51
- package/esm/metric/MetricMutationContext.d.ts +0 -16
- package/esm/metric/MetricMutationContext.d.ts.map +0 -1
- package/esm/metric/MetricMutationContext.js +0 -32
- package/esm/metric/MetricYamlEditor.d.ts +0 -8
- package/esm/metric/MetricYamlEditor.d.ts.map +0 -1
- package/esm/metric/MetricYamlEditor.js +0 -12
- package/esm/parameter/ParameterCreateDialog.d.ts +0 -9
- package/esm/parameter/ParameterCreateDialog.d.ts.map +0 -1
- package/esm/parameter/ParameterCreateDialog.js +0 -56
- package/esm/parameter/ParameterDeleteDialog.d.ts +0 -9
- package/esm/parameter/ParameterDeleteDialog.d.ts.map +0 -1
- package/esm/parameter/ParameterDeleteDialog.js +0 -39
- package/esm/parameter/ParameterDialog.d.ts +0 -13
- package/esm/parameter/ParameterDialog.d.ts.map +0 -1
- package/esm/parameter/ParameterDialog.js +0 -106
- package/esm/parameter/ParameterEditDialog.d.ts +0 -11
- package/esm/parameter/ParameterEditDialog.d.ts.map +0 -1
- package/esm/parameter/ParameterEditDialog.js +0 -35
- package/esm/parameter/ParameterMutationContext.d.ts +0 -16
- package/esm/parameter/ParameterMutationContext.d.ts.map +0 -1
- package/esm/parameter/ParameterMutationContext.js +0 -32
- package/esm/parameter/ParameterYamlEditor.d.ts +0 -10
- package/esm/parameter/ParameterYamlEditor.d.ts.map +0 -1
- package/esm/parameter/ParameterYamlEditor.js +0 -16
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
4
|
-
import { defineMessages, useIntl } from "react-intl";
|
|
5
|
-
import { useWorkspaceStrict } from "@gooddata/sdk-ui";
|
|
6
|
-
import { useToastMessage } from "@gooddata/sdk-ui-kit";
|
|
7
|
-
import { catalogDetailActionDelete, catalogDetailActionDuplicate } from "../automation/testIds.js";
|
|
8
|
-
import { CatalogDetailActionBar } from "../catalogDetail/CatalogDetailActionBar.js";
|
|
9
|
-
import { ShareButton } from "../catalogDetail/share/ShareButton.js";
|
|
10
|
-
import { MetricCreateDialog } from "./MetricCreateDialog.js";
|
|
11
|
-
import { MetricDeleteDialog } from "./MetricDeleteDialog.js";
|
|
12
|
-
import { MetricEditDialog } from "./MetricEditDialog.js";
|
|
13
|
-
import { useMetricMutation } from "./MetricMutationContext.js";
|
|
14
|
-
const messages = defineMessages({
|
|
15
|
-
openInEditor: { id: "analyticsCatalog.metric.actions.openInEditor" },
|
|
16
|
-
duplicate: { id: "analyticsCatalog.metric.dialog.edit.duplicate" },
|
|
17
|
-
delete: { id: "analyticsCatalog.metric.dialog.delete.submit" },
|
|
18
|
-
loadError: { id: "analyticsCatalog.metric.load.error" },
|
|
19
|
-
});
|
|
20
|
-
/**
|
|
21
|
-
* Detail-panel actions for a metric: inline edit, duplicate, and delete via the as-code editor,
|
|
22
|
-
* alongside the shared Share button and "Open in metric editor" action.
|
|
23
|
-
* @internal
|
|
24
|
-
*/
|
|
25
|
-
export function MetricDetailActions({ item, onOpen, canShare, onShare, onCatalogItemCreate, onCatalogItemUpdate, onCatalogItemDelete, }) {
|
|
26
|
-
const intl = useIntl();
|
|
27
|
-
const workspaceId = useWorkspaceStrict();
|
|
28
|
-
const { addError } = useToastMessage();
|
|
29
|
-
const mutation = useMetricMutation();
|
|
30
|
-
const [dialog, setDialog] = useState(undefined);
|
|
31
|
-
const isMounted = useRef(true);
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
// Reset on (re)mount: StrictMode runs mount -> cleanup -> remount, and without this the ref
|
|
34
|
-
// would stay false after the remount even though the component is mounted.
|
|
35
|
-
isMounted.current = true;
|
|
36
|
-
return () => {
|
|
37
|
-
isMounted.current = false;
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
|
-
const actions = useMemo(() => {
|
|
41
|
-
const result = [];
|
|
42
|
-
// The standalone metric editor stays reachable alongside the inline Edit; omitted when the
|
|
43
|
-
// host does not provide an open handler, so the menu never shows a dead item.
|
|
44
|
-
if (onOpen) {
|
|
45
|
-
result.push({ id: "open", label: intl.formatMessage(messages.openInEditor) });
|
|
46
|
-
}
|
|
47
|
-
result.push({
|
|
48
|
-
id: "duplicate",
|
|
49
|
-
label: intl.formatMessage(messages.duplicate),
|
|
50
|
-
dataTestId: catalogDetailActionDuplicate,
|
|
51
|
-
}, {
|
|
52
|
-
id: "delete",
|
|
53
|
-
label: intl.formatMessage(messages.delete),
|
|
54
|
-
isDestructive: true,
|
|
55
|
-
dataTestId: catalogDetailActionDelete,
|
|
56
|
-
});
|
|
57
|
-
return result;
|
|
58
|
-
}, [intl, onOpen]);
|
|
59
|
-
const closeDialog = useCallback(() => setDialog(undefined), []);
|
|
60
|
-
const handleEditOpen = useCallback(() => setDialog({ kind: "edit", item }), [item]);
|
|
61
|
-
const handleActionsMenuSelect = useCallback(async (actionId, event) => {
|
|
62
|
-
if (actionId === "open") {
|
|
63
|
-
onOpen?.(event, {
|
|
64
|
-
item,
|
|
65
|
-
workspaceId,
|
|
66
|
-
newTab: event.metaKey || event.ctrlKey,
|
|
67
|
-
preventDefault: event.preventDefault.bind(event),
|
|
68
|
-
});
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
if (actionId === "delete") {
|
|
72
|
-
setDialog({ kind: "delete", item });
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
if (actionId === "duplicate") {
|
|
76
|
-
// The catalog item carries no MAQL, so show the create dialog in its loading state
|
|
77
|
-
// and feed it the copied definition once the full metric is fetched. Only advance
|
|
78
|
-
// while still in this loading state, so closing the dialog or opening Edit/Delete
|
|
79
|
-
// meanwhile cancels the duplicate.
|
|
80
|
-
setDialog({ kind: "duplicate", isLoading: true });
|
|
81
|
-
try {
|
|
82
|
-
const measure = await mutation.load(item);
|
|
83
|
-
if (isMounted.current) {
|
|
84
|
-
setDialog((current) => current?.kind === "duplicate" && current.isLoading
|
|
85
|
-
? { kind: "duplicate", sourceDefinition: measure, isLoading: false }
|
|
86
|
-
: current);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
if (isMounted.current) {
|
|
91
|
-
addError(messages.loadError);
|
|
92
|
-
setDialog((current) => current?.kind === "duplicate" && current.isLoading ? undefined : current);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}, [addError, item, mutation, onOpen, workspaceId]);
|
|
97
|
-
const handleEditDuplicate = useCallback((sourceDefinition) => {
|
|
98
|
-
setDialog({ kind: "duplicate", sourceDefinition, isLoading: false });
|
|
99
|
-
}, []);
|
|
100
|
-
return (_jsxs(_Fragment, { children: [_jsx(CatalogDetailActionBar, { item: item, workspaceId: workspaceId, actions: actions, leadingActions: canShare && onShare ? _jsx(ShareButton, { onClick: onShare }) : null, onEditClick: handleEditOpen, onActionsMenuSelect: handleActionsMenuSelect }), dialog?.kind === "edit" ? (_jsx(MetricEditDialog, { item: dialog.item, onClose: closeDialog, onSaved: (saved) => onCatalogItemUpdate?.(saved), onDuplicate: handleEditDuplicate })) : null, dialog?.kind === "duplicate" ? (_jsx(MetricCreateDialog, { sourceDefinition: dialog.sourceDefinition, isLoading: dialog.isLoading, onClose: closeDialog, onCreated: (created) => onCatalogItemCreate?.(created) })) : null, dialog?.kind === "delete" ? (_jsx(MetricDeleteDialog, { item: dialog.item, onClose: closeDialog, onDeleted: () => onCatalogItemDelete?.(dialog.item) })) : null] }));
|
|
101
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { IMeasureMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
|
-
import type { MetricYaml } from "./metricConverter.js";
|
|
3
|
-
export type MetricDialogMode = "create" | "edit";
|
|
4
|
-
type Props = {
|
|
5
|
-
mode: MetricDialogMode;
|
|
6
|
-
initialMetric?: MetricYaml;
|
|
7
|
-
isLoading?: boolean;
|
|
8
|
-
onClose: () => void;
|
|
9
|
-
onSubmit: (measure: IMeasureMetadataObjectDefinition) => Promise<void>;
|
|
10
|
-
onDuplicate?: (measure: IMeasureMetadataObjectDefinition) => void;
|
|
11
|
-
};
|
|
12
|
-
export declare function MetricDialog(props: Props): import("react/jsx-runtime").JSX.Element;
|
|
13
|
-
export {};
|
|
14
|
-
//# sourceMappingURL=MetricDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricDialog.d.ts","sourceRoot":"","sources":["../../src/metric/MetricDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAO5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AA0BvD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjD,KAAK,KAAK,GAAG;IACT,IAAI,EAAE,gBAAgB,CAAC;IAGvB,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,gCAAgC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,gCAAgC,KAAK,IAAI,CAAC;CACrE,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,2CA8KxC"}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { Suspense, lazy, useCallback, useMemo, useRef, useState } from "react";
|
|
4
|
-
import { FormattedMessage, defineMessages, useIntl } from "react-intl";
|
|
5
|
-
import { LoadingComponent } from "@gooddata/sdk-ui";
|
|
6
|
-
import { ConfirmDialog, UiButton, UiIcon, UiLink, UiTooltip } from "@gooddata/sdk-ui-kit";
|
|
7
|
-
import { useIsWhiteLabeled } from "../permission/PermissionsContext.js";
|
|
8
|
-
import { extractBackendErrorDetail } from "../utils/backendError.js";
|
|
9
|
-
import { serializeMetricToYaml } from "./metricSerialization.js";
|
|
10
|
-
import { validateMetricYaml } from "./metricValidation.js";
|
|
11
|
-
const MetricYamlEditor = lazy(() => import("./MetricYamlEditor.js").then((m) => ({ default: m.MetricYamlEditor })));
|
|
12
|
-
const METRIC_DOCS_URL = "https://www.gooddata.ai/docs/cloud/api-and-sdk/vs-code-extension/structures/#metric";
|
|
13
|
-
const messages = defineMessages({
|
|
14
|
-
empty: { id: "analyticsCatalog.metric.validation.empty" },
|
|
15
|
-
syntax: { id: "analyticsCatalog.metric.validation.syntax" },
|
|
16
|
-
invalidStructure: { id: "analyticsCatalog.metric.validation.invalidStructure" },
|
|
17
|
-
idImmutable: { id: "analyticsCatalog.metric.dialog.edit.idImmutable" },
|
|
18
|
-
missingMaql: { id: "analyticsCatalog.metric.validation.missingMaql" },
|
|
19
|
-
invalidTags: { id: "analyticsCatalog.metric.validation.invalidTags" },
|
|
20
|
-
dialogSubmitError: { id: "analyticsCatalog.metric.dialog.submit.error" },
|
|
21
|
-
dialogCreateTitle: { id: "analyticsCatalog.metric.dialog.create.title" },
|
|
22
|
-
dialogEditTitle: { id: "analyticsCatalog.metric.dialog.edit.title" },
|
|
23
|
-
dialogCreateSubmit: { id: "analyticsCatalog.metric.dialog.create.submit" },
|
|
24
|
-
dialogEditSubmit: { id: "analyticsCatalog.metric.dialog.edit.submit" },
|
|
25
|
-
dialogCancel: { id: "analyticsCatalog.metric.dialog.cancel" },
|
|
26
|
-
dialogDuplicate: { id: "analyticsCatalog.metric.dialog.edit.duplicate" },
|
|
27
|
-
});
|
|
28
|
-
export function MetricDialog(props) {
|
|
29
|
-
const { mode, initialMetric, isLoading = false, onClose, onSubmit, onDuplicate } = props;
|
|
30
|
-
const intl = useIntl();
|
|
31
|
-
const isEdit = mode === "edit";
|
|
32
|
-
const isWhiteLabeled = useIsWhiteLabeled();
|
|
33
|
-
const initialYaml = useMemo(() => (initialMetric ? serializeMetricToYaml(initialMetric) : ""), [initialMetric]);
|
|
34
|
-
// The user's edits; `null` until they type. Submit falls back to `initialYaml`, so the editor
|
|
35
|
-
// mounts once with real data and is the single source of truth — no re-seed effect needed.
|
|
36
|
-
const yamlValue = useRef(null);
|
|
37
|
-
const [validationError, setValidationError] = useState(null);
|
|
38
|
-
const [submitError, setSubmitError] = useState(null);
|
|
39
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
40
|
-
const [isDirty, setIsDirty] = useState(false);
|
|
41
|
-
const headlineMessage = intl.formatMessage(isEdit ? messages.dialogEditTitle : messages.dialogCreateTitle);
|
|
42
|
-
const submitMessage = intl.formatMessage(isEdit ? messages.dialogEditSubmit : messages.dialogCreateSubmit);
|
|
43
|
-
const cancelMessage = intl.formatMessage(messages.dialogCancel);
|
|
44
|
-
const fixedIdentifier = isEdit ? initialMetric?.id : undefined;
|
|
45
|
-
const validate = useCallback((value, allowIdChange = false) => {
|
|
46
|
-
return validateMetricYaml(value, {
|
|
47
|
-
fixedIdentifier: isEdit && !allowIdChange ? fixedIdentifier : undefined,
|
|
48
|
-
});
|
|
49
|
-
}, [fixedIdentifier, isEdit]);
|
|
50
|
-
const handleClose = useCallback(() => {
|
|
51
|
-
if (!isSubmitting) {
|
|
52
|
-
onClose();
|
|
53
|
-
}
|
|
54
|
-
}, [isSubmitting, onClose]);
|
|
55
|
-
const handleChange = useCallback((nextValue) => {
|
|
56
|
-
yamlValue.current = nextValue;
|
|
57
|
-
setIsDirty(true);
|
|
58
|
-
setSubmitError(null);
|
|
59
|
-
setValidationError(null);
|
|
60
|
-
}, []);
|
|
61
|
-
const handleSubmit = useCallback(async () => {
|
|
62
|
-
const result = validate(yamlValue.current ?? initialYaml);
|
|
63
|
-
if (!result.isValid) {
|
|
64
|
-
setValidationError(intl.formatMessage(messages[result.errorCode]));
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
setIsSubmitting(true);
|
|
68
|
-
setSubmitError(null);
|
|
69
|
-
try {
|
|
70
|
-
await onSubmit(result.measure);
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
setSubmitError(extractBackendErrorDetail(error) ?? intl.formatMessage(messages.dialogSubmitError));
|
|
74
|
-
}
|
|
75
|
-
finally {
|
|
76
|
-
setIsSubmitting(false);
|
|
77
|
-
}
|
|
78
|
-
}, [initialYaml, intl, onSubmit, validate]);
|
|
79
|
-
const handleDuplicate = useCallback(() => {
|
|
80
|
-
if (!onDuplicate) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
setSubmitError(null);
|
|
84
|
-
const result = validate(yamlValue.current ?? initialYaml, true);
|
|
85
|
-
if (!result.isValid) {
|
|
86
|
-
setValidationError(intl.formatMessage(messages[result.errorCode]));
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
onDuplicate(result.measure);
|
|
90
|
-
}, [initialYaml, intl, onDuplicate, validate]);
|
|
91
|
-
const footerLeftRenderer = useCallback(() => (_jsxs("div", { className: "gd-ascode-dialog-footer-left", children: [isWhiteLabeled ? null : (_jsxs(UiLink, { variant: "secondary", href: METRIC_DOCS_URL, target: "_blank", rel: "noopener noreferrer", children: [
|
|
92
|
-
_jsx(UiIcon, { type: "question", size: 14, color: "complementary-6" }), _jsx(FormattedMessage, { id: "analyticsCatalog.metric.dialog.help" })
|
|
93
|
-
] })), isEdit && onDuplicate ? (_jsx(UiButton, { label: intl.formatMessage(messages.dialogDuplicate), variant: "tertiary", isDisabled: isSubmitting || isLoading, onClick: handleDuplicate })) : null] })), [handleDuplicate, intl, isEdit, isLoading, isSubmitting, isWhiteLabeled, onDuplicate]);
|
|
94
|
-
const bodySpinner = (_jsx("div", { className: "gd-ascode-dialog-loading", children: _jsx(LoadingComponent, {}) }));
|
|
95
|
-
return (_jsx(ConfirmDialog, { className: "gd-ascode-dialog", containerClassName: "gd-ascode-dialog-overlay", headline: headlineMessage, cancelButtonText: cancelMessage, submitButtonText: submitMessage, isPositive: true, isSubmitDisabled: isSubmitting || isLoading || (isEdit && !isDirty), isCancelDisabled: isSubmitting, shouldCloseOnEscape: !isSubmitting, onCancel: handleClose, onClose: handleClose, onSubmit: handleSubmit, displayCloseButton: !isSubmitting, footerLeftRenderer: footerLeftRenderer, children: _jsx("div", { className: "gd-ascode-dialog-content", children: _jsx(Suspense, { fallback: bodySpinner, children: isLoading ? (bodySpinner) : (_jsxs(_Fragment, { children: [
|
|
96
|
-
_jsxs("div", { className: "gd-ascode-dialog-section-header", children: [
|
|
97
|
-
_jsx(FormattedMessage, { id: "analyticsCatalog.metric.dialog.sectionHeader" }), _jsx(UiTooltip, { arrowPlacement: "top", optimalPlacement: true, triggerBy: ["hover", "click", "focus"], anchor: _jsx(UiIcon, { type: "question", size: 14, color: "complementary-6" }), content: _jsx(FormattedMessage, { id: "analyticsCatalog.metric.dialog.sectionHeader.tooltip" }) })
|
|
98
|
-
] }), _jsx("div", { className: "gd-ascode-dialog-editor", children: _jsx(MetricYamlEditor, { initialValue: initialYaml, onChange: handleChange, disabled: isSubmitting }) }), validationError || submitError ? (_jsxs("div", { className: "gd-ascode-dialog-error", children: [
|
|
99
|
-
_jsx("span", { className: "gd-ascode-dialog-error-label", children: _jsx(FormattedMessage, { id: "analyticsCatalog.dialog.error.label" }) }), " ", validationError ?? submitError] })) : null] })) }) }) }));
|
|
100
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { IMeasureMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
|
-
import { type ICatalogItemMeasure } from "../catalogItem/types.js";
|
|
3
|
-
type Props = {
|
|
4
|
-
item: ICatalogItemMeasure;
|
|
5
|
-
onClose: () => void;
|
|
6
|
-
onSaved: (item: ICatalogItemMeasure) => void;
|
|
7
|
-
onDuplicate?: (metric: IMeasureMetadataObjectDefinition) => void;
|
|
8
|
-
};
|
|
9
|
-
export declare function MetricEditDialog({ item, onClose, onSaved, onDuplicate }: Props): import("react/jsx-runtime").JSX.Element;
|
|
10
|
-
export {};
|
|
11
|
-
//# sourceMappingURL=MetricEditDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricEditDialog.d.ts","sourceRoot":"","sources":["../../src/metric/MetricEditDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA0B,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAIpG,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAWnE,KAAK,KAAK,GAAG;IACT,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC7C,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,gCAAgC,KAAK,IAAI,CAAC;CACpE,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,KAAK,2CA8D9E"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { useCallback, useMemo } from "react";
|
|
4
|
-
import { defineMessages } from "react-intl";
|
|
5
|
-
import { useCancelablePromise } from "@gooddata/sdk-ui";
|
|
6
|
-
import { useToastMessage } from "@gooddata/sdk-ui-kit";
|
|
7
|
-
import {} from "../catalogItem/types.js";
|
|
8
|
-
import { definitionToMetricYaml, overlayMetricYamlFields } from "./metricConverter.js";
|
|
9
|
-
import { MetricDialog } from "./MetricDialog.js";
|
|
10
|
-
import { useMetricMutation } from "./MetricMutationContext.js";
|
|
11
|
-
const messages = defineMessages({
|
|
12
|
-
metricUpdateSuccess: { id: "analyticsCatalog.metric.update.success" },
|
|
13
|
-
metricLoadError: { id: "analyticsCatalog.metric.load.error" },
|
|
14
|
-
});
|
|
15
|
-
export function MetricEditDialog({ item, onClose, onSaved, onDuplicate }) {
|
|
16
|
-
const { addSuccess, addError } = useToastMessage();
|
|
17
|
-
const mutation = useMetricMutation();
|
|
18
|
-
// The catalog item carries only metadata; the full metric (incl. MAQL and fields the YAML does
|
|
19
|
-
// not carry, such as metricType) is fetched on open and reused as the base for the update. The
|
|
20
|
-
// fetch is re-run only when the item or backend port changes, and a stale in-flight load is
|
|
21
|
-
// discarded when they do.
|
|
22
|
-
const { result: loadedMetric } = useCancelablePromise({
|
|
23
|
-
promise: () => mutation.load(item),
|
|
24
|
-
onError: () => {
|
|
25
|
-
addError(messages.metricLoadError);
|
|
26
|
-
onClose();
|
|
27
|
-
},
|
|
28
|
-
}, [item, mutation]);
|
|
29
|
-
const handleSubmit = useCallback(async (definition) => {
|
|
30
|
-
if (!loadedMetric) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
const savedMetric = await mutation.update(loadedMetric, definition);
|
|
34
|
-
onSaved(savedMetric);
|
|
35
|
-
onClose();
|
|
36
|
-
addSuccess(messages.metricUpdateSuccess);
|
|
37
|
-
}, [addSuccess, loadedMetric, mutation, onClose, onSaved]);
|
|
38
|
-
// The duplicate is seeded from the loaded metric overlaid with the current YAML edits, so the
|
|
39
|
-
// copy inherits fields the YAML cannot express (metricType, isHiddenFromKda) that the parsed
|
|
40
|
-
// editor content alone would not carry.
|
|
41
|
-
const handleDuplicate = useCallback((edited) => {
|
|
42
|
-
if (!loadedMetric || !onDuplicate) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
onDuplicate(overlayMetricYamlFields(loadedMetric, edited));
|
|
46
|
-
}, [loadedMetric, onDuplicate]);
|
|
47
|
-
// Undefined until the fetch completes: the eager dialog frame shows an in-frame spinner via
|
|
48
|
-
// isLoading and mounts the editor (seeded with the real metric) only once this is present.
|
|
49
|
-
const initialMetric = useMemo(() => (loadedMetric ? definitionToMetricYaml(loadedMetric) : undefined), [loadedMetric]);
|
|
50
|
-
return (_jsx(MetricDialog, { mode: "edit", isLoading: !loadedMetric, initialMetric: initialMetric, onClose: onClose, onSubmit: handleSubmit, onDuplicate: onDuplicate ? handleDuplicate : undefined }));
|
|
51
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { type PropsWithChildren } from "react";
|
|
2
|
-
import { type IMetricMutationPort } from "./metricMutationPort.js";
|
|
3
|
-
type ProviderProps = PropsWithChildren<{
|
|
4
|
-
port?: IMetricMutationPort;
|
|
5
|
-
}>;
|
|
6
|
-
/**
|
|
7
|
-
* Must be placed inside `BackendProvider` and `WorkspaceProvider`.
|
|
8
|
-
* @internal
|
|
9
|
-
*/
|
|
10
|
-
export declare function MetricMutationProvider({ children, port }: ProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
-
/**
|
|
12
|
-
* @internal
|
|
13
|
-
*/
|
|
14
|
-
export declare function useMetricMutation(): IMetricMutationPort;
|
|
15
|
-
export {};
|
|
16
|
-
//# sourceMappingURL=MetricMutationContext.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricMutationContext.d.ts","sourceRoot":"","sources":["../../src/metric/MetricMutationContext.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,iBAAiB,EAAsC,MAAM,OAAO,CAAC;AAInF,OAAO,EAAE,KAAK,mBAAmB,EAA+B,MAAM,yBAAyB,CAAC;AAIhG,KAAK,aAAa,GAAG,iBAAiB,CAAC;IACnC,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC9B,CAAC,CAAC;AAEH;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,aAAa,2CAKvE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,mBAAmB,CAMvD"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { createContext, useContext, useMemo } from "react";
|
|
4
|
-
import { useBackendStrict, useWorkspaceStrict } from "@gooddata/sdk-ui";
|
|
5
|
-
import { createMetricMutationAdapter } from "./metricMutationPort.js";
|
|
6
|
-
const MetricMutationContext = createContext(null);
|
|
7
|
-
/**
|
|
8
|
-
* Must be placed inside `BackendProvider` and `WorkspaceProvider`.
|
|
9
|
-
* @internal
|
|
10
|
-
*/
|
|
11
|
-
export function MetricMutationProvider({ children, port }) {
|
|
12
|
-
if (port) {
|
|
13
|
-
return _jsx(MetricMutationContext.Provider, { value: port, children: children });
|
|
14
|
-
}
|
|
15
|
-
return _jsx(DefaultMetricMutationProvider, { children: children });
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* @internal
|
|
19
|
-
*/
|
|
20
|
-
export function useMetricMutation() {
|
|
21
|
-
const mutation = useContext(MetricMutationContext);
|
|
22
|
-
if (!mutation) {
|
|
23
|
-
throw new Error("useMetricMutation must be used within MetricMutationProvider");
|
|
24
|
-
}
|
|
25
|
-
return mutation;
|
|
26
|
-
}
|
|
27
|
-
function DefaultMetricMutationProvider({ children }) {
|
|
28
|
-
const backend = useBackendStrict();
|
|
29
|
-
const workspace = useWorkspaceStrict();
|
|
30
|
-
const mutation = useMemo(() => createMetricMutationAdapter(backend, workspace), [backend, workspace]);
|
|
31
|
-
return _jsx(MetricMutationContext.Provider, { value: mutation, children: children });
|
|
32
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
type Props = {
|
|
2
|
-
initialValue: string;
|
|
3
|
-
onChange?: (value: string) => void;
|
|
4
|
-
disabled?: boolean;
|
|
5
|
-
};
|
|
6
|
-
export declare function MetricYamlEditor({ initialValue, onChange, disabled }: Props): import("react/jsx-runtime").JSX.Element;
|
|
7
|
-
export {};
|
|
8
|
-
//# sourceMappingURL=MetricYamlEditor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricYamlEditor.d.ts","sourceRoot":"","sources":["../../src/metric/MetricYamlEditor.tsx"],"names":[],"mappings":"AAYA,KAAK,KAAK,GAAG;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAgB,EAAE,EAAE,KAAK,2CAWnF"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { defineMessages, useIntl } from "react-intl";
|
|
4
|
-
import { YamlEditor } from "@gooddata/sdk-ui-kit";
|
|
5
|
-
import { metricCompletions } from "./metricCompletions.js";
|
|
6
|
-
const messages = defineMessages({
|
|
7
|
-
syntaxError: { id: "analyticsCatalog.metric.validation.syntax" },
|
|
8
|
-
});
|
|
9
|
-
export function MetricYamlEditor({ initialValue, onChange, disabled = false }) {
|
|
10
|
-
const intl = useIntl();
|
|
11
|
-
return (_jsx(YamlEditor, { initialValue: initialValue, onChange: onChange, disabled: disabled, completionSource: metricCompletions, syntaxErrorMessage: intl.formatMessage(messages.syntaxError) }));
|
|
12
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ICatalogItemParameter } from "../catalogItem/types.js";
|
|
2
|
-
type Props = {
|
|
3
|
-
sourceItem?: ICatalogItemParameter;
|
|
4
|
-
onClose: () => void;
|
|
5
|
-
onCreated?: (item: ICatalogItemParameter) => void;
|
|
6
|
-
};
|
|
7
|
-
export declare function ParameterCreateDialog({ sourceItem, onClose, onCreated }: Props): import("react/jsx-runtime").JSX.Element;
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=ParameterCreateDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ParameterCreateDialog.d.ts","sourceRoot":"","sources":["../../src/parameter/ParameterCreateDialog.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAuBrE,KAAK,KAAK,GAAG;IACT,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;CACrD,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,2CAkD9E"}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { Suspense, lazy, useCallback, useMemo } from "react";
|
|
4
|
-
import { defineMessages } from "react-intl";
|
|
5
|
-
import { useToastMessage } from "@gooddata/sdk-ui-kit";
|
|
6
|
-
import { createCopiedParameter, isDuplicateIdError } from "./parameterCopy.js";
|
|
7
|
-
import { useParameterMutation } from "./ParameterMutationContext.js";
|
|
8
|
-
const ParameterDialog = lazy(() => import("./ParameterDialog.js").then((m) => ({ default: m.ParameterDialog })));
|
|
9
|
-
const messages = defineMessages({
|
|
10
|
-
parameterCreateSuccess: { id: "analyticsCatalog.parameter.create.success" },
|
|
11
|
-
});
|
|
12
|
-
const defaultInitialParameter = {
|
|
13
|
-
title: "My Parameter",
|
|
14
|
-
description: "",
|
|
15
|
-
definition: {
|
|
16
|
-
type: "NUMBER",
|
|
17
|
-
defaultValue: 0,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
export function ParameterCreateDialog({ sourceItem, onClose, onCreated }) {
|
|
21
|
-
const { addSuccess } = useToastMessage();
|
|
22
|
-
const mutation = useParameterMutation();
|
|
23
|
-
const initialParameter = useMemo(() => {
|
|
24
|
-
if (!sourceItem) {
|
|
25
|
-
return defaultInitialParameter;
|
|
26
|
-
}
|
|
27
|
-
return createCopiedParameter({
|
|
28
|
-
id: sourceItem.identifier,
|
|
29
|
-
type: "parameter",
|
|
30
|
-
title: sourceItem.title,
|
|
31
|
-
description: sourceItem.description,
|
|
32
|
-
tags: sourceItem.tags,
|
|
33
|
-
definition: sourceItem.definition,
|
|
34
|
-
});
|
|
35
|
-
}, [sourceItem]);
|
|
36
|
-
const copiedId = sourceItem ? initialParameter.id : undefined;
|
|
37
|
-
const handleSubmit = useCallback(async (parameter) => {
|
|
38
|
-
let createdParameter;
|
|
39
|
-
try {
|
|
40
|
-
createdParameter = await mutation.create(parameter);
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
if (copiedId !== undefined && parameter.id === copiedId && isDuplicateIdError(error)) {
|
|
44
|
-
const { id: _id, ...parameterWithoutId } = parameter;
|
|
45
|
-
createdParameter = await mutation.create(parameterWithoutId);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
throw error;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
onCreated?.(createdParameter);
|
|
52
|
-
onClose();
|
|
53
|
-
addSuccess(messages.parameterCreateSuccess);
|
|
54
|
-
}, [addSuccess, copiedId, mutation, onClose, onCreated]);
|
|
55
|
-
return (_jsx(Suspense, { fallback: null, children: _jsx(ParameterDialog, { mode: "create", initialParameter: initialParameter, onClose: onClose, onSubmit: handleSubmit }) }));
|
|
56
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type ICatalogItemParameter } from "../catalogItem/types.js";
|
|
2
|
-
type Props = {
|
|
3
|
-
item: ICatalogItemParameter;
|
|
4
|
-
onClose: () => void;
|
|
5
|
-
onDeleted: () => void;
|
|
6
|
-
};
|
|
7
|
-
export declare function ParameterDeleteDialog({ item, onClose, onDeleted }: Props): import("react/jsx-runtime").JSX.Element;
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=ParameterDeleteDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ParameterDeleteDialog.d.ts","sourceRoot":"","sources":["../../src/parameter/ParameterDeleteDialog.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAarE,KAAK,KAAK,GAAG;IACT,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,2CA4CxE"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { useCallback, useState } from "react";
|
|
4
|
-
import { FormattedMessage, defineMessages, useIntl } from "react-intl";
|
|
5
|
-
import { ConfirmDialog, useToastMessage } from "@gooddata/sdk-ui-kit";
|
|
6
|
-
import {} from "../catalogItem/types.js";
|
|
7
|
-
import { useParameterMutation } from "./ParameterMutationContext.js";
|
|
8
|
-
const messages = defineMessages({
|
|
9
|
-
title: { id: "analyticsCatalog.parameter.dialog.delete.title" },
|
|
10
|
-
body: { id: "analyticsCatalog.parameter.dialog.delete.body" },
|
|
11
|
-
submit: { id: "analyticsCatalog.parameter.dialog.delete.submit" },
|
|
12
|
-
cancel: { id: "analyticsCatalog.parameter.dialog.cancel" },
|
|
13
|
-
deleteSuccess: { id: "analyticsCatalog.parameter.delete.success" },
|
|
14
|
-
deleteError: { id: "analyticsCatalog.parameter.delete.error" },
|
|
15
|
-
});
|
|
16
|
-
export function ParameterDeleteDialog({ item, onClose, onDeleted }) {
|
|
17
|
-
const intl = useIntl();
|
|
18
|
-
const { addSuccess, addError } = useToastMessage();
|
|
19
|
-
const mutation = useParameterMutation();
|
|
20
|
-
const [isDeleting, setIsDeleting] = useState(false);
|
|
21
|
-
const displayName = item.title || item.identifier;
|
|
22
|
-
const handleDelete = useCallback(async () => {
|
|
23
|
-
setIsDeleting(true);
|
|
24
|
-
try {
|
|
25
|
-
await mutation.delete(item);
|
|
26
|
-
onDeleted();
|
|
27
|
-
onClose();
|
|
28
|
-
addSuccess(messages.deleteSuccess);
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
addError(messages.deleteError);
|
|
32
|
-
setIsDeleting(false);
|
|
33
|
-
}
|
|
34
|
-
}, [addError, addSuccess, item, mutation, onClose, onDeleted]);
|
|
35
|
-
return (_jsx(ConfirmDialog, { headline: intl.formatMessage(messages.title), cancelButtonText: intl.formatMessage(messages.cancel), submitButtonText: intl.formatMessage(messages.submit), isPositive: false, isSubmitDisabled: isDeleting, isCancelDisabled: isDeleting, showProgressIndicator: isDeleting, onCancel: onClose, onClose: onClose, onSubmit: handleDelete, displayCloseButton: !isDeleting, children: _jsx(FormattedMessage, { ...messages.body, values: {
|
|
36
|
-
name: displayName,
|
|
37
|
-
b: (chunks) => _jsx("b", { children: chunks }),
|
|
38
|
-
} }) }));
|
|
39
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { IParameterMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
|
-
import { type ParameterDraft } from "./parameterSerialization.js";
|
|
3
|
-
export type ParameterDialogMode = "create" | "edit";
|
|
4
|
-
type Props = {
|
|
5
|
-
mode: ParameterDialogMode;
|
|
6
|
-
initialParameter?: ParameterDraft;
|
|
7
|
-
onClose: () => void;
|
|
8
|
-
onSubmit: (parameter: IParameterMetadataObjectDefinition) => Promise<void>;
|
|
9
|
-
onDuplicate?: (parameter: IParameterMetadataObjectDefinition) => void;
|
|
10
|
-
};
|
|
11
|
-
export declare function ParameterDialog(props: Props): import("react/jsx-runtime").JSX.Element;
|
|
12
|
-
export {};
|
|
13
|
-
//# sourceMappingURL=ParameterDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ParameterDialog.d.ts","sourceRoot":"","sources":["../../src/parameter/ParameterDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AAO9E,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,6BAA6B,CAAC;AAyB5F,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpD,KAAK,KAAK,GAAG;IACT,IAAI,EAAE,mBAAmB,CAAC;IAC1B,gBAAgB,CAAC,EAAE,cAAc,CAAC;IAClC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,SAAS,EAAE,kCAAkC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,kCAAkC,KAAK,IAAI,CAAC;CACzE,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,2CAqK3C"}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { useCallback, useRef, useState } from "react";
|
|
4
|
-
import { FormattedMessage, defineMessages, useIntl } from "react-intl";
|
|
5
|
-
import { ConfirmDialog, UiButton, UiIcon, UiLink, UiTooltip } from "@gooddata/sdk-ui-kit";
|
|
6
|
-
import { useIsWhiteLabeled } from "../permission/PermissionsContext.js";
|
|
7
|
-
import { extractBackendErrorDetail } from "../utils/backendError.js";
|
|
8
|
-
import { useEnabledParameterTypes } from "./gate.js";
|
|
9
|
-
import { serializeParameterToYaml } from "./parameterSerialization.js";
|
|
10
|
-
import { validateParameterYaml } from "./parameterValidation.js";
|
|
11
|
-
import { ParameterYamlEditor } from "./ParameterYamlEditor.js";
|
|
12
|
-
const PARAMETER_DOCS_URL = "https://www.gooddata.ai/docs/cloud/experimental-features/numeric-parameters/";
|
|
13
|
-
const messages = defineMessages({
|
|
14
|
-
empty: { id: "analyticsCatalog.parameter.validation.empty" },
|
|
15
|
-
syntax: { id: "analyticsCatalog.parameter.validation.syntax" },
|
|
16
|
-
invalidStructure: { id: "analyticsCatalog.parameter.validation.invalidStructure" },
|
|
17
|
-
idImmutable: { id: "analyticsCatalog.parameter.dialog.edit.idImmutable" },
|
|
18
|
-
unsupportedType: { id: "analyticsCatalog.parameter.validation.unsupportedType" },
|
|
19
|
-
invalidDefaultValue: { id: "analyticsCatalog.parameter.validation.invalidDefaultValue" },
|
|
20
|
-
invalidConstraints: { id: "analyticsCatalog.parameter.validation.invalidConstraints" },
|
|
21
|
-
invalidConstraintRange: { id: "analyticsCatalog.parameter.validation.invalidConstraintRange" },
|
|
22
|
-
invalidTags: { id: "analyticsCatalog.parameter.validation.invalidTags" },
|
|
23
|
-
dialogSubmitError: { id: "analyticsCatalog.parameter.dialog.submit.error" },
|
|
24
|
-
dialogCreateTitle: { id: "analyticsCatalog.parameter.dialog.create.title" },
|
|
25
|
-
dialogEditTitle: { id: "analyticsCatalog.parameter.dialog.edit.title" },
|
|
26
|
-
dialogCreateSubmit: { id: "analyticsCatalog.parameter.dialog.create.submit" },
|
|
27
|
-
dialogEditSubmit: { id: "analyticsCatalog.parameter.dialog.edit.submit" },
|
|
28
|
-
dialogCancel: { id: "analyticsCatalog.parameter.dialog.cancel" },
|
|
29
|
-
dialogDuplicate: { id: "analyticsCatalog.parameter.dialog.edit.duplicate" },
|
|
30
|
-
});
|
|
31
|
-
export function ParameterDialog(props) {
|
|
32
|
-
const { mode, initialParameter, onClose, onSubmit, onDuplicate } = props;
|
|
33
|
-
const intl = useIntl();
|
|
34
|
-
const isEdit = mode === "edit";
|
|
35
|
-
const isWhiteLabeled = useIsWhiteLabeled();
|
|
36
|
-
const initialYaml = initialParameter ? serializeParameterToYaml(initialParameter) : "";
|
|
37
|
-
const yamlValue = useRef(initialYaml);
|
|
38
|
-
const [validationError, setValidationError] = useState(null);
|
|
39
|
-
const [submitError, setSubmitError] = useState(null);
|
|
40
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
41
|
-
const [isDirty, setIsDirty] = useState(false);
|
|
42
|
-
const headlineMessage = intl.formatMessage(isEdit ? messages.dialogEditTitle : messages.dialogCreateTitle);
|
|
43
|
-
const submitMessage = intl.formatMessage(isEdit ? messages.dialogEditSubmit : messages.dialogCreateSubmit);
|
|
44
|
-
const cancelMessage = intl.formatMessage(messages.dialogCancel);
|
|
45
|
-
const fixedIdentifier = isEdit ? initialParameter?.id : undefined;
|
|
46
|
-
const enabledTypes = useEnabledParameterTypes();
|
|
47
|
-
const validate = useCallback((value, allowIdChange = false) => {
|
|
48
|
-
return validateParameterYaml(value, {
|
|
49
|
-
enabledTypes,
|
|
50
|
-
fixedIdentifier: isEdit && !allowIdChange ? fixedIdentifier : undefined,
|
|
51
|
-
});
|
|
52
|
-
}, [enabledTypes, fixedIdentifier, isEdit]);
|
|
53
|
-
const formatValidationError = useCallback((result) => intl.formatMessage(messages[result.errorCode], {
|
|
54
|
-
type: result.type,
|
|
55
|
-
enabledTypes: intl.formatList(enabledTypes, { type: "conjunction" }),
|
|
56
|
-
}), [enabledTypes, intl]);
|
|
57
|
-
const handleClose = useCallback(() => {
|
|
58
|
-
if (!isSubmitting) {
|
|
59
|
-
onClose();
|
|
60
|
-
}
|
|
61
|
-
}, [isSubmitting, onClose]);
|
|
62
|
-
const handleChange = useCallback((nextValue) => {
|
|
63
|
-
yamlValue.current = nextValue;
|
|
64
|
-
setIsDirty(true);
|
|
65
|
-
setSubmitError(null);
|
|
66
|
-
setValidationError(null);
|
|
67
|
-
}, []);
|
|
68
|
-
const handleSubmit = useCallback(async () => {
|
|
69
|
-
const result = validate(yamlValue.current);
|
|
70
|
-
if (!result.isValid) {
|
|
71
|
-
setValidationError(formatValidationError(result));
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
setIsSubmitting(true);
|
|
75
|
-
setSubmitError(null);
|
|
76
|
-
try {
|
|
77
|
-
await onSubmit(result.parameter);
|
|
78
|
-
}
|
|
79
|
-
catch (error) {
|
|
80
|
-
setSubmitError(extractBackendErrorDetail(error) ?? intl.formatMessage(messages.dialogSubmitError));
|
|
81
|
-
}
|
|
82
|
-
finally {
|
|
83
|
-
setIsSubmitting(false);
|
|
84
|
-
}
|
|
85
|
-
}, [formatValidationError, intl, onSubmit, validate]);
|
|
86
|
-
const handleDuplicate = useCallback(() => {
|
|
87
|
-
if (!onDuplicate) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
setSubmitError(null);
|
|
91
|
-
const result = validate(yamlValue.current, true);
|
|
92
|
-
if (!result.isValid) {
|
|
93
|
-
setValidationError(formatValidationError(result));
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
onDuplicate(result.parameter);
|
|
97
|
-
}, [formatValidationError, onDuplicate, validate]);
|
|
98
|
-
const footerLeftRenderer = useCallback(() => (_jsxs("div", { className: "gd-ascode-dialog-footer-left", children: [isWhiteLabeled ? null : (_jsxs(UiLink, { variant: "secondary", href: PARAMETER_DOCS_URL, target: "_blank", rel: "noopener noreferrer", children: [
|
|
99
|
-
_jsx(UiIcon, { type: "question", size: 14, color: "complementary-6" }), _jsx(FormattedMessage, { id: "analyticsCatalog.parameter.dialog.help" })
|
|
100
|
-
] })), isEdit && onDuplicate ? (_jsx(UiButton, { label: intl.formatMessage(messages.dialogDuplicate), variant: "tertiary", isDisabled: isSubmitting, onClick: handleDuplicate })) : null] })), [handleDuplicate, intl, isEdit, isSubmitting, isWhiteLabeled, onDuplicate]);
|
|
101
|
-
return (_jsx(ConfirmDialog, { className: "gd-ascode-dialog", containerClassName: "gd-ascode-dialog-overlay", headline: headlineMessage, cancelButtonText: cancelMessage, submitButtonText: submitMessage, isPositive: true, isSubmitDisabled: isSubmitting || (isEdit && !isDirty), isCancelDisabled: isSubmitting, shouldCloseOnEscape: !isSubmitting, onCancel: handleClose, onClose: handleClose, onSubmit: handleSubmit, displayCloseButton: !isSubmitting, footerLeftRenderer: footerLeftRenderer, children: _jsxs("div", { className: "gd-ascode-dialog-content", children: [
|
|
102
|
-
_jsxs("div", { className: "gd-ascode-dialog-section-header", children: [
|
|
103
|
-
_jsx(FormattedMessage, { id: "analyticsCatalog.parameter.dialog.sectionHeader" }), _jsx(UiTooltip, { arrowPlacement: "top", optimalPlacement: true, triggerBy: ["hover", "click", "focus"], anchor: _jsx(UiIcon, { type: "question", size: 14, color: "complementary-6" }), content: _jsx(FormattedMessage, { id: "analyticsCatalog.parameter.dialog.sectionHeader.tooltip" }) })
|
|
104
|
-
] }), _jsx("div", { className: "gd-ascode-dialog-editor", children: _jsx(ParameterYamlEditor, { initialValue: initialYaml, enabledTypes: enabledTypes, onChange: handleChange, disabled: isSubmitting }) }), validationError || submitError ? (_jsxs("div", { className: "gd-ascode-dialog-error", children: [
|
|
105
|
-
_jsx("span", { className: "gd-ascode-dialog-error-label", children: _jsx(FormattedMessage, { id: "analyticsCatalog.dialog.error.label" }) }), " ", validationError ?? submitError] })) : null] }) }));
|
|
106
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { IParameterMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
|
-
import { type ICatalogItemParameter } from "../catalogItem/types.js";
|
|
3
|
-
type Props = {
|
|
4
|
-
item: ICatalogItemParameter;
|
|
5
|
-
onClose: () => void;
|
|
6
|
-
onSaved: (item: ICatalogItemParameter) => void;
|
|
7
|
-
onDuplicate?: (parameter: IParameterMetadataObjectDefinition) => void;
|
|
8
|
-
};
|
|
9
|
-
export declare function ParameterEditDialog({ item, onClose, onSaved, onDuplicate }: Props): import("react/jsx-runtime").JSX.Element;
|
|
10
|
-
export {};
|
|
11
|
-
//# sourceMappingURL=ParameterEditDialog.d.ts.map
|