@gooddata/sdk-ui-gen-ai 11.55.0-alpha.2 → 11.55.0-alpha.3

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 (44) hide show
  1. package/NOTICE +4 -4
  2. package/esm/components/GenAIChatContextIndicator.d.ts +2 -2
  3. package/esm/components/GenAIChatContextIndicator.d.ts.map +1 -1
  4. package/esm/components/GenAIChatContextIndicator.js +81 -13
  5. package/esm/components/GenAiChatContextChooser.d.ts.map +1 -1
  6. package/esm/components/GenAiChatContextChooser.js +4 -3
  7. package/esm/components/GenAiChatContextChooserBody.d.ts +3 -1
  8. package/esm/components/GenAiChatContextChooserBody.d.ts.map +1 -1
  9. package/esm/components/GenAiChatContextChooserBody.js +7 -4
  10. package/esm/components/Input.js +1 -1
  11. package/esm/components/hooks/useContextChangeAnnouncement.d.ts +2 -2
  12. package/esm/components/hooks/useContextChangeAnnouncement.d.ts.map +1 -1
  13. package/esm/components/hooks/useContextChangeAnnouncement.js +9 -4
  14. package/esm/components/hooks/useContextItems.d.ts +9 -3
  15. package/esm/components/hooks/useContextItems.d.ts.map +1 -1
  16. package/esm/components/hooks/useContextItems.js +51 -8
  17. package/esm/context/addContextReference.d.ts +0 -2
  18. package/esm/context/addContextReference.d.ts.map +1 -1
  19. package/esm/context/addContextReference.js +12 -35
  20. package/esm/context/collectContextReferences.d.ts +2 -2
  21. package/esm/context/collectContextReferences.d.ts.map +1 -1
  22. package/esm/context/collectContextReferences.js +22 -20
  23. package/esm/context/removeContextReference.d.ts +2 -16
  24. package/esm/context/removeContextReference.d.ts.map +1 -1
  25. package/esm/context/removeContextReference.js +7 -70
  26. package/esm/context/selectContextReferences.d.ts +5 -0
  27. package/esm/context/selectContextReferences.d.ts.map +1 -0
  28. package/esm/context/selectContextReferences.js +68 -0
  29. package/esm/localization/bundles/en-US.localization-bundle.d.ts +8 -0
  30. package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  31. package/esm/localization/bundles/en-US.localization-bundle.js +8 -0
  32. package/esm/localization/bundles/zh-HK.localization-bundle.js +9 -9
  33. package/esm/store/chatWindow/chatWindowSelectors.d.ts +2 -1
  34. package/esm/store/chatWindow/chatWindowSelectors.d.ts.map +1 -1
  35. package/esm/store/chatWindow/chatWindowSelectors.js +1 -0
  36. package/esm/store/chatWindow/chatWindowSlice.d.ts +2 -2
  37. package/esm/store/chatWindow/chatWindowSlice.d.ts.map +1 -1
  38. package/esm/store/chatWindow/chatWindowSlice.js +11 -6
  39. package/esm/types.d.ts +22 -0
  40. package/esm/types.d.ts.map +1 -1
  41. package/package.json +20 -20
  42. package/styles/css/main.css +4 -0
  43. package/styles/css/main.css.map +1 -1
  44. package/styles/scss/main.scss +5 -0
package/NOTICE CHANGED
@@ -7,9 +7,9 @@
7
7
 
8
8
  The following 3rd-party software packages may be used by or distributed with gooddata-ui-sdk. Any information relevant to third-party vendors listed below are collected using common, reasonable means.
9
9
 
10
- Date generated: 2026-8-30
10
+ Date generated: 2026-8-31
11
11
 
12
- Revision ID: ddb9da987c2b38f109d24ae5d452deb8e2f28bd2
12
+ Revision ID: 14f5c085f7e749fb111a5c2dfbbf7a3d25b73682
13
13
 
14
14
  ================================================================================
15
15
  ================================================================================
@@ -35327,7 +35327,7 @@ MIT
35327
35327
 
35328
35328
  Authors: admin@simonboudrias.com
35329
35329
  Package Manager: NPM
35330
- Project URL: https://www.npmjs.com/package/run-async
35330
+ Project URL: https://github.com/SBoudrias/run-async#readme
35331
35331
  Package Download URL: https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz
35332
35332
  Dependency Path: inquirer > run-async
35333
35333
  File Path(s): common/config/subspaces/sdk/pnpm-lock.yaml
@@ -64321,4 +64321,4 @@ File Path(s): common/config/subspaces/sdk/pnpm-lock.yaml
64321
64321
  --------------------------------------------------------------------------------
64322
64322
  --------------------------------------------------------------------------------
64323
64323
 
64324
- Report Generated by FOSSA on 2026-8-30
64324
+ Report Generated by FOSSA on 2026-8-31
@@ -1,5 +1,5 @@
1
1
  type GenAIChatContextIndicatorOwnProps = {
2
- onDelete?: () => void;
2
+ onUpdate?: () => void;
3
3
  };
4
4
  /**
5
5
  * Shows what ambient context the assistant is answering about — the open dashboard and its live
@@ -9,6 +9,6 @@ type GenAIChatContextIndicatorOwnProps = {
9
9
  *
10
10
  * @internal
11
11
  */
12
- export declare function GenAIChatContextIndicator({ onDelete }: GenAIChatContextIndicatorOwnProps): import("react/jsx-runtime").JSX.Element | null;
12
+ export declare function GenAIChatContextIndicator({ onUpdate }: GenAIChatContextIndicatorOwnProps): import("react/jsx-runtime").JSX.Element | null;
13
13
  export {};
