@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,5 +1,5 @@
|
|
|
1
1
|
// (C) 2026 GoodData Corporation
|
|
2
|
-
import { idRef, } from "@gooddata/sdk-model";
|
|
2
|
+
import { idRef, isMeasureMetadataObject } from "@gooddata/sdk-model";
|
|
3
3
|
import { convertMeasureToCatalogItem } from "../catalogItem/converter.js";
|
|
4
4
|
import { createMeasureCatalogItem, deleteMeasureCatalogItem, getMeasureCatalogItem, getMeasureReferencingObjectsCatalogItem, updateMeasureCatalogItem, } from "../catalogItem/query.js";
|
|
5
5
|
import { overlayMetricYamlFields } from "./metricConverter.js";
|
|
@@ -12,28 +12,26 @@ export function createMetricMutationAdapter(backend, workspace) {
|
|
|
12
12
|
const savedMeasure = await createMeasureCatalogItem(backend, workspace, definition);
|
|
13
13
|
return convertMeasureToCatalogItem(savedMeasure);
|
|
14
14
|
},
|
|
15
|
-
async update(
|
|
16
|
-
|
|
15
|
+
async update(base, definition) {
|
|
16
|
+
// The measures endpoint is a full replace, so overlay the YAML-owned fields onto the loaded
|
|
17
|
+
// measure to carry over what the YAML cannot express (metricType, isHiddenFromKda, identity).
|
|
18
|
+
// `base` must be the persisted measure `load` returned — a bare definition (no server-managed
|
|
19
|
+
// `ref`) would silently drop those fields, so reject it loudly rather than corrupt the update.
|
|
20
|
+
if (!isMeasureMetadataObject(base)) {
|
|
21
|
+
throw new Error("Metric update requires the loaded measure as base, not a bare definition.");
|
|
22
|
+
}
|
|
23
|
+
const savedMeasure = await updateMeasureCatalogItem(backend, workspace, overlayMetricYamlFields(base, definition));
|
|
17
24
|
return convertMeasureToCatalogItem(savedMeasure);
|
|
18
25
|
},
|
|
19
26
|
async delete(ref) {
|
|
20
27
|
await deleteMeasureCatalogItem(backend, workspace, idRef(ref.identifier, "measure"));
|
|
21
28
|
},
|
|
22
|
-
async load(
|
|
23
|
-
return getMeasureCatalogItem(backend, workspace, idRef(
|
|
29
|
+
async load(item) {
|
|
30
|
+
return getMeasureCatalogItem(backend, workspace, idRef(item.identifier, "measure"));
|
|
24
31
|
},
|
|
25
|
-
async
|
|
26
|
-
|
|
32
|
+
async getReferencingObjectsCount(item) {
|
|
33
|
+
const referencing = await getMeasureReferencingObjectsCatalogItem(backend, workspace, idRef(item.identifier, "measure"));
|
|
34
|
+
return (referencing.insights?.length ?? 0) + (referencing.measures?.length ?? 0);
|
|
27
35
|
},
|
|
28
36
|
};
|
|
29
37
|
}
|
|
30
|
-
/**
|
|
31
|
-
* Overlays the fields the as-code YAML owns onto the loaded metric.
|
|
32
|
-
*
|
|
33
|
-
* The measures update endpoint is a full replace, so fields absent from the YAML
|
|
34
|
-
* (`metricType`, `isHiddenFromKda`, identity, ...) must be carried over from the loaded metric to
|
|
35
|
-
* avoid wiping them; `overlayMetricYamlFields` preserves them via the base spread.
|
|
36
|
-
*/
|
|
37
|
-
function mergeMeasureDefinition(existing, definition) {
|
|
38
|
-
return overlayMetricYamlFields(existing, definition);
|
|
39
|
-
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metricValidation.d.ts","sourceRoot":"","sources":["../../src/metric/metricValidation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metricValidation.d.ts","sourceRoot":"","sources":["../../src/metric/metricValidation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAO5E,MAAM,MAAM,sBAAsB,GAC5B;IACI,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,gCAAgC,CAAC;CAC7C,GACD;IACI,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,EAAE,yBAAyB,CAAC;CACxC,CAAC;AAER,MAAM,MAAM,yBAAyB,GAC/B,OAAO,GACP,QAAQ,GACR,kBAAkB,GAClB,aAAa,GACb,aAAa,GACb,aAAa,CAAC;AAEpB,KAAK,yBAAyB,GAAG;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,yBAA8B,GACxC,sBAAsB,CAUxB"}
|
|
@@ -1,47 +1,28 @@
|
|
|
1
1
|
// (C) 2026 GoodData Corporation
|
|
2
|
-
import {
|
|
2
|
+
import { validateYaml } from "../asCode/validateYaml.js";
|
|
3
3
|
import { metricYamlToDefinition } from "./metricConverter.js";
|
|
4
4
|
import { metricSchema } from "./metricSchema.js";
|
|
5
5
|
export function validateMetricYaml(value, options = {}) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return invalid("syntax");
|
|
15
|
-
}
|
|
16
|
-
const result = metricSchema.safeParse(parsed);
|
|
17
|
-
if (!result.success) {
|
|
18
|
-
return classifySchemaError(result.error, parsed);
|
|
19
|
-
}
|
|
20
|
-
if (options.fixedIdentifier !== undefined && result.data.id !== options.fixedIdentifier) {
|
|
21
|
-
return invalid("idImmutable");
|
|
22
|
-
}
|
|
23
|
-
return {
|
|
24
|
-
isValid: true,
|
|
25
|
-
measure: metricYamlToDefinition(result.data),
|
|
26
|
-
};
|
|
6
|
+
const result = validateYaml(value, {
|
|
7
|
+
schema: metricSchema,
|
|
8
|
+
fixedIdentifier: options.fixedIdentifier,
|
|
9
|
+
classifyError: classifyMetricError,
|
|
10
|
+
});
|
|
11
|
+
return result.ok
|
|
12
|
+
? { isValid: true, measure: metricYamlToDefinition(result.data) }
|
|
13
|
+
: { isValid: false, errorCode: result.errorCode };
|
|
27
14
|
}
|
|
28
|
-
function
|
|
15
|
+
function classifyMetricError(error, parsed) {
|
|
29
16
|
const maqlProvided = typeof parsed === "object" && parsed !== null && parsed.maql !== undefined;
|
|
30
17
|
for (const issue of error.issues) {
|
|
31
18
|
const path = issue.path.map(String).join(".");
|
|
32
19
|
if (path === "maql") {
|
|
33
20
|
// A present-but-wrong-typed maql is a structural error, not a missing field.
|
|
34
|
-
return
|
|
21
|
+
return maqlProvided ? "invalidStructure" : "missingMaql";
|
|
35
22
|
}
|
|
36
23
|
if (path === "tags" || path.startsWith("tags.")) {
|
|
37
|
-
return
|
|
24
|
+
return "invalidTags";
|
|
38
25
|
}
|
|
39
26
|
}
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
function invalid(code) {
|
|
43
|
-
return {
|
|
44
|
-
isValid: false,
|
|
45
|
-
errorCode: code,
|
|
46
|
-
};
|
|
27
|
+
return "invalidStructure";
|
|
47
28
|
}
|
|
@@ -37,7 +37,7 @@ export function createTestMetricMutationPort(overrides = {}) {
|
|
|
37
37
|
expression: "SELECT 1",
|
|
38
38
|
format: "#,##0.00",
|
|
39
39
|
}),
|
|
40
|
-
|
|
40
|
+
getReferencingObjectsCount: vi.fn().mockResolvedValue(0),
|
|
41
41
|
...overrides,
|
|
42
42
|
};
|
|
43
43
|
}
|
package/esm/parameter/gate.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { ParameterType } from "@gooddata/sdk-model";
|
|
2
|
+
/** The flag gating catalog parameters. The single source of truth, referenced by the gates below and
|
|
3
|
+
* `parameterDescriptor.featureFlag`. */
|
|
4
|
+
export declare const PARAMETER_FEATURE_FLAG = "enableParameters";
|
|
2
5
|
/**
|
|
3
6
|
* Catalog parameter feature gate.
|
|
4
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/parameter/gate.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/parameter/gate.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD;yCACyC;AACzC,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AAEzD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,aAAa,EAAE,CAM1D"}
|
package/esm/parameter/gate.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
// (C) 2026 GoodData Corporation
|
|
2
2
|
import { useMemo } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { useCanManageAsCode } from "../asCode/gate.js";
|
|
4
|
+
import { useFeatureFlag } from "../permission/PermissionsContext.js";
|
|
5
|
+
/** The flag gating catalog parameters. The single source of truth, referenced by the gates below and
|
|
6
|
+
* `parameterDescriptor.featureFlag`. */
|
|
7
|
+
export const PARAMETER_FEATURE_FLAG = "enableParameters";
|
|
4
8
|
/**
|
|
5
9
|
* Catalog parameter feature gate.
|
|
6
10
|
*/
|
|
7
11
|
export function useIsParametersEnabled() {
|
|
8
|
-
return useFeatureFlag(
|
|
12
|
+
return useFeatureFlag(PARAMETER_FEATURE_FLAG);
|
|
9
13
|
}
|
|
10
14
|
/**
|
|
11
15
|
* Whether the current user can manage parameters in the catalog.
|
|
12
16
|
*/
|
|
13
17
|
export function useCanManageParameter() {
|
|
14
|
-
|
|
15
|
-
const canManageProject = useWorkspacePermission("canManageProject");
|
|
16
|
-
return isParametersEnabled && canManageProject;
|
|
18
|
+
return useCanManageAsCode(PARAMETER_FEATURE_FLAG);
|
|
17
19
|
}
|
|
18
20
|
/**
|
|
19
21
|
* Parameter types authorable in the catalog, gated by `enableStringParameters`.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import type { IParameterMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
2
|
export declare function createCopiedParameter(parameter: IParameterMetadataObjectDefinition): IParameterMetadataObjectDefinition;
|
|
3
|
-
export declare function isDuplicateIdError(error: unknown): boolean;
|
|
4
3
|
//# sourceMappingURL=parameterCopy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parameterCopy.d.ts","sourceRoot":"","sources":["../../src/parameter/parameterCopy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parameterCopy.d.ts","sourceRoot":"","sources":["../../src/parameter/parameterCopy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AAI9E,wBAAgB,qBAAqB,CACjC,SAAS,EAAE,kCAAkC,GAC9C,kCAAkC,CAQpC"}
|
|
@@ -1,48 +1,11 @@
|
|
|
1
1
|
// (C) 2026 GoodData Corporation
|
|
2
|
-
import {
|
|
3
|
-
const canonicalUuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4
|
-
const trailingCopySuffixRegex = /^(.*) \((\d+)\)$/;
|
|
2
|
+
import { deriveCopyIdentity } from "../asCode/copy.js";
|
|
5
3
|
export function createCopiedParameter(parameter) {
|
|
4
|
+
// A parameter definition carries no server-managed fields, so every field other than the
|
|
5
|
+
// re-derived identity is copied as-is.
|
|
6
6
|
const { id: _id, title: _title, ...parameterRest } = parameter;
|
|
7
|
-
const title = getCopiedTitle(parameter.title);
|
|
8
|
-
const id = shouldOmitCopiedId(parameter.id) ? undefined : getCopiedId(title);
|
|
9
7
|
return {
|
|
10
|
-
...(
|
|
11
|
-
...(title === undefined ? {} : { title }),
|
|
8
|
+
...deriveCopyIdentity(parameter),
|
|
12
9
|
...parameterRest,
|
|
13
10
|
};
|
|
14
11
|
}
|
|
15
|
-
function getCopiedTitle(title) {
|
|
16
|
-
if (title === undefined) {
|
|
17
|
-
return undefined;
|
|
18
|
-
}
|
|
19
|
-
if (title === "") {
|
|
20
|
-
return "";
|
|
21
|
-
}
|
|
22
|
-
const match = title.match(trailingCopySuffixRegex);
|
|
23
|
-
if (match) {
|
|
24
|
-
const [, prefix, suffix] = match;
|
|
25
|
-
return `${prefix} (${Number(suffix) + 1})`;
|
|
26
|
-
}
|
|
27
|
-
return `${title} (2)`;
|
|
28
|
-
}
|
|
29
|
-
function shouldOmitCopiedId(id) {
|
|
30
|
-
return id === undefined || isCanonicalUuid(id);
|
|
31
|
-
}
|
|
32
|
-
function getCopiedId(title) {
|
|
33
|
-
if (!title) {
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
36
|
-
const normalizedTitle = title
|
|
37
|
-
.normalize("NFKD")
|
|
38
|
-
.replace(/[\u0300-\u036f]/g, "")
|
|
39
|
-
.replace(/\W/g, "_")
|
|
40
|
-
.toLowerCase();
|
|
41
|
-
return normalizedTitle || undefined;
|
|
42
|
-
}
|
|
43
|
-
function isCanonicalUuid(value) {
|
|
44
|
-
return canonicalUuidRegex.test(value);
|
|
45
|
-
}
|
|
46
|
-
export function isDuplicateIdError(error) {
|
|
47
|
-
return isUnexpectedResponseError(error) && error.httpStatus === 409;
|
|
48
|
-
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IParameterMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
|
+
import type { ICatalogItemParameter } from "../catalogItem/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare const parameterDescriptor: import("../asCode/descriptor.js").IAsCodeDescriptor<IParameterMetadataObjectDefinition, ICatalogItemParameter>;
|
|
7
|
+
//# sourceMappingURL=parameterDescriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parameterDescriptor.d.ts","sourceRoot":"","sources":["../../src/parameter/parameterDescriptor.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AAG9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAqErE;;GAEG;AACH,eAAO,MAAM,mBAAmB,gHA2B9B,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { defineMessages, useIntl } from "react-intl";
|
|
4
|
+
import { defineAsCodeDescriptor } from "../asCode/descriptor.js";
|
|
5
|
+
import { ObjectTypes } from "../objectType/constants.js";
|
|
6
|
+
import { PARAMETER_FEATURE_FLAG, useEnabledParameterTypes } from "./gate.js";
|
|
7
|
+
import { createParameterCompletions } from "./parameterCompletions.js";
|
|
8
|
+
import { createCopiedParameter } from "./parameterCopy.js";
|
|
9
|
+
import { createParameterMutationAdapter } from "./parameterMutationPort.js";
|
|
10
|
+
import { serializeParameterToYaml } from "./parameterSerialization.js";
|
|
11
|
+
import { validateParameterYaml } from "./parameterValidation.js";
|
|
12
|
+
const PARAMETER_DOCS_URL = "https://www.gooddata.ai/docs/cloud/experimental-features/numeric-parameters/";
|
|
13
|
+
const messages = defineMessages({
|
|
14
|
+
createTitle: { id: "analyticsCatalog.parameter.dialog.create.title" },
|
|
15
|
+
editTitle: { id: "analyticsCatalog.parameter.dialog.edit.title" },
|
|
16
|
+
duplicate: { id: "analyticsCatalog.parameter.dialog.edit.duplicate" },
|
|
17
|
+
createDefaultTitle: { id: "analyticsCatalog.parameter.create.defaultTitle" },
|
|
18
|
+
createSuccess: { id: "analyticsCatalog.parameter.create.success" },
|
|
19
|
+
updateSuccess: { id: "analyticsCatalog.parameter.update.success" },
|
|
20
|
+
sectionHeader: { id: "analyticsCatalog.parameter.dialog.sectionHeader" },
|
|
21
|
+
sectionHeaderTooltip: { id: "analyticsCatalog.parameter.dialog.sectionHeader.tooltip" },
|
|
22
|
+
help: { id: "analyticsCatalog.parameter.dialog.help" },
|
|
23
|
+
submitError: { id: "analyticsCatalog.parameter.dialog.submit.error" },
|
|
24
|
+
deleteTitle: { id: "analyticsCatalog.parameter.dialog.delete.title" },
|
|
25
|
+
deleteBody: { id: "analyticsCatalog.parameter.dialog.delete.body" },
|
|
26
|
+
deleteSubmit: { id: "analyticsCatalog.parameter.dialog.delete.submit" },
|
|
27
|
+
deleteSuccess: { id: "analyticsCatalog.parameter.delete.success" },
|
|
28
|
+
deleteError: { id: "analyticsCatalog.parameter.delete.error" },
|
|
29
|
+
});
|
|
30
|
+
const errorMessages = defineMessages({
|
|
31
|
+
empty: { id: "analyticsCatalog.parameter.validation.empty" },
|
|
32
|
+
syntax: { id: "analyticsCatalog.parameter.validation.syntax" },
|
|
33
|
+
invalidStructure: { id: "analyticsCatalog.parameter.validation.invalidStructure" },
|
|
34
|
+
idImmutable: { id: "analyticsCatalog.parameter.dialog.edit.idImmutable" },
|
|
35
|
+
unsupportedType: { id: "analyticsCatalog.parameter.validation.unsupportedType" },
|
|
36
|
+
invalidDefaultValue: { id: "analyticsCatalog.parameter.validation.invalidDefaultValue" },
|
|
37
|
+
invalidConstraints: { id: "analyticsCatalog.parameter.validation.invalidConstraints" },
|
|
38
|
+
invalidConstraintRange: { id: "analyticsCatalog.parameter.validation.invalidConstraintRange" },
|
|
39
|
+
invalidTags: { id: "analyticsCatalog.parameter.validation.invalidTags" },
|
|
40
|
+
});
|
|
41
|
+
function useParameterEditing() {
|
|
42
|
+
const intl = useIntl();
|
|
43
|
+
const enabledTypes = useEnabledParameterTypes();
|
|
44
|
+
const completionSource = useMemo(() => createParameterCompletions(enabledTypes), [enabledTypes]);
|
|
45
|
+
return useMemo(() => ({
|
|
46
|
+
completionSource,
|
|
47
|
+
syntaxErrorMessage: intl.formatMessage(errorMessages.syntax),
|
|
48
|
+
// Parameter YAML round-trips 1:1 to its definition, so serialization is a plain stringify.
|
|
49
|
+
serialize: (definition) => serializeParameterToYaml(definition),
|
|
50
|
+
validate: (value, options) => {
|
|
51
|
+
const result = validateParameterYaml(value, { enabledTypes, ...options });
|
|
52
|
+
return result.isValid
|
|
53
|
+
? { isValid: true, definition: result.parameter }
|
|
54
|
+
: {
|
|
55
|
+
isValid: false,
|
|
56
|
+
error: intl.formatMessage(errorMessages[result.errorCode], {
|
|
57
|
+
type: result.type,
|
|
58
|
+
enabledTypes: intl.formatList(enabledTypes, { type: "conjunction" }),
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
}), [completionSource, enabledTypes, intl]);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
export const parameterDescriptor = defineAsCodeDescriptor({
|
|
68
|
+
objectType: ObjectTypes.PARAMETER,
|
|
69
|
+
docsUrl: PARAMETER_DOCS_URL,
|
|
70
|
+
featureFlag: PARAMETER_FEATURE_FLAG,
|
|
71
|
+
messages,
|
|
72
|
+
useEditing: useParameterEditing,
|
|
73
|
+
createMutationPort: createParameterMutationAdapter,
|
|
74
|
+
emptyDefinition: (defaultTitle) => ({
|
|
75
|
+
type: "parameter",
|
|
76
|
+
title: defaultTitle,
|
|
77
|
+
description: "",
|
|
78
|
+
definition: { type: "NUMBER", defaultValue: 0 },
|
|
79
|
+
}),
|
|
80
|
+
// No port.load: the catalog item maps field-for-field to a definition, so the editor seeds from it.
|
|
81
|
+
editSeed: (item) => ({
|
|
82
|
+
id: item.identifier,
|
|
83
|
+
type: "parameter",
|
|
84
|
+
title: item.title,
|
|
85
|
+
description: item.description,
|
|
86
|
+
tags: item.tags,
|
|
87
|
+
definition: item.definition,
|
|
88
|
+
}),
|
|
89
|
+
// Source is already a definition, so toCopy only re-derives identity; no applyYamlEdits (YAML round-trips 1:1).
|
|
90
|
+
toCopy: createCopiedParameter,
|
|
91
|
+
});
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
2
2
|
import type { IParameterMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
3
|
-
import type {
|
|
3
|
+
import type { IAsCodeMutationPort } from "../asCode/descriptor.js";
|
|
4
|
+
import type { ICatalogItemParameter } from "../catalogItem/types.js";
|
|
4
5
|
/**
|
|
6
|
+
* A parameter's YAML round-trips 1:1 to its definition, so the editor works directly off the catalog
|
|
7
|
+
* item (see the descriptor's `editSeed`) — there is no `load` and no `getReferencingObjectsCount`.
|
|
5
8
|
* @internal
|
|
6
9
|
*/
|
|
7
|
-
export
|
|
8
|
-
create(definition: IParameterMetadataObjectDefinition): Promise<ICatalogItemParameter>;
|
|
9
|
-
update(item: ICatalogItemParameter): Promise<ICatalogItemParameter>;
|
|
10
|
-
delete(ref: ICatalogItemRef): Promise<void>;
|
|
11
|
-
}
|
|
10
|
+
export type IParameterMutationPort = IAsCodeMutationPort<IParameterMetadataObjectDefinition, ICatalogItemParameter>;
|
|
12
11
|
/**
|
|
13
12
|
* @internal
|
|
14
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parameterMutationPort.d.ts","sourceRoot":"","sources":["../../src/parameter/parameterMutationPort.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"parameterMutationPort.d.ts","sourceRoot":"","sources":["../../src/parameter/parameterMutationPort.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AAE9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAOnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,mBAAmB,CACpD,kCAAkC,EAClC,qBAAqB,CACxB,CAAC;AAEF;;GAEG;AACH,wBAAgB,8BAA8B,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,GAClB,sBAAsB,CA2BxB"}
|
|
@@ -10,8 +10,21 @@ export function createParameterMutationAdapter(backend, workspace) {
|
|
|
10
10
|
const savedParameter = await createParameterCatalogItem(backend, workspace, definition);
|
|
11
11
|
return convertParameterToCatalogItem(savedParameter);
|
|
12
12
|
},
|
|
13
|
-
async update(
|
|
14
|
-
|
|
13
|
+
async update(base, definition) {
|
|
14
|
+
// Identity is authoritative from the base the editor started from, never from the editable
|
|
15
|
+
// YAML — a hand-edited `id` must not retarget the update to a different parameter.
|
|
16
|
+
const identity = base.id;
|
|
17
|
+
if (identity === undefined) {
|
|
18
|
+
throw new Error("Cannot update a parameter without an identity.");
|
|
19
|
+
}
|
|
20
|
+
if (definition.id !== undefined && definition.id !== identity) {
|
|
21
|
+
throw new Error("A parameter's identity cannot be changed during an update.");
|
|
22
|
+
}
|
|
23
|
+
// The parsed definition is the complete new state (1:1 round-trip); only its identity is pinned.
|
|
24
|
+
const savedParameter = await updateParameterCatalogItem(backend, workspace, {
|
|
25
|
+
...definition,
|
|
26
|
+
id: identity,
|
|
27
|
+
});
|
|
15
28
|
return convertParameterToCatalogItem(savedParameter);
|
|
16
29
|
},
|
|
17
30
|
async delete(ref) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gooddata/sdk-ui-catalog",
|
|
3
|
-
"version": "11.48.0-alpha.
|
|
3
|
+
"version": "11.48.0-alpha.2",
|
|
4
4
|
"description": "GoodData SDK - Analytics Catalog",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "GoodData Corporation",
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"tslib": "2.8.1",
|
|
42
42
|
"yaml": "2.8.3",
|
|
43
43
|
"zod": "4.3.6",
|
|
44
|
-
"@gooddata/sdk-
|
|
45
|
-
"@gooddata/sdk-
|
|
46
|
-
"@gooddata/sdk-
|
|
47
|
-
"@gooddata/sdk-
|
|
48
|
-
"@gooddata/sdk-
|
|
49
|
-
"@gooddata/sdk-ui-kit": "11.48.0-alpha.
|
|
50
|
-
"@gooddata/sdk-ui-
|
|
51
|
-
"@gooddata/sdk-ui-
|
|
52
|
-
"@gooddata/util": "11.48.0-alpha.
|
|
44
|
+
"@gooddata/sdk-model": "11.48.0-alpha.2",
|
|
45
|
+
"@gooddata/sdk-ui": "11.48.0-alpha.2",
|
|
46
|
+
"@gooddata/sdk-ui-ext": "11.48.0-alpha.2",
|
|
47
|
+
"@gooddata/sdk-code-schemas": "11.48.0-alpha.2",
|
|
48
|
+
"@gooddata/sdk-backend-spi": "11.48.0-alpha.2",
|
|
49
|
+
"@gooddata/sdk-ui-kit": "11.48.0-alpha.2",
|
|
50
|
+
"@gooddata/sdk-ui-theme-provider": "11.48.0-alpha.2",
|
|
51
|
+
"@gooddata/sdk-ui-semantic-search": "11.48.0-alpha.2",
|
|
52
|
+
"@gooddata/util": "11.48.0-alpha.2"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@microsoft/api-documenter": "^7.17.0",
|
|
@@ -89,11 +89,11 @@
|
|
|
89
89
|
"typescript": "5.9.3",
|
|
90
90
|
"vitest": "4.1.8",
|
|
91
91
|
"vitest-dom": "0.1.1",
|
|
92
|
-
"@gooddata/eslint-config": "11.48.0-alpha.
|
|
93
|
-
"@gooddata/
|
|
94
|
-
"@gooddata/
|
|
95
|
-
"@gooddata/sdk-backend-mockingbird": "11.48.0-alpha.
|
|
96
|
-
"@gooddata/stylelint-config": "11.48.0-alpha.
|
|
92
|
+
"@gooddata/eslint-config": "11.48.0-alpha.2",
|
|
93
|
+
"@gooddata/oxlint-config": "11.48.0-alpha.2",
|
|
94
|
+
"@gooddata/i18n-toolkit": "11.48.0-alpha.2",
|
|
95
|
+
"@gooddata/sdk-backend-mockingbird": "11.48.0-alpha.2",
|
|
96
|
+
"@gooddata/stylelint-config": "11.48.0-alpha.2"
|
|
97
97
|
},
|
|
98
98
|
"peerDependencies": {
|
|
99
99
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { IMeasureMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
|
-
import type { ICatalogItemMeasure } from "../catalogItem/types.js";
|
|
3
|
-
type Props = {
|
|
4
|
-
sourceDefinition?: IMeasureMetadataObjectDefinition;
|
|
5
|
-
isLoading?: boolean;
|
|
6
|
-
onClose: () => void;
|
|
7
|
-
onCreated?: (item: ICatalogItemMeasure) => void;
|
|
8
|
-
};
|
|
9
|
-
export declare function MetricCreateDialog({ sourceDefinition, isLoading, onClose, onCreated }: Props): import("react/jsx-runtime").JSX.Element;
|
|
10
|
-
export {};
|
|
11
|
-
//# sourceMappingURL=MetricCreateDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricCreateDialog.d.ts","sourceRoot":"","sources":["../../src/metric/MetricCreateDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAG5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAYnE,KAAK,KAAK,GAAG;IACT,gBAAgB,CAAC,EAAE,gCAAgC,CAAC;IACpD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACnD,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,SAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,2CA0DpG"}
|
|
@@ -1,55 +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, useIntl } from "react-intl";
|
|
5
|
-
import { useToastMessage } from "@gooddata/sdk-ui-kit";
|
|
6
|
-
import { definitionToMetricYaml, mergeCopiedMetricDefinition } from "./metricConverter.js";
|
|
7
|
-
import { createCopiedMetric, isDuplicateIdError } from "./metricCopy.js";
|
|
8
|
-
import { MetricDialog } from "./MetricDialog.js";
|
|
9
|
-
import { useMetricMutation } from "./MetricMutationContext.js";
|
|
10
|
-
const messages = defineMessages({
|
|
11
|
-
metricCreateSuccess: { id: "analyticsCatalog.metric.create.success" },
|
|
12
|
-
metricCreateDefaultTitle: { id: "analyticsCatalog.metric.create.defaultTitle" },
|
|
13
|
-
});
|
|
14
|
-
export function MetricCreateDialog({ sourceDefinition, isLoading = false, onClose, onCreated }) {
|
|
15
|
-
const intl = useIntl();
|
|
16
|
-
const { addSuccess } = useToastMessage();
|
|
17
|
-
const mutation = useMetricMutation();
|
|
18
|
-
// The single source of truth for a duplicate's copy semantics (title bump, id derivation, and
|
|
19
|
-
// which author-owned fields carry over). Undefined for a blank create.
|
|
20
|
-
const copiedMetric = useMemo(() => (sourceDefinition ? createCopiedMetric(sourceDefinition) : undefined), [sourceDefinition]);
|
|
21
|
-
const initialMetric = useMemo(() => {
|
|
22
|
-
if (!copiedMetric) {
|
|
23
|
-
return {
|
|
24
|
-
type: "metric",
|
|
25
|
-
title: intl.formatMessage(messages.metricCreateDefaultTitle),
|
|
26
|
-
maql: "SELECT 1",
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
return definitionToMetricYaml(copiedMetric);
|
|
30
|
-
}, [copiedMetric, intl]);
|
|
31
|
-
const copiedId = copiedMetric ? initialMetric.id : undefined;
|
|
32
|
-
const handleSubmit = useCallback(async (metric) => {
|
|
33
|
-
// A duplicate layers the author's YAML edits over the copied source so its non-YAML
|
|
34
|
-
// fields (metricType, isHiddenFromKda) survive the lossy YAML round-trip; a blank create
|
|
35
|
-
// has no source and persists the parsed YAML as-is.
|
|
36
|
-
const definition = copiedMetric ? mergeCopiedMetricDefinition(copiedMetric, metric) : metric;
|
|
37
|
-
let createdMetric;
|
|
38
|
-
try {
|
|
39
|
-
createdMetric = await mutation.create(definition);
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
if (copiedId !== undefined && definition.id === copiedId && isDuplicateIdError(error)) {
|
|
43
|
-
const { id: _id, ...metricWithoutId } = definition;
|
|
44
|
-
createdMetric = await mutation.create(metricWithoutId);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
throw error;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
onCreated?.(createdMetric);
|
|
51
|
-
onClose();
|
|
52
|
-
addSuccess(messages.metricCreateSuccess);
|
|
53
|
-
}, [addSuccess, copiedId, copiedMetric, mutation, onClose, onCreated]);
|
|
54
|
-
return (_jsx(MetricDialog, { mode: "create", isLoading: isLoading, initialMetric: initialMetric, onClose: onClose, onSubmit: handleSubmit }));
|
|
55
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type ICatalogItemMeasure } from "../catalogItem/types.js";
|
|
2
|
-
type Props = {
|
|
3
|
-
item: ICatalogItemMeasure;
|
|
4
|
-
onClose: () => void;
|
|
5
|
-
onDeleted: () => void;
|
|
6
|
-
};
|
|
7
|
-
export declare function MetricDeleteDialog({ item, onClose, onDeleted }: Props): import("react/jsx-runtime").JSX.Element;
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=MetricDeleteDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricDeleteDialog.d.ts","sourceRoot":"","sources":["../../src/metric/MetricDeleteDialog.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAcnE,KAAK,KAAK,GAAG;IACT,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,2CA+ErE"}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// (C) 2026 GoodData Corporation
|
|
3
|
-
import { useCallback, useEffect, 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 { useMetricMutation } from "./MetricMutationContext.js";
|
|
8
|
-
const messages = defineMessages({
|
|
9
|
-
title: { id: "analyticsCatalog.metric.dialog.delete.title" },
|
|
10
|
-
body: { id: "analyticsCatalog.metric.dialog.delete.body" },
|
|
11
|
-
usageWarning: { id: "analyticsCatalog.metric.dialog.delete.usageWarning" },
|
|
12
|
-
submit: { id: "analyticsCatalog.metric.dialog.delete.submit" },
|
|
13
|
-
cancel: { id: "analyticsCatalog.metric.dialog.cancel" },
|
|
14
|
-
deleteSuccess: { id: "analyticsCatalog.metric.delete.success" },
|
|
15
|
-
deleteError: { id: "analyticsCatalog.metric.delete.error" },
|
|
16
|
-
});
|
|
17
|
-
export function MetricDeleteDialog({ item, onClose, onDeleted }) {
|
|
18
|
-
const intl = useIntl();
|
|
19
|
-
const { addSuccess, addError } = useToastMessage();
|
|
20
|
-
const mutation = useMetricMutation();
|
|
21
|
-
const [isDeleting, setIsDeleting] = useState(false);
|
|
22
|
-
// undefined until the usage lookup resolves; deletion is withheld until then so the dependent-object
|
|
23
|
-
// warning can surface before the user can confirm.
|
|
24
|
-
const [referencingCount, setReferencingCount] = useState(undefined);
|
|
25
|
-
const displayName = item.title || item.identifier;
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
let cancelled = false;
|
|
28
|
-
mutation
|
|
29
|
-
.getReferencingObjects(item)
|
|
30
|
-
.then((referencing) => {
|
|
31
|
-
if (!cancelled) {
|
|
32
|
-
const count = (referencing.insights?.length ?? 0) + (referencing.measures?.length ?? 0);
|
|
33
|
-
setReferencingCount(count);
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
.catch(() => {
|
|
37
|
-
// Usage lookup is advisory; on failure fall back to no warning rather than block deletion.
|
|
38
|
-
if (!cancelled) {
|
|
39
|
-
setReferencingCount(0);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
return () => {
|
|
43
|
-
cancelled = true;
|
|
44
|
-
};
|
|
45
|
-
}, [item, mutation]);
|
|
46
|
-
const handleDelete = useCallback(async () => {
|
|
47
|
-
setIsDeleting(true);
|
|
48
|
-
try {
|
|
49
|
-
await mutation.delete(item);
|
|
50
|
-
onDeleted();
|
|
51
|
-
onClose();
|
|
52
|
-
addSuccess(messages.deleteSuccess);
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
addError(messages.deleteError);
|
|
56
|
-
setIsDeleting(false);
|
|
57
|
-
}
|
|
58
|
-
}, [addError, addSuccess, item, mutation, onClose, onDeleted]);
|
|
59
|
-
const handleClose = useCallback(() => {
|
|
60
|
-
if (!isDeleting) {
|
|
61
|
-
onClose();
|
|
62
|
-
}
|
|
63
|
-
}, [isDeleting, onClose]);
|
|
64
|
-
return (_jsxs(ConfirmDialog, { headline: intl.formatMessage(messages.title), cancelButtonText: intl.formatMessage(messages.cancel), submitButtonText: intl.formatMessage(messages.submit), isPositive: false, isSubmitDisabled: isDeleting || referencingCount === undefined, isCancelDisabled: isDeleting, showProgressIndicator: isDeleting, onCancel: handleClose, onClose: handleClose, onSubmit: handleDelete, displayCloseButton: !isDeleting, children: [_jsx(FormattedMessage, { ...messages.body, values: {
|
|
65
|
-
name: displayName,
|
|
66
|
-
b: (chunks) => _jsx("b", { children: chunks }),
|
|
67
|
-
} }), referencingCount ? (_jsx("div", { children: _jsx(FormattedMessage, { ...messages.usageWarning, values: { count: referencingCount } }) })) : null] }));
|
|
68
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { type MouseEvent } from "react";
|
|
2
|
-
import type { OpenHandlerEvent } from "../catalogDetail/types.js";
|
|
3
|
-
import type { ICatalogItemMeasure, ICatalogItemRef } from "../catalogItem/types.js";
|
|
4
|
-
/**
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
export interface IMetricDetailActionsProps {
|
|
8
|
-
item: ICatalogItemMeasure;
|
|
9
|
-
/** When provided, adds an "Open in metric editor" menu action that opens the standalone editor. */
|
|
10
|
-
onOpen?: (event: MouseEvent, openEvent: OpenHandlerEvent) => void;
|
|
11
|
-
canShare?: boolean;
|
|
12
|
-
onShare?: () => void;
|
|
13
|
-
onCatalogItemCreate?: (item: ICatalogItemMeasure) => void;
|
|
14
|
-
onCatalogItemUpdate?: (item: ICatalogItemMeasure) => void;
|
|
15
|
-
onCatalogItemDelete?: (ref: ICatalogItemRef) => void;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Detail-panel actions for a metric: inline edit, duplicate, and delete via the as-code editor,
|
|
19
|
-
* alongside the shared Share button and "Open in metric editor" action.
|
|
20
|
-
* @internal
|
|
21
|
-
*/
|
|
22
|
-
export declare function MetricDetailActions({ item, onOpen, canShare, onShare, onCatalogItemCreate, onCatalogItemUpdate, onCatalogItemDelete }: IMetricDetailActionsProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
-
//# sourceMappingURL=MetricDetailActions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricDetailActions.d.ts","sourceRoot":"","sources":["../../src/metric/MetricDetailActions.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,UAAU,EAMlB,MAAM,OAAO,CAAC;AAWf,OAAO,KAAK,EAAwB,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxF,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAqBpF;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACtC,IAAI,EAAE,mBAAmB,CAAC;IAC1B,mGAAmG;IACnG,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC1D,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC1D,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;CACxD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,OAAO,EACP,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACtB,EAAE,yBAAyB,2CA6H3B"}
|