@gooddata/sdk-ui-catalog 11.57.0-alpha.4 → 11.57.0-alpha.6

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 (111) hide show
  1. package/esm/catalogDetail/CatalogDetailAttributeLabelsConditionalFormatting.d.ts +12 -0
  2. package/esm/catalogDetail/CatalogDetailAttributeLabelsConditionalFormatting.d.ts.map +1 -0
  3. package/esm/catalogDetail/CatalogDetailAttributeLabelsConditionalFormatting.js +18 -0
  4. package/esm/catalogDetail/CatalogDetailConditionalFormatting.d.ts +13 -3
  5. package/esm/catalogDetail/CatalogDetailConditionalFormatting.d.ts.map +1 -1
  6. package/esm/catalogDetail/CatalogDetailConditionalFormatting.js +49 -32
  7. package/esm/catalogDetail/CatalogDetailContent.d.ts.map +1 -1
  8. package/esm/catalogDetail/CatalogDetailContent.js +3 -1
  9. package/esm/catalogDetail/CatalogDetailTabMetadata.d.ts +3 -2
  10. package/esm/catalogDetail/CatalogDetailTabMetadata.d.ts.map +1 -1
  11. package/esm/catalogDetail/CatalogDetailTabMetadata.js +6 -4
  12. package/esm/catalogDetail/hooks/useCatalogItemLoad.d.ts.map +1 -1
  13. package/esm/catalogDetail/hooks/useCatalogItemLoad.js +12 -3
  14. package/esm/catalogDetail/hooks/useCatalogItemUpdate.d.ts +2 -1
  15. package/esm/catalogDetail/hooks/useCatalogItemUpdate.d.ts.map +1 -1
  16. package/esm/catalogDetail/hooks/useCatalogItemUpdate.js +53 -127
  17. package/esm/catalogItem/query.d.ts +3 -2
  18. package/esm/catalogItem/query.d.ts.map +1 -1
  19. package/esm/catalogItem/query.js +12 -2
  20. package/esm/catalogItem/testFixtures.d.ts +7 -0
  21. package/esm/catalogItem/testFixtures.d.ts.map +1 -0
  22. package/esm/catalogItem/testFixtures.js +21 -0
  23. package/esm/catalogItem/types.d.ts +6 -1
  24. package/esm/catalogItem/types.d.ts.map +1 -1
  25. package/esm/computedAttribute/computedAttributeDescriptor.js +3 -3
  26. package/esm/computedAttribute/computedAttributeMutationPort.d.ts +1 -1
  27. package/esm/computedAttribute/computedAttributeMutationPort.d.ts.map +1 -1
  28. package/esm/computedAttribute/computedAttributeMutationPort.js +3 -1
  29. package/esm/localization/bundles/de-DE.localization-bundle.d.ts +5 -0
  30. package/esm/localization/bundles/de-DE.localization-bundle.d.ts.map +1 -1
  31. package/esm/localization/bundles/de-DE.localization-bundle.js +5 -0
  32. package/esm/localization/bundles/en-AU.localization-bundle.d.ts +5 -0
  33. package/esm/localization/bundles/en-AU.localization-bundle.d.ts.map +1 -1
  34. package/esm/localization/bundles/en-AU.localization-bundle.js +5 -0
  35. package/esm/localization/bundles/en-GB.localization-bundle.d.ts +5 -0
  36. package/esm/localization/bundles/en-GB.localization-bundle.d.ts.map +1 -1
  37. package/esm/localization/bundles/en-GB.localization-bundle.js +5 -0
  38. package/esm/localization/bundles/en-US.localization-bundle.js +3 -3
  39. package/esm/localization/bundles/es-419.localization-bundle.d.ts +5 -0
  40. package/esm/localization/bundles/es-419.localization-bundle.d.ts.map +1 -1
  41. package/esm/localization/bundles/es-419.localization-bundle.js +5 -0
  42. package/esm/localization/bundles/es-ES.localization-bundle.d.ts +5 -0
  43. package/esm/localization/bundles/es-ES.localization-bundle.d.ts.map +1 -1
  44. package/esm/localization/bundles/es-ES.localization-bundle.js +5 -0
  45. package/esm/localization/bundles/fi-FI.localization-bundle.d.ts +5 -0
  46. package/esm/localization/bundles/fi-FI.localization-bundle.d.ts.map +1 -1
  47. package/esm/localization/bundles/fi-FI.localization-bundle.js +5 -0
  48. package/esm/localization/bundles/fr-CA.localization-bundle.d.ts +5 -0
  49. package/esm/localization/bundles/fr-CA.localization-bundle.d.ts.map +1 -1
  50. package/esm/localization/bundles/fr-CA.localization-bundle.js +5 -0
  51. package/esm/localization/bundles/fr-FR.localization-bundle.d.ts +5 -0
  52. package/esm/localization/bundles/fr-FR.localization-bundle.d.ts.map +1 -1
  53. package/esm/localization/bundles/fr-FR.localization-bundle.js +5 -0
  54. package/esm/localization/bundles/id-ID.localization-bundle.d.ts +5 -0
  55. package/esm/localization/bundles/id-ID.localization-bundle.d.ts.map +1 -1
  56. package/esm/localization/bundles/id-ID.localization-bundle.js +5 -0
  57. package/esm/localization/bundles/it-IT.localization-bundle.d.ts +5 -0
  58. package/esm/localization/bundles/it-IT.localization-bundle.d.ts.map +1 -1
  59. package/esm/localization/bundles/it-IT.localization-bundle.js +5 -0
  60. package/esm/localization/bundles/ja-JP.localization-bundle.d.ts +5 -0
  61. package/esm/localization/bundles/ja-JP.localization-bundle.d.ts.map +1 -1
  62. package/esm/localization/bundles/ja-JP.localization-bundle.js +5 -0
  63. package/esm/localization/bundles/ko-KR.localization-bundle.d.ts +5 -0
  64. package/esm/localization/bundles/ko-KR.localization-bundle.d.ts.map +1 -1
  65. package/esm/localization/bundles/ko-KR.localization-bundle.js +5 -0
  66. package/esm/localization/bundles/nl-NL.localization-bundle.d.ts +5 -0
  67. package/esm/localization/bundles/nl-NL.localization-bundle.d.ts.map +1 -1
  68. package/esm/localization/bundles/nl-NL.localization-bundle.js +5 -0
  69. package/esm/localization/bundles/pl-PL.localization-bundle.d.ts +5 -0
  70. package/esm/localization/bundles/pl-PL.localization-bundle.d.ts.map +1 -1
  71. package/esm/localization/bundles/pl-PL.localization-bundle.js +5 -0
  72. package/esm/localization/bundles/pt-BR.localization-bundle.d.ts +5 -0
  73. package/esm/localization/bundles/pt-BR.localization-bundle.d.ts.map +1 -1
  74. package/esm/localization/bundles/pt-BR.localization-bundle.js +5 -0
  75. package/esm/localization/bundles/pt-PT.localization-bundle.d.ts +5 -0
  76. package/esm/localization/bundles/pt-PT.localization-bundle.d.ts.map +1 -1
  77. package/esm/localization/bundles/pt-PT.localization-bundle.js +5 -0
  78. package/esm/localization/bundles/ru-RU.localization-bundle.d.ts +5 -0
  79. package/esm/localization/bundles/ru-RU.localization-bundle.d.ts.map +1 -1
  80. package/esm/localization/bundles/ru-RU.localization-bundle.js +5 -0
  81. package/esm/localization/bundles/sl-SI.localization-bundle.d.ts +5 -0
  82. package/esm/localization/bundles/sl-SI.localization-bundle.d.ts.map +1 -1
  83. package/esm/localization/bundles/sl-SI.localization-bundle.js +5 -0
  84. package/esm/localization/bundles/th-TH.localization-bundle.d.ts +5 -0
  85. package/esm/localization/bundles/th-TH.localization-bundle.d.ts.map +1 -1
  86. package/esm/localization/bundles/th-TH.localization-bundle.js +5 -0
  87. package/esm/localization/bundles/tr-TR.localization-bundle.d.ts +5 -0
  88. package/esm/localization/bundles/tr-TR.localization-bundle.d.ts.map +1 -1
  89. package/esm/localization/bundles/tr-TR.localization-bundle.js +5 -0
  90. package/esm/localization/bundles/uk-UA.localization-bundle.d.ts +5 -0
  91. package/esm/localization/bundles/uk-UA.localization-bundle.d.ts.map +1 -1
  92. package/esm/localization/bundles/uk-UA.localization-bundle.js +5 -0
  93. package/esm/localization/bundles/vi-VN.localization-bundle.d.ts +5 -0
  94. package/esm/localization/bundles/vi-VN.localization-bundle.d.ts.map +1 -1
  95. package/esm/localization/bundles/vi-VN.localization-bundle.js +5 -0
  96. package/esm/localization/bundles/zh-HK.localization-bundle.d.ts +5 -0
  97. package/esm/localization/bundles/zh-HK.localization-bundle.d.ts.map +1 -1
  98. package/esm/localization/bundles/zh-HK.localization-bundle.js +5 -0
  99. package/esm/localization/bundles/zh-Hans.localization-bundle.d.ts +5 -0
  100. package/esm/localization/bundles/zh-Hans.localization-bundle.d.ts.map +1 -1
  101. package/esm/localization/bundles/zh-Hans.localization-bundle.js +5 -0
  102. package/esm/localization/bundles/zh-Hant.localization-bundle.d.ts +5 -0
  103. package/esm/localization/bundles/zh-Hant.localization-bundle.d.ts.map +1 -1
  104. package/esm/localization/bundles/zh-Hant.localization-bundle.js +5 -0
  105. package/esm/sdk-ui-catalog.d.ts +6 -0
  106. package/package.json +19 -19
  107. package/styles/css/detail.css +11 -1
  108. package/styles/css/detail.css.map +1 -1
  109. package/styles/css/main.css +11 -1
  110. package/styles/css/main.css.map +1 -1
  111. package/styles/scss/detail.scss +13 -1