14
14
  //# sourceMappingURL=GenAIChatContextIndicator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GenAIChatContextIndicator.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatContextIndicator.tsx"],"names":[],"mappings":"AA6BA,KAAK,iCAAiC,GAAG;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,QAAQ,EAAE,EAAE,iCAAiC,kDAuExF"}
1
+ {"version":3,"file":"GenAIChatContextIndicator.d.ts","sourceRoot":"","sources":["../../src/components/GenAIChatContextIndicator.tsx"],"names":[],"mappings":"AA0CA,KAAK,iCAAiC,GAAG;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,QAAQ,EAAE,EAAE,iCAAiC,kDAyJxF"}
@@ -3,11 +3,13 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
3
3
  import { useCallback, useMemo } from "react";
4
4
  import { defineMessages, useIntl } from "react-intl";
5
5
  import { useDispatch, useSelector } from "react-redux";
6
- import { UiChip, useIdPrefixed } from "@gooddata/sdk-ui-kit";
6
+ import { Dropdown, UiChip, useIdPrefixed } from "@gooddata/sdk-ui-kit";
7
7
  import { collectContextReferences } from "../context/collectContextReferences.js";
8
- import { contextSetupEnabledSelector, userContextSelector } from "../store/chatWindow/chatWindowSelectors.js";
9
- import { removeContextReferenceAction } from "../store/chatWindow/chatWindowSlice.js";
8
+ import { ambientContextSelector, contextSetupEnabledSelector, selectedContextSelector, userContextSelector, } from "../store/chatWindow/chatWindowSelectors.js";
9
+ import { removeContextReferenceAction, selectedContextReferencesAction, } from "../store/chatWindow/chatWindowSlice.js";
10
+ import { GenAiChatContextChooserBody } from "./GenAiChatContextChooserBody.js";
10
11
  import { useContextChangeAnnouncement } from "./hooks/useContextChangeAnnouncement.js";
12
+ import { useAmbientContextItems } from "./hooks/useContextItems.js";
11
13
  import { getIconByObject, getTypeLabel } from "./utils/icons.js";
