@gooddata/sdk-ui-catalog 11.54.0-alpha.6 → 11.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/asCode/AsCodeDeleteDialog.d.ts.map +1 -1
- package/esm/asCode/AsCodeDeleteDialog.js +19 -6
- package/esm/asCode/descriptor.d.ts +10 -2
- package/esm/asCode/descriptor.d.ts.map +1 -1
- package/esm/asCodeRegistry.d.ts.map +1 -1
- package/esm/asCodeRegistry.js +6 -1
- package/esm/catalogDetail/hooks/useCatalogItemLoad.d.ts.map +1 -1
- package/esm/catalogDetail/hooks/useCatalogItemLoad.js +11 -1
- package/esm/catalogItem/catalogBackend.test.utils.d.ts.map +1 -1
- package/esm/catalogItem/catalogBackend.test.utils.js +5 -0
- package/esm/catalogItem/converter.d.ts +4 -3
- package/esm/catalogItem/converter.d.ts.map +1 -1
- package/esm/catalogItem/converter.js +20 -1
- package/esm/catalogItem/guards.d.ts +5 -1
- package/esm/catalogItem/guards.d.ts.map +1 -1
- package/esm/catalogItem/guards.js +6 -0
- package/esm/catalogItem/query.d.ts +2 -1
- package/esm/catalogItem/query.d.ts.map +1 -1
- package/esm/catalogItem/query.js +34 -0
- package/esm/catalogItem/types.d.ts +13 -1
- package/esm/catalogItem/types.d.ts.map +1 -1
- package/esm/catalogItem/useCatalogEndpoints.d.ts +3 -2
- package/esm/catalogItem/useCatalogEndpoints.d.ts.map +1 -1
- package/esm/catalogItem/useCatalogEndpoints.js +17 -2
- package/esm/catalogItem/useCatalogItemFeed.d.ts +1 -0
- package/esm/catalogItem/useCatalogItemFeed.d.ts.map +1 -1
- package/esm/catalogItem/useCatalogItemFeed.js +1 -0
- package/esm/catalogItem/useCatalogItemSemanticSearch.js +2 -1
- package/esm/computedAttribute/computedAttributeCompletions.d.ts +8 -0
- package/esm/computedAttribute/computedAttributeCompletions.d.ts.map +1 -0
- package/esm/computedAttribute/computedAttributeCompletions.js +21 -0
- package/esm/computedAttribute/computedAttributeConverter.d.ts +38 -0
- package/esm/computedAttribute/computedAttributeConverter.d.ts.map +1 -0
- package/esm/computedAttribute/computedAttributeConverter.js +71 -0
- package/esm/computedAttribute/computedAttributeCopy.d.ts +3 -0
- package/esm/computedAttribute/computedAttributeCopy.d.ts.map +1 -0
- package/esm/computedAttribute/computedAttributeCopy.js +20 -0
- package/esm/computedAttribute/computedAttributeDescriptor.d.ts +7 -0
- package/esm/computedAttribute/computedAttributeDescriptor.d.ts.map +1 -0
- package/esm/computedAttribute/computedAttributeDescriptor.js +101 -0
- package/esm/computedAttribute/computedAttributeMutationPort.d.ts +17 -0
- package/esm/computedAttribute/computedAttributeMutationPort.d.ts.map +1 -0
- package/esm/computedAttribute/computedAttributeMutationPort.js +53 -0
- package/esm/computedAttribute/computedAttributeMutationPort.test.utils.d.ts +4 -0
- package/esm/computedAttribute/computedAttributeMutationPort.test.utils.d.ts.map +1 -0
- package/esm/computedAttribute/computedAttributeMutationPort.test.utils.js +24 -0
- package/esm/computedAttribute/computedAttributeSchema.d.ts +27 -0
- package/esm/computedAttribute/computedAttributeSchema.d.ts.map +1 -0
- package/esm/computedAttribute/computedAttributeSchema.js +27 -0
- package/esm/computedAttribute/computedAttributeSerialization.d.ts +15 -0
- package/esm/computedAttribute/computedAttributeSerialization.d.ts.map +1 -0
- package/esm/computedAttribute/computedAttributeSerialization.js +29 -0
- package/esm/computedAttribute/computedAttributeValidation.d.ts +15 -0
- package/esm/computedAttribute/computedAttributeValidation.d.ts.map +1 -0
- package/esm/computedAttribute/computedAttributeValidation.js +37 -0
- package/esm/computedAttribute/gate.d.ts +4 -0
- package/esm/computedAttribute/gate.d.ts.map +1 -0
- package/esm/computedAttribute/gate.js +4 -0
- package/esm/filter/FilterObjectType.js +3 -3
- package/esm/header/CreateObjectButton.d.ts.map +1 -1
- package/esm/header/CreateObjectButton.js +1 -0
- package/esm/index.d.ts +2 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/insight/insightDescriptor.js +2 -2
- package/esm/insight/insightMutationPort.d.ts +2 -2
- package/esm/insight/insightMutationPort.d.ts.map +1 -1
- package/esm/insight/insightMutationPort.js +3 -3
- package/esm/lineage/const.d.ts.map +1 -1
- package/esm/lineage/const.js +1 -0
- package/esm/localization/bundles/en-US.localization-bundle.d.ts +108 -0
- package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/en-US.localization-bundle.js +108 -0
- package/esm/metric/metricDescriptor.js +2 -2
- package/esm/metric/metricMutationPort.d.ts +2 -2
- package/esm/metric/metricMutationPort.d.ts.map +1 -1
- package/esm/metric/metricMutationPort.js +7 -4
- package/esm/objectType/ObjectTypeIcon.js +1 -1
- package/esm/objectType/ObjectTypeSelect.d.ts +2 -2
- package/esm/objectType/ObjectTypeSelect.d.ts.map +1 -1
- package/esm/objectType/ObjectTypeSelect.js +13 -14
- package/esm/objectType/constants.d.ts +28 -3
- package/esm/objectType/constants.d.ts.map +1 -1
- package/esm/objectType/constants.js +10 -9
- package/esm/objectType/labels.d.ts.map +1 -1
- package/esm/objectType/labels.js +1 -0
- package/esm/objectType/mapping.d.ts +1 -1
- package/esm/objectType/mapping.d.ts.map +1 -1
- package/esm/objectType/types.d.ts +2 -2
- package/esm/objectType/types.d.ts.map +1 -1
- package/esm/sdk-ui-catalog.d.ts +21 -3
- package/package.json +17 -17
- package/styles/css/codeDialog.css +8 -0
- package/styles/css/codeDialog.css.map +1 -1
- package/styles/css/detail.css +9 -1
- package/styles/css/detail.css.map +1 -1
- package/styles/css/main.css +9 -1
- package/styles/css/main.css.map +1 -1
- package/styles/css/objectType.css +1 -1
- package/styles/css/objectType.css.map +1 -1
- package/styles/scss/codeDialog.scss +9 -0
- package/styles/scss/objectType.scss +3 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { COMPUTED_ATTRIBUTE_SCHEMA_KEYS } from "./computedAttributeSchema.js";
|
|
3
|
+
const rootOptions = (COMPUTED_ATTRIBUTE_SCHEMA_KEYS[""] ?? []).map((label) => ({
|
|
4
|
+
label,
|
|
5
|
+
type: "property",
|
|
6
|
+
}));
|
|
7
|
+
/**
|
|
8
|
+
* Completion source for the computed attribute YAML schema. The schema is a flat mapping, so
|
|
9
|
+
* completion only offers the top-level property names, and only at column zero — an indented line
|
|
10
|
+
* sits inside a sequence value (e.g. under `tags:`), where those keys must not be offered.
|
|
11
|
+
*/
|
|
12
|
+
export function computedAttributeCompletions(context) {
|
|
13
|
+
const line = context.state.doc.lineAt(context.pos);
|
|
14
|
+
const before = line.text.slice(0, context.pos - line.from);
|
|
15
|
+
// Trigger only for a key typed at column zero; any leading whitespace means the cursor is nested.
|
|
16
|
+
const match = before.match(/^([\w-]*)$/);
|
|
17
|
+
if (!match) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return { from: context.pos - match[1].length, options: rootOptions, validFor: /^[\w-]*$/ };
|
|
21
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { v1 } from "@gooddata/sdk-code-schemas";
|
|
2
|
+
import type { IComputedAttributeMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
3
|
+
import type { ComputedAttributeSchema } from "./computedAttributeSchema.js";
|
|
4
|
+
/**
|
|
5
|
+
* Canonical AAC computed attribute object with an optional `id`.
|
|
6
|
+
*
|
|
7
|
+
* The `id` is dropped when a computed attribute is created or duplicated so the server derives one;
|
|
8
|
+
* a loaded computed attribute always carries it. Field names otherwise mirror
|
|
9
|
+
* `@gooddata/sdk-code-schemas` `v1.ComputedAttribute`.
|
|
10
|
+
*/
|
|
11
|
+
export type ComputedAttributeYaml = Omit<v1.ComputedAttribute, "id"> & {
|
|
12
|
+
id?: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Maps a computed attribute definition (or a loaded computed attribute, which is a superset) to the
|
|
16
|
+
* canonical AAC object for YAML serialization.
|
|
17
|
+
*
|
|
18
|
+
* Optional meta fields are omitted when empty so the rendered YAML stays terse, matching the
|
|
19
|
+
* analytics-as-code tooling output. The `id` is omitted when the definition has none (e.g. seeding
|
|
20
|
+
* the create dialog from a duplicate) so the server derives a fresh one.
|
|
21
|
+
*/
|
|
22
|
+
export declare function definitionToComputedAttributeYaml(definition: IComputedAttributeMetadataObjectDefinition): ComputedAttributeYaml;
|
|
23
|
+
/**
|
|
24
|
+
* Maps a validated AAC computed attribute object to a backend computed attribute definition.
|
|
25
|
+
*/
|
|
26
|
+
export declare function computedAttributeYamlToDefinition(computedAttribute: ComputedAttributeSchema): IComputedAttributeMetadataObjectDefinition;
|
|
27
|
+
/**
|
|
28
|
+
* The computed attribute's `reconcile`: layers the author's parsed YAML edits over the base
|
|
29
|
+
* definition — the loaded object on an edit, the copy source on a duplicate.
|
|
30
|
+
*
|
|
31
|
+
* The base carries fields the YAML cannot express (`format`, `metricType`, `dataType`, ...), which
|
|
32
|
+
* survive because only the YAML-owned fields are overlaid on top. Identity stays YAML-authoritative:
|
|
33
|
+
* the parsed `id` wins, and its absence lets the server derive a fresh one, so the base's id is
|
|
34
|
+
* intentionally dropped first. (On an edit this is moot — validation pins the parsed id to the loaded
|
|
35
|
+
* object's — but on a duplicate it is what frees the copy from the source's identity.)
|
|
36
|
+
*/
|
|
37
|
+
export declare function reconcileComputedAttributeDefinition(base: IComputedAttributeMetadataObjectDefinition, edited: IComputedAttributeMetadataObjectDefinition): IComputedAttributeMetadataObjectDefinition;
|
|
38
|
+
//# sourceMappingURL=computedAttributeConverter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computedAttributeConverter.d.ts","sourceRoot":"","sources":["../../src/computedAttribute/computedAttributeConverter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,KAAK,EAAE,0CAA0C,EAAE,MAAM,qBAAqB,CAAC;AAEtF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAE5E;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAC7C,UAAU,EAAE,0CAA0C,GACvD,qBAAqB,CAUvB;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAC7C,iBAAiB,EAAE,uBAAuB,GAC3C,0CAA0C,CAU5C;AA2BD;;;;;;;;;GASG;AACH,wBAAgB,oCAAoC,CAChD,IAAI,EAAE,0CAA0C,EAChD,MAAM,EAAE,0CAA0C,GACnD,0CAA0C,CAO5C"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
/**
|
|
3
|
+
* Maps a computed attribute definition (or a loaded computed attribute, which is a superset) to the
|
|
4
|
+
* canonical AAC object for YAML serialization.
|
|
5
|
+
*
|
|
6
|
+
* Optional meta fields are omitted when empty so the rendered YAML stays terse, matching the
|
|
7
|
+
* analytics-as-code tooling output. The `id` is omitted when the definition has none (e.g. seeding
|
|
8
|
+
* the create dialog from a duplicate) so the server derives a fresh one.
|
|
9
|
+
*/
|
|
10
|
+
export function definitionToComputedAttributeYaml(definition) {
|
|
11
|
+
return {
|
|
12
|
+
type: "computed_attribute",
|
|
13
|
+
...(definition.id === undefined ? {} : { id: definition.id }),
|
|
14
|
+
title: definition.title,
|
|
15
|
+
...(definition.description ? { description: definition.description } : {}),
|
|
16
|
+
...(definition.tags && definition.tags.length > 0 ? { tags: definition.tags } : {}),
|
|
17
|
+
maql: definition.expression,
|
|
18
|
+
...(definition.locale ? { locale: definition.locale } : {}),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Maps a validated AAC computed attribute object to a backend computed attribute definition.
|
|
23
|
+
*/
|
|
24
|
+
export function computedAttributeYamlToDefinition(computedAttribute) {
|
|
25
|
+
return {
|
|
26
|
+
type: "computedAttribute",
|
|
27
|
+
...(computedAttribute.id === undefined ? {} : { id: computedAttribute.id }),
|
|
28
|
+
title: computedAttribute.title ?? "",
|
|
29
|
+
description: computedAttribute.description ?? "",
|
|
30
|
+
tags: computedAttribute.tags ?? [],
|
|
31
|
+
expression: computedAttribute.maql,
|
|
32
|
+
...(computedAttribute.locale === undefined ? {} : { locale: computedAttribute.locale }),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The fields the as-code computed attribute YAML owns, extracted from a parsed definition and
|
|
37
|
+
* normalized for persistence. Every other field — `format`, `metricType`, `dataType`, `isNullable`,
|
|
38
|
+
* `nullValue`, and a loaded object's identity (`ref`, `uri`) — lies outside the YAML projection and
|
|
39
|
+
* is preserved by layering these fields over a base object rather than replacing it.
|
|
40
|
+
*
|
|
41
|
+
* `locale` is always returned (normalized to `undefined` when absent), never omitted: it must
|
|
42
|
+
* overwrite the base so that clearing the `locale` line drops a previously set collation. Were it
|
|
43
|
+
* omitted when undefined, the base's stale `locale` would leak through the overlay.
|
|
44
|
+
*/
|
|
45
|
+
function pickComputedAttributeYamlFields(definition) {
|
|
46
|
+
return {
|
|
47
|
+
title: definition.title ?? "",
|
|
48
|
+
description: definition.description ?? "",
|
|
49
|
+
tags: definition.tags ?? [],
|
|
50
|
+
expression: definition.expression,
|
|
51
|
+
locale: definition.locale,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The computed attribute's `reconcile`: layers the author's parsed YAML edits over the base
|
|
56
|
+
* definition — the loaded object on an edit, the copy source on a duplicate.
|
|
57
|
+
*
|
|
58
|
+
* The base carries fields the YAML cannot express (`format`, `metricType`, `dataType`, ...), which
|
|
59
|
+
* survive because only the YAML-owned fields are overlaid on top. Identity stays YAML-authoritative:
|
|
60
|
+
* the parsed `id` wins, and its absence lets the server derive a fresh one, so the base's id is
|
|
61
|
+
* intentionally dropped first. (On an edit this is moot — validation pins the parsed id to the loaded
|
|
62
|
+
* object's — but on a duplicate it is what frees the copy from the source's identity.)
|
|
63
|
+
*/
|
|
64
|
+
export function reconcileComputedAttributeDefinition(base, edited) {
|
|
65
|
+
const { id: _baseId, ...carriedOver } = base;
|
|
66
|
+
return {
|
|
67
|
+
...carriedOver,
|
|
68
|
+
...pickComputedAttributeYamlFields(edited),
|
|
69
|
+
...(edited.id === undefined ? {} : { id: edited.id }),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { IComputedAttributeMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
|
+
export declare function createCopiedComputedAttribute(computedAttribute: IComputedAttributeMetadataObjectDefinition): IComputedAttributeMetadataObjectDefinition;
|
|
3
|
+
//# sourceMappingURL=computedAttributeCopy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computedAttributeCopy.d.ts","sourceRoot":"","sources":["../../src/computedAttribute/computedAttributeCopy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0CAA0C,EAAE,MAAM,qBAAqB,CAAC;AAItF,wBAAgB,6BAA6B,CACzC,iBAAiB,EAAE,0CAA0C,GAC9D,0CAA0C,CAiB5C"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { deriveCopyIdentity } from "../asCode/copy.js";
|
|
3
|
+
export function createCopiedComputedAttribute(computedAttribute) {
|
|
4
|
+
// Whitelist only definition-owned fields; the source may be a loaded computed attribute carrying
|
|
5
|
+
// server-managed fields (uri, ref, timestamps, ...) that must not leak into the definition.
|
|
6
|
+
// The value-shaping fields are author-owned semantics, so they carry over.
|
|
7
|
+
return {
|
|
8
|
+
type: "computedAttribute",
|
|
9
|
+
...deriveCopyIdentity(computedAttribute),
|
|
10
|
+
description: computedAttribute.description,
|
|
11
|
+
tags: computedAttribute.tags,
|
|
12
|
+
expression: computedAttribute.expression,
|
|
13
|
+
...(computedAttribute.format === undefined ? {} : { format: computedAttribute.format }),
|
|
14
|
+
...(computedAttribute.metricType === undefined ? {} : { metricType: computedAttribute.metricType }),
|
|
15
|
+
...(computedAttribute.dataType === undefined ? {} : { dataType: computedAttribute.dataType }),
|
|
16
|
+
...(computedAttribute.isNullable === undefined ? {} : { isNullable: computedAttribute.isNullable }),
|
|
17
|
+
...(computedAttribute.nullValue === undefined ? {} : { nullValue: computedAttribute.nullValue }),
|
|
18
|
+
...(computedAttribute.locale === undefined ? {} : { locale: computedAttribute.locale }),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IComputedAttributeMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
|
+
import type { ICatalogItemComputedAttribute } from "../catalogItem/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare const computedAttributeDescriptor: import("../asCode/descriptor.js").IAsCodeDescriptor<IComputedAttributeMetadataObjectDefinition, ICatalogItemComputedAttribute>;
|
|
7
|
+
//# sourceMappingURL=computedAttributeDescriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computedAttributeDescriptor.d.ts","sourceRoot":"","sources":["../../src/computedAttribute/computedAttributeDescriptor.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,0CAA0C,EAAE,MAAM,qBAAqB,CAAC;AAQtF,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAkF7E;;GAEG;AACH,eAAO,MAAM,2BAA2B,gIAmCtC,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { defineMessages, useIntl } from "react-intl";
|
|
4
|
+
import { defineAsCodeDescriptor, fixedIdentifierOf, } from "../asCode/descriptor.js";
|
|
5
|
+
import { ObjectTypes } from "../objectType/constants.js";
|
|
6
|
+
import { computedAttributeCompletions } from "./computedAttributeCompletions.js";
|
|
7
|
+
import { computedAttributeYamlToDefinition, definitionToComputedAttributeYaml, reconcileComputedAttributeDefinition, } from "./computedAttributeConverter.js";
|
|
8
|
+
import { createCopiedComputedAttribute } from "./computedAttributeCopy.js";
|
|
9
|
+
import { createComputedAttributeMutationAdapter, listComputedAttributeReferences, loadComputedAttribute, } from "./computedAttributeMutationPort.js";
|
|
10
|
+
import { serializeComputedAttributeToYaml } from "./computedAttributeSerialization.js";
|
|
11
|
+
import { validateComputedAttributeYaml } from "./computedAttributeValidation.js";
|
|
12
|
+
import { COMPUTED_ATTRIBUTE_FEATURE_FLAG } from "./gate.js";
|
|
13
|
+
const COMPUTED_ATTRIBUTE_DOCS_URL = "https://www.gooddata.ai/docs/cloud/api-and-sdk/vs-code-extension/structures/#computed-attribute";
|
|
14
|
+
const messages = defineMessages({
|
|
15
|
+
createTitle: { id: "analyticsCatalog.computedAttribute.dialog.create.title" },
|
|
16
|
+
editTitle: { id: "analyticsCatalog.computedAttribute.dialog.edit.title" },
|
|
17
|
+
duplicate: { id: "analyticsCatalog.computedAttribute.dialog.edit.duplicate" },
|
|
18
|
+
createDefaultTitle: { id: "analyticsCatalog.computedAttribute.create.defaultTitle" },
|
|
19
|
+
createSuccess: { id: "analyticsCatalog.computedAttribute.create.success" },
|
|
20
|
+
updateSuccess: { id: "analyticsCatalog.computedAttribute.update.success" },
|
|
21
|
+
sectionHeader: { id: "analyticsCatalog.computedAttribute.dialog.sectionHeader" },
|
|
22
|
+
sectionHeaderTooltip: { id: "analyticsCatalog.computedAttribute.dialog.sectionHeader.tooltip" },
|
|
23
|
+
help: { id: "analyticsCatalog.computedAttribute.dialog.help" },
|
|
24
|
+
submitError: { id: "analyticsCatalog.computedAttribute.dialog.submit.error" },
|
|
25
|
+
deleteTitle: { id: "analyticsCatalog.computedAttribute.dialog.delete.title" },
|
|
26
|
+
deleteBody: { id: "analyticsCatalog.computedAttribute.dialog.delete.body" },
|
|
27
|
+
deleteSubmit: { id: "analyticsCatalog.computedAttribute.dialog.delete.submit" },
|
|
28
|
+
deleteSuccess: { id: "analyticsCatalog.computedAttribute.delete.success" },
|
|
29
|
+
deleteError: { id: "analyticsCatalog.computedAttribute.delete.error" },
|
|
30
|
+
});
|
|
31
|
+
const capabilityMessages = defineMessages({
|
|
32
|
+
loadError: { id: "analyticsCatalog.computedAttribute.load.error" },
|
|
33
|
+
deleteUsageWarning: { id: "analyticsCatalog.computedAttribute.dialog.delete.usageWarning" },
|
|
34
|
+
deleteBlocked: { id: "analyticsCatalog.computedAttribute.dialog.delete.blocked" },
|
|
35
|
+
});
|
|
36
|
+
const errorMessages = defineMessages({
|
|
37
|
+
empty: { id: "analyticsCatalog.computedAttribute.validation.empty" },
|
|
38
|
+
syntax: { id: "analyticsCatalog.computedAttribute.validation.syntax" },
|
|
39
|
+
invalidStructure: { id: "analyticsCatalog.computedAttribute.validation.invalidStructure" },
|
|
40
|
+
idImmutable: { id: "analyticsCatalog.computedAttribute.dialog.edit.idImmutable" },
|
|
41
|
+
missingMaql: { id: "analyticsCatalog.computedAttribute.validation.missingMaql" },
|
|
42
|
+
invalidTags: { id: "analyticsCatalog.computedAttribute.validation.invalidTags" },
|
|
43
|
+
});
|
|
44
|
+
function useComputedAttributeEditing() {
|
|
45
|
+
const intl = useIntl();
|
|
46
|
+
return useMemo(() => ({
|
|
47
|
+
completionSource: computedAttributeCompletions,
|
|
48
|
+
syntaxErrorMessage: intl.formatMessage(errorMessages.syntax),
|
|
49
|
+
// The editor works in the YAML shape, a lossy projection of the computed attribute
|
|
50
|
+
// definition — lossy in what a document carries, which `reconcile` restores, never in
|
|
51
|
+
// whether one exists.
|
|
52
|
+
serialize: (definition) => ({
|
|
53
|
+
yaml: serializeComputedAttributeToYaml(definitionToComputedAttributeYaml(definition)),
|
|
54
|
+
hasCodeForm: true,
|
|
55
|
+
}),
|
|
56
|
+
validate: (value, context) => {
|
|
57
|
+
const result = validateComputedAttributeYaml(value, {
|
|
58
|
+
fixedIdentifier: fixedIdentifierOf(context),
|
|
59
|
+
});
|
|
60
|
+
return result.isValid
|
|
61
|
+
? { isValid: true, definition: result.computedAttribute }
|
|
62
|
+
: { isValid: false, error: intl.formatMessage(errorMessages[result.errorCode]) };
|
|
63
|
+
},
|
|
64
|
+
reconcile: reconcileComputedAttributeDefinition,
|
|
65
|
+
}), [intl]);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
export const computedAttributeDescriptor = defineAsCodeDescriptor({
|
|
71
|
+
objectType: ObjectTypes.COMPUTED_ATTRIBUTE,
|
|
72
|
+
docsUrl: COMPUTED_ATTRIBUTE_DOCS_URL,
|
|
73
|
+
featureFlag: COMPUTED_ATTRIBUTE_FEATURE_FLAG,
|
|
74
|
+
messages,
|
|
75
|
+
useEditing: useComputedAttributeEditing,
|
|
76
|
+
createMutationPort: createComputedAttributeMutationAdapter,
|
|
77
|
+
// The template offers the fields and leaves the MAQL line empty: the expression is the whole
|
|
78
|
+
// point of the object, so a placeholder one would only be text to delete.
|
|
79
|
+
emptyDefinition: (defaultTitle) => computedAttributeYamlToDefinition({
|
|
80
|
+
type: "computed_attribute",
|
|
81
|
+
title: defaultTitle,
|
|
82
|
+
maql: "",
|
|
83
|
+
}),
|
|
84
|
+
// The catalog item carries no MAQL, so the full object is fetched for editing.
|
|
85
|
+
seed: { load: loadComputedAttribute, loadError: capabilityMessages.loadError },
|
|
86
|
+
// Refuses the deletion while a visualization still groups by it, and names those
|
|
87
|
+
// visualizations. The backend currently allows the delete (it would break the insight
|
|
88
|
+
// silently), so the catalog is the guard.
|
|
89
|
+
referenceCounted: {
|
|
90
|
+
load: listComputedAttributeReferences,
|
|
91
|
+
usageWarning: capabilityMessages.deleteUsageWarning,
|
|
92
|
+
listReferences: true,
|
|
93
|
+
blockedBody: capabilityMessages.deleteBlocked,
|
|
94
|
+
},
|
|
95
|
+
// A copied computed attribute derives a human-readable id that can collide on create; identity lets the dialog retry without it.
|
|
96
|
+
identity: {
|
|
97
|
+
read: (definition) => definition.id,
|
|
98
|
+
strip: ({ id: _id, ...definition }) => definition,
|
|
99
|
+
},
|
|
100
|
+
toCopy: createCopiedComputedAttribute,
|
|
101
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
2
|
+
import { type IComputedAttributeMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
3
|
+
import type { IAsCodeMutationPort } from "../asCode/descriptor.js";
|
|
4
|
+
import type { ICatalogItemComputedAttribute } from "../catalogItem/types.js";
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export type IComputedAttributeMutationPort = IAsCodeMutationPort<IComputedAttributeMetadataObjectDefinition, ICatalogItemComputedAttribute>;
|
|
9
|
+
/** Fetches the full computed attribute for editing (the catalog item carries no MAQL). @internal */
|
|
10
|
+
export declare function loadComputedAttribute(backend: IAnalyticalBackend, workspace: string, item: ICatalogItemComputedAttribute): Promise<IComputedAttributeMetadataObjectDefinition>;
|
|
11
|
+
/** Titles of the insights and metrics referencing a computed attribute. @internal */
|
|
12
|
+
export declare function listComputedAttributeReferences(backend: IAnalyticalBackend, workspace: string, item: ICatalogItemComputedAttribute): Promise<string[]>;
|
|
13
|
+
/**
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare function createComputedAttributeMutationAdapter(backend: IAnalyticalBackend, workspace: string): IComputedAttributeMutationPort;
|
|
17
|
+
//# sourceMappingURL=computedAttributeMutationPort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computedAttributeMutationPort.d.ts","sourceRoot":"","sources":["../../src/computedAttribute/computedAttributeMutationPort.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAEH,KAAK,0CAA0C,EAIlD,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGnE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAE7E;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG,mBAAmB,CAC5D,0CAA0C,EAC1C,6BAA6B,CAChC,CAAC;AAYF,oGAAoG;AACpG,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,6BAA6B,GACpC,OAAO,CAAC,0CAA0C,CAAC,CAKrD;AAED,qFAAqF;AACrF,wBAAsB,+BAA+B,CACjD,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,6BAA6B,GACpC,OAAO,CAAC,MAAM,EAAE,CAAC,CASnB;AAED;;GAEG;AACH,wBAAgB,sCAAsC,CAClD,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,GAClB,8BAA8B,CAyBhC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { idRef, insightTitle, isComputedAttributeMetadataObject, } from "@gooddata/sdk-model";
|
|
3
|
+
import { convertComputedAttributeToCatalogItem } from "../catalogItem/converter.js";
|
|
4
|
+
// `id` is definition-expressible yet server-owned: the update targets by it, so a hand-edited id must not retarget it.
|
|
5
|
+
function pickComputedAttributeIdentity(computedAttribute) {
|
|
6
|
+
const { id, ref, uri, created, updated, createdBy, updatedBy, certification, displayForms } = computedAttribute;
|
|
7
|
+
return { id, ref, uri, created, updated, createdBy, updatedBy, certification, displayForms };
|
|
8
|
+
}
|
|
9
|
+
/** Fetches the full computed attribute for editing (the catalog item carries no MAQL). @internal */
|
|
10
|
+
export function loadComputedAttribute(backend, workspace, item) {
|
|
11
|
+
return backend
|
|
12
|
+
.workspace(workspace)
|
|
13
|
+
.computedAttributes()
|
|
14
|
+
.getComputedAttribute(idRef(item.identifier, "computedAttribute"));
|
|
15
|
+
}
|
|
16
|
+
/** Titles of the insights and metrics referencing a computed attribute. @internal */
|
|
17
|
+
export async function listComputedAttributeReferences(backend, workspace, item) {
|
|
18
|
+
const referencing = await backend
|
|
19
|
+
.workspace(workspace)
|
|
20
|
+
.computedAttributes()
|
|
21
|
+
.getComputedAttributeReferencingObjects(idRef(item.identifier, "computedAttribute"));
|
|
22
|
+
return [
|
|
23
|
+
...(referencing.insights ?? []).map((insight) => insightTitle(insight)),
|
|
24
|
+
...(referencing.measures ?? []).map((measure) => measure.title),
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export function createComputedAttributeMutationAdapter(backend, workspace) {
|
|
31
|
+
const computedAttributes = () => backend.workspace(workspace).computedAttributes();
|
|
32
|
+
return {
|
|
33
|
+
async create(definition) {
|
|
34
|
+
const saved = await computedAttributes().createComputedAttribute(definition);
|
|
35
|
+
return convertComputedAttributeToCatalogItem(saved);
|
|
36
|
+
},
|
|
37
|
+
async update(base, definition) {
|
|
38
|
+
if (!isComputedAttributeMetadataObject(base)) {
|
|
39
|
+
throw new Error("Computed attribute update requires the loaded object as base, not a bare definition.");
|
|
40
|
+
}
|
|
41
|
+
// Definition is authoritative (already reconciled); base fills only non-definition fields, and the server-identity pick wins.
|
|
42
|
+
const saved = await computedAttributes().updateComputedAttribute({
|
|
43
|
+
...base,
|
|
44
|
+
...definition,
|
|
45
|
+
...pickComputedAttributeIdentity(base),
|
|
46
|
+
});
|
|
47
|
+
return convertComputedAttributeToCatalogItem(saved);
|
|
48
|
+
},
|
|
49
|
+
async delete(ref) {
|
|
50
|
+
await computedAttributes().deleteComputedAttribute(idRef(ref.identifier, "computedAttribute"));
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IComputedAttributeMutationPort } from "./computedAttributeMutationPort.js";
|
|
2
|
+
/** @internal */
|
|
3
|
+
export declare function createTestComputedAttributeMutationPort(overrides?: Partial<IComputedAttributeMutationPort>): IComputedAttributeMutationPort;
|
|
4
|
+
//# sourceMappingURL=computedAttributeMutationPort.test.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computedAttributeMutationPort.test.utils.d.ts","sourceRoot":"","sources":["../../src/computedAttribute/computedAttributeMutationPort.test.utils.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AAgBzF,gBAAgB;AAChB,wBAAgB,uCAAuC,CACnD,SAAS,GAAE,OAAO,CAAC,8BAA8B,CAAM,GACxD,8BAA8B,CAOhC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
const defaultSavedItem = {
|
|
4
|
+
identifier: "test-computed-attribute",
|
|
5
|
+
type: "computedAttribute",
|
|
6
|
+
title: "Test Computed Attribute",
|
|
7
|
+
description: "",
|
|
8
|
+
tags: [],
|
|
9
|
+
createdBy: "test",
|
|
10
|
+
updatedBy: "test",
|
|
11
|
+
createdAt: null,
|
|
12
|
+
updatedAt: null,
|
|
13
|
+
isLocked: false,
|
|
14
|
+
isEditable: true,
|
|
15
|
+
};
|
|
16
|
+
/** @internal */
|
|
17
|
+
export function createTestComputedAttributeMutationPort(overrides = {}) {
|
|
18
|
+
return {
|
|
19
|
+
create: vi.fn().mockResolvedValue(defaultSavedItem),
|
|
20
|
+
update: vi.fn().mockResolvedValue(defaultSavedItem),
|
|
21
|
+
delete: vi.fn().mockResolvedValue(undefined),
|
|
22
|
+
...overrides,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as z from "zod/mini";
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for the analytics-as-code (AAC) computed attribute YAML shape.
|
|
4
|
+
*
|
|
5
|
+
* Field names and structure mirror the canonical AAC computed attribute definition
|
|
6
|
+
* (`@gooddata/sdk-code-schemas` `v1.ComputedAttribute`) so YAML authored here is interchangeable
|
|
7
|
+
* with computed attributes produced by the analytics-as-code tooling. `id` is optional because the
|
|
8
|
+
* server derives one from the title when it is omitted on create.
|
|
9
|
+
*/
|
|
10
|
+
export declare const computedAttributeSchema: z.ZodMiniObject<{
|
|
11
|
+
type: z.ZodMiniDefault<z.ZodMiniLiteral<"computed_attribute">>;
|
|
12
|
+
id: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
13
|
+
title: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
14
|
+
description: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
15
|
+
tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
|
|
16
|
+
maql: z.ZodMiniString<string>;
|
|
17
|
+
locale: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
18
|
+
}, z.core.$strict>;
|
|
19
|
+
export type ComputedAttributeSchemaInput = z.input<typeof computedAttributeSchema>;
|
|
20
|
+
export type ComputedAttributeSchema = z.infer<typeof computedAttributeSchema>;
|
|
21
|
+
/**
|
|
22
|
+
* Allowed YAML property names keyed by parent mapping, used to power editor autocompletion.
|
|
23
|
+
* The computed attribute schema is flat, so the only entry is the top-level mapping (keyed by `""`),
|
|
24
|
+
* whose value is the object's property names read from zod's public `shape`.
|
|
25
|
+
*/
|
|
26
|
+
export declare const COMPUTED_ATTRIBUTE_SCHEMA_KEYS: Record<string, string[]>;
|
|
27
|
+
//# sourceMappingURL=computedAttributeSchema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computedAttributeSchema.d.ts","sourceRoot":"","sources":["../../src/computedAttribute/computedAttributeSchema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAE9B;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;kBAQlC,CAAC;AAEH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACnF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAEnE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import * as z from "zod/mini";
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for the analytics-as-code (AAC) computed attribute YAML shape.
|
|
5
|
+
*
|
|
6
|
+
* Field names and structure mirror the canonical AAC computed attribute definition
|
|
7
|
+
* (`@gooddata/sdk-code-schemas` `v1.ComputedAttribute`) so YAML authored here is interchangeable
|
|
8
|
+
* with computed attributes produced by the analytics-as-code tooling. `id` is optional because the
|
|
9
|
+
* server derives one from the title when it is omitted on create.
|
|
10
|
+
*/
|
|
11
|
+
export const computedAttributeSchema = z.strictObject({
|
|
12
|
+
type: z._default(z.literal("computed_attribute"), "computed_attribute"),
|
|
13
|
+
id: z.optional(z.string()),
|
|
14
|
+
title: z.optional(z.string()),
|
|
15
|
+
description: z.optional(z.string()),
|
|
16
|
+
tags: z.optional(z.array(z.string())),
|
|
17
|
+
maql: z.string(),
|
|
18
|
+
locale: z.optional(z.string()),
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Allowed YAML property names keyed by parent mapping, used to power editor autocompletion.
|
|
22
|
+
* The computed attribute schema is flat, so the only entry is the top-level mapping (keyed by `""`),
|
|
23
|
+
* whose value is the object's property names read from zod's public `shape`.
|
|
24
|
+
*/
|
|
25
|
+
export const COMPUTED_ATTRIBUTE_SCHEMA_KEYS = {
|
|
26
|
+
"": Object.keys(computedAttributeSchema.shape),
|
|
27
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ComputedAttributeYaml } from "./computedAttributeConverter.js";
|
|
2
|
+
/**
|
|
3
|
+
* Serializes a canonical AAC computed attribute object to YAML.
|
|
4
|
+
*
|
|
5
|
+
* The document is a flat, gap-free list of lines in the order the design prescribes: `id`, `type`,
|
|
6
|
+
* `title`, `description`, then `maql` last, so the expression the author came to write sits at the
|
|
7
|
+
* bottom with the room below it. The `id` line is omitted when the computed attribute has none so
|
|
8
|
+
* the server derives one on create.
|
|
9
|
+
*
|
|
10
|
+
* `description` is always rendered, empty as `""`, so the field an author is likely to fill is
|
|
11
|
+
* offered rather than hidden. An empty `maql` renders as a bare `maql:` (see `nullStr`), an
|
|
12
|
+
* invitation to type rather than a quoted blank to delete.
|
|
13
|
+
*/
|
|
14
|
+
export declare function serializeComputedAttributeToYaml(computedAttribute: ComputedAttributeYaml): string;
|
|
15
|
+
//# sourceMappingURL=computedAttributeSerialization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computedAttributeSerialization.d.ts","sourceRoot":"","sources":["../../src/computedAttribute/computedAttributeSerialization.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E;;;;;;;;;;;GAWG;AACH,wBAAgB,gCAAgC,CAAC,iBAAiB,EAAE,qBAAqB,GAAG,MAAM,CAkBjG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { Document } from "yaml";
|
|
3
|
+
/**
|
|
4
|
+
* Serializes a canonical AAC computed attribute object to YAML.
|
|
5
|
+
*
|
|
6
|
+
* The document is a flat, gap-free list of lines in the order the design prescribes: `id`, `type`,
|
|
7
|
+
* `title`, `description`, then `maql` last, so the expression the author came to write sits at the
|
|
8
|
+
* bottom with the room below it. The `id` line is omitted when the computed attribute has none so
|
|
9
|
+
* the server derives one on create.
|
|
10
|
+
*
|
|
11
|
+
* `description` is always rendered, empty as `""`, so the field an author is likely to fill is
|
|
12
|
+
* offered rather than hidden. An empty `maql` renders as a bare `maql:` (see `nullStr`), an
|
|
13
|
+
* invitation to type rather than a quoted blank to delete.
|
|
14
|
+
*/
|
|
15
|
+
export function serializeComputedAttributeToYaml(computedAttribute) {
|
|
16
|
+
const doc = new Document(computedAttribute.id === undefined
|
|
17
|
+
? { type: "computed_attribute" }
|
|
18
|
+
: { id: computedAttribute.id, type: "computed_attribute" });
|
|
19
|
+
doc.add(doc.createPair("title", computedAttribute.title ?? ""));
|
|
20
|
+
doc.add(doc.createPair("description", computedAttribute.description ?? ""));
|
|
21
|
+
if (computedAttribute.tags && computedAttribute.tags.length > 0) {
|
|
22
|
+
doc.add(doc.createPair("tags", computedAttribute.tags));
|
|
23
|
+
}
|
|
24
|
+
if (computedAttribute.locale) {
|
|
25
|
+
doc.add(doc.createPair("locale", computedAttribute.locale));
|
|
26
|
+
}
|
|
27
|
+
doc.add(doc.createPair("maql", computedAttribute.maql ? computedAttribute.maql : null));
|
|
28
|
+
return doc.toString({ lineWidth: 0, nullStr: "" }).trimEnd();
|
|
29
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IComputedAttributeMetadataObjectDefinition } from "@gooddata/sdk-model";
|
|
2
|
+
export type ComputedAttributeValidationResult = {
|
|
3
|
+
isValid: true;
|
|
4
|
+
computedAttribute: IComputedAttributeMetadataObjectDefinition;
|
|
5
|
+
} | {
|
|
6
|
+
isValid: false;
|
|
7
|
+
errorCode: ComputedAttributeValidationErrorCode;
|
|
8
|
+
};
|
|
9
|
+
export type ComputedAttributeValidationErrorCode = "empty" | "syntax" | "invalidStructure" | "idImmutable" | "missingMaql" | "invalidTags";
|
|
10
|
+
type ValidateComputedAttributeYamlOptions = {
|
|
11
|
+
fixedIdentifier?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function validateComputedAttributeYaml(value: string, options?: ValidateComputedAttributeYamlOptions): ComputedAttributeValidationResult;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=computedAttributeValidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computedAttributeValidation.d.ts","sourceRoot":"","sources":["../../src/computedAttribute/computedAttributeValidation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,0CAA0C,EAAE,MAAM,qBAAqB,CAAC;AAOtF,MAAM,MAAM,iCAAiC,GACvC;IACI,OAAO,EAAE,IAAI,CAAC;IACd,iBAAiB,EAAE,0CAA0C,CAAC;CACjE,GACD;IACI,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,EAAE,oCAAoC,CAAC;CACnD,CAAC;AAER,MAAM,MAAM,oCAAoC,GAC1C,OAAO,GACP,QAAQ,GACR,kBAAkB,GAClB,aAAa,GACb,aAAa,GACb,aAAa,CAAC;AAEpB,KAAK,oCAAoC,GAAG;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAgB,6BAA6B,CACzC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,oCAAyC,GACnD,iCAAiC,CAgBnC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { validateYaml } from "../asCode/validateYaml.js";
|
|
3
|
+
import { computedAttributeYamlToDefinition } from "./computedAttributeConverter.js";
|
|
4
|
+
import { computedAttributeSchema } from "./computedAttributeSchema.js";
|
|
5
|
+
export function validateComputedAttributeYaml(value, options = {}) {
|
|
6
|
+
const result = validateYaml(value, {
|
|
7
|
+
schema: computedAttributeSchema,
|
|
8
|
+
fixedIdentifier: options.fixedIdentifier,
|
|
9
|
+
});
|
|
10
|
+
if (result.ok) {
|
|
11
|
+
return { isValid: true, computedAttribute: computedAttributeYamlToDefinition(result.data) };
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
isValid: false,
|
|
15
|
+
errorCode: result.kind === "schema"
|
|
16
|
+
? classifyComputedAttributeError(result.error, result.parsed)
|
|
17
|
+
: result.kind,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function classifyComputedAttributeError(error, parsed) {
|
|
21
|
+
// A blank `maql:` line parses to null - the seeded template's state - and counts as unwritten,
|
|
22
|
+
// not as a value of the wrong type.
|
|
23
|
+
const maqlProvided = typeof parsed === "object" &&
|
|
24
|
+
parsed !== null &&
|
|
25
|
+
(parsed.maql ?? undefined) !== undefined;
|
|
26
|
+
for (const issue of error.issues) {
|
|
27
|
+
const path = issue.path.map(String).join(".");
|
|
28
|
+
if (path === "maql") {
|
|
29
|
+
// A present-but-wrong-typed maql is a structural error, not a missing field.
|
|
30
|
+
return maqlProvided ? "invalidStructure" : "missingMaql";
|
|
31
|
+
}
|
|
32
|
+
if (path === "tags" || path.startsWith("tags.")) {
|
|
33
|
+
return "invalidTags";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return "invalidStructure";
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/computedAttribute/gate.ts"],"names":[],"mappings":"AAEA;qFACqF;AACrF,eAAO,MAAM,+BAA+B,6BAA6B,CAAC"}
|
|
@@ -3,17 +3,17 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { memo, useId } from "react";
|
|
4
4
|
import { FormattedMessage } from "react-intl";
|
|
5
5
|
import { useCatalogFeedCounter } from "../catalogItem/CatalogFeedContext.js";
|
|
6
|
+
import { useEnabledObjectTypes } from "../catalogItem/useCatalogEndpoints.js";
|
|
6
7
|
import { ObjectTypeSelectMemo } from "../objectType/ObjectTypeSelect.js";
|
|
7
|
-
import { useIsParametersEnabled } from "../parameter/gate.js";
|
|
8
8
|
import { useFilterActions, useFilterState } from "./FilterContext.js";
|
|
9
9
|
import { FilterGroupLayout } from "./FilterGroupLayout.js";
|
|
10
10
|
export function FilterObjectType() {
|
|
11
11
|
const counter = useCatalogFeedCounter();
|
|
12
12
|
const { types } = useFilterState();
|
|
13
13
|
const { setTypes } = useFilterActions();
|
|
14
|
-
const
|
|
14
|
+
const enabledObjectTypes = useEnabledObjectTypes();
|
|
15
15
|
const id = useId();
|
|
16
16
|
const titleId = `filter-object-type-title/${id}`;
|
|
17
|
-
return (_jsx(FilterGroupLayout, { className: "gd-analytics-catalog__filter__group__object-type", title: _jsx(FormattedMessage, { id: "analyticsCatalog.objectType.title" }), titleId: titleId, children: _jsx(ObjectTypeSelectMemo, { counter: counter, selectedTypes: types,
|
|
17
|
+
return (_jsx(FilterGroupLayout, { className: "gd-analytics-catalog__filter__group__object-type", title: _jsx(FormattedMessage, { id: "analyticsCatalog.objectType.title" }), titleId: titleId, children: _jsx(ObjectTypeSelectMemo, { counter: counter, selectedTypes: types, enabledObjectTypes: enabledObjectTypes, onSelect: setTypes, ariaLabelledBy: titleId }) }));
|
|
18
18
|
}
|
|
19
19
|
export const FilterObjectTypeMemo = memo(FilterObjectType);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateObjectButton.d.ts","sourceRoot":"","sources":["../../src/header/CreateObjectButton.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"CreateObjectButton.d.ts","sourceRoot":"","sources":["../../src/header/CreateObjectButton.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AActE,KAAK,KAAK,GAAG;IACT,cAAc,EAAE,CAAC,UAAU,EAAE,uBAAuB,KAAK,IAAI,CAAC;CACjE,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,EAAE,cAAc,EAAE,EAAE,KAAK,2CAsG3D"}
|
|
@@ -13,6 +13,7 @@ const icons = {
|
|
|
13
13
|
[ObjectTypes.VISUALIZATION]: "visualization",
|
|
14
14
|
[ObjectTypes.METRIC]: "metric",
|
|
15
15
|
[ObjectTypes.PARAMETER]: "parameter",
|
|
16
|
+
[ObjectTypes.COMPUTED_ATTRIBUTE]: "ldmAttribute",
|
|
16
17
|
};
|
|
17
18
|
export function CreateObjectButton({ onCreateObject }) {
|
|
18
19
|
const intl = useIntl();
|
package/esm/index.d.ts
CHANGED
|
@@ -7,6 +7,6 @@ export type { ICatalogDetailProps } from "./catalogDetail/CatalogDetail.js";
|
|
|
7
7
|
export type { EditHandlerEvent, OpenHandlerEvent } from "./catalogDetail/types.js";
|
|
8
8
|
export type { ICatalogDetailContentProps } from "./catalogDetail/CatalogDetailContent.js";
|
|
9
9
|
export type { ObjectType, CatalogCreateObjectType } from "./objectType/types.js";
|
|
10
|
-
export type { ICatalogItem, ICatalogItemBase, ICatalogItemRef, ICatalogItemInsight, ICatalogItemMeasure, ICatalogItemParameter, ICatalogItemAttribute, ICatalogItemFact, ICatalogItemDataSet, ICatalogItemDashboard, VisualizationType, } from "./catalogItem/types.js";
|
|
11
|
-
export { isCatalogItemAttribute, isCatalogItemDashboard, isCatalogItemDataSet, isCatalogItemFact, isCatalogItemInsight, isCatalogItemMeasure, isCatalogItemParameter, } from "./catalogItem/guards.js";
|
|
10
|
+
export type { ICatalogItem, ICatalogItemBase, ICatalogItemRef, ICatalogItemInsight, ICatalogItemMeasure, ICatalogItemParameter, ICatalogItemComputedAttribute, ICatalogItemAttribute, ICatalogItemFact, ICatalogItemDataSet, ICatalogItemDashboard, VisualizationType, } from "./catalogItem/types.js";
|
|
11
|
+
export { isCatalogItemAttribute, isCatalogItemComputedAttribute, isCatalogItemDashboard, isCatalogItemDataSet, isCatalogItemFact, isCatalogItemInsight, isCatalogItemMeasure, isCatalogItemParameter, } from "./catalogItem/guards.js";
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|