@gooddata/sdk-ui-catalog 11.50.0-alpha.2 → 11.50.0-alpha.4
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 +1 -3
- package/esm/asCode/AsCodeCreateDialog.d.ts +3 -7
- package/esm/asCode/AsCodeCreateDialog.d.ts.map +1 -1
- package/esm/asCode/AsCodeCreateDialog.js +13 -23
- package/esm/asCode/AsCodeDeleteDialog.d.ts +1 -6
- package/esm/asCode/AsCodeDeleteDialog.d.ts.map +1 -1
- package/esm/asCode/AsCodeDeleteDialog.js +11 -20
- package/esm/asCode/AsCodeDetailActions.d.ts +2 -11
- package/esm/asCode/AsCodeDetailActions.d.ts.map +1 -1
- package/esm/asCode/AsCodeDetailActions.js +16 -22
- package/esm/asCode/AsCodeDialog.d.ts +12 -17
- package/esm/asCode/AsCodeDialog.d.ts.map +1 -1
- package/esm/asCode/AsCodeDialog.js +59 -27
- package/esm/asCode/AsCodeEditDialog.d.ts +3 -8
- package/esm/asCode/AsCodeEditDialog.d.ts.map +1 -1
- package/esm/asCode/AsCodeEditDialog.js +4 -21
- package/esm/asCode/descriptor.d.ts +78 -104
- package/esm/asCode/descriptor.d.ts.map +1 -1
- package/esm/asCode/descriptor.js +13 -4
- package/esm/asCode/serverIdentity.d.ts +7 -0
- package/esm/asCode/serverIdentity.d.ts.map +1 -0
- package/esm/asCode/serverIdentity.js +2 -0
- package/esm/asCode/tests/withMutationPort.d.ts +4 -0
- package/esm/asCode/tests/withMutationPort.d.ts.map +1 -0
- package/esm/asCode/tests/withMutationPort.js +5 -0
- package/esm/asCode/useAsCodeBase.d.ts +5 -8
- package/esm/asCode/useAsCodeBase.d.ts.map +1 -1
- package/esm/asCode/useAsCodeBase.js +20 -18
- package/esm/asCode/useAsCodeLoadFailure.d.ts +8 -0
- package/esm/asCode/useAsCodeLoadFailure.d.ts.map +1 -0
- package/esm/asCode/useAsCodeLoadFailure.js +21 -0
- package/esm/asCode/useMutationPort.d.ts +4 -0
- package/esm/asCode/useMutationPort.d.ts.map +1 -0
- package/esm/asCode/useMutationPort.js +9 -0
- package/esm/asCode/validateYaml.d.ts +16 -12
- package/esm/asCode/validateYaml.d.ts.map +1 -1
- package/esm/asCode/validateYaml.js +8 -9
- package/esm/asCodeRegistry.d.ts +5 -14
- package/esm/asCodeRegistry.d.ts.map +1 -1
- package/esm/asCodeRegistry.js +29 -15
- package/esm/catalog/Catalog.d.ts.map +1 -1
- package/esm/catalog/Catalog.js +2 -8
- package/esm/catalogDetail/CatalogDetailActionBar.d.ts.map +1 -1
- package/esm/catalogDetail/CatalogDetailActionBar.js +4 -8
- package/esm/catalogDetail/CatalogDetailActions.d.ts.map +1 -1
- package/esm/catalogDetail/CatalogDetailActions.js +2 -6
- package/esm/catalogDetail/openHandlerEvent.d.ts +6 -0
- package/esm/catalogDetail/openHandlerEvent.d.ts.map +1 -0
- package/esm/catalogDetail/openHandlerEvent.js +10 -0
- package/esm/header/CreateObjectButton.d.ts +1 -3
- package/esm/header/CreateObjectButton.d.ts.map +1 -1
- package/esm/header/CreateObjectButton.js +10 -22
- package/esm/index.d.ts +2 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +5 -0
- package/esm/insight/gate.d.ts +4 -0
- package/esm/insight/gate.d.ts.map +1 -0
- package/esm/insight/gate.js +4 -0
- package/esm/insight/insightCodecContext.d.ts +22 -0
- package/esm/insight/insightCodecContext.d.ts.map +1 -0
- package/esm/insight/insightCodecContext.js +30 -0
- package/esm/insight/insightCopy.d.ts +4 -0
- package/esm/insight/insightCopy.d.ts.map +1 -0
- package/esm/insight/insightCopy.js +25 -0
- package/esm/insight/insightDescriptor.d.ts +7 -0
- package/esm/insight/insightDescriptor.d.ts.map +1 -0
- package/esm/insight/insightDescriptor.js +69 -0
- package/esm/insight/insightMutationPort.d.ts +13 -0
- package/esm/insight/insightMutationPort.d.ts.map +1 -0
- package/esm/insight/insightMutationPort.js +59 -0
- package/esm/localization/bundles/en-US.localization-bundle.d.ts +72 -0
- package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/en-US.localization-bundle.js +72 -0
- package/esm/metric/gate.d.ts +1 -6
- package/esm/metric/gate.d.ts.map +1 -1
- package/esm/metric/gate.js +1 -9
- package/esm/metric/metricConverter.d.ts +8 -17
- package/esm/metric/metricConverter.d.ts.map +1 -1
- package/esm/metric/metricConverter.js +10 -24
- package/esm/metric/metricDescriptor.d.ts.map +1 -1
- package/esm/metric/metricDescriptor.js +19 -8
- package/esm/metric/metricMutationPort.d.ts +5 -3
- package/esm/metric/metricMutationPort.d.ts.map +1 -1
- package/esm/metric/metricMutationPort.js +21 -14
- package/esm/metric/metricValidation.d.ts.map +1 -1
- package/esm/metric/metricValidation.js +7 -4
- package/esm/metric/tests/metricMutationPort.test.utils.d.ts +1 -4
- package/esm/metric/tests/metricMutationPort.test.utils.d.ts.map +1 -1
- package/esm/metric/tests/metricMutationPort.test.utils.js +1 -19
- package/esm/parameter/gate.d.ts +1 -5
- package/esm/parameter/gate.d.ts.map +1 -1
- package/esm/parameter/gate.js +1 -8
- package/esm/parameter/parameterDescriptor.d.ts.map +1 -1
- package/esm/parameter/parameterDescriptor.js +22 -13
- package/esm/parameter/parameterValidation.d.ts.map +1 -1
- package/esm/parameter/parameterValidation.js +11 -23
- package/esm/sdk-ui-catalog.d.ts +49 -0
- package/package.json +15 -15
- package/esm/asCode/AsCodeMutationContext.d.ts +0 -24
- package/esm/asCode/AsCodeMutationContext.d.ts.map +0 -1
- package/esm/asCode/AsCodeMutationContext.js +0 -40
- package/esm/asCode/gate.d.ts +0 -7
- package/esm/asCode/gate.d.ts.map +0 -1
- package/esm/asCode/gate.js +0 -11
package/esm/asCodeRegistry.js
CHANGED
|
@@ -1,32 +1,24 @@
|
|
|
1
1
|
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { visualizationDescriptor } from "./insight/insightDescriptor.js";
|
|
2
4
|
import { metricDescriptor } from "./metric/metricDescriptor.js";
|
|
3
5
|
import { ObjectTypes } from "./objectType/constants.js";
|
|
4
6
|
import { parameterDescriptor } from "./parameter/parameterDescriptor.js";
|
|
5
|
-
import { useFeatureFlags } from "./permission/PermissionsContext.js";
|
|
6
|
-
/**
|
|
7
|
-
* Every as-code descriptor, keyed by type — the one place the concrete descriptors are registered. The
|
|
8
|
-
* key is the full `AsCodeObjectType` union, so a missing type is a compile error.
|
|
9
|
-
* @internal
|
|
10
|
-
*/
|
|
7
|
+
import { useFeatureFlags, useWorkspacePermission } from "./permission/PermissionsContext.js";
|
|
8
|
+
/** @internal */
|
|
11
9
|
export const asCodeDescriptors = {
|
|
12
10
|
[ObjectTypes.METRIC]: metricDescriptor,
|
|
13
11
|
[ObjectTypes.PARAMETER]: parameterDescriptor,
|
|
12
|
+
[ObjectTypes.VISUALIZATION]: visualizationDescriptor,
|
|
14
13
|
};
|
|
15
14
|
function isAsCodeObjectType(type) {
|
|
16
15
|
return Object.prototype.hasOwnProperty.call(asCodeDescriptors, type);
|
|
17
16
|
}
|
|
18
|
-
/**
|
|
19
|
-
* The as-code descriptor for a catalog object type, or `undefined` if the type is not editable as code.
|
|
20
|
-
* @internal
|
|
21
|
-
*/
|
|
17
|
+
/** @internal */
|
|
22
18
|
export function getAsCodeDescriptor(type) {
|
|
23
19
|
return isAsCodeObjectType(type) ? asCodeDescriptors[type] : undefined;
|
|
24
20
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Whether this descriptor's editor is enabled by the feature flags. A descriptor with no `featureFlag`
|
|
27
|
-
* is always editable; `undefined` (not an as-code type) never is.
|
|
28
|
-
* @internal
|
|
29
|
-
*/
|
|
21
|
+
/** A descriptor with no `featureFlag` is always editable; `undefined` (not an as-code type) never is. @internal */
|
|
30
22
|
export function useIsAsCodeTypeEditable(descriptor) {
|
|
31
23
|
const flags = useFeatureFlags();
|
|
32
24
|
if (descriptor === undefined) {
|
|
@@ -34,3 +26,25 @@ export function useIsAsCodeTypeEditable(descriptor) {
|
|
|
34
26
|
}
|
|
35
27
|
return descriptor.featureFlag === undefined || Boolean(flags?.[descriptor.featureFlag]);
|
|
36
28
|
}
|
|
29
|
+
function useIsAsCodeTypeCreatable(descriptor) {
|
|
30
|
+
const isTypeEditable = useIsAsCodeTypeEditable(descriptor);
|
|
31
|
+
const canManageProject = useWorkspacePermission("canManageProject");
|
|
32
|
+
const createGate = descriptor.useCreateGate?.() ?? true;
|
|
33
|
+
return isTypeEditable && canManageProject && createGate;
|
|
34
|
+
}
|
|
35
|
+
/** @internal */
|
|
36
|
+
export function useCreatableObjectTypes() {
|
|
37
|
+
// One unconditional hook call per registered type (fixed count for the rules of hooks).
|
|
38
|
+
const metric = useIsAsCodeTypeCreatable(asCodeDescriptors[ObjectTypes.METRIC]);
|
|
39
|
+
const parameter = useIsAsCodeTypeCreatable(asCodeDescriptors[ObjectTypes.PARAMETER]);
|
|
40
|
+
const visualization = useIsAsCodeTypeCreatable(asCodeDescriptors[ObjectTypes.VISUALIZATION]);
|
|
41
|
+
return useMemo(() => {
|
|
42
|
+
// The `Record<AsCodeObjectType, …>` makes a newly registered type a compile error until listed here.
|
|
43
|
+
const creatable = {
|
|
44
|
+
[ObjectTypes.METRIC]: metric,
|
|
45
|
+
[ObjectTypes.PARAMETER]: parameter,
|
|
46
|
+
[ObjectTypes.VISUALIZATION]: visualization,
|
|
47
|
+
};
|
|
48
|
+
return new Set(Object.keys(creatable).filter((type) => creatable[type]));
|
|
49
|
+
}, [metric, parameter, visualization]);
|
|
50
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Catalog.d.ts","sourceRoot":"","sources":["../../src/catalog/Catalog.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,OAAO,CAAC;AAIxC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"Catalog.d.ts","sourceRoot":"","sources":["../../src/catalog/Catalog.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,OAAO,CAAC;AAIxC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAIpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAUtE,KAAK,KAAK,GAAG;IACT,OAAO,EAAE,kBAAkB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,eAAe,CAAC;IACrC,sBAAsB,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnF,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/E,qBAAqB,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;IACvD,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,uBAAuB,KAAK,IAAI,CAAC;CAClE,CAAC;AAEF,wBAAgB,OAAO,CAAC,EACpB,kBAAkB,EAClB,OAAO,EACP,SAAS,EACT,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACjB,EAAE,KAAK,2CA4DP"}
|
package/esm/catalog/Catalog.js
CHANGED
|
@@ -4,16 +4,12 @@ import {} from "react";
|
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
5
|
import { ErrorComponent } from "@gooddata/sdk-ui";
|
|
6
6
|
import { LoadingMask } from "@gooddata/sdk-ui-kit";
|
|
7
|
-
import { AsCodeMutationProvider } from "../asCode/AsCodeMutationContext.js";
|
|
8
|
-
import { asCodeDescriptors } from "../asCodeRegistry.js";
|
|
9
7
|
import { CatalogFeedProvider } from "../catalogItem/CatalogFeedContext.js";
|
|
10
8
|
import {} from "../catalogItem/types.js";
|
|
11
9
|
import { CreateObjectButton } from "../header/CreateObjectButton.js";
|
|
12
10
|
import { Header } from "../header/Header.js";
|
|
13
11
|
import { useCatalogItemOpen } from "../main/hooks/useCatalogItemOpen.js";
|
|
14
12
|
import { Main } from "../main/Main.js";
|
|
15
|
-
import { useCanManageMetric } from "../metric/gate.js";
|
|
16
|
-
import { useCanManageParameter } from "../parameter/gate.js";
|
|
17
13
|
import { PermissionsGate } from "../permission/PermissionsGate.js";
|
|
18
14
|
import { useIsCatalogQualityEnabled } from "../quality/gate.js";
|
|
19
15
|
import { QualityScoreCard } from "../quality/QualityScoreCard.js";
|
|
@@ -23,8 +19,6 @@ import { useIsCatalogTrendingObjectsEnabled } from "../tabs/gate.js";
|
|
|
23
19
|
import { Layout } from "./Layout.js";
|
|
24
20
|
export function Catalog({ openCatalogItemRef, backend, workspace, onCatalogItemOpenClick, onCatalogItemNavigation, onCatalogDetailOpened, onCatalogDetailClosed, onCreateObject, }) {
|
|
25
21
|
const intl = useIntl();
|
|
26
|
-
const showParameter = useCanManageParameter();
|
|
27
|
-
const showMetricEditor = useCanManageMetric();
|
|
28
22
|
const isTrendingEnabled = useIsCatalogTrendingObjectsEnabled();
|
|
29
23
|
const isQualityEnabled = useIsCatalogQualityEnabled();
|
|
30
24
|
const { open, openedItem, setItemOpened, onOpenDetail, onCloseDetail, onOpenClick } = useCatalogItemOpen(onCatalogItemOpenClick, onCatalogDetailOpened, onCatalogDetailClosed, openCatalogItemRef);
|
|
@@ -32,6 +26,6 @@ export function Catalog({ openCatalogItemRef, backend, workspace, onCatalogItemO
|
|
|
32
26
|
id: "analyticsCatalog.error.unknown.description",
|
|
33
27
|
}) }), unauthorizedNode: _jsx(ErrorComponent, { message: intl.formatMessage({ id: "analyticsCatalog.error.unauthorized.message" }), description: intl.formatMessage({
|
|
34
28
|
id: "analyticsCatalog.error.unauthorized.description",
|
|
35
|
-
}) }), children:
|
|
36
|
-
|
|
29
|
+
}) }), children: _jsxs(CatalogFeedProvider, { backend: backend, workspace: workspace, children: [_jsx(Header, { searchNode: _jsx(FullTextSearchInput, {}), createNode: onCreateObject ? _jsx(CreateObjectButton, { onCreateObject: onCreateObject }) : null }), isTrendingEnabled ? (_jsx(CatalogTabs, { onItemClick: onOpenDetail })) : isQualityEnabled ? (_jsx(QualityScoreCard, {})) : null, _jsx(Main, { workspace: workspace, backend: backend, open: open, openedItem: openedItem, setItemOpened: setItemOpened, onOpenDetail: onOpenDetail, onCloseDetail: onCloseDetail, onOpenClick: onOpenClick, onCatalogItemNavigation: onCatalogItemNavigation })
|
|
30
|
+
] }) }) }));
|
|
37
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CatalogDetailActionBar.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailActionBar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAW,MAAM,OAAO,CAAC;AAOrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"CatalogDetailActionBar.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailActionBar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAW,MAAM,OAAO,CAAC;AAOrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAUzE,MAAM,MAAM,4BAA4B,GAAG;IACvC,IAAI,EAAE,YAAY,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,YAAY,EAAE,oBAAoB,EAAE,EAAE,CAAC;IACvC,6DAA6D;IAC7D,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5E,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,aAAa,KAAK,IAAI,CAAC;CACtF,CAAC;AAEF;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EACnC,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,cAAc,EACd,WAAW,EACX,mBAAmB,EACtB,EAAE,4BAA4B,2CA8E9B"}
|
|
@@ -4,6 +4,7 @@ import { useMemo } from "react";
|
|
|
4
4
|
import { defineMessages, useIntl } from "react-intl";
|
|
5
5
|
import { Dropdown, UiButton, UiIconButton, UiMenu } from "@gooddata/sdk-ui-kit";
|
|
6
6
|
import { catalogDetailActionsTrigger } from "../automation/testIds.js";
|
|
7
|
+
import { toOpenHandlerEvent } from "./openHandlerEvent.js";
|
|
7
8
|
const messages = defineMessages({
|
|
8
9
|
actionsMenuAriaLabel: { id: "analyticsCatalog.catalogItem.actionsMenu.ariaLabel" },
|
|
9
10
|
});
|
|
@@ -22,14 +23,9 @@ export function CatalogDetailActionBar({ item, workspaceId, actionGroups, leadin
|
|
|
22
23
|
}));
|
|
23
24
|
return groupIndex > 0 ? [{ type: "separator" }, ...items] : items;
|
|
24
25
|
}), [actionGroups]);
|
|
25
|
-
return (_jsxs("div", { className: "gd-analytics-catalog-detail__detail-actions", children: [leadingActions, _jsx(UiButton, { label: intl.formatMessage({ id: "analyticsCatalog.edit" }), variant: "primary", size: "medium", onClick: (event) => {
|
|
26
|
-
onEditClick
|
|
27
|
-
|
|
28
|
-
workspaceId,
|
|
29
|
-
newTab: event.metaKey || event.ctrlKey,
|
|
30
|
-
preventDefault: event.preventDefault.bind(event),
|
|
31
|
-
});
|
|
32
|
-
} }), _jsx(Dropdown, { alignPoints: [{ align: "br tr" }], renderButton: ({ toggleDropdown, buttonRef, ariaAttributes, accessibilityConfig }) => (_jsx(UiIconButton, { ref: (element) => {
|
|
26
|
+
return (_jsxs("div", { className: "gd-analytics-catalog-detail__detail-actions", children: [leadingActions, onEditClick ? (_jsx(UiButton, { label: intl.formatMessage({ id: "analyticsCatalog.edit" }), variant: "primary", size: "medium", onClick: (event) => {
|
|
27
|
+
onEditClick(event, toOpenHandlerEvent(event, item, workspaceId));
|
|
28
|
+
} })) : null, _jsx(Dropdown, { alignPoints: [{ align: "br tr" }], renderButton: ({ toggleDropdown, buttonRef, ariaAttributes, accessibilityConfig }) => (_jsx(UiIconButton, { ref: (element) => {
|
|
33
29
|
buttonRef.current = element;
|
|
34
30
|
}, icon: "ellipsis", variant: "secondary", size: "medium", onClick: toggleDropdown, dataTestId: catalogDetailActionsTrigger, accessibilityConfig: {
|
|
35
31
|
...accessibilityConfig,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CatalogDetailActions.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailActions.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,OAAO,CAAC;AASxC,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"CatalogDetailActions.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailActions.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,OAAO,CAAC;AASxC,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACvC,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClE,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,oBAAoB,CAAC,EACjC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACtB,EAAE,0BAA0B,kDAgD5B"}
|
|
@@ -6,6 +6,7 @@ import { useWorkspaceStrict } from "@gooddata/sdk-ui";
|
|
|
6
6
|
import { UiButton } from "@gooddata/sdk-ui-kit";
|
|
7
7
|
import { AsCodeDetailActions } from "../asCode/AsCodeDetailActions.js";
|
|
8
8
|
import { getAsCodeDescriptor, useIsAsCodeTypeEditable } from "../asCodeRegistry.js";
|
|
9
|
+
import { toOpenHandlerEvent } from "./openHandlerEvent.js";
|
|
9
10
|
import { useCatalogItemShareActions } from "./share/CatalogItemShareProvider.js";
|
|
10
11
|
import { ShareButton } from "./share/ShareButton.js";
|
|
11
12
|
/**
|
|
@@ -36,12 +37,7 @@ export function CatalogDetailActions({ item, canEdit, onOpen, onCatalogItemCreat
|
|
|
36
37
|
return null;
|
|
37
38
|
}
|
|
38
39
|
return (_jsxs("div", { className: "gd-analytics-catalog-detail__header-actions", children: [share.active ? _jsx(ShareButton, { onClick: share.open }) : null, _jsx(UiButton, { label: intl.formatMessage({ id: "analyticsCatalog.catalogItem.open" }), variant: "primary", accessibilityConfig: { role: "link" }, onClick: (event) => {
|
|
39
|
-
onOpen?.(event,
|
|
40
|
-
item,
|
|
41
|
-
workspaceId,
|
|
42
|
-
newTab: event.metaKey || event.ctrlKey,
|
|
43
|
-
preventDefault: event.preventDefault.bind(event),
|
|
44
|
-
});
|
|
40
|
+
onOpen?.(event, toOpenHandlerEvent(event, item, workspaceId));
|
|
45
41
|
} })
|
|
46
42
|
] }));
|
|
47
43
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MouseEvent } from "react";
|
|
2
|
+
import type { ICatalogItem } from "../catalogItem/types.js";
|
|
3
|
+
import type { OpenHandlerEvent } from "./types.js";
|
|
4
|
+
/** @internal */
|
|
5
|
+
export declare function toOpenHandlerEvent(event: MouseEvent, item: ICatalogItem, workspaceId: string): OpenHandlerEvent;
|
|
6
|
+
//# sourceMappingURL=openHandlerEvent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openHandlerEvent.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/openHandlerEvent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,gBAAgB;AAChB,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,YAAY,EAClB,WAAW,EAAE,MAAM,GACpB,gBAAgB,CAOlB"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { CatalogCreateObjectType } from "../objectType/types.js";
|
|
2
2
|
type Props = {
|
|
3
3
|
onCreateObject: (objectType: CatalogCreateObjectType) => void;
|
|
4
|
-
showParameter?: boolean;
|
|
5
|
-
showMetricEditor?: boolean;
|
|
6
4
|
};
|
|
7
|
-
export declare function CreateObjectButton({ onCreateObject
|
|
5
|
+
export declare function CreateObjectButton({ onCreateObject }: Props): import("react/jsx-runtime").JSX.Element;
|
|
8
6
|
export {};
|
|
9
7
|
//# sourceMappingURL=CreateObjectButton.d.ts.map
|
|
@@ -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;AAatE,KAAK,KAAK,GAAG;IACT,cAAc,EAAE,CAAC,UAAU,EAAE,uBAAuB,KAAK,IAAI,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;AAatE,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"}
|
|
@@ -4,7 +4,7 @@ import { useCallback, useMemo, useState } from "react";
|
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
5
|
import { Dropdown, UiButton, UiIcon, UiMenu, } from "@gooddata/sdk-ui-kit";
|
|
6
6
|
import { AsCodeCreateDialog } from "../asCode/AsCodeCreateDialog.js";
|
|
7
|
-
import { getAsCodeDescriptor } from "../asCodeRegistry.js";
|
|
7
|
+
import { getAsCodeDescriptor, useCreatableObjectTypes } from "../asCodeRegistry.js";
|
|
8
8
|
import { useCatalogFeedActions } from "../catalogItem/CatalogFeedContext.js";
|
|
9
9
|
import { ObjectTypes } from "../objectType/constants.js";
|
|
10
10
|
import { getObjectTypeLabel } from "../objectType/labels.js";
|
|
@@ -14,23 +14,12 @@ const icons = {
|
|
|
14
14
|
[ObjectTypes.METRIC]: "metric",
|
|
15
15
|
[ObjectTypes.PARAMETER]: "parameter",
|
|
16
16
|
};
|
|
17
|
-
export function CreateObjectButton({ onCreateObject
|
|
17
|
+
export function CreateObjectButton({ onCreateObject }) {
|
|
18
18
|
const intl = useIntl();
|
|
19
19
|
const { refetchObjectType } = useCatalogFeedActions();
|
|
20
|
-
// The type whose create dialog is open, or undefined when none is. One state for every as-code
|
|
21
|
-
// type, since they all open the same generic dialog.
|
|
22
20
|
const [openType, setOpenType] = useState(undefined);
|
|
23
|
-
//
|
|
24
|
-
const inCatalogTypes =
|
|
25
|
-
const types = new Set();
|
|
26
|
-
if (showMetricEditor) {
|
|
27
|
-
types.add(ObjectTypes.METRIC);
|
|
28
|
-
}
|
|
29
|
-
if (showParameter) {
|
|
30
|
-
types.add(ObjectTypes.PARAMETER);
|
|
31
|
-
}
|
|
32
|
-
return types;
|
|
33
|
-
}, [showMetricEditor, showParameter]);
|
|
21
|
+
// Widened to the full create-menu vocabulary so redirect-only types can be membership-tested.
|
|
22
|
+
const inCatalogTypes = useCreatableObjectTypes();
|
|
34
23
|
const items = useMemo(() => {
|
|
35
24
|
const externalLinkIcon = _jsx(MenuItemIcon, { type: "externalLink" });
|
|
36
25
|
const interactiveItem = (type, redirects) => ({
|
|
@@ -38,21 +27,20 @@ export function CreateObjectButton({ onCreateObject, showParameter, showMetricEd
|
|
|
38
27
|
id: type,
|
|
39
28
|
stringTitle: getObjectTypeLabel(intl, type),
|
|
40
29
|
iconLeft: _jsx(MenuItemIcon, { type: icons[type] }),
|
|
41
|
-
// A redirect create leaves the catalog for the standalone editor; an in-catalog create
|
|
42
|
-
// opens a dialog and needs no external-link affordance.
|
|
43
30
|
iconRight: redirects ? externalLinkIcon : undefined,
|
|
44
31
|
data: type,
|
|
45
32
|
});
|
|
46
|
-
//
|
|
47
|
-
// in a catalog dialog. Metric switches sides: it redirects unless its in-catalog editor is on.
|
|
33
|
+
// Metric and visualization redirect to a standalone editor unless their in-catalog editor is on.
|
|
48
34
|
return [
|
|
49
35
|
interactiveItem(ObjectTypes.DASHBOARD, true),
|
|
50
|
-
|
|
51
|
-
|
|
36
|
+
...(inCatalogTypes.has(ObjectTypes.VISUALIZATION)
|
|
37
|
+
? []
|
|
38
|
+
: [interactiveItem(ObjectTypes.VISUALIZATION, true)]),
|
|
39
|
+
...(inCatalogTypes.has(ObjectTypes.METRIC) ? [] : [interactiveItem(ObjectTypes.METRIC, true)]),
|
|
52
40
|
{ type: "separator" },
|
|
53
41
|
...[...inCatalogTypes].map((type) => interactiveItem(type, false)),
|
|
54
42
|
];
|
|
55
|
-
}, [intl, inCatalogTypes
|
|
43
|
+
}, [intl, inCatalogTypes]);
|
|
56
44
|
const handleSelect = useCallback((item, _event) => {
|
|
57
45
|
if (inCatalogTypes.has(item.data)) {
|
|
58
46
|
setOpenType(item.data);
|
package/esm/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { AnalyticsCatalog, type IAnalyticsCatalogProps } from "./AnalyticsCatalog.js";
|
|
2
2
|
export { AnalyticsCatalogDetail, type IAnalyticsCatalogDetailProps, AnalyticsCatalogDetailContent, type IAnalyticsCatalogDetailContentProps, } from "./AnalyticsCatalogDetail.js";
|
|
3
3
|
export { AnalyticsCatalogFilter, type IAnalyticsCatalogFilterProps } from "./AnalyticsCatalogFilter.js";
|
|
4
|
+
export { InsightCodecProvider, type IInsightCodec, type VisualizationTypePredicate, } from "./insight/insightCodecContext.js";
|
|
5
|
+
export type { IAsCodeEditing, AsCodeValidation, AsCodeValidationContext } from "./asCode/descriptor.js";
|
|
4
6
|
export type { ICatalogDetailProps } from "./catalogDetail/CatalogDetail.js";
|
|
5
7
|
export type { EditHandlerEvent, OpenHandlerEvent } from "./catalogDetail/types.js";
|
|
6
8
|
export type { ICatalogDetailContentProps } from "./catalogDetail/CatalogDetailContent.js";
|
package/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EACH,sBAAsB,EACtB,KAAK,4BAA4B,EACjC,6BAA6B,EAC7B,KAAK,mCAAmC,GAC3C,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,KAAK,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAMxG,YAAY,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACnF,YAAY,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAC1F,YAAY,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACjF,YAAY,EACR,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACH,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,GACzB,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EACH,sBAAsB,EACtB,KAAK,4BAA4B,EACjC,6BAA6B,EAC7B,KAAK,mCAAmC,GAC3C,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,KAAK,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAMxG,OAAO,EACH,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,0BAA0B,GAClC,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAMxG,YAAY,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACnF,YAAY,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAC1F,YAAY,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACjF,YAAY,EACR,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,GACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACH,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,GACzB,MAAM,yBAAyB,CAAC"}
|
package/esm/index.js
CHANGED
|
@@ -6,4 +6,9 @@
|
|
|
6
6
|
export { AnalyticsCatalog } from "./AnalyticsCatalog.js";
|
|
7
7
|
export { AnalyticsCatalogDetail, AnalyticsCatalogDetailContent, } from "./AnalyticsCatalogDetail.js";
|
|
8
8
|
export { AnalyticsCatalogFilter } from "./AnalyticsCatalogFilter.js";
|
|
9
|
+
/*
|
|
10
|
+
* Visualization as-code codec injection. The host supplies the Tiger-coupled AAC codec so this package
|
|
11
|
+
* stays backend-agnostic; without it, visualizations fall back to Analytical Designer.
|
|
12
|
+
*/
|
|
13
|
+
export { InsightCodecProvider, } from "./insight/insightCodecContext.js";
|
|
9
14
|
export { isCatalogItemAttribute, isCatalogItemDashboard, isCatalogItemDataSet, isCatalogItemFact, isCatalogItemInsight, isCatalogItemMeasure, isCatalogItemParameter, } from "./catalogItem/guards.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/insight/gate.ts"],"names":[],"mappings":"AAEA;6CAC6C;AAC7C,eAAO,MAAM,iCAAiC,+CAA+C,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type PropsWithChildren } from "react";
|
|
2
|
+
import type { IInsightDefinition } from "@gooddata/sdk-model";
|
|
3
|
+
import type { IAsCodeEditing } from "../asCode/descriptor.js";
|
|
4
|
+
/** @internal */
|
|
5
|
+
export type IInsightCodec = IAsCodeEditing<IInsightDefinition>;
|
|
6
|
+
/** @internal */
|
|
7
|
+
export type VisualizationTypePredicate = (visualizationType: string) => boolean;
|
|
8
|
+
/** Injects the host-built visualization codec, keeping this package free of the Tiger-coupled convertors. @internal */
|
|
9
|
+
export declare function InsightCodecProvider({ codec, requestLoad, isVisualizationTypeEditable, children }: PropsWithChildren<{
|
|
10
|
+
codec?: IInsightCodec;
|
|
11
|
+
requestLoad: () => Promise<void>;
|
|
12
|
+
isVisualizationTypeEditable?: VisualizationTypePredicate;
|
|
13
|
+
}>): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
/** Whether a host injected the codec machinery; entry points gate on this since without a host the codec never resolves. @internal */
|
|
15
|
+
export declare function useHasInsightCodecHost(): boolean;
|
|
16
|
+
/** The injected codec, or `null` while loading — a pure read; the load is driven by {@link useRequestInsightCodec}. @internal */
|
|
17
|
+
export declare function useInsightCodec(): IInsightCodec | null;
|
|
18
|
+
/** The host's codec-load request lever (contract on {@link InsightCodecContextValue}). @internal */
|
|
19
|
+
export declare function useRequestInsightCodec(): () => Promise<void>;
|
|
20
|
+
/** Per-chart-type editability from the host: false with no host, else its predicate (absent predicate ⇒ all editable). @internal */
|
|
21
|
+
export declare function useIsVisualizationTypeEditable(): VisualizationTypePredicate;
|
|
22
|
+
//# sourceMappingURL=insightCodecContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insightCodecContext.d.ts","sourceRoot":"","sources":["../../src/insight/insightCodecContext.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,iBAAiB,EAAmD,MAAM,OAAO,CAAC;AAEhG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE9D,gBAAgB;AAChB,MAAM,MAAM,aAAa,GAAG,cAAc,CAAC,kBAAkB,CAAC,CAAC;AAE/D,gBAAgB;AAChB,MAAM,MAAM,0BAA0B,GAAG,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC;AAchF,uHAAuH;AACvH,wBAAgB,oBAAoB,CAAC,EACjC,KAAK,EACL,WAAW,EACX,2BAA2B,EAC3B,QAAQ,EACX,EAAE,iBAAiB,CAAC;IACjB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,2BAA2B,CAAC,EAAE,0BAA0B,CAAC;CAC5D,CAAC,2CAMD;AAED,sIAAsI;AACtI,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED,mIAAiI;AACjI,wBAAgB,eAAe,IAAI,aAAa,GAAG,IAAI,CAEtD;AAKD,oGAAoG;AACpG,wBAAgB,sBAAsB,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,CAE5D;AAED,sIAAoI;AACpI,wBAAgB,8BAA8B,IAAI,0BAA0B,CAQ3E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// (C) 2026 GoodData Corporation
|
|
3
|
+
import { createContext, useCallback, useContext, useMemo } from "react";
|
|
4
|
+
const InsightCodecContext = createContext(null);
|
|
5
|
+
/** Injects the host-built visualization codec, keeping this package free of the Tiger-coupled convertors. @internal */
|
|
6
|
+
export function InsightCodecProvider({ codec, requestLoad, isVisualizationTypeEditable, children, }) {
|
|
7
|
+
const value = useMemo(() => ({ codec, requestLoad, isVisualizationTypeEditable }), [codec, requestLoad, isVisualizationTypeEditable]);
|
|
8
|
+
return _jsx(InsightCodecContext.Provider, { value: value, children: children });
|
|
9
|
+
}
|
|
10
|
+
/** Whether a host injected the codec machinery; entry points gate on this since without a host the codec never resolves. @internal */
|
|
11
|
+
export function useHasInsightCodecHost() {
|
|
12
|
+
return useContext(InsightCodecContext) !== null;
|
|
13
|
+
}
|
|
14
|
+
/** The injected codec, or `null` while loading — a pure read; the load is driven by {@link useRequestInsightCodec}. @internal */
|
|
15
|
+
export function useInsightCodec() {
|
|
16
|
+
return useContext(InsightCodecContext)?.codec ?? null;
|
|
17
|
+
}
|
|
18
|
+
// No host: a resolved no-op so the (gated-unreachable) request effect neither fetches nor crashes.
|
|
19
|
+
const noCodecHost = () => Promise.resolve();
|
|
20
|
+
/** The host's codec-load request lever (contract on {@link InsightCodecContextValue}). @internal */
|
|
21
|
+
export function useRequestInsightCodec() {
|
|
22
|
+
return useContext(InsightCodecContext)?.requestLoad ?? noCodecHost;
|
|
23
|
+
}
|
|
24
|
+
/** Per-chart-type editability from the host: false with no host, else its predicate (absent predicate ⇒ all editable). @internal */
|
|
25
|
+
export function useIsVisualizationTypeEditable() {
|
|
26
|
+
const context = useContext(InsightCodecContext);
|
|
27
|
+
const hasHost = context !== null;
|
|
28
|
+
const isVisualizationTypeEditable = context?.isVisualizationTypeEditable;
|
|
29
|
+
return useCallback((visualizationType) => hasHost && (isVisualizationTypeEditable?.(visualizationType) ?? true), [hasHost, isVisualizationTypeEditable]);
|
|
30
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IInsightDefinition } from "@gooddata/sdk-model";
|
|
2
|
+
/** Duplicate: bump the title, copy only author-owned fields — the source's identity/audit fields must not reach create. */
|
|
3
|
+
export declare function createCopiedInsight(source: IInsightDefinition): IInsightDefinition;
|
|
4
|
+
//# sourceMappingURL=insightCopy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insightCopy.d.ts","sourceRoot":"","sources":["../../src/insight/insightCopy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAI9D,6HAA2H;AAC3H,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,CAqBlF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { deriveCopyIdentity } from "../asCode/copy.js";
|
|
3
|
+
/** Duplicate: bump the title, copy only author-owned fields — the source's identity/audit fields must not reach create. */
|
|
4
|
+
export function createCopiedInsight(source) {
|
|
5
|
+
const { insight } = source;
|
|
6
|
+
const { title } = deriveCopyIdentity({ title: insight.title });
|
|
7
|
+
return {
|
|
8
|
+
insight: {
|
|
9
|
+
title: title ?? insight.title,
|
|
10
|
+
visualizationUrl: insight.visualizationUrl,
|
|
11
|
+
buckets: insight.buckets,
|
|
12
|
+
filters: insight.filters,
|
|
13
|
+
sorts: insight.sorts,
|
|
14
|
+
properties: insight.properties,
|
|
15
|
+
...(insight.tags === undefined ? {} : { tags: insight.tags }),
|
|
16
|
+
...(insight.summary === undefined ? {} : { summary: insight.summary }),
|
|
17
|
+
...(insight.attributeFilterConfigs === undefined
|
|
18
|
+
? {}
|
|
19
|
+
: { attributeFilterConfigs: insight.attributeFilterConfigs }),
|
|
20
|
+
...(insight.parameters === undefined ? {} : { parameters: insight.parameters }),
|
|
21
|
+
...(insight.layers === undefined ? {} : { layers: insight.layers }),
|
|
22
|
+
...(insight.isHidden === undefined ? {} : { isHidden: insight.isHidden }),
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IInsightDefinition } from "@gooddata/sdk-model";
|
|
2
|
+
import type { ICatalogItemInsight } from "../catalogItem/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare const visualizationDescriptor: import("../asCode/descriptor.js").IAsCodeDescriptor<IInsightDefinition, ICatalogItemInsight>;
|
|
7
|
+
//# sourceMappingURL=insightDescriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insightDescriptor.d.ts","sourceRoot":"","sources":["../../src/insight/insightDescriptor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAG9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AA+CnE;;GAEG;AACH,eAAO,MAAM,uBAAuB,8FA6BlC,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { defineMessages } from "react-intl";
|
|
3
|
+
import { defineAsCodeDescriptor } from "../asCode/descriptor.js";
|
|
4
|
+
import { ObjectTypes } from "../objectType/constants.js";
|
|
5
|
+
import { VISUALIZATION_EDITOR_FEATURE_FLAG } from "./gate.js";
|
|
6
|
+
import { useHasInsightCodecHost, useInsightCodec, useIsVisualizationTypeEditable, useRequestInsightCodec, } from "./insightCodecContext.js";
|
|
7
|
+
import { createCopiedInsight } from "./insightCopy.js";
|
|
8
|
+
import { countInsightReferences, createInsightMutationAdapter, loadInsight } from "./insightMutationPort.js";
|
|
9
|
+
const VISUALIZATION_DOCS_URL = "https://www.gooddata.ai/docs/cloud/api-and-sdk/vs-code-extension/structures/#visualisation";
|
|
10
|
+
const messages = defineMessages({
|
|
11
|
+
createTitle: { id: "analyticsCatalog.visualization.dialog.create.title" },
|
|
12
|
+
editTitle: { id: "analyticsCatalog.visualization.dialog.edit.title" },
|
|
13
|
+
duplicate: { id: "analyticsCatalog.visualization.dialog.edit.duplicate" },
|
|
14
|
+
createDefaultTitle: { id: "analyticsCatalog.visualization.create.defaultTitle" },
|
|
15
|
+
createSuccess: { id: "analyticsCatalog.visualization.create.success" },
|
|
16
|
+
updateSuccess: { id: "analyticsCatalog.visualization.update.success" },
|
|
17
|
+
sectionHeader: { id: "analyticsCatalog.visualization.dialog.sectionHeader" },
|
|
18
|
+
sectionHeaderTooltip: { id: "analyticsCatalog.visualization.dialog.sectionHeader.tooltip" },
|
|
19
|
+
help: { id: "analyticsCatalog.visualization.dialog.help" },
|
|
20
|
+
submitError: { id: "analyticsCatalog.visualization.dialog.submit.error" },
|
|
21
|
+
deleteTitle: { id: "analyticsCatalog.visualization.dialog.delete.title" },
|
|
22
|
+
deleteBody: { id: "analyticsCatalog.visualization.dialog.delete.body" },
|
|
23
|
+
deleteSubmit: { id: "analyticsCatalog.visualization.dialog.delete.submit" },
|
|
24
|
+
deleteSuccess: { id: "analyticsCatalog.visualization.delete.success" },
|
|
25
|
+
deleteError: { id: "analyticsCatalog.visualization.delete.error" },
|
|
26
|
+
});
|
|
27
|
+
const capabilityMessages = defineMessages({
|
|
28
|
+
loadError: { id: "analyticsCatalog.visualization.load.error" },
|
|
29
|
+
deleteUsageWarning: { id: "analyticsCatalog.visualization.dialog.delete.usageWarning" },
|
|
30
|
+
});
|
|
31
|
+
const actionMessages = defineMessages({
|
|
32
|
+
openInAnalyticalDesigner: { id: "analyticsCatalog.visualization.actions.openInAnalyticalDesigner" },
|
|
33
|
+
});
|
|
34
|
+
function useIsInsightItemEditable(item) {
|
|
35
|
+
return useIsVisualizationTypeEditable()(item.visualizationType);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export const visualizationDescriptor = defineAsCodeDescriptor({
|
|
41
|
+
objectType: ObjectTypes.VISUALIZATION,
|
|
42
|
+
docsUrl: VISUALIZATION_DOCS_URL,
|
|
43
|
+
featureFlag: VISUALIZATION_EDITOR_FEATURE_FLAG,
|
|
44
|
+
messages,
|
|
45
|
+
useEditing: useInsightCodec,
|
|
46
|
+
useRequestEditing: useRequestInsightCodec,
|
|
47
|
+
useIsItemEditable: useIsInsightItemEditable,
|
|
48
|
+
// Without a host-injected codec the editor can never resolve, so creation falls back to Analytical Designer.
|
|
49
|
+
useCreateGate: useHasInsightCodecHost,
|
|
50
|
+
createMutationPort: createInsightMutationAdapter,
|
|
51
|
+
emptyDefinition: (defaultTitle) => ({
|
|
52
|
+
insight: {
|
|
53
|
+
title: defaultTitle,
|
|
54
|
+
visualizationUrl: "local:table",
|
|
55
|
+
buckets: [],
|
|
56
|
+
filters: [],
|
|
57
|
+
sorts: [],
|
|
58
|
+
properties: {},
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
61
|
+
seed: { load: loadInsight, loadError: capabilityMessages.loadError },
|
|
62
|
+
referenceCounted: {
|
|
63
|
+
count: countInsightReferences,
|
|
64
|
+
usageWarning: capabilityMessages.deleteUsageWarning,
|
|
65
|
+
},
|
|
66
|
+
// No identity: an insight definition has no id field, and creates never carry one (backend-assigned).
|
|
67
|
+
toCopy: createCopiedInsight,
|
|
68
|
+
openAction: actionMessages.openInAnalyticalDesigner,
|
|
69
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
2
|
+
import { type IInsightDefinition } from "@gooddata/sdk-model";
|
|
3
|
+
import type { IAsCodeMutationPort } from "../asCode/descriptor.js";
|
|
4
|
+
import type { ICatalogItemInsight } from "../catalogItem/types.js";
|
|
5
|
+
/** @internal */
|
|
6
|
+
export type IInsightMutationPort = IAsCodeMutationPort<IInsightDefinition, ICatalogItemInsight>;
|
|
7
|
+
/** Fetches the full insight for editing (the catalog item carries only metadata). @internal */
|
|
8
|
+
export declare function loadInsight(backend: IAnalyticalBackend, workspace: string, item: ICatalogItemInsight): Promise<IInsightDefinition>;
|
|
9
|
+
/** Counts the dashboards referencing an insight. @internal */
|
|
10
|
+
export declare function countInsightReferences(backend: IAnalyticalBackend, workspace: string, item: ICatalogItemInsight): Promise<number>;
|
|
11
|
+
/** @internal */
|
|
12
|
+
export declare function createInsightMutationAdapter(backend: IAnalyticalBackend, workspace: string): IInsightMutationPort;
|
|
13
|
+
//# sourceMappingURL=insightMutationPort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insightMutationPort.d.ts","sourceRoot":"","sources":["../../src/insight/insightMutationPort.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAiB,KAAK,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAE/F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,gBAAgB;AAChB,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;AAEhG,+FAA+F;AAC/F,wBAAgB,WAAW,CACvB,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,mBAAmB,GAC1B,OAAO,CAAC,kBAAkB,CAAC,CAO7B;AAED,8DAA8D;AAC9D,wBAAsB,sBAAsB,CACxC,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,mBAAmB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAMjB;AAoBD,gBAAgB;AAChB,wBAAgB,4BAA4B,CACxC,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,GAClB,oBAAoB,CAsBtB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { idRef, isInsight } from "@gooddata/sdk-model";
|
|
3
|
+
import { convertInsightToCatalogItem } from "../catalogItem/converter.js";
|
|
4
|
+
/** Fetches the full insight for editing (the catalog item carries only metadata). @internal */
|
|
5
|
+
export function loadInsight(backend, workspace, item) {
|
|
6
|
+
// loadUserData so the base carries createdBy/updatedBy: updateInsight echoes its input rather than
|
|
7
|
+
// the server response, so without them the saved catalog item shows blank authors.
|
|
8
|
+
return backend
|
|
9
|
+
.workspace(workspace)
|
|
10
|
+
.insights()
|
|
11
|
+
.getInsight(idRef(item.identifier, "insight"), { loadUserData: true });
|
|
12
|
+
}
|
|
13
|
+
/** Counts the dashboards referencing an insight. @internal */
|
|
14
|
+
export async function countInsightReferences(backend, workspace, item) {
|
|
15
|
+
const referencing = await backend
|
|
16
|
+
.workspace(workspace)
|
|
17
|
+
.insights()
|
|
18
|
+
.getInsightReferencingObjects(idRef(item.identifier, "insight"));
|
|
19
|
+
return referencing.analyticalDashboards?.length ?? 0;
|
|
20
|
+
}
|
|
21
|
+
function pickInsightIdentity(insight) {
|
|
22
|
+
const { identifier, uri, ref, isLocked, certification } = insight;
|
|
23
|
+
const { created, updated, createdBy, updatedBy } = insight;
|
|
24
|
+
return {
|
|
25
|
+
identifier,
|
|
26
|
+
uri,
|
|
27
|
+
ref,
|
|
28
|
+
isLocked,
|
|
29
|
+
certification,
|
|
30
|
+
created,
|
|
31
|
+
updated,
|
|
32
|
+
createdBy,
|
|
33
|
+
updatedBy,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** @internal */
|
|
37
|
+
export function createInsightMutationAdapter(backend, workspace) {
|
|
38
|
+
const insights = () => backend.workspace(workspace).insights();
|
|
39
|
+
return {
|
|
40
|
+
async create(definition) {
|
|
41
|
+
return convertInsightToCatalogItem(await insights().createInsight(definition));
|
|
42
|
+
},
|
|
43
|
+
async update(base, definition) {
|
|
44
|
+
if (!isInsight(base) || !base.insight.identifier) {
|
|
45
|
+
throw new Error("Visualization update requires the loaded insight as base.");
|
|
46
|
+
}
|
|
47
|
+
// Definition is authoritative for content (already reconciled); re-attach only identity — a
|
|
48
|
+
// base overlay would revert a field the editor cleared.
|
|
49
|
+
const saved = await insights().updateInsight({
|
|
50
|
+
...base,
|
|
51
|
+
insight: { ...definition.insight, ...pickInsightIdentity(base.insight) },
|
|
52
|
+
});
|
|
53
|
+
return convertInsightToCatalogItem(saved);
|
|
54
|
+
},
|
|
55
|
+
async delete(ref) {
|
|
56
|
+
await insights().deleteInsight(idRef(ref.identifier, "insight"));
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|