@gooddata/sdk-ui-ext 11.32.0-alpha.1 → 11.32.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/NOTICE +3 -3
- package/esm/index.d.ts +4 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +2 -0
- package/esm/index.js.map +1 -1
- package/esm/insightPicker/InsightPicker.d.ts +18 -0
- package/esm/insightPicker/InsightPicker.d.ts.map +1 -0
- package/esm/insightPicker/InsightPicker.js +29 -0
- package/esm/insightPicker/InsightPicker.js.map +1 -0
- package/esm/insightPicker/InsightPickerCore.d.ts +3 -0
- package/esm/insightPicker/InsightPickerCore.d.ts.map +1 -0
- package/esm/insightPicker/InsightPickerCore.js +117 -0
- package/esm/insightPicker/InsightPickerCore.js.map +1 -0
- package/esm/insightPicker/InsightPickerFilterBar.d.ts +21 -0
- package/esm/insightPicker/InsightPickerFilterBar.d.ts.map +1 -0
- package/esm/insightPicker/InsightPickerFilterBar.js +46 -0
- package/esm/insightPicker/InsightPickerFilterBar.js.map +1 -0
- package/esm/insightPicker/InsightPickerMenu.d.ts +10 -0
- package/esm/insightPicker/InsightPickerMenu.d.ts.map +1 -0
- package/esm/insightPicker/InsightPickerMenu.js +22 -0
- package/esm/insightPicker/InsightPickerMenu.js.map +1 -0
- package/esm/insightPicker/InsightPickerRow.d.ts +17 -0
- package/esm/insightPicker/InsightPickerRow.d.ts.map +1 -0
- package/esm/insightPicker/InsightPickerRow.js +19 -0
- package/esm/insightPicker/InsightPickerRow.js.map +1 -0
- package/esm/insightPicker/InsightPickerSortDropdown.d.ts +9 -0
- package/esm/insightPicker/InsightPickerSortDropdown.d.ts.map +1 -0
- package/esm/insightPicker/InsightPickerSortDropdown.js +29 -0
- package/esm/insightPicker/InsightPickerSortDropdown.js.map +1 -0
- package/esm/insightPicker/messages.d.ts +60 -0
- package/esm/insightPicker/messages.d.ts.map +1 -0
- package/esm/insightPicker/messages.js +62 -0
- package/esm/insightPicker/messages.js.map +1 -0
- package/esm/insightPicker/types.d.ts +107 -0
- package/esm/insightPicker/types.d.ts.map +1 -0
- package/esm/insightPicker/types.js +3 -0
- package/esm/insightPicker/types.js.map +1 -0
- package/esm/insightPicker/useInsightPickerFilters.d.ts +17 -0
- package/esm/insightPicker/useInsightPickerFilters.d.ts.map +1 -0
- package/esm/insightPicker/useInsightPickerFilters.js +55 -0
- package/esm/insightPicker/useInsightPickerFilters.js.map +1 -0
- package/esm/insightPicker/useInsightPickerHybridSearch.d.ts +25 -0
- package/esm/insightPicker/useInsightPickerHybridSearch.d.ts.map +1 -0
- package/esm/insightPicker/useInsightPickerHybridSearch.js +66 -0
- package/esm/insightPicker/useInsightPickerHybridSearch.js.map +1 -0
- package/esm/insightPicker/useInsightPickerState.d.ts +21 -0
- package/esm/insightPicker/useInsightPickerState.d.ts.map +1 -0
- package/esm/insightPicker/useInsightPickerState.js +49 -0
- package/esm/insightPicker/useInsightPickerState.js.map +1 -0
- package/esm/internal/components/insightList/useInsightPagedList.d.ts +33 -1
- package/esm/internal/components/insightList/useInsightPagedList.d.ts.map +1 -1
- package/esm/internal/components/insightList/useInsightPagedList.js +37 -9
- package/esm/internal/components/insightList/useInsightPagedList.js.map +1 -1
- package/esm/internal/index.d.ts +1 -1
- package/esm/internal/index.d.ts.map +1 -1
- package/esm/internal/index.js.map +1 -1
- package/esm/internal/translations/en-US.localization-bundle.d.ts +76 -0
- package/esm/internal/translations/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/internal/translations/en-US.localization-bundle.js +76 -0
- package/esm/internal/translations/en-US.localization-bundle.js.map +1 -1
- package/esm/sdk-ui-ext.d.ts +183 -1
- package/package.json +21 -20
- package/styles/css/main.css +160 -0
- package/styles/css/main.css.map +1 -1
- package/styles/internal/css/insightPicker.css +161 -0
- package/styles/internal/css/insightPicker.css.map +1 -0
- package/styles/internal/scss/insightPicker.scss +189 -0
- package/styles/scss/main.scss +1 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { defineMessages } from "react-intl";
|
|
3
|
+
export const messages = defineMessages({
|
|
4
|
+
searchPlaceholder: {
|
|
5
|
+
id: "insightPicker.searchPlaceholder",
|
|
6
|
+
},
|
|
7
|
+
tabAll: {
|
|
8
|
+
id: "insightPicker.tabs.all",
|
|
9
|
+
},
|
|
10
|
+
tabMy: {
|
|
11
|
+
id: "insightPicker.tabs.my",
|
|
12
|
+
},
|
|
13
|
+
noInsightsFound: {
|
|
14
|
+
id: "insightPicker.noInsightsFound",
|
|
15
|
+
},
|
|
16
|
+
noInsights: {
|
|
17
|
+
id: "insightPicker.noInsights",
|
|
18
|
+
},
|
|
19
|
+
sortByHeader: {
|
|
20
|
+
id: "insightPicker.sortBy.header",
|
|
21
|
+
},
|
|
22
|
+
sortByLastModified: {
|
|
23
|
+
id: "insightPicker.sortBy.lastModified",
|
|
24
|
+
},
|
|
25
|
+
sortByName: {
|
|
26
|
+
id: "insightPicker.sortBy.name",
|
|
27
|
+
},
|
|
28
|
+
filters: {
|
|
29
|
+
id: "insightPicker.filters",
|
|
30
|
+
},
|
|
31
|
+
filterCreatedBy: {
|
|
32
|
+
id: "insightPicker.filter.createdBy",
|
|
33
|
+
},
|
|
34
|
+
filterCreatedByMe: {
|
|
35
|
+
id: "insightPicker.filter.createdByMe",
|
|
36
|
+
},
|
|
37
|
+
filterAll: {
|
|
38
|
+
id: "insightPicker.filter.all",
|
|
39
|
+
},
|
|
40
|
+
filterApply: {
|
|
41
|
+
id: "insightPicker.filter.apply",
|
|
42
|
+
},
|
|
43
|
+
filterCancel: {
|
|
44
|
+
id: "insightPicker.filter.cancel",
|
|
45
|
+
},
|
|
46
|
+
filterTag: {
|
|
47
|
+
id: "insightPicker.filter.tag",
|
|
48
|
+
},
|
|
49
|
+
sortDirectionAscending: {
|
|
50
|
+
id: "insightPicker.sortDirection.ascending",
|
|
51
|
+
},
|
|
52
|
+
sortDirectionDescending: {
|
|
53
|
+
id: "insightPicker.sortDirection.descending",
|
|
54
|
+
},
|
|
55
|
+
menuActions: {
|
|
56
|
+
id: "insightPicker.menu.actions",
|
|
57
|
+
},
|
|
58
|
+
resetFilters: {
|
|
59
|
+
id: "insightPicker.resetFilters",
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/insightPicker/messages.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,CAAC;IACnC,iBAAiB,EAAE;QACf,EAAE,EAAE,iCAAiC;KACxC;IACD,MAAM,EAAE;QACJ,EAAE,EAAE,wBAAwB;KAC/B;IACD,KAAK,EAAE;QACH,EAAE,EAAE,uBAAuB;KAC9B;IACD,eAAe,EAAE;QACb,EAAE,EAAE,+BAA+B;KACtC;IACD,UAAU,EAAE;QACR,EAAE,EAAE,0BAA0B;KACjC;IACD,YAAY,EAAE;QACV,EAAE,EAAE,6BAA6B;KACpC;IACD,kBAAkB,EAAE;QAChB,EAAE,EAAE,mCAAmC;KAC1C;IACD,UAAU,EAAE;QACR,EAAE,EAAE,2BAA2B;KAClC;IACD,OAAO,EAAE;QACL,EAAE,EAAE,uBAAuB;KAC9B;IACD,eAAe,EAAE;QACb,EAAE,EAAE,gCAAgC;KACvC;IACD,iBAAiB,EAAE;QACf,EAAE,EAAE,kCAAkC;KACzC;IACD,SAAS,EAAE;QACP,EAAE,EAAE,0BAA0B;KACjC;IACD,WAAW,EAAE;QACT,EAAE,EAAE,4BAA4B;KACnC;IACD,YAAY,EAAE;QACV,EAAE,EAAE,6BAA6B;KACpC;IACD,SAAS,EAAE;QACP,EAAE,EAAE,0BAA0B;KACjC;IACD,sBAAsB,EAAE;QACpB,EAAE,EAAE,uCAAuC;KAC9C;IACD,uBAAuB,EAAE;QACrB,EAAE,EAAE,wCAAwC;KAC/C;IACD,WAAW,EAAE;QACT,EAAE,EAAE,4BAA4B;KACnC;IACD,YAAY,EAAE;QACV,EAAE,EAAE,4BAA4B;KACnC;CACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { type ReactElement, type ReactNode } from "react";
|
|
2
|
+
import { type IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
3
|
+
import { type IInsight, type ObjRef } from "@gooddata/sdk-model";
|
|
4
|
+
import { type ILocale } from "@gooddata/sdk-ui";
|
|
5
|
+
/**
|
|
6
|
+
* Sort field for the insight picker.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export type InsightPickerSortBy = "lastModified" | "name";
|
|
10
|
+
/**
|
|
11
|
+
* Sort direction for the insight picker.
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export type InsightPickerSortDirection = "asc" | "desc";
|
|
15
|
+
/**
|
|
16
|
+
* Represents a single insight item in the picker.
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export interface IInsightPickerItem {
|
|
20
|
+
ref: ObjRef;
|
|
21
|
+
title: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
identifier: string;
|
|
24
|
+
uri?: string;
|
|
25
|
+
isLocked: boolean;
|
|
26
|
+
created?: string;
|
|
27
|
+
updated?: string;
|
|
28
|
+
visualizationUrl: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Menu action for the insight picker's three-dots menu.
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export interface IInsightPickerMenuAction {
|
|
35
|
+
id: string;
|
|
36
|
+
title: string;
|
|
37
|
+
onClick: (item: IInsightPickerItem) => void;
|
|
38
|
+
isDestructive?: boolean;
|
|
39
|
+
hasSeparator?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Props for a custom menu renderer.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export interface IInsightPickerMenuProps {
|
|
46
|
+
item: IInsightPickerItem;
|
|
47
|
+
closeMenu: () => void;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Props passed to a custom renderItem function.
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
export interface IInsightPickerRenderItemProps {
|
|
54
|
+
item: IInsightPickerItem;
|
|
55
|
+
type: string;
|
|
56
|
+
width: number;
|
|
57
|
+
isSelected: boolean;
|
|
58
|
+
sourceInsight?: IInsight;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Props for the InsightPicker component.
|
|
62
|
+
*
|
|
63
|
+
* The picker is fully controlled — all state (search, sort, filters) must be
|
|
64
|
+
* managed by the consumer and passed as props. This ensures state persists
|
|
65
|
+
* across open/close cycles.
|
|
66
|
+
*
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
export interface IInsightPickerProps {
|
|
70
|
+
backend?: IAnalyticalBackend;
|
|
71
|
+
workspace?: string;
|
|
72
|
+
locale?: ILocale;
|
|
73
|
+
/** Include only insights with these tags (URL-scoped). */
|
|
74
|
+
includeTags?: string[];
|
|
75
|
+
/** Exclude insights with these tags (URL-scoped). */
|
|
76
|
+
excludeTags?: string[];
|
|
77
|
+
/**
|
|
78
|
+
* Author identifier for the current user.
|
|
79
|
+
* Used to populate the "Me" option in the author filter.
|
|
80
|
+
*/
|
|
81
|
+
author?: string;
|
|
82
|
+
enabledVisualizationClassesUrls?: string[];
|
|
83
|
+
selectedInsightId?: string;
|
|
84
|
+
enableDescriptions?: boolean;
|
|
85
|
+
metadataTimeZone?: string;
|
|
86
|
+
enableSemanticSearch?: boolean;
|
|
87
|
+
maxHeight?: number;
|
|
88
|
+
width?: number;
|
|
89
|
+
searchQuery: string;
|
|
90
|
+
onSearchChange: (query: string) => void;
|
|
91
|
+
sortBy: InsightPickerSortBy;
|
|
92
|
+
sortDirection: InsightPickerSortDirection;
|
|
93
|
+
onSortChange: (sortBy: InsightPickerSortBy, sortDirection: InsightPickerSortDirection) => void;
|
|
94
|
+
/** Selected author IDs. Empty array = "All". */
|
|
95
|
+
authorFilter: string[];
|
|
96
|
+
onAuthorFilterChange: (authorIds: string[]) => void;
|
|
97
|
+
/** Selected tag values. Empty array = "All". */
|
|
98
|
+
tagFilter: string[];
|
|
99
|
+
onTagFilterChange: (tagIds: string[]) => void;
|
|
100
|
+
onSelect: (insightRef: ObjRef, item: IInsightPickerItem) => void;
|
|
101
|
+
onDescriptionPanelOpen?: (description: string) => void;
|
|
102
|
+
onItemActivate?: (item: IInsightPickerItem, sourceInsight?: IInsight) => void;
|
|
103
|
+
menuActions?: IInsightPickerMenuAction[];
|
|
104
|
+
renderMenu?: (props: IInsightPickerMenuProps) => ReactNode;
|
|
105
|
+
renderItem?: (props: IInsightPickerRenderItemProps) => ReactElement;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/insightPicker/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/insightPicker/types.ts"],"names":[],"mappings":"AAAA,gCAAgC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
2
|
+
import { type IUiAsyncTableFilterOption } from "@gooddata/sdk-ui-kit";
|
|
3
|
+
/**
|
|
4
|
+
* Loads author and tag filter options from the analytics catalog API.
|
|
5
|
+
* Uses the same endpoints as the analytical catalog component:
|
|
6
|
+
* - getCreatedBy() → list of users who created objects
|
|
7
|
+
* - getTags() → list of available tags
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare function useInsightPickerFilters(backend: IAnalyticalBackend, workspace: string, currentAuthor?: string): {
|
|
12
|
+
authorOptions: IUiAsyncTableFilterOption[];
|
|
13
|
+
tagOptions: IUiAsyncTableFilterOption[];
|
|
14
|
+
authorsLoaded: boolean;
|
|
15
|
+
tagsLoaded: boolean;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=useInsightPickerFilters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInsightPickerFilters.d.ts","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerFilters.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGpE,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAItE;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACnC,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM;;;;;EA+CzB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { useIntl } from "react-intl";
|
|
4
|
+
import { useCancelablePromise } from "@gooddata/sdk-ui";
|
|
5
|
+
import { messages } from "./messages.js";
|
|
6
|
+
/**
|
|
7
|
+
* Loads author and tag filter options from the analytics catalog API.
|
|
8
|
+
* Uses the same endpoints as the analytical catalog component:
|
|
9
|
+
* - getCreatedBy() → list of users who created objects
|
|
10
|
+
* - getTags() → list of available tags
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export function useInsightPickerFilters(backend, workspace, currentAuthor) {
|
|
15
|
+
const intl = useIntl();
|
|
16
|
+
// --- Load authors ---
|
|
17
|
+
const { result: createdByResult, status: authorsStatus } = useCancelablePromise({
|
|
18
|
+
promise: () => backend.workspace(workspace).genAI().getAnalyticsCatalog().getCreatedBy(),
|
|
19
|
+
onError: (error) => console.error("Failed to load authors:", error),
|
|
20
|
+
}, [backend, workspace]);
|
|
21
|
+
const meLabel = intl.formatMessage(messages.filterCreatedByMe);
|
|
22
|
+
const authorOptions = useMemo(() => {
|
|
23
|
+
const users = createdByResult?.users ?? [];
|
|
24
|
+
const sorted = sortUsers(users);
|
|
25
|
+
return sorted.map((user) => ({
|
|
26
|
+
value: user.login,
|
|
27
|
+
label: user.login === currentAuthor ? meLabel : (user.fullName ?? user.login),
|
|
28
|
+
}));
|
|
29
|
+
}, [createdByResult?.users, currentAuthor, meLabel]);
|
|
30
|
+
// --- Load tags ---
|
|
31
|
+
const { result: tagsResult, status: tagsStatus } = useCancelablePromise({
|
|
32
|
+
promise: () => backend.workspace(workspace).genAI().getAnalyticsCatalog().getTags(),
|
|
33
|
+
onError: (error) => console.error("Failed to load tags:", error),
|
|
34
|
+
}, [backend, workspace]);
|
|
35
|
+
const tagOptions = useMemo(() => {
|
|
36
|
+
const tags = tagsResult?.tags ?? [];
|
|
37
|
+
return [...tags]
|
|
38
|
+
.sort((a, b) => a.localeCompare(b))
|
|
39
|
+
.map((tag) => ({
|
|
40
|
+
value: tag,
|
|
41
|
+
label: tag,
|
|
42
|
+
}));
|
|
43
|
+
}, [tagsResult?.tags]);
|
|
44
|
+
const authorsLoaded = authorsStatus === "success";
|
|
45
|
+
const tagsLoaded = tagsStatus === "success";
|
|
46
|
+
return { authorOptions, tagOptions, authorsLoaded, tagsLoaded };
|
|
47
|
+
}
|
|
48
|
+
function sortUsers(users) {
|
|
49
|
+
return [...users].sort((a, b) => {
|
|
50
|
+
const nameA = (a.fullName ?? a.login).toLowerCase();
|
|
51
|
+
const nameB = (b.fullName ?? b.login).toLowerCase();
|
|
52
|
+
return nameA.localeCompare(nameB);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=useInsightPickerFilters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInsightPickerFilters.js","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerFilters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type IInsight } from "@gooddata/sdk-model";
|
|
2
|
+
import { type IInsightPickerItem } from "./types.js";
|
|
3
|
+
interface IUseInsightPickerHybridSearchOptions {
|
|
4
|
+
insights: IInsight[];
|
|
5
|
+
searchQuery: string;
|
|
6
|
+
onSearchChange: (query: string) => void;
|
|
7
|
+
enableSemanticSearch?: boolean;
|
|
8
|
+
includeTags?: string[];
|
|
9
|
+
excludeTags?: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Wraps useHybridSearch with the insight-specific item mapping and search state sync.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare function useInsightPickerHybridSearch({ insights, searchQuery, onSearchChange, enableSemanticSearch, includeTags, excludeTags }: IUseInsightPickerHybridSearchOptions): {
|
|
17
|
+
searchState: import("@gooddata/sdk-ui-semantic-search").ISearchState;
|
|
18
|
+
semanticSearchState: import("@gooddata/sdk-ui-semantic-search").ISemanticSearchState;
|
|
19
|
+
searchEntries: IInsightPickerItem[];
|
|
20
|
+
displayItems: IInsightPickerItem[];
|
|
21
|
+
isSearching: boolean;
|
|
22
|
+
handleSearchChange: (query: string) => void;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=useInsightPickerHybridSearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInsightPickerHybridSearch.d.ts","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerHybridSearch.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,QAAQ,EAWhB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAsBrD,UAAU,oCAAoC;IAC1C,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,EACzC,QAAQ,EACR,WAAW,EACX,cAAc,EACd,oBAA2B,EAC3B,WAAW,EACX,WAAW,EACd,EAAE,oCAAoC;;;;;;;EAuEtC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
3
|
+
import { insightCreated, insightId, insightIsLocked, insightSummary, insightTitle, insightUpdated, insightUri, insightVisualizationUrl, uriRef, } from "@gooddata/sdk-model";
|
|
4
|
+
import { customMatcher, useHybridSearch, } from "@gooddata/sdk-ui-semantic-search";
|
|
5
|
+
const SEMANTIC_SEARCH_OBJECT_TYPES = ["visualization"];
|
|
6
|
+
const insightItemBuilder = (item, { ref }) => ({
|
|
7
|
+
ref,
|
|
8
|
+
title: item.title,
|
|
9
|
+
description: item.description,
|
|
10
|
+
identifier: item.id,
|
|
11
|
+
isLocked: false,
|
|
12
|
+
created: item.createdAt,
|
|
13
|
+
updated: item.modifiedAt ?? item.createdAt,
|
|
14
|
+
visualizationUrl: item.visualizationUrl ?? "",
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Wraps useHybridSearch with the insight-specific item mapping and search state sync.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export function useInsightPickerHybridSearch({ insights, searchQuery, onSearchChange, enableSemanticSearch = true, includeTags, excludeTags, }) {
|
|
22
|
+
const searchEntries = useMemo(() => insights.map((insight) => ({
|
|
23
|
+
ref: uriRef(insightUri(insight)),
|
|
24
|
+
title: insightTitle(insight),
|
|
25
|
+
description: insightSummary(insight),
|
|
26
|
+
identifier: insightId(insight),
|
|
27
|
+
uri: insightUri(insight),
|
|
28
|
+
isLocked: insightIsLocked(insight),
|
|
29
|
+
created: insightCreated(insight),
|
|
30
|
+
updated: insightUpdated(insight),
|
|
31
|
+
visualizationUrl: insightVisualizationUrl(insight),
|
|
32
|
+
})), [insights]);
|
|
33
|
+
const matcher = useMemo(() => customMatcher(["title", "description", "identifier"]), []);
|
|
34
|
+
const { searchState, semanticSearchState, search: hybridSearch, onSearchQueryChange: setHybridSearchQuery, } = useHybridSearch({
|
|
35
|
+
objectTypes: SEMANTIC_SEARCH_OBJECT_TYPES,
|
|
36
|
+
allowSematicSearch: enableSemanticSearch,
|
|
37
|
+
itemBuilder: insightItemBuilder,
|
|
38
|
+
includeTags,
|
|
39
|
+
excludeTags,
|
|
40
|
+
matcher,
|
|
41
|
+
});
|
|
42
|
+
// Sync controlled search query into hybrid search on mount
|
|
43
|
+
const initializedSearch = useRef(false);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!initializedSearch.current) {
|
|
46
|
+
initializedSearch.current = true;
|
|
47
|
+
setHybridSearchQuery(searchQuery);
|
|
48
|
+
}
|
|
49
|
+
}, [searchQuery, setHybridSearchQuery]);
|
|
50
|
+
const handleSearchChange = useCallback((query) => {
|
|
51
|
+
setHybridSearchQuery(query);
|
|
52
|
+
onSearchChange(query);
|
|
53
|
+
}, [setHybridSearchQuery, onSearchChange]);
|
|
54
|
+
const isSearching = searchState.query !== "";
|
|
55
|
+
const { searchItems, searchRelatedItems } = useMemo(() => hybridSearch({ items: searchEntries }), [hybridSearch, searchEntries]);
|
|
56
|
+
const displayItems = useMemo(() => (isSearching ? [...searchItems, ...searchRelatedItems] : searchEntries), [isSearching, searchEntries, searchItems, searchRelatedItems]);
|
|
57
|
+
return {
|
|
58
|
+
searchState,
|
|
59
|
+
semanticSearchState,
|
|
60
|
+
searchEntries,
|
|
61
|
+
displayItems,
|
|
62
|
+
isSearching,
|
|
63
|
+
handleSearchChange,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=useInsightPickerHybridSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInsightPickerHybridSearch.js","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerHybridSearch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type InsightPickerSortBy, type InsightPickerSortDirection } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Managed state for the InsightPicker component.
|
|
4
|
+
* Use this hook in the consumer to own all picker state so it persists
|
|
5
|
+
* across open/close cycles. Spread the returned object into `<InsightPicker>`.
|
|
6
|
+
*
|
|
7
|
+
* @param author - current user identifier; when provided, authorFilter defaults to [author] ("Me")
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare function useInsightPickerState(author?: string): {
|
|
11
|
+
searchQuery: string;
|
|
12
|
+
onSearchChange: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
13
|
+
sortBy: InsightPickerSortBy;
|
|
14
|
+
sortDirection: InsightPickerSortDirection;
|
|
15
|
+
onSortChange: (newSortBy: InsightPickerSortBy, newDirection: InsightPickerSortDirection) => void;
|
|
16
|
+
authorFilter: string[];
|
|
17
|
+
onAuthorFilterChange: (nextAuthorFilter: string[]) => void;
|
|
18
|
+
tagFilter: string[];
|
|
19
|
+
onTagFilterChange: import("react").Dispatch<import("react").SetStateAction<string[]>>;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=useInsightPickerState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInsightPickerState.d.ts","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerState.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAEvF;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,MAAM;;;;;;;;;;EA6CpD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Managed state for the InsightPicker component.
|
|
5
|
+
* Use this hook in the consumer to own all picker state so it persists
|
|
6
|
+
* across open/close cycles. Spread the returned object into `<InsightPicker>`.
|
|
7
|
+
*
|
|
8
|
+
* @param author - current user identifier; when provided, authorFilter defaults to [author] ("Me")
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export function useInsightPickerState(author) {
|
|
12
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
13
|
+
const [sortBy, setSortBy] = useState("lastModified");
|
|
14
|
+
const [sortDirection, setSortDirection] = useState("desc");
|
|
15
|
+
const [authorFilter, setAuthorFilter] = useState(author ? [author] : []);
|
|
16
|
+
const [tagFilter, setTagFilter] = useState([]);
|
|
17
|
+
// Latches to true on first user change and stays latched — once the user picks their own
|
|
18
|
+
// filter, we never re-apply the "Me" default, even if `author` arrives late.
|
|
19
|
+
const isAuthorFilterModified = useRef(false);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!author || isAuthorFilterModified.current) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const isAuthorFilterInSync = authorFilter.length === 1 && authorFilter[0] === author;
|
|
25
|
+
if (!isAuthorFilterInSync) {
|
|
26
|
+
setAuthorFilter([author]);
|
|
27
|
+
}
|
|
28
|
+
}, [author, authorFilter]);
|
|
29
|
+
const onAuthorFilterChange = useCallback((nextAuthorFilter) => {
|
|
30
|
+
isAuthorFilterModified.current = true;
|
|
31
|
+
setAuthorFilter(nextAuthorFilter);
|
|
32
|
+
}, []);
|
|
33
|
+
const onSortChange = useCallback((newSortBy, newDirection) => {
|
|
34
|
+
setSortBy(newSortBy);
|
|
35
|
+
setSortDirection(newDirection);
|
|
36
|
+
}, []);
|
|
37
|
+
return {
|
|
38
|
+
searchQuery,
|
|
39
|
+
onSearchChange: setSearchQuery,
|
|
40
|
+
sortBy,
|
|
41
|
+
sortDirection,
|
|
42
|
+
onSortChange,
|
|
43
|
+
authorFilter,
|
|
44
|
+
onAuthorFilterChange,
|
|
45
|
+
tagFilter,
|
|
46
|
+
onTagFilterChange: setTagFilter,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=useInsightPickerState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInsightPickerState.js","sourceRoot":"","sources":["../../src/insightPicker/useInsightPickerState.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIjE;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAe,EAAE;IACnD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAsB,cAAc,CAAC,CAAC;IAC1E,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAA6B,MAAM,CAAC,CAAC;IACvF,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAW,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACnF,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAW,EAAE,CAAC,CAAC;IACzD,2FAAyF;IACzF,6EAA6E;IAC7E,MAAM,sBAAsB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE7C,SAAS,CAAC,GAAG,EAAE,CAAC;QACZ,IAAI,CAAC,MAAM,IAAI,sBAAsB,CAAC,OAAO,EAAE,CAAC;YAC5C,OAAO;QACX,CAAC;QAED,MAAM,oBAAoB,GAAG,YAAY,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC;QACrF,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACxB,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9B,CAAC;IAAA,CACJ,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAE3B,MAAM,oBAAoB,GAAG,WAAW,CAAC,CAAC,gBAA0B,EAAE,EAAE,CAAC;QACrE,sBAAsB,CAAC,OAAO,GAAG,IAAI,CAAC;QACtC,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAAA,CACrC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,YAAY,GAAG,WAAW,CAC5B,CAAC,SAA8B,EAAE,YAAwC,EAAE,EAAE,CAAC;QAC1E,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAAA,CAClC,EACD,EAAE,CACL,CAAC;IAEF,OAAO;QACH,WAAW;QACX,cAAc,EAAE,cAAc;QAC9B,MAAM;QACN,aAAa;QACb,YAAY;QACZ,YAAY;QACZ,oBAAoB;QACpB,SAAS;QACT,iBAAiB,EAAE,YAAY;KAClC,CAAC;AAAA,CACL"}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { type IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
|
|
2
2
|
import { type IInsight } from "@gooddata/sdk-model";
|
|
3
3
|
import { type ITab } from "@gooddata/sdk-ui-kit";
|
|
4
|
+
/**
|
|
5
|
+
* Sort field for the insights paged list. Mirrors `InsightPickerSortBy` in the public API.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export type InsightListSortBy = "lastModified" | "name";
|
|
9
|
+
/**
|
|
10
|
+
* Sort direction for the insights paged list.
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export type InsightListSortDirection = "asc" | "desc";
|
|
4
14
|
/**
|
|
5
15
|
* Tabs ids for insights paged list hook
|
|
6
16
|
* @internal
|
|
@@ -20,6 +30,26 @@ export interface IUsePagedDropdownConfig {
|
|
|
20
30
|
tabsIds: ITabsIds;
|
|
21
31
|
tags?: string[];
|
|
22
32
|
excludeTags?: string[];
|
|
33
|
+
/**
|
|
34
|
+
* Sort field. When omitted, defaults to the backend's default ordering
|
|
35
|
+
* (modifiedAt, createdAt, title — descending).
|
|
36
|
+
*/
|
|
37
|
+
sortBy?: InsightListSortBy;
|
|
38
|
+
/**
|
|
39
|
+
* Sort direction. Defaults to "desc".
|
|
40
|
+
*/
|
|
41
|
+
sortDirection?: InsightListSortDirection;
|
|
42
|
+
/**
|
|
43
|
+
* When provided, filters insights by these author IDs (createdBy).
|
|
44
|
+
* Replaces the tab-based author filtering.
|
|
45
|
+
*/
|
|
46
|
+
createdByFilter?: string[];
|
|
47
|
+
/**
|
|
48
|
+
* When true, always includes createdBy/modifiedBy in the query response
|
|
49
|
+
* so author metadata is available on loaded insights.
|
|
50
|
+
* Only used by the enhanced insight picker — other consumers should leave this off.
|
|
51
|
+
*/
|
|
52
|
+
includeAuthorInfo?: boolean;
|
|
23
53
|
}
|
|
24
54
|
/**
|
|
25
55
|
* Result of useInsightPagedList hook
|
|
@@ -58,9 +88,11 @@ export interface IUsePagedDropdownResult {
|
|
|
58
88
|
* @param tabsIds - tabs ids
|
|
59
89
|
* @param tags - fetch only the insights with these tags
|
|
60
90
|
* @param excludeTags - omit insights with these tags during fetch
|
|
91
|
+
* @param sortBy - sort field
|
|
92
|
+
* @param sortDirection - sort direction
|
|
61
93
|
* @returns useInsightPagedList result
|
|
62
94
|
*
|
|
63
95
|
* @internal
|
|
64
96
|
*/
|
|
65
|
-
export declare function useInsightPagedList({ backend, workspaceId, author, tabsIds, tags, excludeTags }: IUsePagedDropdownConfig): IUsePagedDropdownResult;
|
|
97
|
+
export declare function useInsightPagedList({ backend, workspaceId, author, tabsIds, tags, excludeTags, sortBy, sortDirection, createdByFilter, includeAuthorInfo }: IUsePagedDropdownConfig): IUsePagedDropdownResult;
|
|
66
98
|
//# sourceMappingURL=useInsightPagedList.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInsightPagedList.d.ts","sourceRoot":"","sources":["../../../../src/internal/components/insightList/useInsightPagedList.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,kBAAkB,EAA2B,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAIjD;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"useInsightPagedList.d.ts","sourceRoot":"","sources":["../../../../src/internal/components/insightList/useInsightPagedList.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,kBAAkB,EAA2B,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAIjD;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,MAAM,CAAC;AAExD;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtD;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;OAGG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,OAAO,CAAC;KACxB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,kBAAkB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3E,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,UAAU,EAAE,MAAM,IAAI,CAAC;CAC1B;AAWD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,OAAO,EACP,WAAW,EACX,MAAM,EACN,OAAO,EACP,IAAI,EACJ,WAAW,EACX,MAAM,EACN,aAAsC,EACtC,eAAe,EACf,iBAAyB,EAC5B,EAAE,uBAAuB,GAAG,uBAAuB,CAsOnD"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
// (C) 2026 GoodData Corporation
|
|
2
|
-
import { useCallback, useRef, useState } from "react";
|
|
2
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { debounce, isEmpty } from "lodash-es";
|
|
4
4
|
const ITEMS_PER_PAGE = 50;
|
|
5
|
-
const
|
|
5
|
+
const DEFAULT_SORT_DIRECTION = "desc";
|
|
6
|
+
function buildSorting(sortBy, direction) {
|
|
7
|
+
if (sortBy === "name") {
|
|
8
|
+
return [`title,${direction}`];
|
|
9
|
+
}
|
|
10
|
+
return [`modifiedAt,createdAt,title,${direction}`];
|
|
11
|
+
}
|
|
6
12
|
/**
|
|
7
13
|
* Hook to fetch insights paged list
|
|
8
14
|
* @param backend - analytical backend
|
|
@@ -11,11 +17,13 @@ const DEFAULT_INSIGHT_SORT = ["modifiedAt,createdAt,title,desc"];
|
|
|
11
17
|
* @param tabsIds - tabs ids
|
|
12
18
|
* @param tags - fetch only the insights with these tags
|
|
13
19
|
* @param excludeTags - omit insights with these tags during fetch
|
|
20
|
+
* @param sortBy - sort field
|
|
21
|
+
* @param sortDirection - sort direction
|
|
14
22
|
* @returns useInsightPagedList result
|
|
15
23
|
*
|
|
16
24
|
* @internal
|
|
17
25
|
*/
|
|
18
|
-
export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tags, excludeTags, }) {
|
|
26
|
+
export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tags, excludeTags, sortBy, sortDirection = DEFAULT_SORT_DIRECTION, createdByFilter, includeAuthorInfo = false, }) {
|
|
19
27
|
const [items, setItems] = useState([]);
|
|
20
28
|
const [totalItemsCount, setTotalItemsCount] = useState(undefined);
|
|
21
29
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -26,6 +34,7 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
|
|
|
26
34
|
const [selectedTabId, setSelectedTabId] = useState(tabsIds.my);
|
|
27
35
|
const abortControllerRef = useRef(null);
|
|
28
36
|
const initialLoadCompletedRef = useRef(false);
|
|
37
|
+
const sorting = useMemo(() => buildSorting(sortBy, sortDirection), [sortBy, sortDirection]);
|
|
29
38
|
const totalItems = totalItemsCount ?? items.length;
|
|
30
39
|
const hasNextPage = totalItems > items.length;
|
|
31
40
|
const skeletonItemsCount = hasNextPage ? Math.min(ITEMS_PER_PAGE, totalItems - items.length) : 0;
|
|
@@ -58,17 +67,24 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
|
|
|
58
67
|
.getInsightsQuery()
|
|
59
68
|
.withSize(ITEMS_PER_PAGE)
|
|
60
69
|
.withPage(page)
|
|
61
|
-
.withSorting(
|
|
70
|
+
.withSorting(sorting);
|
|
62
71
|
const searchedTitle = searchValue || undefined;
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
// When includeAuthorInfo is true (picker mode), only use the explicit createdByFilter.
|
|
73
|
+
// Otherwise fall back to the legacy tab-based author filtering.
|
|
74
|
+
const searchedAuthor = !includeAuthorInfo && tabId === tabsIds.my && isEmpty(searchValue) ? author : undefined;
|
|
75
|
+
const effectiveCreatedBy = createdByFilter?.length
|
|
76
|
+
? createdByFilter
|
|
77
|
+
: searchedAuthor
|
|
78
|
+
? [searchedAuthor]
|
|
79
|
+
: undefined;
|
|
80
|
+
if (includeAuthorInfo || effectiveCreatedBy) {
|
|
65
81
|
query.withInclude(["createdBy", "modifiedBy"]);
|
|
66
82
|
}
|
|
67
83
|
const filter = {
|
|
68
84
|
...((tags?.length ?? 0) > 0 ? { tags } : {}),
|
|
69
85
|
...((excludeTags?.length ?? 0) > 0 ? { excludeTags } : {}),
|
|
70
86
|
...(searchedTitle ? { title: searchedTitle } : {}),
|
|
71
|
-
...(
|
|
87
|
+
...(effectiveCreatedBy ? { createdBy: effectiveCreatedBy } : {}),
|
|
72
88
|
};
|
|
73
89
|
if (Object.keys(filter).length > 0) {
|
|
74
90
|
query.withFilter(filter);
|
|
@@ -99,7 +115,7 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
|
|
|
99
115
|
.getInsightsQuery()
|
|
100
116
|
.withSize(ITEMS_PER_PAGE)
|
|
101
117
|
.withPage(0)
|
|
102
|
-
.withSorting(
|
|
118
|
+
.withSorting(sorting);
|
|
103
119
|
const allFilter = {
|
|
104
120
|
...((tags?.length ?? 0) > 0 ? { tags } : {}),
|
|
105
121
|
...((excludeTags?.length ?? 0) > 0 ? { excludeTags } : {}),
|
|
@@ -129,7 +145,17 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
|
|
|
129
145
|
setIsNextPageLoading(false);
|
|
130
146
|
}
|
|
131
147
|
}
|
|
132
|
-
}, [
|
|
148
|
+
}, [
|
|
149
|
+
backend,
|
|
150
|
+
workspaceId,
|
|
151
|
+
author,
|
|
152
|
+
tabsIds,
|
|
153
|
+
tags,
|
|
154
|
+
excludeTags,
|
|
155
|
+
sorting,
|
|
156
|
+
createdByFilter,
|
|
157
|
+
includeAuthorInfo,
|
|
158
|
+
]);
|
|
133
159
|
const loadNextPage = useCallback(() => {
|
|
134
160
|
if (!hasNextPage || isNextPageLoading || isLoading) {
|
|
135
161
|
return;
|
|
@@ -163,9 +189,11 @@ export function useInsightPagedList({ backend, workspaceId, author, tabsIds, tag
|
|
|
163
189
|
}, []);
|
|
164
190
|
const shouldLoadNextPage = useCallback((lastItemIndex, itemsCount) => lastItemIndex >= itemsCount - 5, []);
|
|
165
191
|
const loadInitialItems = useCallback(() => {
|
|
192
|
+
setCurrentPage(0);
|
|
166
193
|
void fetchItems({ page: 0, search: "", tabId: undefined, resetItems: true });
|
|
167
194
|
}, [fetchItems]);
|
|
168
195
|
const resetItems = useCallback(() => {
|
|
196
|
+
setCurrentPage(0);
|
|
169
197
|
void fetchItems({ page: 0, search: search, tabId: selectedTabId, resetItems: true });
|
|
170
198
|
}, [fetchItems, search, selectedTabId]);
|
|
171
199
|
return {
|