@gooddata/sdk-ui-gen-ai 11.53.0-alpha.1 → 11.53.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/components/GenAiChatContextChooser.d.ts.map +1 -1
- package/esm/components/GenAiChatContextChooser.js +9 -11
- package/esm/components/GenAiChatContextChooserBody.d.ts +17 -0
- package/esm/components/GenAiChatContextChooserBody.d.ts.map +1 -0
- package/esm/components/GenAiChatContextChooserBody.js +82 -0
- package/esm/components/hooks/useContextItems.d.ts +1 -4
- package/esm/components/hooks/useContextItems.d.ts.map +1 -1
- package/esm/components/hooks/useContextItems.js +1 -22
- package/esm/components/intelligence/data/categoryDetailRows.d.ts.map +1 -1
- package/esm/components/intelligence/data/categoryDetailRows.js +90 -7
- package/esm/components/intelligence/data/deriveInteractionIntelligenceFromSteps.d.ts +2 -0
- package/esm/components/intelligence/data/deriveInteractionIntelligenceFromSteps.d.ts.map +1 -1
- package/esm/components/intelligence/data/deriveInteractionIntelligenceFromSteps.js +12 -0
- package/esm/components/intelligence/data/mergeDetailRows.d.ts +3 -1
- package/esm/components/intelligence/data/mergeDetailRows.d.ts.map +1 -1
- package/esm/components/intelligence/data/mergeDetailRows.js +66 -2
- package/esm/components/intelligence/data/types.d.ts +6 -1
- package/esm/components/intelligence/data/types.d.ts.map +1 -1
- package/esm/components/intelligence/detail/DetailRowValue.js +1 -1
- package/esm/components/intelligence/panel/IntelligenceCategoryRow.d.ts +2 -2
- package/esm/components/intelligence/panel/IntelligenceCategoryRow.d.ts.map +1 -1
- package/esm/components/intelligence/panel/IntelligenceCategoryRow.js +3 -3
- package/esm/localization/bundles/en-US.localization-bundle.d.ts +68 -0
- package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/localization/bundles/en-US.localization-bundle.js +68 -0
- package/esm/store/messages/messagesSelectors.d.ts.map +1 -1
- package/esm/store/messages/messagesSelectors.js +5 -1
- package/esm/store/messages/messagesSlice.d.ts +5 -1
- package/esm/store/messages/messagesSlice.d.ts.map +1 -1
- package/esm/store/messages/messagesSlice.js +14 -2
- package/esm/store/sideEffects/onUserMessage.d.ts.map +1 -1
- package/esm/store/sideEffects/onUserMessage.js +14 -1
- package/esm/types.d.ts +5 -0
- package/esm/types.d.ts.map +1 -1
- package/package.json +20 -20
- package/styles/css/main.css +42 -0
- package/styles/css/main.css.map +1 -1
- package/styles/scss/main.scss +33 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GenAiChatContextChooser.d.ts","sourceRoot":"","sources":["../../src/components/GenAiChatContextChooser.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"GenAiChatContextChooser.d.ts","sourceRoot":"","sources":["../../src/components/GenAiChatContextChooser.tsx"],"names":[],"mappings":"AAUA,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,kDAoDxF"}
|
|
@@ -2,9 +2,10 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
// (C) 2026 GoodData Corporation
|
|
3
3
|
import { defineMessages, useIntl } from "react-intl";
|
|
4
4
|
import { useDispatch, useSelector } from "react-redux";
|
|
5
|
-
import { Dropdown, UiIconButton,
|
|
5
|
+
import { Dropdown, UiIconButton, useIdPrefixed } from "@gooddata/sdk-ui-kit";
|
|
6
6
|
import { ambientContextSelector, userContextSelector } from "../store/chatWindow/chatWindowSelectors.js";
|
|
7
7
|
import { addContextReferenceAction } from "../store/chatWindow/chatWindowSlice.js";
|
|
8
|
+
import { GenAiChatContextChooserBody } from "./GenAiChatContextChooserBody.js";
|
|
8
9
|
import { useContextItems } from "./hooks/useContextItems.js";
|
|
9
10
|
const msgs = defineMessages({
|
|
10
11
|
add: {
|
|
@@ -14,22 +15,19 @@ const msgs = defineMessages({
|
|
|
14
15
|
export function GenAiChatContextChooser({ onAddContext }) {
|
|
15
16
|
const intl = useIntl();
|
|
16
17
|
const dispatch = useDispatch();
|
|
18
|
+
const titleId = useIdPrefixed("context-chooser-title");
|
|
17
19
|
const ambient = useSelector((state) => ambientContextSelector(state));
|
|
18
20
|
const active = useSelector((state) => userContextSelector(state));
|
|
19
|
-
const
|
|
21
|
+
const inputItems = useContextItems(ambient, active);
|
|
22
|
+
const addContextLabel = intl.formatMessage(msgs.add);
|
|
20
23
|
if (!ambient) {
|
|
21
24
|
return null;
|
|
22
25
|
}
|
|
23
26
|
return (_jsx("div", { className: "gd-gen-ai-chat__input__context", children: _jsx(Dropdown, { alignPoints: [{ align: "tl bl", offset: { x: 0, y: 0 } }], closeOnEscape: true, fullscreenOnMobile: false, autofocusOnOpen: true, accessibilityConfig: {}, renderButton: ({ isOpen, toggleDropdown, accessibilityConfig }) => (_jsx(UiIconButton, { icon: "plus", variant: "tertiary", size: "small", dataTestId: "choose_context", isActive: isOpen, accessibilityConfig: {
|
|
24
27
|
...accessibilityConfig,
|
|
25
|
-
ariaLabel:
|
|
26
|
-
}, onClick: toggleDropdown, isDisabled: !
|
|
27
|
-
dispatch(addContextReferenceAction({ object: item
|
|
28
|
-
onAddContext?.(item
|
|
29
|
-
closeDropdown();
|
|
28
|
+
ariaLabel: addContextLabel,
|
|
29
|
+
}, onClick: toggleDropdown, isDisabled: !inputItems.length })), renderBody: ({ closeDropdown, ariaAttributes }) => (_jsx(GenAiChatContextChooserBody, { inputItems: inputItems, title: addContextLabel, titleId: titleId, ariaAttributes: ariaAttributes, closeDropdown: closeDropdown, onSelect: (item) => {
|
|
30
|
+
dispatch(addContextReferenceAction({ object: item }));
|
|
31
|
+
onAddContext?.(item);
|
|
30
32
|
} })) }) }));
|
|
31
33
|
}
|
|
32
|
-
function ContextMenuHeader() {
|
|
33
|
-
const intl = useIntl();
|
|
34
|
-
return _jsx(UiSubmenuHeader, { title: intl.formatMessage(msgs.add), height: "medium" });
|
|
35
|
-
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type IGenAIContextObject } from "../types.js";
|
|
2
|
+
type GenAiChatContextChooserBodyProps = {
|
|
3
|
+
inputItems: IGenAIContextObject[];
|
|
4
|
+
title: string;
|
|
5
|
+
titleId: string;
|
|
6
|
+
isLoading?: boolean;
|
|
7
|
+
ariaAttributes: {
|
|
8
|
+
id: string;
|
|
9
|
+
role?: string;
|
|
10
|
+
"aria-labelledby"?: string;
|
|
11
|
+
};
|
|
12
|
+
onSelect: (item: IGenAIContextObject) => void;
|
|
13
|
+
closeDropdown: () => void;
|
|
14
|
+
};
|
|
15
|
+
export declare function GenAiChatContextChooserBody({ inputItems, title, titleId, isLoading, ariaAttributes, onSelect, closeDropdown }: GenAiChatContextChooserBodyProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=GenAiChatContextChooserBody.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GenAiChatContextChooserBody.d.ts","sourceRoot":"","sources":["../../src/components/GenAiChatContextChooserBody.tsx"],"names":[],"mappings":"AAsBA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AA6BvD,KAAK,gCAAgC,GAAG;IACpC,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,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,SAAiB,EACjB,cAAc,EACd,QAAQ,EACR,aAAa,EAChB,EAAE,gCAAgC,2CA+HlC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// (C) 2026 GoodData Corporation
|
|
3
|
+
import { useCallback, useId, useMemo, useState } from "react";
|
|
4
|
+
import cx from "classnames";
|
|
5
|
+
import { defineMessages, useIntl } from "react-intl";
|
|
6
|
+
import { DEFAULT_ITEM_HEIGHT, DETAILED_ANNOUNCEMENT_THRESHOLD, Input, NoData, ScopedIdStore, ShortenedText, UiIcon, UiPagedVirtualList, UiSearchResultsAnnouncement, UiSubmenuHeader, isTypingKey, useScopedIdStoreValue, } from "@gooddata/sdk-ui-kit";
|
|
7
|
+
import { getIconByType } from "./utils/icons.js";
|
|
8
|
+
const SEARCH_FIELD_VISIBILITY_THRESHOLD = 7;
|
|
9
|
+
const MAX_VISIBLE_ITEMS = 7;
|
|
10
|
+
const LOADING_SKELETON_ITEMS_COUNT = 3;
|
|
11
|
+
const msgs = defineMessages({
|
|
12
|
+
close: {
|
|
13
|
+
id: "gd.gen-ai.context.close",
|
|
14
|
+
},
|
|
15
|
+
listAriaLabel: {
|
|
16
|
+
id: "gd.gen-ai.context.list.ariaLabel",
|
|
17
|
+
},
|
|
18
|
+
searchPlaceholder: {
|
|
19
|
+
id: "gd.gen-ai.context.search.placeholder",
|
|
20
|
+
},
|
|
21
|
+
searchAriaLabel: {
|
|
22
|
+
id: "gd.gen-ai.context.search.ariaLabel",
|
|
23
|
+
},
|
|
24
|
+
noMatchingData: {
|
|
25
|
+
id: "gd.gen-ai.context.noMatchingData",
|
|
26
|
+
},
|
|
27
|
+
noDataAvailable: {
|
|
28
|
+
id: "gd.gen-ai.context.noDataAvailable",
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
export function GenAiChatContextChooserBody({ inputItems, title, titleId, isLoading = false, ariaAttributes, onSelect, closeDropdown, }) {
|
|
32
|
+
const intl = useIntl();
|
|
33
|
+
const listboxId = useId();
|
|
34
|
+
const [searchString, setSearchString] = useState("");
|
|
35
|
+
const isSearchFieldVisible = inputItems.length > SEARCH_FIELD_VISIBILITY_THRESHOLD && !isLoading;
|
|
36
|
+
const searchStringToUse = isSearchFieldVisible ? searchString : "";
|
|
37
|
+
const normalizedSearch = searchStringToUse.trim().toLowerCase();
|
|
38
|
+
const filteredItems = useMemo(() => {
|
|
39
|
+
if (!normalizedSearch) {
|
|
40
|
+
return inputItems;
|
|
41
|
+
}
|
|
42
|
+
return inputItems.filter((item) => item.title.toLowerCase().includes(normalizedSearch));
|
|
43
|
+
}, [inputItems, normalizedSearch]);
|
|
44
|
+
const scopedIdStoreValue = useScopedIdStoreValue((item) => `${item.type}-${item.id}`);
|
|
45
|
+
const handleSelect = useCallback((item) => {
|
|
46
|
+
onSelect(item);
|
|
47
|
+
closeDropdown();
|
|
48
|
+
}, [closeDropdown, onSelect]);
|
|
49
|
+
const hasNoData = !isLoading && filteredItems.length === 0;
|
|
50
|
+
const hasNoMatchingData = hasNoData && normalizedSearch.length > 0;
|
|
51
|
+
const searchFilled = searchString.length > 0;
|
|
52
|
+
const onEscKeyPress = useCallback((event) => {
|
|
53
|
+
if (searchFilled) {
|
|
54
|
+
event.stopPropagation();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
closeDropdown();
|
|
58
|
+
}
|
|
59
|
+
}, [closeDropdown, searchFilled]);
|
|
60
|
+
const listMaxHeight = Math.min(Math.max(filteredItems.length, 1), MAX_VISIBLE_ITEMS) * DEFAULT_ITEM_HEIGHT;
|
|
61
|
+
return (_jsxs("div", { ...ariaAttributes, "aria-labelledby": titleId, className: "gd-gen-ai-chat__context-chooser", "data-testid": "context_chooser_menu", children: [
|
|
62
|
+
_jsx(UiSubmenuHeader, { title: title, titleId: titleId, height: "medium", onClose: closeDropdown, closeAriaLabel: intl.formatMessage(msgs.close) }), isSearchFieldVisible ? (_jsxs(_Fragment, { children: [
|
|
63
|
+
_jsx("div", { onKeyDown: (event) => {
|
|
64
|
+
if (isTypingKey(event)) {
|
|
65
|
+
event.stopPropagation();
|
|
66
|
+
}
|
|
67
|
+
}, children: _jsx(Input, { className: cx("gd-list-searchfield", "gd-flex-item"), value: searchStringToUse, onChange: (value) => setSearchString(String(value)), onEscKeyPress: onEscKeyPress, placeholder: intl.formatMessage(msgs.searchPlaceholder), autofocus: true, clearOnEsc: true, isSearch: true, isSmall: true, type: "search", accessibilityConfig: {
|
|
68
|
+
ariaLabel: intl.formatMessage(msgs.searchAriaLabel),
|
|
69
|
+
ariaControls: listboxId,
|
|
70
|
+
} }) }), _jsx(UiSearchResultsAnnouncement, { totalResults: normalizedSearch ? filteredItems.length : undefined, resultValues: filteredItems.length <= DETAILED_ANNOUNCEMENT_THRESHOLD
|
|
71
|
+
? filteredItems.map((item) => item.title)
|
|
72
|
+
: undefined })
|
|
73
|
+
] })) : null, hasNoData ? (_jsx(NoData, { hasNoMatchingData: hasNoMatchingData, notFoundLabel: intl.formatMessage(msgs.noMatchingData), noDataLabel: intl.formatMessage(msgs.noDataAvailable) })) : (_jsx(ScopedIdStore, { value: scopedIdStoreValue, children: _jsx(UiPagedVirtualList, { maxHeight: listMaxHeight, items: filteredItems, itemHeight: DEFAULT_ITEM_HEIGHT, itemsGap: 0, itemPadding: 0, skeletonItemsCount: isLoading ? LOADING_SKELETON_ITEMS_COUNT : 0, isLoading: isLoading, representAs: "listbox", closeDropdown: closeDropdown, onKeyDownConfirm: handleSelect, listboxProps: {
|
|
74
|
+
id: listboxId,
|
|
75
|
+
"aria-label": intl.formatMessage(msgs.listAriaLabel),
|
|
76
|
+
}, children: (item) => _jsx(ContextChooserItem, { item: item, onSelect: () => handleSelect(item) }) }) }))] }));
|
|
77
|
+
}
|
|
78
|
+
function ContextChooserItem({ item, onSelect }) {
|
|
79
|
+
const icon = getIconByType(item.type);
|
|
80
|
+
return (_jsxs("div", { className: "gd-list-item", title: item.title, onClick: onSelect, children: [icon.iconBefore ? _jsx(UiIcon, { size: 16, type: icon.iconBefore, color: icon.iconColor }) : null, _jsx(ShortenedText, { ellipsisPosition: "end", children: item.title })
|
|
81
|
+
] }));
|
|
82
|
+
}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { type IGenAIUserContext } from "@gooddata/sdk-model";
|
|
2
|
-
import { type IUiMenuItem } from "@gooddata/sdk-ui-kit";
|
|
3
2
|
import { type IGenAIContextObject } from "../../types.js";
|
|
4
|
-
export declare function useContextItems(ambient: IGenAIUserContext | undefined, active: IGenAIUserContext | undefined):
|
|
5
|
-
interactive: IGenAIContextObject;
|
|
6
|
-
}>[];
|
|
3
|
+
export declare function useContextItems(ambient: IGenAIUserContext | undefined, active: IGenAIUserContext | undefined): IGenAIContextObject[];
|
|
7
4
|
//# sourceMappingURL=useContextItems.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useContextItems.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useContextItems.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"useContextItems.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useContextItems.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAM7D,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,wBAAgB,eAAe,CAC3B,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,MAAM,EAAE,iBAAiB,GAAG,SAAS,GACtC,mBAAmB,EAAE,CAgBvB"}
|
|
@@ -1,34 +1,13 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
1
|
// (C) 2026 GoodData Corporation
|
|
3
2
|
import { useMemo } from "react";
|
|
4
3
|
import { useIntl } from "react-intl";
|
|
5
|
-
import { UiIcon } from "@gooddata/sdk-ui-kit";
|
|
6
4
|
import { collectAvailableReferences, collectContextReferences, } from "../../context/collectContextReferences.js";
|
|
7
|
-
import { getIconByType } from "../utils/icons.js";
|
|
8
5
|
export function useContextItems(ambient, active) {
|
|
9
6
|
const intl = useIntl();
|
|
10
7
|
const emptyReferenceLabel = intl.formatMessage({ id: "gd.gen-ai.context.untitled" });
|
|
11
8
|
return useMemo(() => {
|
|
12
|
-
const items = [];
|
|
13
9
|
const currentReferences = collectAvailableReferences(ambient, emptyReferenceLabel);
|
|
14
10
|
const selectedReferences = collectContextReferences(active, emptyReferenceLabel);
|
|
15
|
-
currentReferences.
|
|
16
|
-
const isSelected = selectedReferences.some((selectedReference) => selectedReference.id === reference.id && selectedReference.type === reference.type);
|
|
17
|
-
if (!isSelected) {
|
|
18
|
-
const icon = getIconByType(reference.type);
|
|
19
|
-
items.push({
|
|
20
|
-
type: "interactive",
|
|
21
|
-
id: reference.id,
|
|
22
|
-
data: reference,
|
|
23
|
-
stringTitle: reference.title,
|
|
24
|
-
...(icon.iconBefore
|
|
25
|
-
? {
|
|
26
|
-
iconLeft: _jsx(UiIcon, { size: 16, type: icon.iconBefore, color: icon.iconColor }),
|
|
27
|
-
}
|
|
28
|
-
: {}),
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
return items;
|
|
11
|
+
return currentReferences.filter((reference) => !selectedReferences.some((selectedReference) => selectedReference.id === reference.id && selectedReference.type === reference.type));
|
|
33
12
|
}, [active, ambient, emptyReferenceLabel]);
|
|
34
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categoryDetailRows.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/categoryDetailRows.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"categoryDetailRows.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/categoryDetailRows.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAKR,2BAA2B,EAI9B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,KAAK,EACR,mCAAmC,EAEnC,yBAAyB,EAC5B,MAAM,YAAY,CAAC;AAiDpB;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,2BAA2B,GAAG,mCAAmC,EAAE,CAmB3G;AAqED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,MAAM,EAAE,2BAA2B,GAAG,yBAAyB,EAAE,CAmB9F"}
|
|
@@ -27,6 +27,10 @@ const MESSAGES = defineMessages({
|
|
|
27
27
|
searched: { id: "gd.gen-ai.interactionIntelligence.detail.searched" },
|
|
28
28
|
found: { id: "gd.gen-ai.interactionIntelligence.detail.found" },
|
|
29
29
|
used: { id: "gd.gen-ai.interactionIntelligence.detail.used" },
|
|
30
|
+
useAlways: { id: "gd.gen-ai.interactionIntelligence.detail.useAlways" },
|
|
31
|
+
useWhenRelevant: { id: "gd.gen-ai.interactionIntelligence.detail.useWhenRelevant" },
|
|
32
|
+
appliedInTotal: { id: "gd.gen-ai.interactionIntelligence.detail.appliedInTotal" },
|
|
33
|
+
memoriesCount: { id: "gd.gen-ai.interactionIntelligence.detail.memoriesCount" },
|
|
30
34
|
skillsCount: { id: "gd.gen-ai.interactionIntelligence.detail.skillsCount" },
|
|
31
35
|
foundGroup: { id: "gd.gen-ai.interactionIntelligence.detail.foundGroup" },
|
|
32
36
|
matchScore: { id: "gd.gen-ai.interactionIntelligence.detail.matchScore" },
|
|
@@ -34,6 +38,13 @@ const MESSAGES = defineMessages({
|
|
|
34
38
|
excerptUsed: { id: "gd.gen-ai.interactionIntelligence.excerpt.used" },
|
|
35
39
|
excerptDocuments: { id: "gd.gen-ai.interactionIntelligence.excerpt.documents" },
|
|
36
40
|
excerptActivated: { id: "gd.gen-ai.interactionIntelligence.excerpt.activated" },
|
|
41
|
+
excerptMemories: { id: "gd.gen-ai.interactionIntelligence.excerpt.memories" },
|
|
42
|
+
metrics: { id: "gd.gen-ai.interactionIntelligence.detail.metrics" },
|
|
43
|
+
groupedBy: { id: "gd.gen-ai.interactionIntelligence.detail.groupedBy" },
|
|
44
|
+
filteredBy: { id: "gd.gen-ai.interactionIntelligence.detail.filteredBy" },
|
|
45
|
+
visualization: { id: "gd.gen-ai.interactionIntelligence.detail.visualization" },
|
|
46
|
+
result: { id: "gd.gen-ai.interactionIntelligence.detail.result" },
|
|
47
|
+
resultSize: { id: "gd.gen-ai.interactionIntelligence.detail.resultSize" },
|
|
37
48
|
});
|
|
38
49
|
/**
|
|
39
50
|
* The list row's right-hand excerpt for one occurrence of a category, built from the same
|
|
@@ -43,10 +54,14 @@ const MESSAGES = defineMessages({
|
|
|
43
54
|
*/
|
|
44
55
|
export function excerptForDetail(detail) {
|
|
45
56
|
switch (detail.category) {
|
|
57
|
+
case "applyMemory":
|
|
58
|
+
return applyMemoryExcerpt(detail);
|
|
46
59
|
case "catalogSearch":
|
|
47
60
|
return catalogSearchExcerpt(detail);
|
|
48
61
|
case "knowledgeSearch":
|
|
49
62
|
return knowledgeSearchExcerpt(detail);
|
|
63
|
+
case "metricQuery":
|
|
64
|
+
return metricQueryExcerpt(detail);
|
|
50
65
|
case "skillRouting":
|
|
51
66
|
return skillRoutingExcerpt(detail);
|
|
52
67
|
case "composeAnswer":
|
|
@@ -60,6 +75,9 @@ export function excerptForDetail(detail) {
|
|
|
60
75
|
function countFragment(id, count) {
|
|
61
76
|
return count > 0 ? [{ id, values: { count } }] : [];
|
|
62
77
|
}
|
|
78
|
+
function applyMemoryExcerpt(detail) {
|
|
79
|
+
return countFragment(MESSAGES.excerptMemories.id, detail.items.length);
|
|
80
|
+
}
|
|
63
81
|
function catalogSearchExcerpt(detail) {
|
|
64
82
|
const foundCount = detail.found.reduce((sum, group) => sum + group.titles.length, 0);
|
|
65
83
|
return [
|
|
@@ -70,6 +88,20 @@ function catalogSearchExcerpt(detail) {
|
|
|
70
88
|
function knowledgeSearchExcerpt(detail) {
|
|
71
89
|
return countFragment(MESSAGES.excerptDocuments.id, detail.documents.length);
|
|
72
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* The size of what a query returned, once both of its halves are known. Not keyed on `count`,
|
|
93
|
+
* which the caller would sum across occurrences — a size must not be summed.
|
|
94
|
+
*/
|
|
95
|
+
function resultSize(detail) {
|
|
96
|
+
const { resultRows, resultColumns } = detail;
|
|
97
|
+
return resultRows === undefined || resultColumns === undefined
|
|
98
|
+
? undefined
|
|
99
|
+
: { rows: resultRows, columns: resultColumns };
|
|
100
|
+
}
|
|
101
|
+
function metricQueryExcerpt(detail) {
|
|
102
|
+
const size = resultSize(detail);
|
|
103
|
+
return size ? [{ id: MESSAGES.resultSize.id, values: size }] : [];
|
|
104
|
+
}
|
|
73
105
|
function skillRoutingExcerpt(detail) {
|
|
74
106
|
return countFragment(MESSAGES.excerptActivated.id, detail.activated.length);
|
|
75
107
|
}
|
|
@@ -87,10 +119,14 @@ function composeAnswerExcerpt(detail) {
|
|
|
87
119
|
/** The category's detail rows, built from one action's detail body. */
|
|
88
120
|
export function rowsForDetail(detail) {
|
|
89
121
|
switch (detail.category) {
|
|
122
|
+
case "applyMemory":
|
|
123
|
+
return applyMemoryRows(detail);
|
|
90
124
|
case "catalogSearch":
|
|
91
125
|
return catalogSearchRows(detail);
|
|
92
126
|
case "knowledgeSearch":
|
|
93
127
|
return knowledgeSearchRows(detail);
|
|
128
|
+
case "metricQuery":
|
|
129
|
+
return metricQueryRows(detail);
|
|
94
130
|
case "skillRouting":
|
|
95
131
|
return skillRoutingRows(detail);
|
|
96
132
|
case "composeAnswer":
|
|
@@ -106,10 +142,10 @@ export function rowsForDetail(detail) {
|
|
|
106
142
|
* `text` drawn from a known/stable set (e.g. {@link ANSWER_OUTPUT_LABEL_MESSAGES}) — absent
|
|
107
143
|
* otherwise, when the text is never translated.
|
|
108
144
|
*/
|
|
109
|
-
function textRow(labelId, text, textId) {
|
|
145
|
+
function textRow(labelId, text, textId, textValues) {
|
|
110
146
|
return text === undefined || text === ""
|
|
111
147
|
? []
|
|
112
|
-
: [{ labelId, value: { kind: "text", text: String(text), textId } }];
|
|
148
|
+
: [{ labelId, value: { kind: "text", text: String(text), textId, textValues } }];
|
|
113
149
|
}
|
|
114
150
|
/**
|
|
115
151
|
* A row listing `items`, truncated past {@link MAX_DETAIL_LIST_ITEMS}, or nothing when the list
|
|
@@ -148,11 +184,24 @@ function knowledgeSearchRows(detail) {
|
|
|
148
184
|
...textRow(MESSAGES.bestMatch.id, detail.bestMatch),
|
|
149
185
|
];
|
|
150
186
|
}
|
|
187
|
+
/** A query's request and execution arrive separately, so each half builds only the rows it covers. */
|
|
188
|
+
function metricQueryRows(detail) {
|
|
189
|
+
const size = resultSize(detail);
|
|
190
|
+
return [
|
|
191
|
+
...listRow(MESSAGES.metrics.id, labels(detail.metrics)),
|
|
192
|
+
...listRow(MESSAGES.groupedBy.id, labels(detail.groupedBy)),
|
|
193
|
+
...listRow(MESSAGES.filteredBy.id, labels(detail.filteredBy)),
|
|
194
|
+
...textRow(MESSAGES.visualization.id, detail.visualization),
|
|
195
|
+
...(size ? textRow(MESSAGES.result.id, size.rows, MESSAGES.resultSize.id, size) : []),
|
|
196
|
+
];
|
|
197
|
+
}
|
|
151
198
|
function skillRoutingRows(detail) {
|
|
152
|
-
const availableCount = detail.available.length;
|
|
153
199
|
return [
|
|
154
|
-
...listRow(MESSAGES.available.id, detail.available
|
|
155
|
-
|
|
200
|
+
...listRow(MESSAGES.available.id, labels(detail.available), {
|
|
201
|
+
id: MESSAGES.skillsCount.id,
|
|
202
|
+
values: { count: detail.available.length },
|
|
203
|
+
}),
|
|
204
|
+
...listRow(MESSAGES.activated.id, labels(detail.activated)),
|
|
156
205
|
];
|
|
157
206
|
}
|
|
158
207
|
function composeAnswerRows(detail) {
|
|
@@ -165,11 +214,41 @@ function composeAnswerRows(detail) {
|
|
|
165
214
|
...textRow(MESSAGES.suggestedActions.id, detail.suggestedActions),
|
|
166
215
|
];
|
|
167
216
|
}
|
|
217
|
+
/** Counts every item it applied, but lists only the titled ones — an untitled item was still applied. */
|
|
218
|
+
function memoryStrategyRow(labelId, items) {
|
|
219
|
+
if (items.length === 0) {
|
|
220
|
+
return [];
|
|
221
|
+
}
|
|
222
|
+
const listed = items.filter((item) => item.title !== "");
|
|
223
|
+
return [
|
|
224
|
+
{
|
|
225
|
+
labelId,
|
|
226
|
+
value: {
|
|
227
|
+
kind: "list",
|
|
228
|
+
heading: MESSAGES.memoriesCount.id,
|
|
229
|
+
headingId: MESSAGES.memoriesCount.id,
|
|
230
|
+
headingValues: { count: items.length },
|
|
231
|
+
...truncate(listed.map((item) => ({ label: item.title, meta: scoreMeta(item.score) }))),
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
];
|
|
235
|
+
}
|
|
236
|
+
function applyMemoryRows(detail) {
|
|
237
|
+
const { items } = detail;
|
|
238
|
+
return [
|
|
239
|
+
...memoryStrategyRow(MESSAGES.useAlways.id, items.filter((item) => item.strategy === "always")),
|
|
240
|
+
...memoryStrategyRow(MESSAGES.useWhenRelevant.id, items.filter((item) => item.strategy === "auto")),
|
|
241
|
+
// A count with no list under it, so a text row rather than a headed empty list.
|
|
242
|
+
...textRow(MESSAGES.appliedInTotal.id, items.length || undefined, MESSAGES.memoriesCount.id, {
|
|
243
|
+
count: items.length,
|
|
244
|
+
}),
|
|
245
|
+
];
|
|
246
|
+
}
|
|
168
247
|
function catalogSearchRows(detail) {
|
|
169
248
|
const found = detail.found.filter((group) => group.titles.length > 0);
|
|
170
249
|
return [
|
|
171
250
|
...listRow(MESSAGES.query.id, detail.query.map((keyword) => ({ label: keyword }))),
|
|
172
|
-
...listRow(MESSAGES.searched.id, detail.requestedTypes
|
|
251
|
+
...listRow(MESSAGES.searched.id, labels(detail.requestedTypes)),
|
|
173
252
|
...(found.length === 0
|
|
174
253
|
? []
|
|
175
254
|
: [
|
|
@@ -186,7 +265,7 @@ function catalogSearchRows(detail) {
|
|
|
186
265
|
count: group.titles.length,
|
|
187
266
|
objectType: group.objectType,
|
|
188
267
|
},
|
|
189
|
-
...truncate(group.titles
|
|
268
|
+
...truncate(labels(group.titles)),
|
|
190
269
|
})),
|
|
191
270
|
},
|
|
192
271
|
},
|
|
@@ -194,6 +273,10 @@ function catalogSearchRows(detail) {
|
|
|
194
273
|
...listRow(MESSAGES.used.id, detail.used.map((match) => ({ label: match.title, meta: scoreMeta(match.score) }))),
|
|
195
274
|
];
|
|
196
275
|
}
|
|
276
|
+
/** Plain strings as list items. */
|
|
277
|
+
function labels(values) {
|
|
278
|
+
return values.map((label) => ({ label }));
|
|
279
|
+
}
|
|
197
280
|
/** Caps a list at {@link MAX_DETAIL_LIST_ITEMS}, reporting the remainder as `truncatedCount`. */
|
|
198
281
|
function truncate(items) {
|
|
199
282
|
if (items.length <= MAX_DETAIL_LIST_ITEMS) {
|
|
@@ -10,6 +10,8 @@ import type { IInteractionIntelligence, IInteractionIntelligenceTotals } from ".
|
|
|
10
10
|
* though its step keeps its time regardless.
|
|
11
11
|
*
|
|
12
12
|
* A tile's `index` is its array position, not the backend's `stepIndex` — it is the highlight key.
|
|
13
|
+
* A category can also come from a detail that belongs to the response rather than a step, which
|
|
14
|
+
* yields a row with no `stepIndexes` and so nothing to highlight.
|
|
13
15
|
* @internal
|
|
14
16
|
*/
|
|
15
17
|
export declare function deriveInteractionIntelligenceFromSteps(responseId: string, trace: IChatConversationResponseTrace): IInteractionIntelligence;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deriveInteractionIntelligenceFromSteps.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/deriveInteractionIntelligenceFromSteps.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AAIxE,OAAO,KAAK,EAIR,wBAAwB,EACxB,8BAA8B,EAEjC,MAAM,YAAY,CAAC;AAqBpB
|
|
1
|
+
{"version":3,"file":"deriveInteractionIntelligenceFromSteps.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/deriveInteractionIntelligenceFromSteps.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AAIxE,OAAO,KAAK,EAIR,wBAAwB,EACxB,8BAA8B,EAEjC,MAAM,YAAY,CAAC;AAqBpB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sCAAsC,CAClD,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,8BAA8B,GACtC,wBAAwB,CAgE1B;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAC/C,KAAK,EAAE,8BAA8B,GACtC,8BAA8B,CAYhC"}
|
|
@@ -24,11 +24,23 @@ const CATEGORY_LABEL_MESSAGES = defineMessages({
|
|
|
24
24
|
* though its step keeps its time regardless.
|
|
25
25
|
*
|
|
26
26
|
* A tile's `index` is its array position, not the backend's `stepIndex` — it is the highlight key.
|
|
27
|
+
* A category can also come from a detail that belongs to the response rather than a step, which
|
|
28
|
+
* yields a row with no `stepIndexes` and so nothing to highlight.
|
|
27
29
|
* @internal
|
|
28
30
|
*/
|
|
29
31
|
export function deriveInteractionIntelligenceFromSteps(responseId, trace) {
|
|
30
32
|
const sorted = [...trace.steps].sort((a, b) => a.stepIndex - b.stepIndex);
|
|
31
33
|
const byCategory = new Map();
|
|
34
|
+
// Seeded first, so a response-scoped category sorts above the steps' own — it happened before
|
|
35
|
+
// them. Its `stepIndexes` stay empty: there is no tile it ran in.
|
|
36
|
+
for (const { detail } of trace.responseDetails ?? []) {
|
|
37
|
+
if (!detail) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const entry = byCategory.get(detail.category) ?? { stepIndexes: [], details: [] };
|
|
41
|
+
byCategory.set(detail.category, entry);
|
|
42
|
+
entry.details.push(detail);
|
|
43
|
+
}
|
|
32
44
|
const steps = sorted.map((step, index) => {
|
|
33
45
|
const actions = trace.detailsByStepId[step.stepId] ?? [];
|
|
34
46
|
const categoriesInStep = [];
|
|
@@ -5,7 +5,9 @@ import type { IInteractionStepDetailRow } from "./types.js";
|
|
|
5
5
|
* across occurrences merges by value kind:
|
|
6
6
|
* - `list` rows concatenate `items` (and sum `truncatedCount`), keeping the first occurrence
|
|
7
7
|
* that authors a `heading`/`bulleted`.
|
|
8
|
-
* - `groups` rows concatenate the `groups` arrays across occurrences
|
|
8
|
+
* - `groups` rows concatenate the `groups` arrays across occurrences, then merge groups that
|
|
9
|
+
* describe the same thing (same heading key, e.g. Catalogue search's `objectType`) the same way
|
|
10
|
+
* `list` rows merge — so two steps each finding metrics render one metric group, not two.
|
|
9
11
|
* - `text` rows become a plain, unheaded `list` of each occurrence's text as one item — the same
|
|
10
12
|
* "stacked plain list" look already used for single-occurrence match lists like "Used".
|
|
11
13
|
* - Mismatched kinds across occurrences fall back to the first occurrence's row.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeDetailRows.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/mergeDetailRows.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAA8B,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAExF
|
|
1
|
+
{"version":3,"file":"mergeDetailRows.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/mergeDetailRows.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAA8B,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAExF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,yBAAyB,EAAE,EAAE,GAAG,yBAAyB,EAAE,CAcrG"}
|
|
@@ -6,7 +6,9 @@ import { MAX_DETAIL_LIST_ITEMS } from "./constants.js";
|
|
|
6
6
|
* across occurrences merges by value kind:
|
|
7
7
|
* - `list` rows concatenate `items` (and sum `truncatedCount`), keeping the first occurrence
|
|
8
8
|
* that authors a `heading`/`bulleted`.
|
|
9
|
-
* - `groups` rows concatenate the `groups` arrays across occurrences
|
|
9
|
+
* - `groups` rows concatenate the `groups` arrays across occurrences, then merge groups that
|
|
10
|
+
* describe the same thing (same heading key, e.g. Catalogue search's `objectType`) the same way
|
|
11
|
+
* `list` rows merge — so two steps each finding metrics render one metric group, not two.
|
|
10
12
|
* - `text` rows become a plain, unheaded `list` of each occurrence's text as one item — the same
|
|
11
13
|
* "stacked plain list" look already used for single-occurrence match lists like "Used".
|
|
12
14
|
* - Mismatched kinds across occurrences fall back to the first occurrence's row.
|
|
@@ -58,7 +60,7 @@ function mergeRowGroup(rows) {
|
|
|
58
60
|
labelId: first.labelId,
|
|
59
61
|
value: {
|
|
60
62
|
kind: "groups",
|
|
61
|
-
groups: rows.flatMap((row) => (row.value.kind === "groups" ? row.value.groups : [])),
|
|
63
|
+
groups: mergeGroups(rows.flatMap((row) => (row.value.kind === "groups" ? row.value.groups : []))),
|
|
62
64
|
},
|
|
63
65
|
};
|
|
64
66
|
}
|
|
@@ -75,6 +77,68 @@ function mergeRowGroup(rows) {
|
|
|
75
77
|
// Mismatched value kinds across occurrences: fall back to the first occurrence's row.
|
|
76
78
|
return first;
|
|
77
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Merges already-concatenated groups so that groups describing the same thing become one. Without
|
|
82
|
+
* this, a category running in N steps renders N separate "2 metric" groups instead of one "4
|
|
83
|
+
* metric". Groups with no resolvable key are left alone rather than pooled together, since an
|
|
84
|
+
* unkeyed group carries no evidence it describes the same thing as any other.
|
|
85
|
+
*/
|
|
86
|
+
function mergeGroups(groups) {
|
|
87
|
+
// One ordered sequence of buckets, so a group renders where it was first seen whether or not
|
|
88
|
+
// it has a key — an unkeyed group is its own bucket and holds its position among the rest.
|
|
89
|
+
const buckets = [];
|
|
90
|
+
const bucketsByKey = new Map();
|
|
91
|
+
for (const group of groups) {
|
|
92
|
+
const key = groupKey(group);
|
|
93
|
+
const existing = key === undefined ? undefined : bucketsByKey.get(key);
|
|
94
|
+
if (existing) {
|
|
95
|
+
existing.push(group);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const bucket = [group];
|
|
99
|
+
buckets.push(bucket);
|
|
100
|
+
if (key !== undefined) {
|
|
101
|
+
bucketsByKey.set(key, bucket);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return buckets.map((bucket) => {
|
|
105
|
+
const [firstGroup] = bucket;
|
|
106
|
+
if (bucket.length === 1) {
|
|
107
|
+
return firstGroup;
|
|
108
|
+
}
|
|
109
|
+
const mergedItems = mergeLists(bucket);
|
|
110
|
+
const totalCount = mergedItems.items.length + (mergedItems.truncatedCount ?? 0);
|
|
111
|
+
return {
|
|
112
|
+
...firstGroup,
|
|
113
|
+
// Restated from the merged total so the heading describes every occurrence, not the
|
|
114
|
+
// first — matching how the `list` branch restates its own heading count.
|
|
115
|
+
headingValues: firstGroup.headingValues
|
|
116
|
+
? { ...firstGroup.headingValues, count: totalCount }
|
|
117
|
+
: undefined,
|
|
118
|
+
...mergedItems,
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Identifies which groups describe the same thing. Keyed on `headingId` together with the
|
|
124
|
+
* heading's interpolated identity (e.g. Catalogue search's `objectType`), so groups from
|
|
125
|
+
* different heading types can never collide — a `headingId` with nothing to interpolate is an
|
|
126
|
+
* identity of its own. Falls back to a verbatim `heading`, and to `undefined` when a group
|
|
127
|
+
* carries no heading at all, which leaves it unmerged.
|
|
128
|
+
*/
|
|
129
|
+
function groupKey(group) {
|
|
130
|
+
const { headingId, headingValues, heading } = group;
|
|
131
|
+
if (headingId === undefined) {
|
|
132
|
+
return heading === undefined ? undefined : `heading:${JSON.stringify(heading)}`;
|
|
133
|
+
}
|
|
134
|
+
// `count` varies per occurrence by definition — it must not take part in the key. The rest
|
|
135
|
+
// is serialized rather than concatenated, so neither a value containing the separator nor a
|
|
136
|
+
// number and its string form can collide.
|
|
137
|
+
const identity = Object.entries(headingValues ?? {})
|
|
138
|
+
.filter(([name]) => name !== "count")
|
|
139
|
+
.sort(([a], [b]) => a.localeCompare(b));
|
|
140
|
+
return `id:${JSON.stringify([headingId, identity])}`;
|
|
141
|
+
}
|
|
78
142
|
/**
|
|
79
143
|
* Concatenates several lists' `items` and sums their `truncatedCount`s, re-applying the per-list
|
|
80
144
|
* cap to the result — each occurrence was capped on its own, so concatenating N of them would
|
|
@@ -54,6 +54,8 @@ export type IInteractionStepDetailRowValue = {
|
|
|
54
54
|
* rendering `text` verbatim when absent.
|
|
55
55
|
*/
|
|
56
56
|
textId?: string;
|
|
57
|
+
/** Values to interpolate into `textId`'s message, e.g. `{ count: 110 }`. */
|
|
58
|
+
textValues?: Record<string, string | number>;
|
|
57
59
|
text: string;
|
|
58
60
|
} | ({
|
|
59
61
|
kind: "list";
|
|
@@ -106,7 +108,10 @@ export interface IInteractionCategory {
|
|
|
106
108
|
category: GenAIInteractionStepCategory;
|
|
107
109
|
/** i18n message id for the category's display label, when it is one of a known/stable set. */
|
|
108
110
|
labelId?: string;
|
|
109
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Indexes into {@link IInteractionIntelligence.steps} where this category occurred. Empty for
|
|
113
|
+
* a category that belongs to the response rather than any step, which highlights nothing.
|
|
114
|
+
*/
|
|
110
115
|
stepIndexes: number[];
|
|
111
116
|
/** The list row's right-hand summary. Absent renders no excerpt. */
|
|
112
117
|
excerpt?: IInteractionCategoryExcerpt;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAE9E;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;KAAE,CAAC;CACnE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,8BAA8B,EAAE,CAAC;IACxC,oFAAoF;IACpF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0FAAwF;IACxF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACtC,iGAA+F;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,8BAA8B,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACpC;IACI,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CAChB,GACD,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,0BAA0B,CAAC,GAC/C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,0BAA0B,EAAE,CAAA;CAAE,CAAC;AAE/D;;;;GAIG;AACH,MAAM,WAAW,mCAAmC;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC5C;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IACxC,SAAS,EAAE,mCAAmC,EAAE,CAAC;CACpD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,4FAA0F;IAC1F,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,4BAA4B,EAAE,CAAC;CAC9C;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,QAAQ,EAAE,4BAA4B,CAAC;IACvC,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/data/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAE9E;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;KAAE,CAAC;CACnE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,8BAA8B,EAAE,CAAC;IACxC,oFAAoF;IACpF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0FAAwF;IACxF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACtC,iGAA+F;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,8BAA8B,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACpC;IACI,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;CAChB,GACD,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,0BAA0B,CAAC,GAC/C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,0BAA0B,EAAE,CAAA;CAAE,CAAC;AAE/D;;;;GAIG;AACH,MAAM,WAAW,mCAAmC;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC5C;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IACxC,SAAS,EAAE,mCAAmC,EAAE,CAAC;CACpD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,4FAA0F;IAC1F,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,4BAA4B,EAAE,CAAC;CAC9C;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,QAAQ,EAAE,4BAA4B,CAAC;IACvC,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oEAAoE;IACpE,OAAO,CAAC,EAAE,2BAA2B,CAAC;IACtC;;;;OAIG;IACH,UAAU,EAAE,yBAAyB,EAAE,CAAC;CAC3C;AAED;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,8BAA8B,CAAC;IACvC,mCAAmC;IACnC,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,+DAA+D;IAC/D,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,4FAA4F;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,+EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG,MAAM,GAAG,QAAQ,CAAC"}
|
|
@@ -14,7 +14,7 @@ function DetailList({ heading, headingId, headingValues, items, truncatedCount,
|
|
|
14
14
|
export function DetailRowValue({ value }) {
|
|
15
15
|
const intl = useIntl();
|
|
16
16
|
if (value.kind === "text") {
|
|
17
|
-
return resolveMessage(intl, value.textId, value.text);
|
|
17
|
+
return resolveMessage(intl, value.textId, value.text, value.textValues);
|
|
18
18
|
}
|
|
19
19
|
if (value.kind === "list") {
|
|
20
20
|
return _jsx(DetailList, { ...value });
|
|
@@ -7,8 +7,8 @@ export interface IIntelligenceCategoryRowProps {
|
|
|
7
7
|
/**
|
|
8
8
|
* One list row: the category's icon, its label, a content excerpt on the right (never a
|
|
9
9
|
* duration — that figure was always a fabricated per-category aggregate), and a chevron to open
|
|
10
|
-
* its detail view. Reports its own hover state up so the shared timeline can highlight the
|
|
11
|
-
*
|
|
10
|
+
* its detail view. Reports its own hover state up so the shared timeline can highlight the steps
|
|
11
|
+
* this category occurred in.
|
|
12
12
|
*/
|
|
13
13
|
export declare function IntelligenceCategoryRow({ category, onSelect, onHoverChange }: IIntelligenceCategoryRowProps): import("react/jsx-runtime").JSX.Element;
|
|
14
14
|
//# sourceMappingURL=IntelligenceCategoryRow.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntelligenceCategoryRow.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IntelligenceCategoryRow.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAM7D,MAAM,WAAW,6BAA6B;IAC1C,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACpC,QAAQ,EACR,QAAQ,EACR,aAAa,EAChB,EAAE,6BAA6B,
|
|
1
|
+
{"version":3,"file":"IntelligenceCategoryRow.d.ts","sourceRoot":"","sources":["../../../../src/components/intelligence/panel/IntelligenceCategoryRow.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAM7D,MAAM,WAAW,6BAA6B;IAC1C,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACpC,QAAQ,EACR,QAAQ,EACR,aAAa,EAChB,EAAE,6BAA6B,2CA+B/B"}
|
|
@@ -8,12 +8,12 @@ import { IconCircle } from "./IconCircle.js";
|
|
|
8
8
|
/**
|
|
9
9
|
* One list row: the category's icon, its label, a content excerpt on the right (never a
|
|
10
10
|
* duration — that figure was always a fabricated per-category aggregate), and a chevron to open
|
|
11
|
-
* its detail view. Reports its own hover state up so the shared timeline can highlight the
|
|
12
|
-
*
|
|
11
|
+
* its detail view. Reports its own hover state up so the shared timeline can highlight the steps
|
|
12
|
+
* this category occurred in.
|
|
13
13
|
*/
|
|
14
14
|
export function IntelligenceCategoryRow({ category, onSelect, onHoverChange, }) {
|
|
15
15
|
const intl = useIntl();
|
|
16
16
|
return (_jsxs("button", { type: "button", className: e("category-row"), onClick: onSelect, onMouseEnter: () => onHoverChange(true), onMouseLeave: () => onHoverChange(false), onFocus: () => onHoverChange(true), onBlur: () => onHoverChange(false), children: [
|
|
17
|
-
_jsx(IconCircle, { category: category.category }), _jsx("span", { className: e("category-row__label"), children: resolveMessage(intl, category.labelId, category.category) }),
|
|
17
|
+
_jsx(IconCircle, { category: category.category }), _jsx("span", { className: e("category-row__label"), children: resolveMessage(intl, category.labelId, category.category) }), _jsx("span", { className: e("category-row__excerpt"), children: category.excerpt?.fragments.map((fragment, index) => (_jsx("span", { children: intl.formatMessage({ id: fragment.id }, fragment.values) }, index))) }), _jsx(UiIcon, { type: "navigateRight", size: 16, color: "complementary-6", accessibilityConfig: { ariaHidden: true } })
|
|
18
18
|
] }));
|
|
19
19
|
}
|