@gooddata/sdk-ui-catalog 11.48.0-alpha.0 → 11.48.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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/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/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
|