@@ -0,0 +1,12 @@
1
+ import { type IAttributeDisplayFormMetadataObject, type ISemanticConditionalFormatting, type ISeparators, type ObjRef } from "@gooddata/sdk-model";
2
+ export interface ICatalogDetailAttributeLabelsConditionalFormattingProps {
3
+ labels: IAttributeDisplayFormMetadataObject[];
4
+ canEdit: boolean;
5
+ onLabelConditionalFormattingChange: (labelRef: ObjRef, conditionalFormatting: ISemanticConditionalFormatting | undefined) => void;
6
+ separators?: ISeparators;
7
+ }
8
+ /**
9
+ * One "Conditional formatting" row listing the attribute's labels, primary label first.
10
+ */
11
+ export declare function CatalogDetailAttributeLabelsConditionalFormatting({ labels, canEdit, onLabelConditionalFormattingChange, separators, }: ICatalogDetailAttributeLabelsConditionalFormattingProps): import("react/jsx-runtime").JSX.Element | null;
12
+ //# sourceMappingURL=CatalogDetailAttributeLabelsConditionalFormatting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CatalogDetailAttributeLabelsConditionalFormatting.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailAttributeLabelsConditionalFormatting.tsx"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,mCAAmC,EACxC,KAAK,8BAA8B,EACnC,KAAK,WAAW,EAChB,KAAK,MAAM,EACd,MAAM,qBAAqB,CAAC;AAS7B,MAAM,WAAW,uDAAuD;IACpE,MAAM,EAAE,mCAAmC,EAAE,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,kCAAkC,EAAE,CAChC,QAAQ,EAAE,MAAM,EAChB,qBAAqB,EAAE,8BAA8B,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,UAAU,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAgB,iDAAiD,CAAC,EAC9D,MAAM,EACN,OAAO,EACP,kCAAkC,EAClC,UAAU,GACb,EAAE,uDAAuD,kDA6BzD"}
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // (C) 2026 GoodData Corporation
3
+ import { FormattedMessage } from "react-intl";
4
+ import {} from "@gooddata/sdk-model";
5
+ import { sortShareableLabels } from "@gooddata/sdk-ui-ext";
6
+ import { CatalogDetailConditionalFormattingControl, labelTargetOption, } from "./CatalogDetailConditionalFormatting.js";
7
+ import { CatalogDetailContentRow } from "./CatalogDetailContentRow.js";
8
+ /**
9
+ * One "Conditional formatting" row listing the attribute's labels, primary label first.
10
+ */
11
+ export function CatalogDetailAttributeLabelsConditionalFormatting({ labels, canEdit, onLabelConditionalFormattingChange, separators, }) {
12
+ if (labels.length === 0) {
13
+ return null;
14
+ }
15
+ return (_jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.conditionalFormatting" }), alignTop: true, content: _jsx("div", { className: "gd-analytics-catalog-detail__cf-labels", children: sortShareableLabels(labels).map((label) => (_jsxs("div", { className: "gd-analytics-catalog-detail__cf-label", children: [_jsx("span", { className: "gd-analytics-catalog-detail__cf-label-title", children: label.title }), _jsx(CatalogDetailConditionalFormattingControl, { targetOption: labelTargetOption(label), conditionalFormatting: label.conditionalFormatting, canEdit: canEdit, onConditionalFormattingChange: (conditionalFormatting) => {
16
+ onLabelConditionalFormattingChange(label.ref, conditionalFormatting);
17
+ }, separators: separators })] }, label.id))) }) }));
18
+ }
@@ -1,12 +1,22 @@
1
- import { type ISemanticConditionalFormatting, type ISeparators } from "@gooddata/sdk-model";
2
- export interface ICatalogDetailConditionalFormattingProps {
1
+ import { type IAttributeDisplayFormMetadataObject, type ISemanticConditionalFormatting, type ISeparators } from "@gooddata/sdk-model";
2
+ import { type ITargetOption } from "@gooddata/sdk-ui-ext";
3
+ export declare function measureTargetOption(measure: {
3
4
  identifier: string;
4
5
  title: string;
5
6
  format?: string | null;
7
+ }): ITargetOption;
8
+ export declare function labelTargetOption(label: IAttributeDisplayFormMetadataObject): ITargetOption;
9
+ export interface ICatalogDetailConditionalFormattingProps {
10
+ targetOption: ITargetOption;
6
11
  conditionalFormatting?: ISemanticConditionalFormatting;
7
12
  canEdit: boolean;
8
13
  onConditionalFormattingChange: (conditionalFormatting: ISemanticConditionalFormatting | undefined) => void;
9
14
  separators?: ISeparators;
10
15
  }
11
- export declare function CatalogDetailConditionalFormatting({ identifier, title, format, conditionalFormatting, canEdit, onConditionalFormattingChange, separators, }: ICatalogDetailConditionalFormattingProps): import("react/jsx-runtime").JSX.Element;
16
+ /**
17
+ * The toggle, button and dialog for one catalog object, without a row around it.
18
+ */
19
+ export declare function CatalogDetailConditionalFormattingControl({ targetOption, conditionalFormatting, canEdit, onConditionalFormattingChange, separators, }: ICatalogDetailConditionalFormattingProps): import("react/jsx-runtime").JSX.Element;
20
+ /** {@link CatalogDetailConditionalFormattingControl} in a row titled "Conditional formatting". */
21
+ export declare function CatalogDetailConditionalFormatting(props: ICatalogDetailConditionalFormattingProps): import("react/jsx-runtime").JSX.Element;
12
22
  //# sourceMappingURL=CatalogDetailConditionalFormatting.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CatalogDetailConditionalFormatting.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailConditionalFormatting.tsx"],"names":[],"mappings":"AAOA,OAAO,EACH,KAAK,8BAA8B,EACnC,KAAK,WAAW,EAEnB,MAAM,qBAAqB,CAAC;AAkB7B,MAAM,WAAW,wCAAwC;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,qBAAqB,CAAC,EAAE,8BAA8B,CAAC;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,6BAA6B,EAAE,CAC3B,qBAAqB,EAAE,8BAA8B,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,UAAU,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED,wBAAgB,kCAAkC,CAAC,EAC/C,UAAU,EACV,KAAK,EACL,MAAM,EACN,qBAAqB,EACrB,OAAO,EACP,6BAA6B,EAC7B,UAAU,GACb,EAAE,wCAAwC,2CAqF1C"}
1
+ {"version":3,"file":"CatalogDetailConditionalFormatting.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailConditionalFormatting.tsx"],"names":[],"mappings":"AAOA,OAAO,EACH,KAAK,mCAAmC,EACxC,KAAK,8BAA8B,EACnC,KAAK,WAAW,EAEnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEH,KAAK,aAAa,EAIrB,MAAM,sBAAsB,CAAC;AAW9B,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GAAG,aAAa,CAOhB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,mCAAmC,GAAG,aAAa,CAM3F;AAED,MAAM,WAAW,wCAAwC;IACrD,YAAY,EAAE,aAAa,CAAC;IAC5B,qBAAqB,CAAC,EAAE,8BAA8B,CAAC;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,6BAA6B,EAAE,CAC3B,qBAAqB,EAAE,8BAA8B,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,UAAU,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAgB,yCAAyC,CAAC,EACtD,YAAY,EACZ,qBAAqB,EACrB,OAAO,EACP,6BAA6B,EAC7B,UAAU,GACb,EAAE,wCAAwC,2CA2E1C;AAED,kGAAkG;AAClG,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,wCAAwC,2CAOjG"}
@@ -5,48 +5,65 @@ import cx from "classnames";
5
5
  import { FormattedMessage, defineMessages, useIntl } from "react-intl";