12
14
  const msgs = defineMessages({
13
15
  untitled: {
@@ -19,6 +21,9 @@ const msgs = defineMessages({
19
21
  groupLabel: {
20
22
  id: "gd.gen-ai.context.group.ariaLabel",
21
23
  },
24
+ focusOn: {
25
+ id: "gd.gen-ai.context.focus_on",
26
+ },
22
27
  });
23
28
  /**
24
29
  * Shows what ambient context the assistant is answering about — the open dashboard and its live
@@ -28,32 +33,95 @@ const msgs = defineMessages({
28
33
  *
29
34
  * @internal
30
35
  */
31
- export function GenAIChatContextIndicator({ onDelete }) {
36
+ export function GenAIChatContextIndicator({ onUpdate }) {
32
37
  const intl = useIntl();
33
38
  const emptyReferenceLabel = intl.formatMessage(msgs.untitled);
34
39
  const groupLabelId = useIdPrefixed("context-indicator-label");
35
40
  const isContextSetupEnabled = useSelector(contextSetupEnabledSelector);
36
- const context = useSelector(userContextSelector);
37
- const references = useMemo(() => collectContextReferences(context, emptyReferenceLabel), [context, emptyReferenceLabel]);
41
+ const ambientContext = useSelector(ambientContextSelector);
42
+ const userContext = useSelector(userContextSelector);
43
+ const selectedContext = useSelector(selectedContextSelector);
44
+ const { items, search, setSearch, selectedIds } = useAmbientContextItems(ambientContext);
45
+ const addContextLabel = intl.formatMessage(msgs.focusOn);
46
+ const titleId = useIdPrefixed("context-focuson-title");
47
+ const references = useMemo(() => collectContextReferences(userContext, selectedContext, emptyReferenceLabel), [userContext, selectedContext, emptyReferenceLabel]);
38
48
  const dispatch = useDispatch();
39
49
  const removeContextReference = useCallback((payload) => dispatch(removeContextReferenceAction(payload)), [dispatch]);
50
+ const onAmbientToggleHandler = useCallback(() => {
51
+ return () => {
52
+ dispatch(selectedContextReferencesAction({
53
+ ...selectedContext,
54
+ activated: !selectedContext?.activated,
55
+ }));
56
+ onUpdate?.();
57
+ };
58
+ }, [dispatch, onUpdate, selectedContext]);
40
59
  const onDeleteHandler = useCallback((reference) => {
41
60
  return () => {
42
61
  removeContextReference({ object: reference });
43
- onDelete?.();
62
+ onUpdate?.();
44
63
  };
45
- }, [removeContextReference, onDelete]);
46
- const announcement = useContextChangeAnnouncement(references);
64
+ }, [removeContextReference, onUpdate]);
65
+ const onOpenStateChanged = useCallback(() => {
66
+ setSearch("");
67
+ }, [setSearch]);
68
+ const announcement = useContextChangeAnnouncement(selectedContext, references);
47
69
  if (!isContextSetupEnabled) {
48
70
  return null;
49
71
  }
50
- return (_jsxs(_Fragment, { children: [references.length > 0 ? (_jsxs(_Fragment, { children: [
51
- _jsx("span", { className: "sr-only", id: groupLabelId, children: intl.formatMessage(msgs.groupLabel) }), _jsx("div", { className: "gd-gen-ai-chat__context-indicator", role: "group", "aria-labelledby": groupLabelId, children: references.map((reference, index) => (_jsx(UiChip, { isDisabled: true, isDeletable: true, ...getIconByObject(reference), label: reference.title, isExpandable: false, onDelete: onDeleteHandler(reference), accessibilityConfig: {
72
+ return (_jsxs(_Fragment, { children: [
73
+ _jsxs(ContextWrapper, { groupLabel: msgs.groupLabel, groupLabelId: groupLabelId, children: [selectedContext?.dashboard ? (_jsx(Dropdown, { alignPoints: [{ align: "tl bl", offset: { x: 0, y: 0 } }], closeOnEscape: true, fullscreenOnMobile: false, autofocusOnOpen: true, accessibilityConfig: { popupRole: "dialog" }, onOpenStateChanged: onOpenStateChanged, renderButton: ({ isOpen, toggleDropdown, accessibilityConfig }) => {
74
+ const item = selectedContext.visualization ?? selectedContext.dashboard;
75
+ if (!item) {
76
+ return null;
77
+ }
78
+ return (_jsx(UiChip, { isActionable: true, isExpandable: true, isActive: isOpen, ...getIconByObject(item), label: getSelectedTitle(selectedContext, emptyReferenceLabel), iconAction: selectedContext.activated ? "visible" : "invisible", variant: selectedContext.activated ? "normal" : "inactive", onClick: toggleDropdown, onAction: onAmbientToggleHandler(), accessibilityConfig: {
79
+ ...accessibilityConfig,
80
+ deleteAriaLabel: intl.formatMessage(msgs.remove, {
81
+ title: getSelectedTitle(selectedContext, emptyReferenceLabel),
82
+ }),
83
+ iconBeforeAriaLabel: getTypeLabel(item.type, intl),
84
+ } }));
85
+ }, renderBody: ({ closeDropdown, ariaAttributes }) => (_jsx(GenAiChatContextChooserBody, { inputItems: items, selectedIds: selectedIds, title: addContextLabel, titleId: titleId, search: search, onSearchChange: setSearch, ariaAttributes: ariaAttributes, closeDropdown: closeDropdown, onSelect: (item) => {
86
+ dispatch(selectedContextReferencesAction({
87
+ ...selectedContext,
88
+ ...(item.type === "dashboard"
89
+ ? {
90
+ dashboard: item,
91
+ visualization: undefined,
92
+ }
93
+ : {}),
94
+ ...(item.type === "visualization" || item.type === "widget"
95
+ ? {
96
+ visualization: item,
97
+ }
98
+ : {}),
99
+ activated: true,
100
+ }));
101
+ onUpdate?.();
102
+ } })) })) : null, references.length > 0
103
+ ? references.map((reference, index) => (_jsx(UiChip, { isDisabled: true, isDeletable: true, ...getIconByObject(reference), label: reference.title, isExpandable: false, onDelete: onDeleteHandler(reference), accessibilityConfig: {
52
104
  deleteAriaLabel: intl.formatMessage(msgs.remove, {
53
105
  title: reference.title,
54
106
  }),
55
107
  iconBeforeAriaLabel: getTypeLabel(reference.type, intl),
56
- } }, index))) })
57
- ] })) : null, _jsx("span", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement })
108
+ } }, index)))
109
+ : null] }), _jsx("span", { className: "sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement })
58
110
  ] }));
59
111
  }
112
+ function ContextWrapper({ groupLabel, groupLabelId, children }) {
113
+ const intl = useIntl();
114
+ return (_jsxs(_Fragment, { children: [
115
+ _jsx("span", { className: "sr-only", id: groupLabelId, children: intl.formatMessage(groupLabel) }), _jsx("div", { className: "gd-gen-ai-chat__context-indicator", role: "group", "aria-labelledby": groupLabelId, children: children })
116
+ ] }));
117
+ }
118
+ // utils
119
+ function getSelectedTitle(selectedContext, emptyReferenceLabel) {
120
+ const label = [
121
+ ...(selectedContext.dashboard ? [selectedContext.dashboard.title || emptyReferenceLabel] : []),
122
+ ...(selectedContext.visualization
123
+ ? [selectedContext.visualization.title || emptyReferenceLabel]
124
+ : []),
125
+ ];
126
+ return label.join(" / ");
127
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"GenAiChatContextChooser.d.ts","sourceRoot":"","sources":["../../src/components/GenAiChatContextChooser.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAWvD,KAAK,+BAA+B,GAAG;IACnC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACzD,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,EAAE,YAAY,EAAE,EAAE,+BAA+B,kDA4ExF"}
1
+ {"version":3,"file":"GenAiChatContextChooser.d.ts","sourceRoot":"","sources":["../../src/components/GenAiChatContextChooser.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAWvD,KAAK,+BAA+B,GAAG;IACnC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACzD,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,EAAE,YAAY,EAAE,EAAE,+BAA+B,kDA6ExF"}
@@ -4,10 +4,10 @@ import { useCallback } from "react";
4
4
  import { defineMessages, useIntl } from "react-intl";
5
5
  import { useDispatch, useSelector } from "react-redux";
6
6
  import { Dropdown, UiIconButton, useIdPrefixed } from "@gooddata/sdk-ui-kit";
7
- import { ambientContextSelector, userContextSelector } from "../store/chatWindow/chatWindowSelectors.js";
7
+ import { ambientContextSelector, selectedContextSelector, userContextSelector, } from "../store/chatWindow/chatWindowSelectors.js";
8
8
  import { addContextReferenceAction, initContextObjectsAction } from "../store/chatWindow/chatWindowSlice.js";
9
9
  import { GenAiChatContextChooserBody } from "./GenAiChatContextChooserBody.js";
10
- import { useContextItems } from "./hooks/useContextItems.js";
10
+ import { useUserContextItems } from "./hooks/useContextItems.js";
11
11
  const msgs = defineMessages({
12
12
  add: {
13
13
  id: "gd.gen-ai.context.add_context",
@@ -18,8 +18,9 @@ export function GenAiChatContextChooser({ onAddContext }) {
18
18
  const dispatch = useDispatch();
19
19
  const titleId = useIdPrefixed("context-chooser-title");
20
20
  const ambient = useSelector((state) => ambientContextSelector(state));
21
+ const selected = useSelector((state) => selectedContextSelector(state));
21
22
  const active = useSelector((state) => userContextSelector(state));
22
- const { items: inputItems, search, setSearch, isLoading, hasNextPage, loadNextPage, } = useContextItems(ambient, active);
23
+ const { items: inputItems, search, setSearch, isLoading, hasNextPage, loadNextPage, } = useUserContextItems(ambient, selected, active);
23
24
  const addContextLabel = intl.formatMessage(msgs.add);
24
25
  const onOpenStateChanged = useCallback((isOpen) => {
25
26
  setSearch("");
@@ -1,3 +1,4 @@
1
+ import { type ObjRef } from "@gooddata/sdk-model";
1
2
  import { type IGenAIContextObject } from "../types.js";
2
3
  type GenAiChatContextChooserBodyProps = {
3
4
  inputItems: IGenAIContextObject[];
@@ -5,6 +6,7 @@ type GenAiChatContextChooserBodyProps = {
5
6
  titleId: string;
6
7
  search: string;
7
8
  onSearchChange: (search: string) => void;
9
+ selectedIds?: ObjRef[];
8
10
  isLoading?: boolean;
9
11
  hasNextPage?: boolean;
10
12
  loadNextPage?: () => void;
@@ -16,6 +18,6 @@ type GenAiChatContextChooserBodyProps = {
16
18
  onSelect: (item: IGenAIContextObject) => void;
17
19
  closeDropdown: () => void;
18
20
  };
19
- export declare function GenAiChatContextChooserBody({ inputItems, title, titleId, search, onSearchChange, isLoading, hasNextPage, loadNextPage, ariaAttributes, onSelect, closeDropdown }: GenAiChatContextChooserBodyProps): import("react/jsx-runtime").JSX.Element;
21
+ export declare function GenAiChatContextChooserBody({ inputItems, title, titleId, search, selectedIds, onSearchChange, isLoading, hasNextPage, loadNextPage, ariaAttributes, onSelect, closeDropdown }: GenAiChatContextChooserBodyProps): import("react/jsx-runtime").JSX.Element;
20
22
  export {};
21
23
  //# sourceMappingURL=GenAiChatContextChooserBody.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GenAiChatContextChooserBody.d.ts","sourceRoot":"","sources":["../../src/components/GenAiChatContextChooserBody.tsx"],"names":[],"mappings":"AAuBA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AA8BvD,KAAK,gCAAgC,GAAG;IACpC,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,EAAE;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC9C,aAAa,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,EACxC,UAAU,EACV,KAAK,EACL,OAAO,EACP,MAAM,EACN,cAAc,EACd,SAAiB,EACjB,WAAmB,EACnB,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,aAAa,EAChB,EAAE,gCAAgC,2CAmIlC"}
1
+ {"version":3,"file":"GenAiChatContextChooserBody.d.ts","sourceRoot":"","sources":["../../src/components/GenAiChatContextChooserBody.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,MAAM,EAAmB,MAAM,qBAAqB,CAAC;AAiBnE,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AA8BvD,KAAK,gCAAgC,GAAG;IACpC,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,EAAE;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,QAAQ,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC9C,aAAa,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,EACxC,UAAU,EACV,KAAK,EACL,OAAO,EACP,MAAM,EACN,WAAW,EACX,cAAc,EACd,SAAiB,EACjB,WAAmB,EACnB,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,aAAa,EAChB,EAAE,gCAAgC,2CAyIlC"}
@@ -3,6 +3,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
3
3
  import { useCallback, useEffect, useId } from "react";
4
4
  import cx from "classnames";
5
5
  import { defineMessages, useIntl } from "react-intl";
6
+ import { areObjRefsEqual } from "@gooddata/sdk-model";
6
7
  import { useDebouncedState } from "@gooddata/sdk-ui";
7
8
  import { DEFAULT_ITEM_HEIGHT, DETAILED_ANNOUNCEMENT_THRESHOLD, Input, NoData, ScopedIdStore, ShortenedText, UiIcon, UiPagedVirtualList, UiSearchResultsAnnouncement, UiSubmenuHeader, isTypingKey, useScopedIdStoreValue, } from "@gooddata/sdk-ui-kit";
8
9
  import { getIconByObject } from "./utils/icons.js";
@@ -30,7 +31,7 @@ const msgs = defineMessages({
30
31
  id: "gd.gen-ai.context.noDataAvailable",
31
32
  },
32
33
  });
33
- export function GenAiChatContextChooserBody({ inputItems, title, titleId, search, onSearchChange, isLoading = false, hasNextPage = false, loadNextPage, ariaAttributes, onSelect, closeDropdown, }) {
34
+ export function GenAiChatContextChooserBody({ inputItems, title, titleId, search, selectedIds, onSearchChange, isLoading = false, hasNextPage = false, loadNextPage, ariaAttributes, onSelect, closeDropdown, }) {
34
35
  const intl = useIntl();
35
36
  const listboxId = useId();
36
37
  const [searchString, setSearchString, debouncedSearch] = useDebouncedState(search, SEARCH_DEBOUNCE_MS);
@@ -76,10 +77,12 @@ export function GenAiChatContextChooserBody({ inputItems, title, titleId, search
76
77
  ] })) : null, shouldShowPagedList ? (_jsx(ScopedIdStore, { value: scopedIdStoreValue, children: _jsx(UiPagedVirtualList, { maxHeight: listMaxHeight, items: inputItems, itemHeight: DEFAULT_ITEM_HEIGHT, itemsGap: 0, itemPadding: 0, skeletonItemsCount: skeletonItemsCount, isLoading: isLoading, hasNextPage: hasNextPage, loadNextPage: loadNextPage, representAs: "listbox", closeDropdown: closeDropdown, onKeyDownConfirm: handleSelect, listboxProps: {
77
78
  id: listboxId,
78
79
  "aria-label": intl.formatMessage(msgs.listAriaLabel),
79
- }, children: (item) => _jsx(ContextChooserItem, { item: item, onSelect: () => handleSelect(item) }) }) })) : (_jsx(NoData, { hasNoMatchingData: hasNoMatchingData, notFoundLabel: intl.formatMessage(msgs.noMatchingData), noDataLabel: intl.formatMessage(msgs.noDataAvailable) }))] }));
80
+ }, children: (item) => (_jsx(ContextChooserItem, { item: item, selected: selectedIds?.some((r) => areObjRefsEqual(r, item.ref)), onSelect: () => handleSelect(item) })) }) })) : (_jsx(NoData, { hasNoMatchingData: hasNoMatchingData, notFoundLabel: intl.formatMessage(msgs.noMatchingData), noDataLabel: intl.formatMessage(msgs.noDataAvailable) }))] }));
80
81
  }
81
- function ContextChooserItem({ item, onSelect }) {
82
+ function ContextChooserItem({ item, selected, onSelect, }) {
82
83
  const icon = getIconByObject(item);
83
- return (_jsxs("div", { className: "gd-list-item", onClick: onSelect, children: [icon.iconBefore ? _jsx(UiIcon, { size: 16, type: icon.iconBefore, color: icon.iconColor }) : null, _jsx(ShortenedText, { ellipsisPosition: "end", children: item.title })
84
+ return (_jsxs("div", { className: cx("gd-list-item", {
85
+ "gd-list-item--selected": selected,
86
+ }), onClick: onSelect, "aria-selected": selected, children: [icon.iconBefore ? _jsx(UiIcon, { size: 16, type: icon.iconBefore, color: icon.iconColor }) : null, _jsx(ShortenedText, { ellipsisPosition: "end", children: item.title })
84
87
  ] }));
85
88
  }
@@ -113,7 +113,7 @@ function InputComponent({ autofocus = false, canManage, canAnalyze, targetRef })
113
113
  "gd-gen-ai-chat__input--no-agents": hasNoAgents,
114
114
  }), children: _jsxs("div", { className: "gd-gen-ai-chat__input__content", children: [
115
115
  _jsx(HintText, { focused: focused, where: "top" }), _jsxs("div", { className: "gd-gen-ai-chat__input__container", children: [
116
- _jsx("div", { className: "gd-gen-ai-chat__input__context", onMouseDown: handleContextMouseDown, children: _jsx(GenAIChatContextIndicator, { onDelete: handleOnFocus }) }), _jsx("div", { ref: targetRef, onFocus: handleOnFocus }), _jsx("div", { className: "gd-gen-ai-chat__input__text", ...ref, children: _jsx(SyntaxHighlightingInput, { className: "gd-gen-ai-chat__input__mc", placeholder: intl.formatMessage(msgs.placeholder), label: isMac ? intl.formatMessage(msgs.labelMac) : intl.formatMessage(msgs.labelWin), value: value, autocompletion: {
116
+ _jsx("div", { className: "gd-gen-ai-chat__input__context", onMouseDown: handleContextMouseDown, children: _jsx(GenAIChatContextIndicator, { onUpdate: handleOnFocus }) }), _jsx("div", { ref: targetRef, onFocus: handleOnFocus }), _jsx("div", { className: "gd-gen-ai-chat__input__text", ...ref, children: _jsx(SyntaxHighlightingInput, { className: "gd-gen-ai-chat__input__mc", placeholder: intl.formatMessage(msgs.placeholder), label: isMac ? intl.formatMessage(msgs.labelMac) : intl.formatMessage(msgs.labelWin), value: value, autocompletion: {
117
117
  aboveCursor: true,
118
118
  whenTyping: true,
119
119
  whenTypingDelay: 300,
@@ -1,9 +1,9 @@
1
- import { type IGenAIContextObject } from "../../types.js";
1
+ import { type IGenAIContextObject, type SelectedContext } from "../../types.js";
2
2
  /**
3
3
  * Turns each change of the assistant context into one spoken sentence: what was added, what was
4
4
  * removed, that the whole context was swapped (the user navigated to another dashboard), or that
5
5
  * nothing is left.
6
6
  * @internal
7
7
  */
8
- export declare function useContextChangeAnnouncement(references: IGenAIContextObject[]): string;
8
+ export declare function useContextChangeAnnouncement(selected: SelectedContext | undefined, references: IGenAIContextObject[]): string;
9
9
  //# sourceMappingURL=useContextChangeAnnouncement.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useContextChangeAnnouncement.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useContextChangeAnnouncement.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAmB1D;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,mBAAmB,EAAE,GAAG,MAAM,CAwBtF"}
1
+ {"version":3,"file":"useContextChangeAnnouncement.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useContextChangeAnnouncement.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAmBhF;;;;;GAKG;AACH,wBAAgB,4BAA4B,CACxC,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,UAAU,EAAE,mBAAmB,EAAE,GAClC,MAAM,CA6BR"}
@@ -22,24 +22,29 @@ const ANNOUNCEMENT_DELAY = 250;
22
22
  * nothing is left.
23
23
  * @internal
24
24
  */
25
- export function useContextChangeAnnouncement(references) {
25
+ export function useContextChangeAnnouncement(selected, references) {
26
26
  const intl = useIntl();
27
27
  const [announcement, setAnnouncement] = useState("");
28
28
  const previousReferences = useRef(null);
29
29
  useEffect(() => {
30
30
  const previous = previousReferences.current;
31
- previousReferences.current = references;
31
+ const all = [
32
+ ...(selected?.activated && selected.dashboard ? [selected.dashboard] : []),
33
+ ...(selected?.activated && selected.visualization ? [selected.visualization] : []),
34
+ ...references,
35
+ ];
36
+ previousReferences.current = all;
32
37
  if (previous === null) {
33
38
  return undefined;
34
39
  }
35
- const message = getAnnouncement(previous, references, intl);
40
+ const message = getAnnouncement(previous, all, intl);
36
41
  if (!message) {
37
42
  return undefined;
38
43
  }
39
44
  setAnnouncement("");
40
45
  const timeout = setTimeout(() => setAnnouncement(message), ANNOUNCEMENT_DELAY);
41
46
  return () => clearTimeout(timeout);
42
- }, [references, intl]);
47
+ }, [references, intl, selected]);
43
48
  return announcement;
44
49
  }
45
50
  function getAnnouncement(previous, current, intl) {
@@ -1,6 +1,6 @@
1
- import { type IGenAIUserContext } from "@gooddata/sdk-model";
2
- import { type IGenAIContextObject } from "../../types.js";
3
- export declare function useContextItems(ambient: IGenAIUserContext | undefined, active: IGenAIUserContext | undefined): {
1
+ import { type IGenAIUserContext, type ObjRef } from "@gooddata/sdk-model";
2
+ import { type IGenAIContextObject, type SelectedContext } from "../../types.js";
3
+ export declare function useUserContextItems(ambientContext: IGenAIUserContext | undefined, selectedContext: SelectedContext | undefined, activeContext: IGenAIUserContext | undefined): {
4
4
  items: IGenAIContextObject[];
5
5
  search: string;
6
6
  setSearch: (value: string) => void;
@@ -8,4 +8,10 @@ export declare function useContextItems(ambient: IGenAIUserContext | undefined,
8
8
  hasNextPage: boolean;
9
9
  loadNextPage: () => void;
10
10
  };
11
+ export declare function useAmbientContextItems(ambientContext: IGenAIUserContext | undefined): {
12
+ items: IGenAIContextObject[];
13
+ search: string;
14
+ setSearch: (value: string) => void;
15
+ selectedIds: ObjRef[];
16
+ };
11
17
  //# sourceMappingURL=useContextItems.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useContextItems.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useContextItems.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,iBAAiB,EAAmB,MAAM,qBAAqB,CAAC;AAc9E,OAAO,EAIH,KAAK,mBAAmB,EAC3B,MAAM,gBAAgB,CAAC;AAExB,wBAAgB,eAAe,CAC3B,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,MAAM,EAAE,iBAAiB,GAAG,SAAS;;;;;;;EAqExC"}
1
+ {"version":3,"file":"useContextItems.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useContextItems.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,MAAM,EAAmB,MAAM,qBAAqB,CAAC;AAe3F,OAAO,EAIH,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACvB,MAAM,gBAAgB,CAAC;AAExB,wBAAgB,mBAAmB,CAC/B,cAAc,EAAE,iBAAiB,GAAG,SAAS,EAC7C,eAAe,EAAE,eAAe,GAAG,SAAS,EAC5C,aAAa,EAAE,iBAAiB,GAAG,SAAS;;;;;;;EA8E/C;AAED,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,iBAAiB,GAAG,SAAS;;;;;EA0CnF"}
@@ -4,9 +4,9 @@ import { useIntl } from "react-intl";
4
4
  import { useDispatch, useSelector } from "react-redux";
5
5
  import { serializeObjRef } from "@gooddata/sdk-model";
6
6
  import { collectAvailableReferences, collectContextReferences, } from "../../context/collectContextReferences.js";
7
- import { contextObjectsSearchSelector, contextObjectsSelector, } from "../../store/chatWindow/chatWindowSelectors.js";
7
+ import { contextObjectsSearchSelector, contextObjectsSelector, selectedContextSelector, } from "../../store/chatWindow/chatWindowSelectors.js";
8
8
  import { loadContextObjectsNextPageAction, setContextObjectsSearchAction, } from "../../store/chatWindow/chatWindowSlice.js";
9
- export function useContextItems(ambient, active) {
9
+ export function useUserContextItems(ambientContext, selectedContext, activeContext) {
10
10
  const intl = useIntl();
11
11
  const dispatch = useDispatch();
12
12
  const emptyReferenceLabel = intl.formatMessage({ id: "gd.gen-ai.context.untitled" });
@@ -16,10 +16,9 @@ export function useContextItems(ambient, active) {
16
16
  const visualizations = contextObjects.visualization;
17
17
  const items = useMemo(() => {
18
18
  const matchesSearch = titleMatcher(search);
19
- const ambientReferences = collectAvailableReferences(ambient, emptyReferenceLabel).filter(matchesSearch);
20
- const selectedReferences = collectContextReferences(active, emptyReferenceLabel);
19
+ const selectedReferences = collectContextReferences(activeContext, selectedContext, emptyReferenceLabel);
21
20
  const offered = new Set();
22
- collectAvailableReferences(ambient, emptyReferenceLabel).forEach((reference) => {
21
+ collectAvailableReferences(ambientContext, emptyReferenceLabel).forEach((reference) => {
23
22
  offered.add(serializeObjRef(reference.ref));
24
23
  if (reference.insightRef) {
25
24
  offered.add(serializeObjRef(reference.insightRef));
@@ -29,8 +28,16 @@ export function useContextItems(ambient, active) {
29
28
  ...searchable(dashboards, "dashboard", emptyReferenceLabel, matchesSearch),
30
29
  ...searchable(visualizations, "visualization", emptyReferenceLabel, matchesSearch),
31
30
  ].filter((reference) => !offered.has(serializeObjRef(reference.ref)));
32
- return [...ambientReferences, ...workspaceReferences].filter((reference) => !selectedReferences.some((selectedReference) => isSameObject(selectedReference, reference)));
33
- }, [active, ambient, dashboards, visualizations, emptyReferenceLabel, search]);
31
+ return workspaceReferences.filter((reference) => !selectedReferences.some((selectedReference) => isSameObject(selectedReference, reference)));
32
+ }, [
33
+ search,
34
+ ambientContext,
35
+ emptyReferenceLabel,
36
+ activeContext,
37
+ selectedContext,
38
+ dashboards,
39
+ visualizations,
40
+ ]);
34
41
  const setSearch = useCallback((value) => {
35
42
  if (value === search) {
36
43
  return;
@@ -57,8 +64,44 @@ export function useContextItems(ambient, active) {
57
64
  loadNextPage,
58
65
  };
59
66
  }
67
+ export function useAmbientContextItems(ambientContext) {
68
+ const intl = useIntl();
69
+ const dispatch = useDispatch();
70
+ const emptyReferenceLabel = intl.formatMessage({ id: "gd.gen-ai.context.untitled" });
71
+ const thisDashboardLabel = intl.formatMessage({ id: "gd.gen-ai.context.this" });
72
+ const search = useSelector(contextObjectsSearchSelector);
73
+ const selected = useSelector(selectedContextSelector);
74
+ const items = useMemo(() => {
75
+ const matchesSearch = titleMatcher(search);
76
+ return collectAvailableReferences(ambientContext, emptyReferenceLabel)
77
+ .map((item) => {
78
+ if (item.type === "dashboard") {
79
+ return {
80
+ ...item,
81
+ title: thisDashboardLabel,
82
+ };
83
+ }
84
+ return item;
85
+ })
86
+ .filter(matchesSearch);
87
+ }, [search, ambientContext, emptyReferenceLabel, thisDashboardLabel]);
88
+ const setSearch = useCallback((value) => {
89
+ if (value === search) {
90
+ return;
91
+ }
92
+ dispatch(setContextObjectsSearchAction({ search: value }));
93
+ }, [dispatch, search]);
94
+ return {
95
+ items,
96
+ search,
97
+ setSearch,
98
+ selectedIds: [
99
+ selected?.visualization?.ref ? selected?.visualization?.ref : selected?.dashboard?.ref,
100
+ ].filter(Boolean),
101
+ };
102
+ }
60
103
  function titleMatcher(search) {
61
- const normalized = search.trim().toLowerCase();
104
+ const normalized = (search || "").trim().toLowerCase();
62
105
  return normalized ? (reference) => reference.title.toLowerCase().includes(normalized) : () => true;
63
106
  }
64
107
  function searchable(list, type, emptyReferenceLabel, matchesSearch) {
@@ -1,5 +1,3 @@
1
- import { type IGenAIUserContext } from "@gooddata/sdk-model";
2
1
  import { type IGenAIContextObject, type StoreContext } from "../types.js";
3
2
  export declare function addContextReference(context: StoreContext, reference?: IGenAIContextObject): StoreContext;
4
- export declare function addAmbientContextReferences(context: StoreContext, userContext?: IGenAIUserContext): StoreContext;
5
3
  //# sourceMappingURL=addContextReference.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"addContextReference.d.ts","sourceRoot":"","sources":["../../src/context/addContextReference.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,iBAAiB,EAEzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAO1E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,mBAAmB,GAAG,YAAY,CA+DxG;AAUD,wBAAgB,2BAA2B,CACvC,OAAO,EAAE,YAAY,EACrB,WAAW,CAAC,EAAE,iBAAiB,GAChC,YAAY,CAkBd"}
1
+ {"version":3,"file":"addContextReference.d.ts","sourceRoot":"","sources":["../../src/context/addContextReference.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAG1E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,mBAAmB,GAAG,YAAY,CA6DxG"}
@@ -1,27 +1,22 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { areObjRefsEqual, } from "@gooddata/sdk-model";
2
+ import { areObjRefsEqual } from "@gooddata/sdk-model";
3
3
  import { convertGenAiTypeToReferenceType } from "../utils.js";
4
- import { mergeContexts } from "./build.js";
5
- import { isReferenceChanged } from "./isReferenceChanged.js";
6
- import { removeAmbientContribution, removeReferencesCoveredByAmbient } from "./removeContextReference.js";
7
4
  export function addContextReference(context, reference) {
8
- const { ambient, active } = context;
5
+ const { active } = context;
9
6
  if (!reference) {
10
7
  return context;
11
8
  }
12
- if (reference.where === "view.dashboard" && ambient?.view?.dashboard) {
13
- const ambientDashboard = ambient.view.dashboard;
14
- if (areObjRefsEqual(ambientDashboard.ref, reference.ref)) {
15
- return {
16
- ...context,
17
- active: {
18
- ...active,
19
- view: {
20
- dashboard: ambientDashboard,
21
- },
9
+ if (reference.where === "view.dashboard") {
10
+ return {
11
+ ...context,
12
+ active: {
13
+ ...active,
14
+ view: {
15
+ ...active?.view,
16
+ dashboard: context.ambient?.view?.dashboard,
22
17
  },
23
- };
24
- }
18
+ },
19
+ };
25
20
  }
26
21
  if (reference.where === "referencedObjects") {
27
22
  const refContext = reference.context;
@@ -59,21 +54,3 @@ export function addContextReference(context, reference) {
59
54
  }
60
55
  return context;
61
56
  }
62
- function pruneForNewAmbient(active, previousAmbient, newAmbient) {
63
- return removeReferencesCoveredByAmbient(removeAmbientContribution(active, previousAmbient), newAmbient);
64
- }
65
- export function addAmbientContextReferences(context, userContext) {
66
- const referenceChanged = isReferenceChanged(context.ambient, userContext);
67
- const updateActive = Boolean(!context.ambient || context.active?.view?.dashboard || referenceChanged);
68
- return {
69
- ...context,
70
- ambient: userContext,
71
- ...(updateActive
72
- ? {
73
- active: mergeContexts(referenceChanged
74
- ? pruneForNewAmbient(context.active, context.ambient, userContext)
75
- : context.active, userContext),
76
- }
77
- : {}),
78
- };
79
- }
@@ -1,5 +1,5 @@
1
1
  import { type IGenAIUserContext } from "@gooddata/sdk-model";
2
- import { type IGenAIContextObject } from "../types.js";
3
- export declare function collectContextReferences(context: IGenAIUserContext | undefined, placeholderTitle?: string): IGenAIContextObject[];
2
+ import { type IGenAIContextObject, type SelectedContext } from "../types.js";
3
+ export declare function collectContextReferences(userContext: IGenAIUserContext | undefined, selectedContext: SelectedContext | undefined, placeholderTitle?: string): IGenAIContextObject[];
4
4
  export declare function collectAvailableReferences(context: IGenAIUserContext | undefined, placeholderTitle?: string): IGenAIContextObject[];
5
5
  //# sourceMappingURL=collectContextReferences.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collectContextReferences.d.ts","sourceRoot":"","sources":["../../src/context/collectContextReferences.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,iBAAiB,EAGzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGvD,wBAAgB,wBAAwB,CACpC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,gBAAgB,CAAC,EAAE,MAAM,GAC1B,mBAAmB,EAAE,CAwCvB;AAED,wBAAgB,0BAA0B,CACtC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,gBAAgB,CAAC,EAAE,MAAM,GAC1B,mBAAmB,EAAE,CAuFvB"}
1
+ {"version":3,"file":"collectContextReferences.d.ts","sourceRoot":"","sources":["../../src/context/collectContextReferences.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,iBAAiB,EAIzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAG7E,wBAAgB,wBAAwB,CACpC,WAAW,EAAE,iBAAiB,GAAG,SAAS,EAC1C,eAAe,EAAE,eAAe,GAAG,SAAS,EAC5C,gBAAgB,CAAC,EAAE,MAAM,GAC1B,mBAAmB,EAAE,CA0CvB;AAED,wBAAgB,0BAA0B,CACtC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,gBAAgB,CAAC,EAAE,MAAM,GAC1B,mBAAmB,EAAE,CAuFvB"}
@@ -1,31 +1,33 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { isIdentifierRef, serializeObjRef, } from "@gooddata/sdk-model";
2
+ import { areObjRefsEqual, isIdentifierRef, serializeObjRef, } from "@gooddata/sdk-model";
3
3
  import { convertReferenceTypeToGenAiType } from "../utils.js";
4
- export function collectContextReferences(context, placeholderTitle) {
5
- if (!context) {
6
- return [];
7
- }
8
- const references = [];
4
+ export function collectContextReferences(userContext, selectedContext, placeholderTitle) {
5
+ const userReferences = [];
9
6
  // dashboard
10
- const dashboard = context.view?.dashboard;
11
- if (dashboard) {
12
- const ref = dashboard.ref;
7
+ const userDashboard = userContext?.view?.dashboard;
8
+ if (userDashboard) {
9
+ const ref = userDashboard.ref;
13
10
  const id = isIdentifierRef(ref) ? ref.identifier : ref.uri;
14
- references.push({
15
- id,
16
- ref,
17
- type: "dashboard",
18
- where: "view.dashboard",
19
- title: dashboard.title || placeholderTitle || id,
20
- nesting: 0,
21
- });
11
+ if (!areObjRefsEqual(ref, selectedContext?.dashboard?.ref)) {
12
+ userReferences.push({
13
+ id,
14
+ ref,
15
+ nesting: 0,
16
+ type: "dashboard",
17
+ where: "view.dashboard",
18
+ title: userDashboard.title || placeholderTitle || id,
19
+ });
20
+ }
22
21
  }
23
22
  // references
24
- context.referencedObjects?.forEach((obj) => {
23
+ userContext?.referencedObjects?.forEach((obj) => {
24
+ if (areObjRefsEqual(obj.context?.ref, selectedContext?.dashboard?.ref)) {
25
+ return;
26
+ }
25
27
  obj.objects.forEach((item) => {
26
28
  const ref = item.ref;
27
29
  const id = isIdentifierRef(ref) ? ref.identifier : ref.uri;
28
- references.push({
30
+ userReferences.push({
29
31
  id,
30
32
  ref,
31
33
  nesting: 1,
@@ -35,7 +37,7 @@ export function collectContextReferences(context, placeholderTitle) {
35
37
  });
36
38
  });
37
39
  });
38
- return references.sort((a, b) => a.nesting - b.nesting);
40
+ return userReferences.sort((a, b) => a.nesting - b.nesting);
39
41
  }
40
42
  export function collectAvailableReferences(context, placeholderTitle) {
41
43
  if (!context) {