@gooddata/sdk-ui-catalog 11.48.0-alpha.1 → 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.
Files changed (123) hide show
  1. package/esm/AnalyticsCatalogDetail.d.ts.map +1 -1
  2. package/esm/AnalyticsCatalogDetail.js +3 -3
  3. package/esm/asCode/AsCodeCreateDialog.d.ts +17 -0
  4. package/esm/asCode/AsCodeCreateDialog.d.ts.map +1 -0
  5. package/esm/asCode/AsCodeCreateDialog.js +51 -0
  6. package/esm/asCode/AsCodeDeleteDialog.d.ts +17 -0
  7. package/esm/asCode/AsCodeDeleteDialog.d.ts.map +1 -0
  8. package/esm/asCode/AsCodeDeleteDialog.js +55 -0
  9. package/esm/asCode/AsCodeDetailActions.d.ts +27 -0
  10. package/esm/asCode/AsCodeDetailActions.d.ts.map +1 -0
  11. package/esm/asCode/AsCodeDetailActions.js +66 -0
  12. package/esm/asCode/AsCodeDialog.d.ts +24 -0
  13. package/esm/asCode/AsCodeDialog.d.ts.map +1 -0
  14. package/esm/asCode/AsCodeDialog.js +94 -0
  15. package/esm/asCode/AsCodeEditDialog.d.ts +18 -0
  16. package/esm/asCode/AsCodeEditDialog.d.ts.map +1 -0
  17. package/esm/asCode/AsCodeEditDialog.js +38 -0
  18. package/esm/asCode/AsCodeEditorBody.d.ts +16 -0
  19. package/esm/asCode/AsCodeEditorBody.d.ts.map +1 -0
  20. package/esm/asCode/AsCodeEditorBody.js +10 -0
  21. package/esm/asCode/AsCodeMutationContext.d.ts +24 -0
  22. package/esm/asCode/AsCodeMutationContext.d.ts.map +1 -0
  23. package/esm/asCode/AsCodeMutationContext.js +40 -0
  24. package/esm/asCode/copy.d.ts +18 -0
  25. package/esm/asCode/copy.d.ts.map +1 -0
  26. package/esm/asCode/copy.js +58 -0
  27. package/esm/asCode/descriptor.d.ts +160 -0
  28. package/esm/asCode/descriptor.d.ts.map +1 -0
  29. package/esm/asCode/descriptor.js +8 -0
  30. package/esm/asCode/gate.d.ts +7 -0
  31. package/esm/asCode/gate.d.ts.map +1 -0
  32. package/esm/asCode/gate.js +11 -0
  33. package/esm/asCode/useAsCodeBase.d.ts +18 -0
  34. package/esm/asCode/useAsCodeBase.d.ts.map +1 -0
  35. package/esm/asCode/useAsCodeBase.js +27 -0
  36. package/esm/asCode/validateYaml.d.ts +39 -0
  37. package/esm/asCode/validateYaml.d.ts.map +1 -0
  38. package/esm/asCode/validateYaml.js +28 -0
  39. package/esm/asCodeRegistry.d.ts +20 -0
  40. package/esm/asCodeRegistry.d.ts.map +1 -0
  41. package/esm/asCodeRegistry.js +36 -0
  42. package/esm/catalog/Catalog.d.ts.map +1 -1
  43. package/esm/catalog/Catalog.js +4 -4
  44. package/esm/catalogDetail/CatalogDetailActions.d.ts +4 -2
  45. package/esm/catalogDetail/CatalogDetailActions.d.ts.map +1 -1
  46. package/esm/catalogDetail/CatalogDetailActions.js +22 -78
  47. package/esm/catalogDetail/CatalogDetailContent.d.ts.map +1 -1
  48. package/esm/catalogDetail/CatalogDetailContent.js +1 -3
  49. package/esm/catalogItem/query.d.ts +4 -2
  50. package/esm/catalogItem/query.d.ts.map +1 -1
  51. package/esm/catalogItem/query.js +6 -6
  52. package/esm/header/CreateObjectButton.d.ts.map +1 -1
  53. package/esm/header/CreateObjectButton.js +29 -28
  54. package/esm/localization/bundles/en-US.localization-bundle.d.ts +16 -24
  55. package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  56. package/esm/localization/bundles/en-US.localization-bundle.js +16 -24
  57. package/esm/metric/gate.d.ts +3 -4
  58. package/esm/metric/gate.d.ts.map +1 -1
  59. package/esm/metric/gate.js +5 -10
  60. package/esm/metric/metricCopy.d.ts +0 -1
  61. package/esm/metric/metricCopy.d.ts.map +1 -1
  62. package/esm/metric/metricCopy.js +3 -45
  63. package/esm/metric/metricDescriptor.d.ts +7 -0
  64. package/esm/metric/metricDescriptor.d.ts.map +1 -0
  65. package/esm/metric/metricDescriptor.js +74 -0
  66. package/esm/metric/metricMutationPort.d.ts +7 -10
  67. package/esm/metric/metricMutationPort.d.ts.map +1 -1
  68. package/esm/metric/metricMutationPort.js +15 -17
  69. package/esm/metric/metricValidation.d.ts.map +1 -1
  70. package/esm/metric/metricValidation.js +13 -32
  71. package/esm/metric/tests/metricMutationPort.test.utils.js +1 -1
  72. package/esm/parameter/gate.d.ts +3 -0
  73. package/esm/parameter/gate.d.ts.map +1 -1
  74. package/esm/parameter/gate.js +7 -5
  75. package/esm/parameter/parameterCopy.d.ts +0 -1
  76. package/esm/parameter/parameterCopy.d.ts.map +1 -1
  77. package/esm/parameter/parameterCopy.js +4 -41
  78. package/esm/parameter/parameterDescriptor.d.ts +7 -0
  79. package/esm/parameter/parameterDescriptor.d.ts.map +1 -0
  80. package/esm/parameter/parameterDescriptor.js +91 -0
  81. package/esm/parameter/parameterMutationPort.d.ts +5 -6
  82. package/esm/parameter/parameterMutationPort.d.ts.map +1 -1
  83. package/esm/parameter/parameterMutationPort.js +15 -2
  84. package/package.json +15 -15
  85. package/esm/metric/MetricCreateDialog.d.ts +0 -11
  86. package/esm/metric/MetricCreateDialog.d.ts.map +0 -1
  87. package/esm/metric/MetricCreateDialog.js +0 -55
  88. package/esm/metric/MetricDeleteDialog.d.ts +0 -9
  89. package/esm/metric/MetricDeleteDialog.d.ts.map +0 -1
  90. package/esm/metric/MetricDeleteDialog.js +0 -68
  91. package/esm/metric/MetricDetailActions.d.ts +0 -23
  92. package/esm/metric/MetricDetailActions.d.ts.map +0 -1
  93. package/esm/metric/MetricDetailActions.js +0 -101
  94. package/esm/metric/MetricDialog.d.ts +0 -14
  95. package/esm/metric/MetricDialog.d.ts.map +0 -1
  96. package/esm/metric/MetricDialog.js +0 -100
  97. package/esm/metric/MetricEditDialog.d.ts +0 -11
  98. package/esm/metric/MetricEditDialog.d.ts.map +0 -1
  99. package/esm/metric/MetricEditDialog.js +0 -51
  100. package/esm/metric/MetricMutationContext.d.ts +0 -16
  101. package/esm/metric/MetricMutationContext.d.ts.map +0 -1
  102. package/esm/metric/MetricMutationContext.js +0 -32
  103. package/esm/metric/MetricYamlEditor.d.ts +0 -8
  104. package/esm/metric/MetricYamlEditor.d.ts.map +0 -1
  105. package/esm/metric/MetricYamlEditor.js +0 -12
  106. package/esm/parameter/ParameterCreateDialog.d.ts +0 -9
  107. package/esm/parameter/ParameterCreateDialog.d.ts.map +0 -1
  108. package/esm/parameter/ParameterCreateDialog.js +0 -56
  109. package/esm/parameter/ParameterDeleteDialog.d.ts +0 -9
  110. package/esm/parameter/ParameterDeleteDialog.d.ts.map +0 -1
  111. package/esm/parameter/ParameterDeleteDialog.js +0 -39
  112. package/esm/parameter/ParameterDialog.d.ts +0 -13
  113. package/esm/parameter/ParameterDialog.d.ts.map +0 -1
  114. package/esm/parameter/ParameterDialog.js +0 -106
  115. package/esm/parameter/ParameterEditDialog.d.ts +0 -11
  116. package/esm/parameter/ParameterEditDialog.d.ts.map +0 -1
  117. package/esm/parameter/ParameterEditDialog.js +0 -35
  118. package/esm/parameter/ParameterMutationContext.d.ts +0 -16
  119. package/esm/parameter/ParameterMutationContext.d.ts.map +0 -1
  120. package/esm/parameter/ParameterMutationContext.js +0 -32
  121. package/esm/parameter/ParameterYamlEditor.d.ts +0 -10
  122. package/esm/parameter/ParameterYamlEditor.d.ts.map +0 -1
  123. package/esm/parameter/ParameterYamlEditor.js +0 -16
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsCatalogDetail.d.ts","sourceRoot":"","sources":["../src/AnalyticsCatalogDetail.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAIpE,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAEH,KAAK,0BAA0B,EAClC,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAIjE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAOxD;;GAEG;AACH,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,YAAY,CAAC;IACtG;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EACnC,OAAO,EACP,SAAS,EACT,MAAM,EACN,GAAG,SAAS,EACf,EAAE,4BAA4B,2CAM9B;AAED;;GAEG;AACH,MAAM,WAAW,mCAAoC,SAAQ,IAAI,CAC7D,0BAA0B,EAC1B,UAAU,GAAG,YAAY,CAC5B;IACG;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC3E;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,EAC1C,OAAO,EACP,SAAS,EACT,MAAM,EACN,GAAG,SAAS,EACf,EAAE,mCAAmC,2CAMrC"}
1
+ {"version":3,"file":"AnalyticsCatalogDetail.d.ts","sourceRoot":"","sources":["../src/AnalyticsCatalogDetail.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAMpE,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAEH,KAAK,0BAA0B,EAClC,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAMxD;;GAEG;AACH,MAAM,WAAW,4BAA6B,SAAQ,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,YAAY,CAAC;IACtG;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EACnC,OAAO,EACP,SAAS,EACT,MAAM,EACN,GAAG,SAAS,EACf,EAAE,4BAA4B,2CAM9B;AAED;;GAEG;AACH,MAAM,WAAW,mCAAoC,SAAQ,IAAI,CAC7D,0BAA0B,EAC1B,UAAU,GAAG,YAAY,CAC5B;IACG;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC3E;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,EAC1C,OAAO,EACP,SAAS,EACT,MAAM,EACN,GAAG,SAAS,EACf,EAAE,mCAAmC,2CAMrC"}
@@ -1,14 +1,14 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { BackendProvider, WorkspaceProvider, useBackendStrict, useWorkspaceStrict } from "@gooddata/sdk-ui";
3
3
  import { ToastsCenterContextProvider } from "@gooddata/sdk-ui-kit";
4
+ import { AsCodeMutationProvider } from "./asCode/AsCodeMutationContext.js";
5
+ import { asCodeDescriptors } from "./asCodeRegistry.js";
4
6
  import { CatalogDetail } from "./catalogDetail/CatalogDetail.js";
5
7
  import { CatalogDetailContent, } from "./catalogDetail/CatalogDetailContent.js";
6
8
  import { CatalogResourceProvider } from "./catalogResource/CatalogResourceProvider.js";
7
9
  import { IntlWrapper } from "./localization/IntlWrapper.js";
8
- import { MetricMutationProvider } from "./metric/MetricMutationContext.js";
9
10
  import {} from "./objectType/types.js";
10
11
  import { OverlayProvider } from "./overlay/OverlayProvider.js";
11
- import { ParameterMutationProvider } from "./parameter/ParameterMutationContext.js";
12
12
  import { PermissionsProvider } from "./permission/PermissionsContext.js";
13
13
  import { usePermissionsQuery } from "./permission/usePermissionsQuery.js";
14
14
  import { QualityProvider } from "./quality/QualityContext.js";
@@ -28,5 +28,5 @@ function Providers(props) {
28
28
  const backend = useBackendStrict(props.backend);
29
29
  const workspace = useWorkspaceStrict(props.workspace);
30
30
  const permissionsState = usePermissionsQuery({ backend, workspace });
31
- return (_jsx(BackendProvider, { backend: backend, children: _jsx(WorkspaceProvider, { workspace: workspace, children: _jsx(IntlWrapper, { locale: props.locale, children: _jsx(ToastsCenterContextProvider, { children: _jsx(OverlayProvider, { children: _jsx(PermissionsProvider, { permissionsState: permissionsState, children: _jsx(QualityProvider, { backend: backend, workspace: workspace, children: _jsx(CatalogResourceProvider, { backend: backend, workspace: workspace, children: _jsx(ParameterMutationProvider, { children: _jsx(MetricMutationProvider, { children: props.children }) }) }) }) }) }) }) }) }) }));
31
+ return (_jsx(BackendProvider, { backend: backend, children: _jsx(WorkspaceProvider, { workspace: workspace, children: _jsx(IntlWrapper, { locale: props.locale, children: _jsx(ToastsCenterContextProvider, { children: _jsx(OverlayProvider, { children: _jsx(PermissionsProvider, { permissionsState: permissionsState, children: _jsx(QualityProvider, { backend: backend, workspace: workspace, children: _jsx(CatalogResourceProvider, { backend: backend, workspace: workspace, children: _jsx(AsCodeMutationProvider, { descriptors: asCodeDescriptors, children: props.children }) }) }) }) }) }) }) }) }));
32
32
  }
@@ -0,0 +1,17 @@
1
+ import type { ICatalogItem } from "../catalogItem/types.js";
2
+ import type { IAsCodeDefinition, IAsCodeDescriptor } from "./descriptor.js";
3
+ type Props = {
4
+ descriptor: IAsCodeDescriptor;
5
+ duplicateOf?: ICatalogItem;
6
+ duplicateSource?: IAsCodeDefinition;
7
+ onClose: () => void;
8
+ onCreated?: (item: ICatalogItem) => void;
9
+ };
10
+ /**
11
+ * Creates an as-code object — blank, or seeded from a copy source when duplicating. Generic over the
12
+ * entity type via its descriptor.
13
+ * @internal
14
+ */
15
+ export declare function AsCodeCreateDialog({ descriptor, duplicateOf, duplicateSource, onClose, onCreated }: Props): import("react/jsx-runtime").JSX.Element;
16
+ export {};
17
+ //# sourceMappingURL=AsCodeCreateDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsCodeCreateDialog.d.ts","sourceRoot":"","sources":["../../src/asCode/AsCodeCreateDialog.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAI5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAG5E,KAAK,KAAK,GAAG;IACT,UAAU,EAAE,iBAAiB,CAAC;IAE9B,WAAW,CAAC,EAAE,YAAY,CAAC;IAG3B,eAAe,CAAC,EAAE,iBAAiB,CAAC;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;CAC5C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,2CA8DzG"}
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useCallback, useMemo } from "react";
4
+ import { useIntl } from "react-intl";
5
+ import { useToastMessage } from "@gooddata/sdk-ui-kit";
6
+ import { AsCodeDialog } from "./AsCodeDialog.js";
7
+ import { isDuplicateIdError } from "./copy.js";
8
+ import { useAsCodeBase } from "./useAsCodeBase.js";
9
+ /**
10
+ * Creates an as-code object — blank, or seeded from a copy source when duplicating. Generic over the
11
+ * entity type via its descriptor.
12
+ * @internal
13
+ */
14
+ export function AsCodeCreateDialog({ descriptor, duplicateOf, duplicateSource, onClose, onCreated }) {
15
+ const intl = useIntl();
16
+ const { addSuccess, addError } = useToastMessage();
17
+ const { base: loadedSource, isLoading, port, } = useAsCodeBase(descriptor, duplicateOf, () => {
18
+ if (descriptor.messages.loadError) {
19
+ addError(descriptor.messages.loadError);
20
+ }
21
+ onClose();
22
+ });
23
+ const source = duplicateSource ?? loadedSource;
24
+ const copied = useMemo(() => (source === undefined ? undefined : descriptor.toCopy(source)), [descriptor, source]);
25
+ const initialDefinition = useMemo(() => copied ?? descriptor.emptyDefinition(intl.formatMessage(descriptor.messages.createDefaultTitle)), [copied, descriptor, intl]);
26
+ const copiedId = copied?.id;
27
+ const handleSubmit = useCallback(async (definition) => {
28
+ // A duplicate re-applies the copied source's non-YAML fields; otherwise persist the parsed YAML.
29
+ const toPersist = copied && descriptor.applyYamlEdits
30
+ ? descriptor.applyYamlEdits(copied, definition)
31
+ : definition;
32
+ let created;
33
+ try {
34
+ created = await port.create(toPersist);
35
+ }
36
+ catch (error) {
37
+ // The copied identity collided; let the backend derive a fresh one by dropping the id.
38
+ if (copiedId !== undefined && toPersist.id === copiedId && isDuplicateIdError(error)) {
39
+ const { id: _id, ...withoutId } = toPersist;
40
+ created = await port.create(withoutId);
41
+ }
42
+ else {
43
+ throw error;
44
+ }
45
+ }
46
+ onCreated?.(created);
47
+ onClose();
48
+ addSuccess(descriptor.messages.createSuccess);
49
+ }, [addSuccess, copied, copiedId, descriptor, onClose, onCreated, port]);
50
+ return (_jsx(AsCodeDialog, { descriptor: descriptor, mode: "create", isLoading: isLoading, initialDefinition: isLoading ? undefined : initialDefinition, onClose: onClose, onSubmit: handleSubmit }));
51
+ }
@@ -0,0 +1,17 @@
1
+ import type { ICatalogItem } from "../catalogItem/types.js";
2
+ import type { IAsCodeDescriptor } from "./descriptor.js";
3
+ type Props = {
4
+ descriptor: IAsCodeDescriptor;
5
+ item: ICatalogItem;
6
+ onClose: () => void;
7
+ onDeleted: () => void;
8
+ };
9
+ /**
10
+ * Confirms deletion of an as-code object. A type that reports a referencing count (see
11
+ * `port.getReferencingObjectsCount`) withholds the confirm until the lookup resolves and warns when
12
+ * the object is in use; a type without one deletes straight away. Generic over the descriptor.
13
+ * @internal
14
+ */
15
+ export declare function AsCodeDeleteDialog({ descriptor, item, onClose, onDeleted }: Props): import("react/jsx-runtime").JSX.Element;
16
+ export {};
17
+ //# sourceMappingURL=AsCodeDeleteDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsCodeDeleteDialog.d.ts","sourceRoot":"","sources":["../../src/asCode/AsCodeDeleteDialog.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAMzD,KAAK,KAAK,GAAG;IACT,UAAU,EAAE,iBAAiB,CAAC;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,2CAkEjF"}
@@ -0,0 +1,55 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } 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 { useCancelablePromise } from "@gooddata/sdk-ui";
6
+ import { ConfirmDialog, useToastMessage } from "@gooddata/sdk-ui-kit";
7
+ import { useAsCodePort } from "./AsCodeMutationContext.js";
8
+ const messages = defineMessages({
9
+ cancel: { id: "analyticsCatalog.asCode.dialog.cancel" },
10
+ });
11
+ /**
12
+ * Confirms deletion of an as-code object. A type that reports a referencing count (see
13
+ * `port.getReferencingObjectsCount`) withholds the confirm until the lookup resolves and warns when
14
+ * the object is in use; a type without one deletes straight away. Generic over the descriptor.
15
+ * @internal
16
+ */
17
+ export function AsCodeDeleteDialog({ descriptor, item, onClose, onDeleted }) {
18
+ const intl = useIntl();
19
+ const { addSuccess, addError } = useToastMessage();
20
+ const port = useAsCodePort(descriptor.objectType);
21
+ const { messages: msg } = descriptor;
22
+ const [isDeleting, setIsDeleting] = useState(false);
23
+ // For a type with a usage lookup, withhold deletion until it resolves so the dependent-object
24
+ // warning can surface first; a type without one has nothing to wait for, so starts unblocked.
25
+ const lookup = port.getReferencingObjectsCount;
26
+ const { result, status } = useCancelablePromise({ promise: lookup ? () => lookup(item) : undefined }, [
27
+ item,
28
+ port,
29
+ ]);
30
+ // The lookup is advisory: no lookup or a failed one means no warning and nothing to wait for.
31
+ const referencingCount = !lookup || status === "error" ? 0 : result;
32
+ const displayName = item.title || item.identifier;
33
+ const handleDelete = useCallback(async () => {
34
+ setIsDeleting(true);
35
+ try {
36
+ await port.delete(item);
37
+ onDeleted();
38
+ onClose();
39
+ addSuccess(msg.deleteSuccess);
40
+ }
41
+ catch {
42
+ addError(msg.deleteError);
43
+ setIsDeleting(false);
44
+ }
45
+ }, [addError, addSuccess, item, msg, onClose, onDeleted, port]);
46
+ const handleClose = useCallback(() => {
47
+ if (!isDeleting) {
48
+ onClose();
49
+ }
50
+ }, [isDeleting, onClose]);
51
+ return (_jsxs(ConfirmDialog, { headline: intl.formatMessage(msg.deleteTitle), cancelButtonText: intl.formatMessage(messages.cancel), submitButtonText: intl.formatMessage(msg.deleteSubmit), isPositive: false, isSubmitDisabled: isDeleting || referencingCount === undefined, isCancelDisabled: isDeleting, showProgressIndicator: isDeleting, onCancel: handleClose, onClose: handleClose, onSubmit: handleDelete, displayCloseButton: !isDeleting, children: [_jsx(FormattedMessage, { ...msg.deleteBody, values: {
52
+ name: displayName,
53
+ b: (chunks) => _jsx("b", { children: chunks }),
54
+ } }), referencingCount && msg.deleteUsageWarning ? (_jsx("div", { children: _jsx(FormattedMessage, { ...msg.deleteUsageWarning, values: { count: referencingCount } }) })) : null] }));
55
+ }
@@ -0,0 +1,27 @@
1
+ import { type MouseEvent } from "react";
2
+ import type { OpenHandlerEvent } from "../catalogDetail/types.js";
3
+ import type { ICatalogItem, ICatalogItemRef } from "../catalogItem/types.js";
4
+ import type { IAsCodeDescriptor } from "./descriptor.js";
5
+ /**
6
+ * @internal
7
+ */
8
+ export interface IAsCodeDetailActionsProps {
9
+ descriptor: IAsCodeDescriptor;
10
+ item: ICatalogItem;
11
+ /** When provided and the descriptor declares an `openAction` (e.g. "Open in metric editor"), that
12
+ * action opens the standalone editor through this handler; omitted, it is not offered. */
13
+ onOpen?: (event: MouseEvent, openEvent: OpenHandlerEvent) => void;
14
+ canShare?: boolean;
15
+ onShare?: () => void;
16
+ onCatalogItemCreate?: (item: ICatalogItem) => void;
17
+ onCatalogItemUpdate?: (item: ICatalogItem) => void;
18
+ onCatalogItemDelete?: (ref: ICatalogItemRef) => void;
19
+ }
20
+ /**
21
+ * Detail-panel actions for an as-code object: inline edit, duplicate, and delete via the shared
22
+ * dialogs, plus the Share button and the descriptor's open action if it declares one. Generic over the
23
+ * entity type via its descriptor.
24
+ * @internal
25
+ */
26
+ export declare function AsCodeDetailActions({ descriptor, item, onOpen, canShare, onShare, onCatalogItemCreate, onCatalogItemUpdate, onCatalogItemDelete }: IAsCodeDetailActionsProps): import("react/jsx-runtime").JSX.Element;
27
+ //# sourceMappingURL=AsCodeDetailActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsCodeDetailActions.d.ts","sourceRoot":"","sources":["../../src/asCode/AsCodeDetailActions.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAsB,KAAK,UAAU,EAAkC,MAAM,OAAO,CAAC;AAS5F,OAAO,KAAK,EAAwB,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxF,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK7E,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAY5E;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACtC,UAAU,EAAE,iBAAiB,CAAC;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB;+FAC2F;IAC3F,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,YAAY,KAAK,IAAI,CAAC;IACnD,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;CACxD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,UAAU,EACV,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,OAAO,EACP,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACtB,EAAE,yBAAyB,2CAgG3B"}
@@ -0,0 +1,66 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useCallback, useMemo, useState } from "react";
4
+ import { useIntl } from "react-intl";
5
+ import { useWorkspaceStrict } from "@gooddata/sdk-ui";
6
+ import { catalogDetailActionDelete, catalogDetailActionDuplicate } from "../automation/testIds.js";
7
+ import { CatalogDetailActionBar } from "../catalogDetail/CatalogDetailActionBar.js";
8
+ import { ShareButton } from "../catalogDetail/share/ShareButton.js";
9
+ import { AsCodeCreateDialog } from "./AsCodeCreateDialog.js";
10
+ import { AsCodeDeleteDialog } from "./AsCodeDeleteDialog.js";
11
+ import { AsCodeEditDialog } from "./AsCodeEditDialog.js";
12
+ const OPEN_ACTION_ID = "open";
13
+ /**
14
+ * Detail-panel actions for an as-code object: inline edit, duplicate, and delete via the shared
15
+ * dialogs, plus the Share button and the descriptor's open action if it declares one. Generic over the
16
+ * entity type via its descriptor.
17
+ * @internal
18
+ */
19
+ export function AsCodeDetailActions({ descriptor, item, onOpen, canShare, onShare, onCatalogItemCreate, onCatalogItemUpdate, onCatalogItemDelete, }) {
20
+ const intl = useIntl();
21
+ const workspaceId = useWorkspaceStrict();
22
+ const [dialog, setDialog] = useState(undefined);
23
+ const actions = useMemo(() => {
24
+ const result = [];
25
+ // The open action reaches the standalone editor via onOpen, so it is offered only when the host
26
+ // provides that handler and the descriptor declares one; the menu then never shows a dead item.
27
+ if (onOpen && descriptor.openAction) {
28
+ result.push({ id: OPEN_ACTION_ID, label: intl.formatMessage(descriptor.openAction) });
29
+ }
30
+ result.push({
31
+ id: "duplicate",
32
+ label: intl.formatMessage(descriptor.messages.duplicate),
33
+ dataTestId: catalogDetailActionDuplicate,
34
+ }, {
35
+ id: "delete",
36
+ label: intl.formatMessage(descriptor.messages.deleteSubmit),
37
+ isDestructive: true,
38
+ dataTestId: catalogDetailActionDelete,
39
+ });
40
+ return result;
41
+ }, [descriptor, intl, onOpen]);
42
+ const closeDialog = useCallback(() => setDialog(undefined), []);
43
+ const handleEditOpen = useCallback(() => setDialog({ kind: "edit", item }), [item]);
44
+ const handleActionsMenuSelect = useCallback((actionId, event) => {
45
+ if (actionId === OPEN_ACTION_ID) {
46
+ onOpen?.(event, {
47
+ item,
48
+ workspaceId,
49
+ newTab: event.metaKey || event.ctrlKey,
50
+ preventDefault: event.preventDefault.bind(event),
51
+ });
52
+ return;
53
+ }
54
+ if (actionId === "delete") {
55
+ setDialog({ kind: "delete", item });
56
+ return;
57
+ }
58
+ if (actionId === "duplicate") {
59
+ setDialog({ kind: "duplicate", duplicateOf: item });
60
+ }
61
+ }, [item, onOpen, workspaceId]);
62
+ const handleEditDuplicate = useCallback((source) => {
63
+ setDialog({ kind: "duplicate", duplicateSource: source });
64
+ }, []);
65
+ 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(AsCodeEditDialog, { descriptor: descriptor, item: dialog.item, onClose: closeDialog, onSaved: onCatalogItemUpdate, onDuplicate: handleEditDuplicate })) : null, dialog?.kind === "duplicate" ? (_jsx(AsCodeCreateDialog, { descriptor: descriptor, duplicateOf: dialog.duplicateOf, duplicateSource: dialog.duplicateSource, onClose: closeDialog, onCreated: onCatalogItemCreate })) : null, dialog?.kind === "delete" ? (_jsx(AsCodeDeleteDialog, { descriptor: descriptor, item: dialog.item, onClose: closeDialog, onDeleted: () => onCatalogItemDelete?.(dialog.item) })) : null] }));
66
+ }
@@ -0,0 +1,24 @@
1
+ import type { IAsCodeDefinition, IAsCodeDescriptor } from "./descriptor.js";
2
+ /** Whether the dialog creates a new object or edits an existing one. */
3
+ type AsCodeDialogMode = "create" | "edit";
4
+ type Props = {
5
+ descriptor: IAsCodeDescriptor;
6
+ mode: AsCodeDialogMode;
7
+ initialDefinition?: IAsCodeDefinition;
8
+ isLoading?: boolean;
9
+ fixedIdentifier?: string;
10
+ onClose: () => void;
11
+ onSubmit: (definition: IAsCodeDefinition) => Promise<void>;
12
+ onDuplicate?: (definition: IAsCodeDefinition) => void;
13
+ };
14
+ /**
15
+ * Generic create/edit dialog for an as-code object, entity-agnostic via its `descriptor`: it renders
16
+ * the shared editor chrome and delegates serialization, validation, and copy to the descriptor. The
17
+ * caller owns loading and persistence (passes `initialDefinition`, handles `onSubmit`); this component
18
+ * owns only the editing surface.
19
+ *
20
+ * @internal
21
+ */
22
+ export declare function AsCodeDialog(props: Props): import("react/jsx-runtime").JSX.Element;
23
+ export {};
24
+ //# sourceMappingURL=AsCodeDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsCodeDialog.d.ts","sourceRoot":"","sources":["../../src/asCode/AsCodeDialog.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAa5E,wEAAwE;AACxE,KAAK,gBAAgB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1C,KAAK,KAAK,GAAG;IACT,UAAU,EAAE,iBAAiB,CAAC;IAC9B,IAAI,EAAE,gBAAgB,CAAC;IAIvB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,UAAU,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACzD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,2CAyKxC"}
@@ -0,0 +1,94 @@
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
+ const AsCodeEditorBody = lazy(() => import("./AsCodeEditorBody.js").then((m) => ({ default: m.AsCodeEditorBody })));
10
+ // Chrome shared by every as-code type; the entity-specific copy comes from `descriptor.messages`.
11
+ const messages = defineMessages({
12
+ createSubmit: { id: "analyticsCatalog.asCode.dialog.create.submit" },
13
+ editSubmit: { id: "analyticsCatalog.asCode.dialog.edit.submit" },
14
+ cancel: { id: "analyticsCatalog.asCode.dialog.cancel" },
15
+ });
16
+ /**
17
+ * Generic create/edit dialog for an as-code object, entity-agnostic via its `descriptor`: it renders
18
+ * the shared editor chrome and delegates serialization, validation, and copy to the descriptor. The
19
+ * caller owns loading and persistence (passes `initialDefinition`, handles `onSubmit`); this component
20
+ * owns only the editing surface.
21
+ *
22
+ * @internal
23
+ */
24
+ export function AsCodeDialog(props) {
25
+ const { descriptor, mode, initialDefinition, isLoading = false, fixedIdentifier } = props;
26
+ const { onClose, onSubmit, onDuplicate } = props;
27
+ const intl = useIntl();
28
+ const isEdit = mode === "edit";
29
+ const isWhiteLabeled = useIsWhiteLabeled();
30
+ // The descriptor is fixed for the dialog's lifetime (one dialog edits one entity type), so calling
31
+ // its `useEditing` hook here is unconditional and stable — the rules of hooks hold.
32
+ const editing = descriptor.useEditing();
33
+ const { serialize, validate, completionSource, syntaxErrorMessage } = editing;
34
+ const initialYaml = useMemo(() => (initialDefinition === undefined ? "" : serialize(initialDefinition)), [initialDefinition, serialize]);
35
+ // The user's edits; `null` until they type. Submit falls back to `initialYaml`, so the editor
36
+ // mounts once with real data and is the single source of truth — no re-seed effect needed.
37
+ const yamlValue = useRef(null);
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 ? descriptor.messages.editTitle : descriptor.messages.createTitle);
43
+ const submitMessage = intl.formatMessage(isEdit ? messages.editSubmit : messages.createSubmit);
44
+ const cancelMessage = intl.formatMessage(messages.cancel);
45
+ const handleClose = useCallback(() => {
46
+ if (!isSubmitting) {
47
+ onClose();
48
+ }
49
+ }, [isSubmitting, onClose]);
50
+ const handleChange = useCallback((nextValue) => {
51
+ yamlValue.current = nextValue;
52
+ setIsDirty(true);
53
+ setSubmitError(null);
54
+ setValidationError(null);
55
+ }, []);
56
+ const handleSubmit = useCallback(async () => {
57
+ const result = validate(yamlValue.current ?? initialYaml, { fixedIdentifier });
58
+ if (!result.isValid) {
59
+ setValidationError(result.error);
60
+ return;
61
+ }
62
+ setIsSubmitting(true);
63
+ setSubmitError(null);
64
+ try {
65
+ await onSubmit(result.definition);
66
+ }
67
+ catch (error) {
68
+ setSubmitError(extractBackendErrorDetail(error) ?? intl.formatMessage(descriptor.messages.submitError));
69
+ }
70
+ finally {
71
+ setIsSubmitting(false);
72
+ }
73
+ }, [descriptor, fixedIdentifier, initialYaml, intl, onSubmit, validate]);
74
+ const handleDuplicate = useCallback(() => {
75
+ if (!onDuplicate) {
76
+ return;
77
+ }
78
+ setSubmitError(null);
79
+ // A duplicate is a fresh object, so identity is not fixed even though we started from an edit.
80
+ const result = validate(yamlValue.current ?? initialYaml, { fixedIdentifier: undefined });
81
+ if (!result.isValid) {
82
+ setValidationError(result.error);
83
+ return;
84
+ }
85
+ onDuplicate(result.definition);
86
+ }, [initialYaml, onDuplicate, validate]);
87
+ const footerLeftRenderer = useCallback(() => (_jsxs("div", { className: "gd-ascode-dialog-footer-left", children: [isWhiteLabeled ? null : (_jsxs(UiLink, { variant: "secondary", href: descriptor.docsUrl, target: "_blank", rel: "noopener noreferrer", children: [
88
+ _jsx(UiIcon, { type: "question", size: 14, color: "complementary-6" }), intl.formatMessage(descriptor.messages.help)] })), isEdit && onDuplicate ? (_jsx(UiButton, { label: intl.formatMessage(descriptor.messages.duplicate), variant: "tertiary", isDisabled: isSubmitting || isLoading, onClick: handleDuplicate })) : null] })), [descriptor, handleDuplicate, intl, isEdit, isLoading, isSubmitting, isWhiteLabeled, onDuplicate]);
89
+ const bodySpinner = (_jsx("div", { className: "gd-ascode-dialog-loading", children: _jsx(LoadingComponent, {}) }));
90
+ 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: [
91
+ _jsxs("div", { className: "gd-ascode-dialog-section-header", children: [intl.formatMessage(descriptor.messages.sectionHeader), _jsx(UiTooltip, { arrowPlacement: "top", optimalPlacement: true, triggerBy: ["hover", "click", "focus"], anchor: _jsx(UiIcon, { type: "question", size: 14, color: "complementary-6" }), content: intl.formatMessage(descriptor.messages.sectionHeaderTooltip) })
92
+ ] }), _jsx("div", { className: "gd-ascode-dialog-editor", children: _jsx(AsCodeEditorBody, { initialValue: initialYaml, onChange: handleChange, disabled: isSubmitting, completionSource: completionSource, syntaxErrorMessage: syntaxErrorMessage }) }), validationError || submitError ? (_jsxs("div", { className: "gd-ascode-dialog-error", children: [
93
+ _jsx("span", { className: "gd-ascode-dialog-error-label", children: _jsx(FormattedMessage, { id: "analyticsCatalog.dialog.error.label" }) }), " ", validationError ?? submitError] })) : null] })) }) }) }));
94
+ }
@@ -0,0 +1,18 @@
1
+ import type { ICatalogItem } from "../catalogItem/types.js";
2
+ import type { IAsCodeDefinition, IAsCodeDescriptor } from "./descriptor.js";
3
+ type Props = {
4
+ descriptor: IAsCodeDescriptor;
5
+ item: ICatalogItem;
6
+ onClose: () => void;
7
+ onSaved?: (item: ICatalogItem) => void;
8
+ onDuplicate?: (source: IAsCodeDefinition) => void;
9
+ };
10
+ /**
11
+ * Edits an existing as-code object. Its editable definition is resolved by {@link useAsCodeBase} —
12
+ * fetched for a type with `port.load` (a metric's MAQL), or mapped from the item for one without.
13
+ * Generic over the entity type via its descriptor.
14
+ * @internal
15
+ */
16
+ export declare function AsCodeEditDialog({ descriptor, item, onClose, onSaved, onDuplicate }: Props): import("react/jsx-runtime").JSX.Element;
17
+ export {};
18
+ //# sourceMappingURL=AsCodeEditDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsCodeEditDialog.d.ts","sourceRoot":"","sources":["../../src/asCode/AsCodeEditDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAG5E,KAAK,KAAK,GAAG;IACT,UAAU,EAAE,iBAAiB,CAAC;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAGvC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACrD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,KAAK,2CA6C1F"}
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { useCallback } from "react";
4
+ import { useToastMessage } from "@gooddata/sdk-ui-kit";
5
+ import { AsCodeDialog } from "./AsCodeDialog.js";
6
+ import { useAsCodeBase } from "./useAsCodeBase.js";
7
+ /**
8
+ * Edits an existing as-code object. Its editable definition is resolved by {@link useAsCodeBase} —
9
+ * fetched for a type with `port.load` (a metric's MAQL), or mapped from the item for one without.
10
+ * Generic over the entity type via its descriptor.
11
+ * @internal
12
+ */
13
+ export function AsCodeEditDialog({ descriptor, item, onClose, onSaved, onDuplicate }) {
14
+ const { addSuccess, addError } = useToastMessage();
15
+ const { base, isLoading, port } = useAsCodeBase(descriptor, item, () => {
16
+ if (descriptor.messages.loadError) {
17
+ addError(descriptor.messages.loadError);
18
+ }
19
+ onClose();
20
+ });
21
+ const handleSubmit = useCallback(async (definition) => {
22
+ if (base === undefined) {
23
+ return;
24
+ }
25
+ const saved = await port.update(base, definition);
26
+ onSaved?.(saved);
27
+ onClose();
28
+ addSuccess(descriptor.messages.updateSuccess);
29
+ }, [addSuccess, base, descriptor, onClose, onSaved, port]);
30
+ const handleDuplicate = useCallback((edited) => {
31
+ if (base === undefined || !onDuplicate) {
32
+ return;
33
+ }
34
+ // Overlay the edits onto the loaded base so the copy keeps fields the YAML can't express.
35
+ onDuplicate(descriptor.applyYamlEdits ? descriptor.applyYamlEdits(base, edited) : edited);
36
+ }, [base, descriptor, onDuplicate]);
37
+ return (_jsx(AsCodeDialog, { descriptor: descriptor, mode: "edit", isLoading: isLoading, initialDefinition: base, fixedIdentifier: item.identifier, onClose: onClose, onSubmit: handleSubmit, onDuplicate: onDuplicate ? handleDuplicate : undefined }));
38
+ }
@@ -0,0 +1,16 @@
1
+ import type { CompletionSource } from "@codemirror/autocomplete";
2
+ type Props = {
3
+ initialValue: string;
4
+ onChange: (value: string) => void;
5
+ disabled: boolean;
6
+ completionSource: CompletionSource;
7
+ syntaxErrorMessage: string;
8
+ };
9
+ /**
10
+ * The editor half of {@link AsCodeDialog}, split into its own module so the dialog can `lazy()`-load
11
+ * it: this keeps CodeMirror out of the eager catalog bundle. The completion source and syntax-error
12
+ * copy come from the entity's descriptor, so this stays entity-agnostic.
13
+ */
14
+ export declare function AsCodeEditorBody({ initialValue, onChange, disabled, completionSource, syntaxErrorMessage }: Props): import("react/jsx-runtime").JSX.Element;
15
+ export {};
16
+ //# sourceMappingURL=AsCodeEditorBody.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsCodeEditorBody.d.ts","sourceRoot":"","sources":["../../src/asCode/AsCodeEditorBody.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAIjE,KAAK,KAAK,GAAG;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,kBAAkB,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAC7B,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EACrB,EAAE,KAAK,2CAUP"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { YamlEditor } from "@gooddata/sdk-ui-kit";
3
+ /**
4
+ * The editor half of {@link AsCodeDialog}, split into its own module so the dialog can `lazy()`-load
5
+ * it: this keeps CodeMirror out of the eager catalog bundle. The completion source and syntax-error
6
+ * copy come from the entity's descriptor, so this stays entity-agnostic.
7
+ */
8
+ export function AsCodeEditorBody({ initialValue, onChange, disabled, completionSource, syntaxErrorMessage, }) {
9
+ return (_jsx(YamlEditor, { initialValue: initialValue, onChange: onChange, disabled: disabled, completionSource: completionSource, syntaxErrorMessage: syntaxErrorMessage }));
10
+ }
@@ -0,0 +1,24 @@
1
+ import { type PropsWithChildren } from "react";
2
+ import type { ObjectType } from "../objectType/types.js";
3
+ import type { AsCodeObjectType, IAsCodeDescriptor, IAsCodeMutationPort } from "./descriptor.js";
4
+ type AsCodeMutations = Partial<Record<AsCodeObjectType, IAsCodeMutationPort>>;
5
+ type ProviderProps = PropsWithChildren<{
6
+ /** Descriptors for each as-code capable object type; used to build adapters. */
7
+ descriptors?: Record<AsCodeObjectType, IAsCodeDescriptor>;
8
+ /** Per-type port overrides for tests. */
9
+ ports?: AsCodeMutations;
10
+ }>;
11
+ /**
12
+ * Builds and provides one mutation port per supplied descriptor. Must be placed inside `BackendProvider`
13
+ * and `WorkspaceProvider`.
14
+ * @internal
15
+ */
16
+ export declare function AsCodeMutationProvider({ children, descriptors, ports }: ProviderProps): import("react/jsx-runtime").JSX.Element;
17
+ /**
18
+ * The mutation port for one as-code type. Throws for a non-as-code type (a caller should only reach
19
+ * this via a resolved descriptor) or when the provider is missing.
20
+ * @internal
21
+ */
22
+ export declare function useAsCodePort(type: ObjectType): IAsCodeMutationPort;
23
+ export {};
24
+ //# sourceMappingURL=AsCodeMutationContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsCodeMutationContext.d.ts","sourceRoot":"","sources":["../../src/asCode/AsCodeMutationContext.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,iBAAiB,EAAsC,MAAM,OAAO,CAAC;AAInF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEhG,KAAK,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAI9E,KAAK,aAAa,GAAG,iBAAiB,CAAC;IACnC,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;IAC1D,yCAAyC;IACzC,KAAK,CAAC,EAAE,eAAe,CAAC;CAC3B,CAAC,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,aAAa,2CAerF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,mBAAmB,CAUnE"}
@@ -0,0 +1,40 @@
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
+ const AsCodeMutationContext = createContext(null);
6
+ /**
7
+ * Builds and provides one mutation port per supplied descriptor. Must be placed inside `BackendProvider`
8
+ * and `WorkspaceProvider`.
9
+ * @internal
10
+ */
11
+ export function AsCodeMutationProvider({ children, descriptors, ports }) {
12
+ const backend = useBackendStrict();
13
+ const workspace = useWorkspaceStrict();
14
+ const mutations = useMemo(() => {
15
+ const built = {};
16
+ // Object.entries widens the key to string; the map's own type guarantees it is an AsCodeObjectType.
17
+ const entries = Object.entries(descriptors ?? {});
18
+ for (const [type, descriptor] of entries) {
19
+ built[type] = descriptor.createMutationPort(backend, workspace);
20
+ }
21
+ return { ...built, ...ports };
22
+ }, [backend, workspace, descriptors, ports]);
23
+ return _jsx(AsCodeMutationContext.Provider, { value: mutations, children: children });
24
+ }
25
+ /**
26
+ * The mutation port for one as-code type. Throws for a non-as-code type (a caller should only reach
27
+ * this via a resolved descriptor) or when the provider is missing.
28
+ * @internal
29
+ */
30
+ export function useAsCodePort(type) {
31
+ const mutations = useContext(AsCodeMutationContext);
32
+ if (!mutations) {
33
+ throw new Error("useAsCodePort must be used within AsCodeMutationProvider");
34
+ }
35
+ const port = mutations[type];
36
+ if (!port) {
37
+ throw new Error(`No as-code mutation port is registered for object type "${type}".`);
38
+ }
39
+ return port;
40
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Derives the identity (id + title) of a copied as-code object from the original; the remaining
3
+ * fields are copied by each type.
4
+ *
5
+ * The title gains a ` (2)` suffix, or increments an existing ` (N)`. The id is re-derived from that
6
+ * title or dropped (see `shouldOmitCopiedId`). Absent fields are left off so a spread does not
7
+ * introduce them.
8
+ */
9
+ export declare function deriveCopyIdentity(source: {
10
+ id?: string;
11
+ title?: string;
12
+ }): {
13
+ id?: string;
14
+ title?: string;
15
+ };
16
+ /** A create failed because the chosen id already exists (backend responds with HTTP 409). */
17
+ export declare function isDuplicateIdError(error: unknown): boolean;
18
+ //# sourceMappingURL=copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../../src/asCode/copy.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IACzE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAOA;AAwCD,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE1D"}