6
6
  import { isSemanticConditionalFormattingEnabled, } from "@gooddata/sdk-model";
7
7
  import { ConditionalFormattingDialog, isPercentFormat, newRule, semanticRuleFor, } from "@gooddata/sdk-ui-ext";
8
- import { UiButton } from "@gooddata/sdk-ui-kit";
8
+ import { UiButton, useId } from "@gooddata/sdk-ui-kit";
9
9
  import { CatalogDetailContentRow } from "./CatalogDetailContentRow.js";
10
10
  const messages = defineMessages({
11
11
  toggleAriaLabel: { id: "analyticsCatalog.conditionalFormatting.toggleAriaLabel" },
12
12
  edit: { id: "analyticsCatalog.conditionalFormatting.edit" },
13
13
  add: { id: "analyticsCatalog.conditionalFormatting.add" },
14
14
  });
15
- export function CatalogDetailConditionalFormatting({ identifier, title, format, conditionalFormatting, canEdit, onConditionalFormattingChange, separators, }) {
15
+ export function measureTargetOption(measure) {
16
+ return {
17
+ value: `measure:${measure.identifier}`,
18
+ title: measure.title,
19
+ target: { kind: "measure", measureIdentifier: measure.identifier },
20
+ isPercent: isPercentFormat(measure.format ?? undefined),
21
+ };
22
+ }
23
+ export function labelTargetOption(label) {
24
+ return {
25
+ value: `attribute:${label.id}`,
26
+ title: label.title,
27
+ target: { kind: "attribute", attributeIdentifier: label.id },
28
+ };
29
+ }
30
+ /**
31
+ * The toggle, button and dialog for one catalog object, without a row around it.
32
+ */
33
+ export function CatalogDetailConditionalFormattingControl({ targetOption, conditionalFormatting, canEdit, onConditionalFormattingChange, separators, }) {
16
34
  const intl = useIntl();
17
35
  const [isOpen, setIsOpen] = useState(false);
18
- const targetOption = {
19
- value: `measure:${identifier}`,
20
- title,
21
- target: { kind: "measure", measureIdentifier: identifier },
22
- isPercent: isPercentFormat(format ?? undefined),
23
- };
36
+ const anchorId = useId();
37
+ const anchorElementId = `s-cf-catalog-popover-anchor-${anchorId}`;
24
38
  // A stored value with no conditions counts as no rule.
25
39
  const authored = conditionalFormatting?.conditions.length ? conditionalFormatting : undefined;
26
40
  const isEnabled = authored !== undefined && isSemanticConditionalFormattingEnabled(authored);
27
41
  const rule = authored ? semanticRuleFor(targetOption, authored) : newRule(targetOption);
28
- return (_jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.conditionalFormatting" }), content: _jsxs(_Fragment, { children: [authored ? (_jsxs("label", { className: "input-checkbox-toggle s-cf-catalog-toggle-label", children: [_jsx("input", { type: "checkbox", checked: isEnabled, disabled: !canEdit, "aria-label": intl.formatMessage(messages.toggleAriaLabel, { title }), onChange: (event) => {
29
- onConditionalFormattingChange({
30
- ...authored,
31
- enabled: event.target.checked,
32
- });
33
- }, className: cx("s-checkbox-toggle", canEdit ? "s-enabled" : "s-disabled") }), _jsx("span", { className: "input-label-text" })] })) : null, _jsx(UiButton, { dataTestId: "cf-catalog-open", size: "small", variant: "tertiary", iconBefore: authored ? undefined : "plus", label: intl.formatMessage(authored ? messages.edit : messages.add), isDisabled: !canEdit, onClick: () => setIsOpen(true) }), _jsx("span", { className: "s-cf-catalog-popover-anchor" }), isOpen ? (_jsx(ConditionalFormattingDialog, { rule: rule, isNew: !authored, fixedTarget: true, targetOptions: [targetOption], separators: separators, alignTo: ".s-cf-catalog-popover-anchor", onDelete: authored
34
- ? () => {
35
- onConditionalFormattingChange(undefined);
36
- setIsOpen(false);
37
- }
38
- : undefined, onSubmit: (intent) => {
39
- // "inherited" needs the semanticByTarget fallback, which this usage never passes.
40
- if (intent.mode !== "custom") {
41
- return;
42
- }
43
- onConditionalFormattingChange({
44
- ...(conditionalFormatting?.version
45
- ? { version: conditionalFormatting.version }
46
- : {}),
47
- conditions: intent.rule.conditions,
48
- // A new rule takes effect immediately; an edit keeps the row's toggle state.
49
- enabled: authored ? isEnabled : true,
50
- });
51
- }, onClose: () => setIsOpen(false) })) : null] }) }));
42
+ return (_jsxs(_Fragment, { children: [authored ? (_jsxs("label", { className: "input-checkbox-toggle gd-analytics-catalog-detail__cf-toggle s-cf-catalog-toggle-label", children: [_jsx("input", { type: "checkbox", checked: isEnabled, disabled: !canEdit, "aria-label": intl.formatMessage(messages.toggleAriaLabel, {
43
+ title: targetOption.title,
44
+ }), onChange: (event) => {
45
+ onConditionalFormattingChange({ ...authored, enabled: event.target.checked });
46
+ }, className: cx("s-checkbox-toggle", canEdit ? "s-enabled" : "s-disabled") }), _jsx("span", { className: "input-label-text" })] })) : null, _jsx(UiButton, { dataTestId: "cf-catalog-open", size: "small", variant: "tertiary", iconBefore: authored ? undefined : "plus", label: intl.formatMessage(authored ? messages.edit : messages.add), isDisabled: !canEdit, onClick: () => setIsOpen(true) }), _jsx("span", { id: anchorElementId, className: "s-cf-catalog-popover-anchor" }), isOpen ? (_jsx(ConditionalFormattingDialog, { rule: rule, isNew: !authored, fixedTarget: true, targetOptions: [targetOption], separators: separators, alignTo: `#${anchorElementId}`, onDelete: authored
47
+ ? () => {
48
+ onConditionalFormattingChange(undefined);
49
+ setIsOpen(false);
50
+ }
51
+ : undefined, onSubmit: (intent) => {
52
+ // "inherited" needs the semanticByTarget fallback, which this usage never passes.
53
+ if (intent.mode !== "custom") {
54
+ return;
55
+ }
56
+ onConditionalFormattingChange({
57
+ ...(conditionalFormatting?.version
58
+ ? { version: conditionalFormatting.version }
59
+ : {}),
60
+ conditions: intent.rule.conditions,
61
+ // A new rule takes effect immediately; an edit keeps the row's toggle state.
62
+ enabled: authored ? isEnabled : true,
63
+ });
64
+ }, onClose: () => setIsOpen(false) })) : null] }));
65
+ }
66
+ /** {@link CatalogDetailConditionalFormattingControl} in a row titled "Conditional formatting". */
67
+ export function CatalogDetailConditionalFormatting(props) {
68
+ return (_jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.conditionalFormatting" }), content: _jsx(CatalogDetailConditionalFormattingControl, { ...props }) }));
52
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CatalogDetailContent.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailContent.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAgC,MAAM,OAAO,CAAC;AAUtE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAGlF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAkBzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AASnD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACvC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B;;OAEG;IACH,gBAAgB,CAAC,EAAE,eAAe,GAAG,YAAY,GAAG,IAAI,CAAC;IACzD;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5E;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;OAEG;IACH,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;IAC5E;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;IACrD;;OAEG;IACH,wBAAwB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EACjC,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,GAC1B,EAAE,0BAA0B,2CAwN5B"}
1
+ {"version":3,"file":"CatalogDetailContent.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailContent.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAgC,MAAM,OAAO,CAAC;AAUtE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAGlF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAkBzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AASnD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACvC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B;;OAEG;IACH,gBAAgB,CAAC,EAAE,eAAe,GAAG,YAAY,GAAG,IAAI,CAAC;IACzD;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5E;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;OAEG;IACH,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;IAC5E;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACnD;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;IACrD;;OAEG;IACH,wBAAwB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EACjC,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,GAC1B,EAAE,0BAA0B,2CA4N5B"}
@@ -39,7 +39,7 @@ const Tabs = {
39
39
  export function CatalogDetailContent({ objectId, objectType, objectDefinition, onOpenClick, onTagClick, onCatalogItemCreate, onCatalogItemUpdate, onCatalogItemDelete, onCatalogItemUpdateError, onCatalogItemNavigation, }) {
40
40
  const intl = useIntl();
41
41
  const { result: { user: currentUser, permissions, settings } = {} } = usePermissionsState();
42
- const { item, status, error, updateItemTitle, updateItemDescription, updateItemTags, updateItemIsHidden, updateItemIsHiddenFromKda, updateItemMetricType, updateItemFormat, updateItemConditionalFormatting, updateItemCertification, applyItemUpdate, applyItemDelete, } = useCatalogItemUpdate({
42
+ const { item, status, error, updateItemTitle, updateItemDescription, updateItemTags, updateItemIsHidden, updateItemIsHiddenFromKda, updateItemMetricType, updateItemFormat, updateItemConditionalFormatting, updateItemLabelConditionalFormatting, updateItemCertification, applyItemUpdate, applyItemDelete, } = useCatalogItemUpdate({
43
43
  currentUser,
44
44
  objectId,
45
45
  objectType,
@@ -132,6 +132,8 @@ export function CatalogDetailContent({ objectId, objectType, objectDefinition, o
132
132
  updateItemFormat(format);
133
133
  }, onConditionalFormattingChange: (conditionalFormatting) => {
134
134
  updateItemConditionalFormatting(conditionalFormatting);
135
+ }, onLabelConditionalFormattingChange: (labelRef, conditionalFormatting) => {
136
+ updateItemLabelConditionalFormatting(labelRef, conditionalFormatting);
135
137
  }, separators: separators, currencyFormatOverride: enableMetricFormatOverrides ? currencyFormatOverride : undefined, enableMetricFormatOverrides: enableMetricFormatOverrides, accessRow: _jsx(CatalogItemAccessRow, {}) })), selectedTabId === Tabs.CERTIFICATION && isCertificationVisible ? (_jsx(CatalogDetailTabCertification, { item: item, canEdit: canEdit, onCertificationChange: (certification) => {
136
138
  updateItemCertification(certification);
137
139
  } })) : null, selectedTabId === Tabs.QUALITY &&
@@ -1,5 +1,5 @@
1
1
  import type { ReactNode } from "react";
2
- import type { ISemanticConditionalFormatting, ISeparators, MetricType } from "@gooddata/sdk-model";
2
+ import type { ISemanticConditionalFormatting, ISeparators, MetricType, ObjRef } from "@gooddata/sdk-model";
3
3
  import { type IUiTagDef } from "@gooddata/sdk-ui-kit";
4
4
  import { type ICatalogItem } from "../catalogItem/types.js";
5
5
  type Props = {
@@ -13,6 +13,7 @@ type Props = {
13
13
  onMetricTypeChange?: (metricType: MetricType | undefined) => void;
14
14
  onFormatChange?: (format: string | null) => void;
15
15
  onConditionalFormattingChange?: (conditionalFormatting: ISemanticConditionalFormatting | undefined) => void;
16
+ onLabelConditionalFormattingChange?: (labelRef: ObjRef, conditionalFormatting: ISemanticConditionalFormatting | undefined) => void;
16
17
  separators?: ISeparators;
17
18
  currencyFormatOverride?: string | null;
18
19
  enableMetricFormatOverrides?: boolean;
@@ -27,6 +28,6 @@ type Props = {
27
28
  */
28
29
  showDatasetRow?: boolean;
29
30
  };
30
- export declare function CatalogDetailTabMetadata({ item, canEdit, onTagClick, onTagAdd, onTagRemove, onIsHiddenChange, onIsHiddenFromKdaChange, onMetricTypeChange, onFormatChange, onConditionalFormattingChange, separators, currencyFormatOverride, enableMetricFormatOverrides, accessRow, showDatasetRow, }: Props): import("react/jsx-runtime").JSX.Element;
31
+ export declare function CatalogDetailTabMetadata({ item, canEdit, onTagClick, onTagAdd, onTagRemove, onIsHiddenChange, onIsHiddenFromKdaChange, onMetricTypeChange, onFormatChange, onConditionalFormattingChange, onLabelConditionalFormattingChange, separators, currencyFormatOverride, enableMetricFormatOverrides, accessRow, showDatasetRow, }: Props): import("react/jsx-runtime").JSX.Element;
31
32
  export {};
32
33
  //# sourceMappingURL=CatalogDetailTabMetadata.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CatalogDetailTabMetadata.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailTabMetadata.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,8BAA8B,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACnG,OAAO,EAAE,KAAK,SAAS,EAA6B,MAAM,sBAAsB,CAAC;AAUjF,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAU5D,KAAK,KAAK,GAAG;IACT,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACnC,WAAW,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACtC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,uBAAuB,EAAE,CAAC,eAAe,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5D,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,KAAK,IAAI,CAAC;IAClE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,6BAA6B,CAAC,EAAE,CAC5B,qBAAqB,EAAE,8BAA8B,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,EACrC,IAAI,EACJ,OAAO,EACP,UAAU,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,6BAA6B,EAC7B,UAAU,EACV,sBAAsB,EACtB,2BAA2B,EAC3B,SAAS,EACT,cAAc,GACjB,EAAE,KAAK,2CA+JP"}
1
+ {"version":3,"file":"CatalogDetailTabMetadata.d.ts","sourceRoot":"","sources":["../../src/catalogDetail/CatalogDetailTabMetadata.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,8BAA8B,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC3G,OAAO,EAAE,KAAK,SAAS,EAA6B,MAAM,sBAAsB,CAAC;AAUjF,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAc5D,KAAK,KAAK,GAAG;IACT,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACnC,WAAW,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACtC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,uBAAuB,EAAE,CAAC,eAAe,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5D,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,KAAK,IAAI,CAAC;IAClE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,6BAA6B,CAAC,EAAE,CAC5B,qBAAqB,EAAE,8BAA8B,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,kCAAkC,CAAC,EAAE,CACjC,QAAQ,EAAE,MAAM,EAChB,qBAAqB,EAAE,8BAA8B,GAAG,SAAS,KAChE,IAAI,CAAC;IACV,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,EACrC,IAAI,EACJ,OAAO,EACP,UAAU,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,6BAA6B,EAC7B,kCAAkC,EAClC,UAAU,EACV,sBAAsB,EACtB,2BAA2B,EAC3B,SAAS,EACT,cAAc,GACjB,EAAE,KAAK,2CAqKP"}
@@ -7,18 +7,20 @@ import { getVisualizationType, isCatalogItemAttribute, isCatalogItemDataSet, isC
7
7
  import {} from "../catalogItem/types.js";
8
8
  import { getObjectTypeLabel } from "../objectType/labels.js";
9
9
  import { useFeatureFlag } from "../permission/PermissionsContext.js";
10
- import { CatalogDetailConditionalFormatting } from "./CatalogDetailConditionalFormatting.js";
10
+ import { CatalogDetailAttributeLabelsConditionalFormatting } from "./CatalogDetailAttributeLabelsConditionalFormatting.js";
11
+ import { CatalogDetailConditionalFormatting, measureTargetOption, } from "./CatalogDetailConditionalFormatting.js";
11
12
  import { CatalogDetailContentRow } from "./CatalogDetailContentRow.js";
12
13
  import { CatalogDetailGranularities } from "./CatalogDetailGranularities.js";
13
14
  import { CatalogDetailMetricSettings } from "./CatalogDetailMetricSettings.js";
14
15
  import { CatalogDetailTags } from "./CatalogDetailTags.js";
15
- export function CatalogDetailTabMetadata({ item, canEdit, onTagClick, onTagAdd, onTagRemove, onIsHiddenChange, onIsHiddenFromKdaChange, onMetricTypeChange, onFormatChange, onConditionalFormattingChange, separators, currencyFormatOverride, enableMetricFormatOverrides, accessRow, showDatasetRow, }) {
16
+ export function CatalogDetailTabMetadata({ item, canEdit, onTagClick, onTagAdd, onTagRemove, onIsHiddenChange, onIsHiddenFromKdaChange, onMetricTypeChange, onFormatChange, onConditionalFormattingChange, onLabelConditionalFormattingChange, separators, currencyFormatOverride, enableMetricFormatOverrides, accessRow, showDatasetRow, }) {
16
17
  const enableSemanticConditionalFormatting = useFeatureFlag("enableSemanticConditionalFormatting");
17
18
  const intl = useIntl();
18
19
  const isMeasure = isCatalogItemMeasure(item);
20
+ const isAttribute = isCatalogItemAttribute(item);
19
21
  const isDataSet = isCatalogItemDataSet(item);
20
22
  const granularities = isDataSet ? (item.dataSet.attributes ?? []) : [];
21
- const datasetTitle = isCatalogItemAttribute(item) || isCatalogItemFact(item) ? item.dataSet?.title : undefined;
23
+ const datasetTitle = isAttribute || isCatalogItemFact(item) ? item.dataSet?.title : undefined;
22
24
  return (_jsxs("dl", { className: "gd-analytics-catalog-detail__tab-content", children: [_jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.type" }), content: getObjectTypeLabel(intl, item.type, getVisualizationType(item)) }), showDatasetRow && datasetTitle ? (_jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.dataSet" }), content: datasetTitle })) : null, isDataSet && granularities.length > 0 ? (_jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.granularities" }), content: _jsx(CatalogDetailGranularities, { granularities: granularities }) })) : null, _jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.createdBy" }), content: item.createdBy ?? undefined }), _jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.createdAt" }), content: item.createdAt ? _jsx(UiDate, { date: item.createdAt, locale: intl.locale }) : undefined }), item.createdBy === item.updatedBy && !item.updatedBy ? null : (_jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.updatedBy" }), content: item.updatedBy ?? undefined })), item.createdAt?.getTime() === item.updatedAt?.getTime() ? null : (_jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.updatedAt" }), content: item.updatedAt ? _jsx(UiDate, { date: item.updatedAt, locale: intl.locale }) : undefined })), isCatalogItemHidable(item) ? (_jsx(CatalogDetailContentRow, { title: _jsxs(_Fragment, { children: [_jsx(FormattedMessage, { id: "analyticsCatalog.column.title.isHidden" }), _jsx(UiTooltip, { anchor: _jsx(UiIcon, { type: "question", size: 12, color: "complementary-6" }), content: _jsx(FormattedMessage, { id: "analyticsCatalog.column.isHidden.field.tooltip" }), arrowPlacement: "left", optimalPlacement: true, offset: 10, triggerBy: ["hover", "click"] })] }), content: _jsxs("label", { className: "input-checkbox-toggle", children: [_jsx("input", { type: "checkbox", checked: item.isHidden !== true, disabled: !canEdit, "aria-label": intl.formatMessage({
23
25
  id: "analyticsCatalog.column.title.isHidden",
24
26
  }), onChange: (event) => {
@@ -27,5 +29,5 @@ export function CatalogDetailTabMetadata({ item, canEdit, onTagClick, onTagAdd,
27
29
  id: "analyticsCatalog.column.title.isHiddenFromKda",
28
30
  }), onChange: (event) => {
29
31
  onIsHiddenFromKdaChange(!event.target.checked);
30
- }, className: cx("s-checkbox-toggle", canEdit ? "s-enabled" : "s-disabled") }), _jsx("span", { className: "input-label-text" })] }) })) : null, isMeasure && enableMetricFormatOverrides ? (_jsx(CatalogDetailMetricSettings, { metricType: item.metricType, format: item.format, canEdit: canEdit, separators: separators, currencyFormatOverride: currencyFormatOverride, onMetricTypeChange: onMetricTypeChange, onFormatChange: onFormatChange, enableMetricFormatOverrides: enableMetricFormatOverrides })) : null, isMeasure && enableSemanticConditionalFormatting && onConditionalFormattingChange ? (_jsx(CatalogDetailConditionalFormatting, { identifier: item.identifier, title: item.title, format: item.format, conditionalFormatting: item.conditionalFormatting, canEdit: canEdit, onConditionalFormattingChange: onConditionalFormattingChange, separators: separators })) : null, accessRow, _jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.tags" }), content: _jsx(CatalogDetailTags, { tags: item.tags, canEdit: canEdit, onTagClick: onTagClick, onTagAdd: onTagAdd, onTagRemove: onTagRemove }) })] }));
32
+ }, className: cx("s-checkbox-toggle", canEdit ? "s-enabled" : "s-disabled") }), _jsx("span", { className: "input-label-text" })] }) })) : null, isMeasure && enableMetricFormatOverrides ? (_jsx(CatalogDetailMetricSettings, { metricType: item.metricType, format: item.format, canEdit: canEdit, separators: separators, currencyFormatOverride: currencyFormatOverride, onMetricTypeChange: onMetricTypeChange, onFormatChange: onFormatChange, enableMetricFormatOverrides: enableMetricFormatOverrides })) : null, isMeasure && enableSemanticConditionalFormatting && onConditionalFormattingChange ? (_jsx(CatalogDetailConditionalFormatting, { targetOption: measureTargetOption(item), conditionalFormatting: item.conditionalFormatting, canEdit: canEdit, onConditionalFormattingChange: onConditionalFormattingChange, separators: separators })) : null, isAttribute && enableSemanticConditionalFormatting && onLabelConditionalFormattingChange ? (_jsx(CatalogDetailAttributeLabelsConditionalFormatting, { labels: item.labels ?? [], canEdit: canEdit, onLabelConditionalFormattingChange: onLabelConditionalFormattingChange, separators: separators })) : null, accessRow, _jsx(CatalogDetailContentRow, { title: _jsx(FormattedMessage, { id: "analyticsCatalog.column.title.tags" }), content: _jsx(CatalogDetailTags, { tags: item.tags, canEdit: canEdit, onTagClick: onTagClick, onTagAdd: onTagAdd, onTagRemove: onTagRemove }) })] }));
31
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useCatalogItemLoad.d.ts","sourceRoot":"","sources":["../../../src/catalogDetail/hooks/useCatalogItemLoad.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACrF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE,eAAe,GAAG,YAAY,GAAG,IAAI,CAAC;CAC5D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,mBAAmB,GAAG;IACjG,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACpD,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC;CACjB,CAuDA"}
1
+ {"version":3,"file":"useCatalogItemLoad.d.ts","sourceRoot":"","sources":["../../../src/catalogDetail/hooks/useCatalogItemLoad.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACrF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE,eAAe,GAAG,YAAY,GAAG,IAAI,CAAC;CAC5D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,mBAAmB,GAAG;IACjG,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACpD,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC;CACjB,CAyDA"}
@@ -1,7 +1,7 @@
1
1
  // (C) 2025-2026 GoodData Corporation
2
2
  import { convertError, isNotFound, useBackendStrict, useCancelablePromise, useWorkspaceStrict, } from "@gooddata/sdk-ui";
3
3
  import { convertAttributeToCatalogItem, convertComputedAttributeToCatalogItem, convertDashboardToCatalogItem, convertDataSetToCatalogItem, convertFactToCatalogItem, convertInsightToCatalogItem, convertMeasureToCatalogItem, convertParameterToCatalogItem, } from "../../catalogItem/converter.js";
4
- import { isCatalogItemLoaded, isCatalogItemMeasure } from "../../catalogItem/guards.js";
4
+ import { isCatalogItemAttribute, isCatalogItemLoaded, isCatalogItemMeasure, } from "../../catalogItem/guards.js";
5
5
  import {} from "../../catalogItem/types.js";
6
6
  import {} from "../../objectType/types.js";
7
7
  import { useFeatureFlag } from "../../permission/PermissionsContext.js";
@@ -11,7 +11,9 @@ export function useCatalogItemLoad({ objectDefinition, objectId, objectType }) {
11
11
  const backend = useBackendStrict();
12
12
  const workspace = useWorkspaceStrict();
13
13
  const loadPermissions = useFeatureFlag("enableMetricPermissions");
14
- const filled = isCatalogItemLoaded(objectDefinition) && !awaitsPermissions(objectDefinition, loadPermissions);
14
+ const filled = isCatalogItemLoaded(objectDefinition) &&
15
+ !awaitsPermissions(objectDefinition, loadPermissions) &&
16
+ !awaitsLabels(objectDefinition);
15
17
  const { status, error, result } = useCancelablePromise({
16
18
  promise: () => {
17
19
  // Object id and type are required
@@ -56,6 +58,10 @@ export function useCatalogItemLoad({ objectDefinition, objectId, objectType }) {
56
58
  function awaitsPermissions(item, loadPermissions) {
57
59
  return loadPermissions && isCatalogItemMeasure(item) && item.permissions === undefined;
58
60
  }
61
+ // List queries don't include labels; only the detail fetch below does.
62
+ function awaitsLabels(item) {
63
+ return isCatalogItemAttribute(item) && item.labels === undefined;
64
+ }
59
65
  async function loadObjectDefinition(workspace, id, type, loadPermissions) {
60
66
  switch (type) {
61
67
  case "attribute":
@@ -67,7 +73,10 @@ async function loadObjectDefinition(workspace, id, type, loadPermissions) {
67
73
  }, {
68
74
  include: ["dataset"],
69
75
  })
70
- .then(convertAttributeToCatalogItem);
76
+ .then((attribute) => ({
77
+ ...convertAttributeToCatalogItem(attribute),
78
+ labels: attribute.displayForms,
79
+ }));
71
80
  case "dataSet":
72
81
  return workspace
73
82
  .datasets()
@@ -1,4 +1,4 @@
1
- import { type IUser, type MetricType } from "@gooddata/sdk-model";
1
+ import { type ISemanticConditionalFormatting, type IUser, type MetricType, type ObjRef } from "@gooddata/sdk-model";
2
2
  import { type ICatalogItem, type ICatalogItemMeasure, type ICatalogItemRef } from "../../catalogItem/types.js";
3
3
  import { type ObjectType } from "../../objectType/types.js";
4
4
  export interface IUseCatalogItemUpdate {
@@ -22,6 +22,7 @@ export declare function useCatalogItemUpdate({ currentUser, objectId, objectType
22
22
  updateItemMetricType: (metricType: MetricType | undefined) => void;
23
23
  updateItemFormat: (format: string | null) => void;
24
24
  updateItemConditionalFormatting: (conditionalFormatting: ICatalogItemMeasure["conditionalFormatting"]) => void;
25
+ updateItemLabelConditionalFormatting: (labelRef: ObjRef, conditionalFormatting: ISemanticConditionalFormatting | undefined) => void;
25
26
  updateItemCertification: (certification: ICatalogItem["certification"]) => void;
26
27
  applyItemUpdate: (updated: ICatalogItem) => void;
27
28
  applyItemDelete: (ref: ICatalogItemRef) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useCatalogItemUpdate.d.ts","sourceRoot":"","sources":["../../../src/catalogDetail/hooks/useCatalogItemUpdate.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAUlE,OAAO,EACH,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACvB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAI5D,MAAM,WAAW,qBAAqB;IAClC,WAAW,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE,eAAe,GAAG,YAAY,GAAG,IAAI,CAAC;IACzD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACpC;AAID,wBAAgB,oBAAoB,CAAC,EACjC,WAAW,EACX,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,OAAO,GACV,EAAE,qBAAqB;;;;6BA4DR,MAAM;yCAsBA,MAAM;2BAsBb,MAAM,EAAE;mCAsBJ,OAAO;iDA0BA,OAAO;uCA8BZ,UAAU,GAAG,SAAS;+BA2B1B,MAAM,GAAG,IAAI;6DA+BE,mBAAmB,CAAC,uBAAuB,CAAC;6CAwCpD,YAAY,CAAC,eAAe,CAAC;+BA9OnC,YAAY;2BAUhB,eAAe;EA8R5B"}
1
+ {"version":3,"file":"useCatalogItemUpdate.d.ts","sourceRoot":"","sources":["../../../src/catalogDetail/hooks/useCatalogItemUpdate.ts"],"names":[],"mappings":"AAOA,OAAO,EACH,KAAK,8BAA8B,EACnC,KAAK,KAAK,EACV,KAAK,UAAU,EACf,KAAK,MAAM,EAEd,MAAM,qBAAqB,CAAC;AAgB7B,OAAO,EACH,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACvB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAI5D,MAAM,WAAW,qBAAqB;IAClC,WAAW,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE,eAAe,GAAG,YAAY,GAAG,IAAI,CAAC;IACzD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACpC;AAID,wBAAgB,oBAAoB,CAAC,EACjC,WAAW,EACX,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,OAAO,GACV,EAAE,qBAAqB;;;;6BAyFR,MAAM;yCAIA,MAAM;2BAIb,MAAM,EAAE;mCAIJ,OAAO;iDAQA,OAAO;uCAQZ,UAAU,GAAG,SAAS;+BAY1B,MAAM,GAAG,IAAI;6DAYE,mBAAmB,CAAC,uBAAuB,CAAC;qDAYzD,MAAM,yBAAyB,8BAA8B,GAAG,SAAS;6CAqBpE,YAAY,CAAC,eAAe,CAAC;+BApInC,YAAY;2BAUhB,eAAe;EA6J5B"}
@@ -1,11 +1,11 @@
1
1
  // (C) 2025-2026 GoodData Corporation
2
2
  import { useCallback, useEffect, useState } from "react";
3
3
  import { isEqual } from "lodash-es";
4
- import {} from "@gooddata/sdk-model";
4
+ import { areObjRefsEqual, } from "@gooddata/sdk-model";
5
5
  import { useBackendStrict, useWorkspaceStrict } from "@gooddata/sdk-ui";
6
6
  import { getDisplayName } from "../../catalogItem/converter.js";
7
- import { isCatalogItemHidable, isCatalogItemLoaded, isCatalogItemMeasure } from "../../catalogItem/guards.js";
8
- import { persistMeasureConditionalFormatting, updateCatalogItem, updateCatalogItemCertification, } from "../../catalogItem/query.js";
7
+ import { isCatalogItemAttribute, isCatalogItemHidable, isCatalogItemLoaded, isCatalogItemMeasure, } from "../../catalogItem/guards.js";
8
+ import { persistLabelConditionalFormatting, persistMeasureConditionalFormatting, updateCatalogItem, updateCatalogItemCertification, } from "../../catalogItem/query.js";
9
9
  import {} from "../../catalogItem/types.js";
10
10
  import { useMounted } from "../../hooks/useMounted.js";
11
11
  import {} from "../../objectType/types.js";
@@ -48,142 +48,66 @@ export function useCatalogItemUpdate({ currentUser, objectId, objectType, object
48
48
  setItem(null);
49
49
  onDelete?.(ref);
50
50
  }, [onDelete]);
51
- const updateItemTitle = useCallback((title) => {
52
- updateItem(backend, workspace, currentUser, item, status !== "success", () => ({
53
- title,
54
- }), (newItem) => {
51
+ // One optimistic update flow for every field: apply locally, persist, revert on failure.
52
+ const runUpdate = useCallback((target, updater, persist, options) => {
53
+ updateItem(backend, workspace, currentUser, target, status !== "success", updater, (newItem) => {
55
54
  setItem(newItem);
56
55
  onUpdate?.(newItem);
57
56
  }, (err) => {
58
- revertItemUpdate(err, item);
59
- });
60
- }, [backend, currentUser, item, onUpdate, revertItemUpdate, status, workspace]);
61
- const updateItemDescription = useCallback((description) => {
62
- updateItem(backend, workspace, currentUser, item, status !== "success", () => ({
63
- description,
64
- }), (newItem) => {
65
- setItem(newItem);
66
- onUpdate?.(newItem);
67
- }, (err) => {
68
- revertItemUpdate(err, item);
69
- });
70
- }, [backend, currentUser, item, onUpdate, revertItemUpdate, status, workspace]);
71
- const updateItemTags = useCallback((tags) => {
72
- updateItem(backend, workspace, currentUser, item, status !== "success", () => ({
73
- tags,
74
- }), (newItem) => {
75
- setItem(newItem);
76
- onUpdate?.(newItem);
77
- }, (err) => {
78
- revertItemUpdate(err, item);
79
- });
80
- }, [backend, currentUser, item, onUpdate, revertItemUpdate, status, workspace]);
57
+ revertItemUpdate(err, target);
58
+ }, persist, options);
59
+ }, [backend, currentUser, onUpdate, revertItemUpdate, status, workspace]);
60
+ const updateItemTitle = useCallback((title) => runUpdate(item, () => ({ title })), [item, runUpdate]);
61
+ const updateItemDescription = useCallback((description) => runUpdate(item, () => ({ description })), [item, runUpdate]);
62
+ const updateItemTags = useCallback((tags) => runUpdate(item, () => ({ tags })), [item, runUpdate]);
81
63
  const updateItemIsHidden = useCallback((isHidden) => {
82
- if (!isCatalogItemHidable(item)) {
83
- return;
64
+ if (isCatalogItemHidable(item)) {
65
+ runUpdate(item, () => ({ isHidden }));
84
66
  }
85
- updateItem(backend, workspace, currentUser, item, status !== "success", () => ({
86
- isHidden,
87
- }), (newItem) => {
88
- setItem(newItem);
89
- onUpdate?.(newItem);
90
- }, (err) => {
91
- revertItemUpdate(err, item);
92
- });
93
- }, [backend, currentUser, item, onUpdate, revertItemUpdate, status, workspace]);
67
+ }, [item, runUpdate]);
94
68
  const updateItemIsHiddenFromKda = useCallback((isHiddenFromKda) => {
95
- if (!isCatalogItemMeasure(item)) {
96
- return;
69
+ if (isCatalogItemMeasure(item)) {
70
+ runUpdate(item, () => ({ isHiddenFromKda }));
97
71
  }
98
- updateItem(backend, workspace, currentUser, item, status !== "success", () => ({
99
- isHiddenFromKda,
100
- }), (newItem) => {
101
- setItem(newItem);
102
- onUpdate?.(newItem);
103
- }, (err) => {
104
- revertItemUpdate(err, item);
105
- });
106
- }, [backend, currentUser, item, onUpdate, revertItemUpdate, status, workspace]);
107
- const persistMeasureChanges = useCallback((nextItem) => persistMeasureMetadata(backend, workspace, nextItem), [backend, workspace]);
72
+ }, [item, runUpdate]);
108
73
  const updateItemMetricType = useCallback((metricType) => {
109
- if (!isCatalogItemMeasure(item)) {
110
- return;
74
+ if (isCatalogItemMeasure(item)) {
75
+ runUpdate(item, () => ({ metricType }), (next) => persistMeasureMetadata(backend, workspace, next));
111
76
  }
112
- updateItem(backend, workspace, currentUser, item, status !== "success", () => ({
113
- metricType,
114
- }), (newItem) => {
115
- setItem(newItem);
116
- onUpdate?.(newItem);
117
- }, (err) => {
118
- revertItemUpdate(err, item);
119
- }, persistMeasureChanges);
120
- }, [backend, currentUser, item, onUpdate, persistMeasureChanges, revertItemUpdate, status, workspace]);
77
+ }, [backend, item, runUpdate, workspace]);
121
78
  const updateItemFormat = useCallback((format) => {
122
- if (!isCatalogItemMeasure(item)) {
123
- return;
79
+ if (isCatalogItemMeasure(item)) {
80
+ runUpdate(item, () => ({ format }), (next) => persistMeasureMetadata(backend, workspace, next));
124
81
  }
125
- updateItem(backend, workspace, currentUser, item, status !== "success", () => ({
126
- format,
127
- }), (newItem) => {
128
- setItem(newItem);
129
- onUpdate?.(newItem);
130
- }, (err) => {
131
- revertItemUpdate(err, item);
132
- }, persistMeasureChanges);
133
- }, [backend, currentUser, item, onUpdate, persistMeasureChanges, revertItemUpdate, status, workspace]);
134
- const persistMeasureConditionalFormattingChanges = useCallback((nextItem) => persistMeasureConditionalFormatting(backend, workspace, nextItem), [backend, workspace]);
82
+ }, [backend, item, runUpdate, workspace]);
135
83
  const updateItemConditionalFormatting = useCallback((conditionalFormatting) => {
136
- if (!isCatalogItemMeasure(item)) {
84
+ if (isCatalogItemMeasure(item)) {
85
+ runUpdate(item, () => ({ conditionalFormatting }), (next) => persistMeasureConditionalFormatting(backend, workspace, next));
86
+ }
87
+ }, [backend, item, runUpdate, workspace]);
88
+ const updateItemLabelConditionalFormatting = useCallback((labelRef, conditionalFormatting) => {
89
+ if (!isCatalogItemAttribute(item)) {
137
90
  return;
138
91
  }
139
- updateItem(backend, workspace, currentUser, item, status !== "success", () => ({
140
- conditionalFormatting,
141
- }), (newItem) => {
142
- setItem(newItem);
143
- onUpdate?.(newItem);
144
- }, (err) => {
145
- revertItemUpdate(err, item);
146
- }, persistMeasureConditionalFormattingChanges);
147
- }, [
148
- backend,
149
- currentUser,
150
- item,
151
- onUpdate,
152
- persistMeasureConditionalFormattingChanges,
153
- revertItemUpdate,
154
- status,
155
- workspace,
156
- ]);
157
- const persistCertificationChanges = useCallback((newItem) => updateCatalogItemCertification(backend, workspace, newItem), [backend, workspace]);
158
- const updateItemCertification = useCallback((certification) => {
159
- updateItem(backend, workspace, currentUser, item, status !== "success", () => ({
160
- certification: certification
161
- ? {
162
- ...certification,
163
- ...(certification.status === "CERTIFIED"
164
- ? {
165
- certifiedAt: new Date(),
166
- certifiedBy: getDisplayName(currentUser),
167
- }
168
- : {}),
169
- }
170
- : undefined,
171
- }), (newItem) => {
172
- setItem(newItem);
173
- onUpdate?.(newItem);
174
- }, (err) => {
175
- revertItemUpdate(err, item);
176
- }, persistCertificationChanges);
177
- }, [
178
- backend,
179
- currentUser,
180
- item,
181
- onUpdate,
182
- persistCertificationChanges,
183
- revertItemUpdate,
184
- status,
185
- workspace,
186
- ]);
92
+ const label = item.labels?.find((candidate) => areObjRefsEqual(candidate.ref, labelRef));
93
+ if (!label) {
94
+ return;
95
+ }
96
+ const updatedLabel = { ...label, conditionalFormatting };
97
+ runUpdate(item, () => ({
98
+ labels: item.labels?.map((candidate) => (candidate === label ? updatedLabel : candidate)),
99
+ }), () => persistLabelConditionalFormatting(backend, workspace, updatedLabel), { touch: false });
100
+ }, [backend, item, runUpdate, workspace]);
101
+ const updateItemCertification = useCallback((certification) => runUpdate(item, () => ({
102
+ certification: certification
103
+ ? {
104
+ ...certification,
105
+ ...(certification.status === "CERTIFIED"
106
+ ? { certifiedAt: new Date(), certifiedBy: getDisplayName(currentUser) }
107
+ : {}),
108
+ }
109
+ : undefined,
110
+ }), (next) => updateCatalogItemCertification(backend, workspace, next)), [backend, currentUser, item, runUpdate, workspace]);
187
111
  return {
188
112
  item,
189
113
  status,
@@ -196,12 +120,13 @@ export function useCatalogItemUpdate({ currentUser, objectId, objectType, object
196
120
  updateItemMetricType,
197
121
  updateItemFormat,
198
122
  updateItemConditionalFormatting,
123
+ updateItemLabelConditionalFormatting,
199
124
  updateItemCertification,
200
125
  applyItemUpdate,
201
126
  applyItemDelete,
202
127
  };
203
128
  }
204
- function updateItem(backend, workspace, user, item, disabled, updater, onUpdate, onError, persist) {
129
+ function updateItem(backend, workspace, user, item, disabled, updater, onUpdate, onError, persist, options = {}) {
205
130
  if (disabled || !item) {
206
131
  return;
207
132
  }
@@ -209,7 +134,8 @@ function updateItem(backend, workspace, user, item, disabled, updater, onUpdate,
209
134
  if (!hasChanges(item, itemChanges)) {
210
135
  return;
211
136
  }
212
- const newItem = makeUpdatedItem(user, item, itemChanges);
137
+ // A label patch does not touch the attribute itself, so it must not stamp updatedAt/updatedBy.
138
+ const newItem = options.touch === false ? { ...item, ...itemChanges } : makeUpdatedItem(user, item, itemChanges);
213
139
  onUpdate(newItem);
214
140
  const persistFn = persist ?? ((nextItem) => updateCatalogItem(backend, workspace, nextItem));
215
141
  Promise.resolve(persistFn(newItem)).catch(onError);
@@ -1,5 +1,5 @@
1
1
  import type { IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
2
- import { type IMeasureMetadataObject, type IMeasureMetadataObjectDefinition, type IParameterMetadataObjectDefinition, type ObjRef } from "@gooddata/sdk-model";
2
+ import { type IAttributeDisplayFormMetadataObject, type IMeasureMetadataObject, type IMeasureMetadataObjectDefinition, type IParameterMetadataObjectDefinition, type ObjRef } from "@gooddata/sdk-model";
3
3
  import type { ICatalogItem, ICatalogItemMeasure, ICatalogItemQueryOptions } from "./types.js";
4
4
  export declare function getDashboardsQuery({ backend, workspace, search, origin, id, excludeId, createdBy, excludeCreatedBy, tags, excludeTags, isHidden, certification, pageSize, }: ICatalogItemQueryOptions): import("@gooddata/sdk-backend-spi").IDashboardsQuery;
5
5
  export declare function getInsightsQuery({ backend, workspace, search, origin, id, excludeId, createdBy, excludeCreatedBy, tags, excludeTags, isHidden, certification, pageSize, }: ICatalogItemQueryOptions): import("@gooddata/sdk-backend-spi").IInsightsQuery;
@@ -10,7 +10,8 @@ export declare function getAttributesQuery({ backend, workspace, search, origin,
10
10
  export declare function getFactsQuery({ backend, workspace, search, origin, id, excludeId, tags, excludeTags, isHidden, pageSize, }: ICatalogItemQueryOptions): import("@gooddata/sdk-backend-spi").IFactsQuery;
11
11
  export declare function getDateDatasetsQuery({ backend, workspace, search, origin, id, excludeId, tags, excludeTags, isHidden, pageSize, }: ICatalogItemQueryOptions): import("@gooddata/sdk-backend-spi").IDatasetsQuery;
12
12
  export declare function updateCatalogItem(backend: IAnalyticalBackend, workspace: string, item: ICatalogItem): Promise<import("@gooddata/sdk-model").IAttributeMetadataObject> | Promise<import("@gooddata/sdk-model").IDashboard<import("@gooddata/sdk-model").IDashboardWidget>> | Promise<import("@gooddata/sdk-model").IDataSetMetadataObject> | Promise<import("@gooddata/sdk-model").IFactMetadataObject> | Promise<import("@gooddata/sdk-model").IParameterMetadataObject> | Promise<import("@gooddata/sdk-model").IComputedAttributeMetadataObject> | Promise<import("@gooddata/sdk-model").IInsight> | Promise<IMeasureMetadataObject>;
13
- export declare function persistMeasureConditionalFormatting(backend: IAnalyticalBackend, workspace: string, item: ICatalogItemMeasure): Promise<undefined>;
13
+ export declare function persistMeasureConditionalFormatting(backend: IAnalyticalBackend, workspace: string, item: ICatalogItemMeasure): Promise<IMeasureMetadataObject>;
14
+ export declare function persistLabelConditionalFormatting(backend: IAnalyticalBackend, workspace: string, label: IAttributeDisplayFormMetadataObject): Promise<IAttributeDisplayFormMetadataObject>;
14
15
  export declare function createParameterCatalogItem(backend: IAnalyticalBackend, workspace: string, parameter: IParameterMetadataObjectDefinition): Promise<import("@gooddata/sdk-model").IParameterMetadataObject>;
15
16
  export declare function updateParameterCatalogItem(backend: IAnalyticalBackend, workspace: string, definition: IParameterMetadataObjectDefinition & {
16
17
  id: string;