@robosystems/core 0.3.0
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/LICENSE +21 -0
- package/README.md +252 -0
- package/actions/entity-actions.d.ts +8 -0
- package/actions/entity-actions.js +16 -0
- package/actions/graph-actions.d.ts +3 -0
- package/actions/graph-actions.js +13 -0
- package/auth-components/AppSwitcher.d.ts +6 -0
- package/auth-components/AppSwitcher.js +28 -0
- package/auth-components/AuthGuard.d.ts +7 -0
- package/auth-components/AuthGuard.js +31 -0
- package/auth-components/AuthProvider.d.ts +9 -0
- package/auth-components/AuthProvider.js +565 -0
- package/auth-components/SessionWarningDialog.d.ts +1 -0
- package/auth-components/SessionWarningDialog.js +51 -0
- package/auth-components/SignInForm.d.ts +20 -0
- package/auth-components/SignInForm.js +139 -0
- package/auth-components/SignUpForm.d.ts +15 -0
- package/auth-components/SignUpForm.js +167 -0
- package/auth-components/TurnstileWidget.d.ts +99 -0
- package/auth-components/TurnstileWidget.js +224 -0
- package/auth-components/index.d.ts +6 -0
- package/auth-components/index.js +6 -0
- package/auth-core/cleanup.d.ts +44 -0
- package/auth-core/cleanup.js +157 -0
- package/auth-core/client.d.ts +121 -0
- package/auth-core/client.js +767 -0
- package/auth-core/config.d.ts +19 -0
- package/auth-core/config.js +56 -0
- package/auth-core/hooks.d.ts +19 -0
- package/auth-core/hooks.js +63 -0
- package/auth-core/index.d.ts +6 -0
- package/auth-core/index.js +6 -0
- package/auth-core/sso.d.ts +42 -0
- package/auth-core/sso.js +281 -0
- package/auth-core/token-storage.d.ts +58 -0
- package/auth-core/token-storage.js +177 -0
- package/auth-core/types.d.ts +145 -0
- package/auth-core/types.js +1 -0
- package/components/EntitySelector.d.ts +44 -0
- package/components/EntitySelector.js +64 -0
- package/components/EntitySelectorCore.d.ts +45 -0
- package/components/EntitySelectorCore.js +67 -0
- package/components/GraphSelectorCore.d.ts +21 -0
- package/components/GraphSelectorCore.js +39 -0
- package/components/PageLayout.d.ts +8 -0
- package/components/PageLayout.js +5 -0
- package/components/RepositoryGuard.d.ts +68 -0
- package/components/RepositoryGuard.js +91 -0
- package/components/console/ConsoleContent.d.ts +4 -0
- package/components/console/ConsoleContent.js +612 -0
- package/components/console/ConsoleMarkdown.d.ts +11 -0
- package/components/console/ConsoleMarkdown.js +49 -0
- package/components/console/ProgressiveText.d.ts +6 -0
- package/components/console/ProgressiveText.js +21 -0
- package/components/console/graphAwareConfig.d.ts +70 -0
- package/components/console/graphAwareConfig.js +411 -0
- package/components/console/index.d.ts +6 -0
- package/components/console/index.js +4 -0
- package/components/console/types.d.ts +84 -0
- package/components/console/types.js +1 -0
- package/components/graph-filters.d.ts +75 -0
- package/components/graph-filters.js +111 -0
- package/components/index.d.ts +10 -0
- package/components/index.js +9 -0
- package/components/repositories/ActiveSubscriptions.d.ts +26 -0
- package/components/repositories/ActiveSubscriptions.js +103 -0
- package/components/repositories/BrowseRepositories.d.ts +11 -0
- package/components/repositories/BrowseRepositories.js +184 -0
- package/components/repositories/index.d.ts +2 -0
- package/components/repositories/index.js +2 -0
- package/components/search/SearchContent.d.ts +4 -0
- package/components/search/SearchContent.js +168 -0
- package/components/search/index.d.ts +2 -0
- package/components/search/index.js +1 -0
- package/components/search/types.d.ts +15 -0
- package/components/search/types.js +1 -0
- package/contexts/entity-context.d.ts +28 -0
- package/contexts/entity-context.js +89 -0
- package/contexts/graph-context.d.ts +27 -0
- package/contexts/graph-context.js +128 -0
- package/contexts/index.d.ts +5 -0
- package/contexts/index.js +5 -0
- package/contexts/org-context.d.ts +25 -0
- package/contexts/org-context.js +64 -0
- package/contexts/service-offerings-context.d.ts +45 -0
- package/contexts/service-offerings-context.js +98 -0
- package/contexts/sidebar-context.d.ts +18 -0
- package/contexts/sidebar-context.js +44 -0
- package/hooks/index.d.ts +6 -0
- package/hooks/index.js +6 -0
- package/hooks/use-api-error.d.ts +3 -0
- package/hooks/use-api-error.js +24 -0
- package/hooks/use-media-query.d.ts +1 -0
- package/hooks/use-media-query.js +21 -0
- package/hooks/use-streaming-query.d.ts +22 -0
- package/hooks/use-streaming-query.js +142 -0
- package/hooks/use-toast.d.ts +37 -0
- package/hooks/use-toast.js +117 -0
- package/hooks/use-user-limits.d.ts +12 -0
- package/hooks/use-user-limits.js +73 -0
- package/hooks/use-user.d.ts +11 -0
- package/hooks/use-user.js +39 -0
- package/index.d.ts +29 -0
- package/index.js +77 -0
- package/lib/entity-cookie.d.ts +10 -0
- package/lib/entity-cookie.js +38 -0
- package/lib/graph-cookie.d.ts +11 -0
- package/lib/graph-cookie.js +62 -0
- package/lib/graph-tiers.d.ts +41 -0
- package/lib/graph-tiers.js +107 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/sidebar-cookie.d.ts +11 -0
- package/lib/sidebar-cookie.js +42 -0
- package/library/colors.d.ts +4 -0
- package/library/colors.js +41 -0
- package/library/components/ClassificationPicker.d.ts +8 -0
- package/library/components/ClassificationPicker.js +55 -0
- package/library/components/ElementBrowser.d.ts +11 -0
- package/library/components/ElementBrowser.js +106 -0
- package/library/components/ElementDetail.d.ts +7 -0
- package/library/components/ElementDetail.js +97 -0
- package/library/components/LibraryHierarchy.d.ts +13 -0
- package/library/components/LibraryHierarchy.js +380 -0
- package/library/components/TaxonomySidebar.d.ts +6 -0
- package/library/components/TaxonomySidebar.js +45 -0
- package/library/index.d.ts +8 -0
- package/library/index.js +7 -0
- package/package.json +37 -0
- package/research/CoverageCard.d.ts +12 -0
- package/research/CoverageCard.js +15 -0
- package/research/CoverageGrid.d.ts +6 -0
- package/research/CoverageGrid.js +9 -0
- package/research/CoverageHistory.d.ts +5 -0
- package/research/CoverageHistory.js +7 -0
- package/research/ResearchArticle.d.ts +15 -0
- package/research/ResearchArticle.js +26 -0
- package/research/catalog.d.ts +14 -0
- package/research/catalog.js +42 -0
- package/research/index.d.ts +6 -0
- package/research/index.js +9 -0
- package/research/types.d.ts +38 -0
- package/research/types.js +4 -0
- package/task-monitoring/hooks.d.ts +26 -0
- package/task-monitoring/hooks.js +126 -0
- package/task-monitoring/index.d.ts +5 -0
- package/task-monitoring/index.js +7 -0
- package/task-monitoring/operationErrors.d.ts +82 -0
- package/task-monitoring/operationErrors.js +251 -0
- package/task-monitoring/operationHooks.d.ts +117 -0
- package/task-monitoring/operationHooks.js +536 -0
- package/task-monitoring/operationMonitor.d.ts +78 -0
- package/task-monitoring/operationMonitor.js +200 -0
- package/task-monitoring/operationTypes.d.ts +236 -0
- package/task-monitoring/operationTypes.js +60 -0
- package/task-monitoring/taskMonitor.d.ts +14 -0
- package/task-monitoring/taskMonitor.js +132 -0
- package/task-monitoring/types.d.ts +31 -0
- package/task-monitoring/types.js +1 -0
- package/theme/flowbite-theme.d.ts +758 -0
- package/theme/flowbite-theme.js +765 -0
- package/theme/index.d.ts +1 -0
- package/theme/index.js +1 -0
- package/types/entity.d.ts +19 -0
- package/types/index.d.ts +2 -0
- package/types/index.js +1 -0
- package/types/user.d.ts +6 -0
- package/ui-components/ConfirmModal.d.ts +41 -0
- package/ui-components/ConfirmModal.js +19 -0
- package/ui-components/EmptyState.d.ts +22 -0
- package/ui-components/EmptyState.js +10 -0
- package/ui-components/LoadingState.d.ts +27 -0
- package/ui-components/LoadingState.js +12 -0
- package/ui-components/Logo.d.ts +28 -0
- package/ui-components/Logo.js +95 -0
- package/ui-components/Spinner.d.ts +37 -0
- package/ui-components/Spinner.js +48 -0
- package/ui-components/StatCard.d.ts +21 -0
- package/ui-components/StatCard.js +10 -0
- package/ui-components/api-keys/ApiKeyDisplay.d.ts +13 -0
- package/ui-components/api-keys/ApiKeyDisplay.js +7 -0
- package/ui-components/api-keys/ApiKeyTable.d.ts +9 -0
- package/ui-components/api-keys/ApiKeyTable.js +17 -0
- package/ui-components/api-keys/ApiKeysCard.d.ts +6 -0
- package/ui-components/api-keys/ApiKeysCard.js +97 -0
- package/ui-components/api-keys/CreateApiKeyModal.d.ts +11 -0
- package/ui-components/api-keys/CreateApiKeyModal.js +47 -0
- package/ui-components/api-keys/SecureApiKeyField.d.ts +13 -0
- package/ui-components/api-keys/SecureApiKeyField.js +64 -0
- package/ui-components/api-keys/index.d.ts +5 -0
- package/ui-components/api-keys/index.js +5 -0
- package/ui-components/chat/ChatHeader.d.ts +12 -0
- package/ui-components/chat/ChatHeader.js +5 -0
- package/ui-components/chat/ChatInputArea.d.ts +16 -0
- package/ui-components/chat/ChatInputArea.js +9 -0
- package/ui-components/chat/ChatMessage.d.ts +7 -0
- package/ui-components/chat/ChatMessage.js +24 -0
- package/ui-components/chat/DeepResearchToggle.d.ts +8 -0
- package/ui-components/chat/DeepResearchToggle.js +13 -0
- package/ui-components/chat/index.d.ts +9 -0
- package/ui-components/chat/index.js +8 -0
- package/ui-components/chat/types.d.ts +23 -0
- package/ui-components/chat/types.js +51 -0
- package/ui-components/forms/PasswordRequirements.d.ts +10 -0
- package/ui-components/forms/PasswordRequirements.js +15 -0
- package/ui-components/forms/SettingsCard.d.ts +11 -0
- package/ui-components/forms/SettingsCard.js +5 -0
- package/ui-components/forms/SettingsFormField.d.ts +18 -0
- package/ui-components/forms/SettingsFormField.js +17 -0
- package/ui-components/forms/StatusAlert.d.ts +8 -0
- package/ui-components/forms/StatusAlert.js +7 -0
- package/ui-components/forms/index.d.ts +4 -0
- package/ui-components/forms/index.js +4 -0
- package/ui-components/index.d.ts +13 -0
- package/ui-components/index.js +18 -0
- package/ui-components/layout/CoreNavbar.d.ts +14 -0
- package/ui-components/layout/CoreNavbar.js +53 -0
- package/ui-components/layout/CoreSidebar.d.ts +28 -0
- package/ui-components/layout/CoreSidebar.js +62 -0
- package/ui-components/layout/LandingFooter.d.ts +28 -0
- package/ui-components/layout/LandingFooter.js +34 -0
- package/ui-components/layout/PageContainer.d.ts +8 -0
- package/ui-components/layout/PageContainer.js +17 -0
- package/ui-components/layout/PageHeader.d.ts +23 -0
- package/ui-components/layout/PageHeader.js +12 -0
- package/ui-components/layout/SettingsContainer.d.ts +10 -0
- package/ui-components/layout/SettingsContainer.js +9 -0
- package/ui-components/layout/ThemeToggle.d.ts +4 -0
- package/ui-components/layout/ThemeToggle.js +6 -0
- package/ui-components/layout/index.d.ts +7 -0
- package/ui-components/layout/index.js +7 -0
- package/ui-components/settings/GeneralInformationCard.d.ts +12 -0
- package/ui-components/settings/GeneralInformationCard.js +72 -0
- package/ui-components/settings/PasswordInformationCard.d.ts +10 -0
- package/ui-components/settings/PasswordInformationCard.js +167 -0
- package/ui-components/settings/SettingsPageHeader.d.ts +7 -0
- package/ui-components/settings/SettingsPageHeader.js +6 -0
- package/ui-components/settings/index.d.ts +3 -0
- package/ui-components/settings/index.js +3 -0
- package/ui-components/support/SupportModal.d.ts +15 -0
- package/ui-components/support/SupportModal.js +74 -0
- package/ui-components/support/index.d.ts +2 -0
- package/ui-components/support/index.js +1 -0
- package/ui-components/types/index.d.ts +39 -0
- package/ui-components/types/index.js +1 -0
- package/utils/index.d.ts +31 -0
- package/utils/index.js +38 -0
- package/utils/turnstile-config.d.ts +11 -0
- package/utils/turnstile-config.js +19 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as SDK from '@robosystems/client';
|
|
4
|
+
import { Alert, Badge, Button, Card, Select, Spinner, TextInput, ToggleSwitch, } from 'flowbite-react';
|
|
5
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
6
|
+
import { HiChevronDown, HiChevronUp, HiSearch } from 'react-icons/hi';
|
|
7
|
+
import ReactMarkdown from 'react-markdown';
|
|
8
|
+
import remarkGfm from 'remark-gfm';
|
|
9
|
+
import { useIsRepository } from '../../components/RepositoryGuard';
|
|
10
|
+
import { useGraphContext } from '../../contexts';
|
|
11
|
+
import { PageLayout } from '../PageLayout';
|
|
12
|
+
const PAGE_SIZE = 20;
|
|
13
|
+
export function SearchContent({ config }) {
|
|
14
|
+
var _a, _b, _c;
|
|
15
|
+
const { state: graphState } = useGraphContext();
|
|
16
|
+
const graphId = graphState.currentGraphId;
|
|
17
|
+
const { isRepository } = useIsRepository();
|
|
18
|
+
// Search state
|
|
19
|
+
const [query, setQuery] = useState('');
|
|
20
|
+
const [sourceType, setSourceType] = useState((_a = config.defaultSourceType) !== null && _a !== void 0 ? _a : '');
|
|
21
|
+
const [entity, setEntity] = useState('');
|
|
22
|
+
const [formType, setFormType] = useState('');
|
|
23
|
+
const [fiscalYear, setFiscalYear] = useState('');
|
|
24
|
+
const [semantic, setSemantic] = useState(false);
|
|
25
|
+
// Results state
|
|
26
|
+
const [results, setResults] = useState([]);
|
|
27
|
+
const [total, setTotal] = useState(0);
|
|
28
|
+
const [offset, setOffset] = useState(0);
|
|
29
|
+
const [loading, setLoading] = useState(false);
|
|
30
|
+
const [error, setError] = useState(null);
|
|
31
|
+
const [searchedQuery, setSearchedQuery] = useState('');
|
|
32
|
+
// Document stats
|
|
33
|
+
const [docCount, setDocCount] = useState(null);
|
|
34
|
+
// Expanded section
|
|
35
|
+
const [expandedDocId, setExpandedDocId] = useState(null);
|
|
36
|
+
const [sectionContent, setSectionContent] = useState(null);
|
|
37
|
+
const [sectionLoading, setSectionLoading] = useState(false);
|
|
38
|
+
// Filters visibility
|
|
39
|
+
const [showFilters, setShowFilters] = useState((_b = config.showFilters) !== null && _b !== void 0 ? _b : false);
|
|
40
|
+
const filters = (_c = config.filters) !== null && _c !== void 0 ? _c : { sourceType: true };
|
|
41
|
+
// Load document stats when graph changes (skip for shared repositories)
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!graphId || isRepository) {
|
|
44
|
+
setDocCount(null);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
SDK.listDocuments({ path: { graph_id: graphId } })
|
|
48
|
+
.then((res) => {
|
|
49
|
+
if (res.data) {
|
|
50
|
+
setDocCount(res.data.total);
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
.catch(() => { });
|
|
54
|
+
}, [graphId, isRepository]);
|
|
55
|
+
// Reset when graph changes
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
setResults([]);
|
|
58
|
+
setTotal(0);
|
|
59
|
+
setOffset(0);
|
|
60
|
+
setSearchedQuery('');
|
|
61
|
+
setError(null);
|
|
62
|
+
setExpandedDocId(null);
|
|
63
|
+
setSectionContent(null);
|
|
64
|
+
}, [graphId]);
|
|
65
|
+
const handleSearch = useCallback(async (newOffset = 0) => {
|
|
66
|
+
if (!graphId || !query.trim())
|
|
67
|
+
return;
|
|
68
|
+
setLoading(true);
|
|
69
|
+
setError(null);
|
|
70
|
+
setExpandedDocId(null);
|
|
71
|
+
setSectionContent(null);
|
|
72
|
+
try {
|
|
73
|
+
const body = {
|
|
74
|
+
query: query.trim(),
|
|
75
|
+
size: PAGE_SIZE,
|
|
76
|
+
offset: newOffset,
|
|
77
|
+
};
|
|
78
|
+
if (sourceType)
|
|
79
|
+
body.source_type = sourceType;
|
|
80
|
+
if (entity)
|
|
81
|
+
body.entity = entity;
|
|
82
|
+
if (formType)
|
|
83
|
+
body.form_type = formType;
|
|
84
|
+
if (fiscalYear) {
|
|
85
|
+
const parsed = parseInt(fiscalYear, 10);
|
|
86
|
+
if (Number.isFinite(parsed))
|
|
87
|
+
body.fiscal_year = parsed;
|
|
88
|
+
}
|
|
89
|
+
if (semantic)
|
|
90
|
+
body.semantic = true;
|
|
91
|
+
const res = await SDK.searchDocuments({
|
|
92
|
+
path: { graph_id: graphId },
|
|
93
|
+
body: body,
|
|
94
|
+
});
|
|
95
|
+
if (res.data) {
|
|
96
|
+
const data = res.data;
|
|
97
|
+
setResults(data.hits);
|
|
98
|
+
setTotal(data.total);
|
|
99
|
+
setOffset(newOffset);
|
|
100
|
+
setSearchedQuery(data.query);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
setError('Search failed. Please try again.');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (_a) {
|
|
107
|
+
setError('An error occurred while searching.');
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
setLoading(false);
|
|
111
|
+
}
|
|
112
|
+
}, [graphId, query, sourceType, entity, formType, fiscalYear, semantic]);
|
|
113
|
+
const handleKeyDown = (e) => {
|
|
114
|
+
if (e.key === 'Enter') {
|
|
115
|
+
handleSearch(0);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const handleExpand = async (docId) => {
|
|
119
|
+
if (expandedDocId === docId) {
|
|
120
|
+
setExpandedDocId(null);
|
|
121
|
+
setSectionContent(null);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (!graphId)
|
|
125
|
+
return;
|
|
126
|
+
setExpandedDocId(docId);
|
|
127
|
+
setSectionContent(null);
|
|
128
|
+
setSectionLoading(true);
|
|
129
|
+
try {
|
|
130
|
+
const res = await SDK.getDocumentSection({
|
|
131
|
+
path: { graph_id: graphId, document_id: docId },
|
|
132
|
+
});
|
|
133
|
+
if (res.data) {
|
|
134
|
+
setSectionContent(res.data);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (_a) {
|
|
138
|
+
setSectionContent(null);
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
setSectionLoading(false);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const hasFilters = filters.entity ||
|
|
145
|
+
filters.formType ||
|
|
146
|
+
filters.fiscalYear ||
|
|
147
|
+
filters.sourceType ||
|
|
148
|
+
filters.semantic;
|
|
149
|
+
if (!graphId) {
|
|
150
|
+
return (_jsx(PageLayout, { children: _jsxs("div", { className: "py-12 text-center", children: [_jsx("div", { className: "from-primary-500 to-secondary-600 mx-auto mb-4 w-fit rounded-lg bg-gradient-to-br p-3", children: _jsx(HiSearch, { className: "h-8 w-8 text-white" }) }), _jsx("h2", { className: "font-heading text-lg font-semibold text-gray-700 dark:text-gray-300", children: config.title }), _jsx("p", { className: "mt-2 text-gray-500 dark:text-gray-400", children: "Select a graph to search documents." })] }) }));
|
|
151
|
+
}
|
|
152
|
+
return (_jsxs(PageLayout, { children: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx("div", { className: "from-primary-500 to-secondary-600 rounded-lg bg-gradient-to-br p-3", children: _jsx(HiSearch, { className: "h-8 w-8 text-white" }) }), _jsxs("div", { children: [_jsx("h1", { className: "font-heading text-3xl font-bold text-gray-900 dark:text-white", children: config.title }), _jsxs("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: [config.description, docCount !== null && docCount > 0 && (_jsxs("span", { className: "ml-2 text-gray-400 dark:text-gray-500", children: ["(", docCount, " document", docCount !== 1 ? 's' : '', " indexed)"] }))] })] })] }), _jsx(Card, { children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex gap-2", children: [_jsx(TextInput, { className: "flex-1", placeholder: config.placeholder, value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: handleKeyDown, icon: HiSearch }), _jsx(Button, { color: "purple", onClick: () => handleSearch(0), disabled: loading || !query.trim(), children: loading ? (_jsx(Spinner, { size: "sm", className: "text-white" })) : ('Search') })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-4", children: [hasFilters && (_jsxs("button", { type: "button", onClick: () => setShowFilters(!showFilters), className: "flex items-center gap-1 text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200", children: ["Filters", showFilters ? (_jsx(HiChevronUp, { className: "h-4 w-4" })) : (_jsx(HiChevronDown, { className: "h-4 w-4" }))] })), filters.semantic && (_jsx(ToggleSwitch, { checked: semantic, onChange: setSemantic, label: "Semantic search" }))] }), showFilters && hasFilters && (_jsxs("div", { className: "grid grid-cols-1 gap-3 border-t border-gray-200 pt-4 sm:grid-cols-2 lg:grid-cols-4 dark:border-gray-700", children: [filters.sourceType && (_jsxs("div", { children: [_jsx("label", { htmlFor: "search-source-type", className: "mb-1 block text-xs font-medium text-gray-500 dark:text-gray-400", children: "Source Type" }), _jsxs(Select, { id: "search-source-type", value: sourceType, onChange: (e) => setSourceType(e.target.value), children: [_jsx("option", { value: "", children: "All types" }), _jsx("option", { value: "uploaded_doc", children: "Uploaded Documents" }), _jsx("option", { value: "memory", children: "AI Memories" }), _jsx("option", { value: "narrative_section", children: "Narrative Sections" }), _jsx("option", { value: "xbrl_textblock", children: "XBRL Text Blocks" }), _jsx("option", { value: "ixbrl_disclosure", children: "iXBRL Disclosures" })] })] })), filters.entity && (_jsxs("div", { children: [_jsx("label", { htmlFor: "search-entity", className: "mb-1 block text-xs font-medium text-gray-500 dark:text-gray-400", children: "Entity / Ticker" }), _jsx(TextInput, { id: "search-entity", placeholder: "e.g. NVDA", value: entity, onChange: (e) => setEntity(e.target.value) })] })), filters.formType && (_jsxs("div", { children: [_jsx("label", { htmlFor: "search-form-type", className: "mb-1 block text-xs font-medium text-gray-500 dark:text-gray-400", children: "Form Type" }), _jsxs(Select, { id: "search-form-type", value: formType, onChange: (e) => setFormType(e.target.value), children: [_jsx("option", { value: "", children: "All forms" }), _jsx("option", { value: "10-K", children: "10-K (Annual)" }), _jsx("option", { value: "10-Q", children: "10-Q (Quarterly)" }), _jsx("option", { value: "8-K", children: "8-K (Current)" }), _jsx("option", { value: "20-F", children: "20-F (Foreign Annual)" })] })] })), filters.fiscalYear && (_jsxs("div", { children: [_jsx("label", { htmlFor: "search-fiscal-year", className: "mb-1 block text-xs font-medium text-gray-500 dark:text-gray-400", children: "Fiscal Year" }), _jsx(TextInput, { id: "search-fiscal-year", type: "number", placeholder: "e.g. 2024", min: 1900, max: 2100, value: fiscalYear, onChange: (e) => setFiscalYear(e.target.value) })] }))] }))] }) }), error && (_jsx(Alert, { color: "failure", children: _jsx("span", { children: error }) })), results.length > 0 && (_jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "flex items-center justify-between", children: _jsxs("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: ["Showing ", offset + 1, "\u2013", Math.min(offset + PAGE_SIZE, total), " of", ' ', total, " results for \"", searchedQuery, "\""] }) }), results.map((hit) => {
|
|
153
|
+
var _a;
|
|
154
|
+
return (_jsxs(Card, { children: [_jsx("button", { type: "button", className: "w-full cursor-pointer text-left", onClick: () => handleExpand(hit.document_id), "aria-expanded": expandedDocId === hit.document_id, children: _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("h3", { className: "text-base font-semibold text-gray-900 dark:text-white", children: hit.document_title || hit.section_label || 'Untitled' }), hit.section_label && hit.document_title && (_jsxs("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: ["/ ", hit.section_label] }))] }), _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-2", children: [_jsx(Badge, { color: "info", size: "xs", children: hit.score.toFixed(2) }), _jsx(Badge, { color: "gray", size: "xs", children: hit.source_type }), hit.entity_ticker && (_jsx(Badge, { color: "purple", size: "xs", children: hit.entity_ticker })), hit.form_type && (_jsx(Badge, { color: "warning", size: "xs", children: hit.form_type })), hit.fiscal_year && (_jsxs(Badge, { color: "gray", size: "xs", children: ["FY", hit.fiscal_year] })), (_a = hit.tags) === null || _a === void 0 ? void 0 : _a.map((tag) => (_jsx(Badge, { color: "purple", size: "xs", children: tag }, tag)))] }), hit.snippet && (_jsx("p", { className: "mt-3 line-clamp-2 text-sm text-gray-500 dark:text-gray-400", children: hit.snippet }))] }), _jsx("div", { className: "ml-3 shrink-0 pt-1", children: expandedDocId === hit.document_id ? (_jsx(HiChevronUp, { className: "h-5 w-5 text-gray-400" })) : (_jsx(HiChevronDown, { className: "h-5 w-5 text-gray-400" })) })] }) }), expandedDocId === hit.document_id && (_jsx("div", { className: "border-t border-gray-200 pt-4 dark:border-gray-700", children: sectionLoading ? (_jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-500", children: [_jsx(Spinner, { size: "sm" }), "Loading full content..."] })) : sectionContent ? (_jsxs("div", { children: [_jsx("div", { className: "prose prose-sm prose-gray max-h-96 max-w-none overflow-auto rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-600 dark:bg-gray-800", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: {
|
|
155
|
+
h1: ({ children }) => (_jsx("h1", { className: "text-gray-900 dark:text-white", children: children })),
|
|
156
|
+
h2: ({ children }) => (_jsx("h2", { className: "text-gray-900 dark:text-white", children: children })),
|
|
157
|
+
h3: ({ children }) => (_jsx("h3", { className: "text-gray-900 dark:text-white", children: children })),
|
|
158
|
+
h4: ({ children }) => (_jsx("h4", { className: "text-gray-900 dark:text-white", children: children })),
|
|
159
|
+
p: ({ children }) => (_jsx("p", { className: "text-gray-700 dark:text-gray-200", children: children })),
|
|
160
|
+
li: ({ children }) => (_jsx("li", { className: "text-gray-700 dark:text-gray-200", children: children })),
|
|
161
|
+
strong: ({ children }) => (_jsx("strong", { className: "text-gray-900 dark:text-white", children: children })),
|
|
162
|
+
table: ({ children }) => (_jsx("div", { className: "overflow-x-auto", children: _jsx("table", { className: "min-w-full border-collapse text-sm", children: children }) })),
|
|
163
|
+
thead: ({ children }) => (_jsx("thead", { className: "border-b-2 border-gray-300 dark:border-gray-600", children: children })),
|
|
164
|
+
th: ({ children }) => (_jsx("th", { className: "px-3 py-2 text-left font-semibold text-gray-900 dark:text-white", children: children })),
|
|
165
|
+
td: ({ children }) => (_jsx("td", { className: "border-t border-gray-200 px-3 py-2 text-gray-700 dark:border-gray-700 dark:text-gray-200", children: children })),
|
|
166
|
+
}, children: sectionContent.content }) }), sectionContent.content_length && (_jsxs("p", { className: "mt-2 text-xs text-gray-400 dark:text-gray-500", children: [sectionContent.content_length.toLocaleString(), ' ', "characters"] }))] })) : (_jsx("p", { className: "text-sm text-gray-500", children: "Could not load section content." })) }))] }, hit.document_id));
|
|
167
|
+
}), total > PAGE_SIZE && (_jsxs("div", { className: "flex items-center justify-between pt-2", children: [_jsx(Button, { color: "gray", size: "sm", disabled: offset === 0 || loading, onClick: () => handleSearch(Math.max(0, offset - PAGE_SIZE)), children: "Previous" }), _jsxs("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: ["Page ", Math.floor(offset / PAGE_SIZE) + 1, " of", ' ', Math.ceil(total / PAGE_SIZE)] }), _jsx(Button, { color: "gray", size: "sm", disabled: offset + PAGE_SIZE >= total || loading, onClick: () => handleSearch(offset + PAGE_SIZE), children: "Next" })] }))] })), !loading && searchedQuery && results.length === 0 && (_jsxs("div", { className: "py-8 text-center", children: [_jsxs("p", { className: "text-gray-500 dark:text-gray-400", children: ["No results found for \"", searchedQuery, "\"."] }), _jsx("p", { className: "mt-1 text-sm text-gray-400 dark:text-gray-500", children: "Try a different query or adjust your filters." })] }))] }));
|
|
168
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SearchContent } from './SearchContent';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface SearchFilterConfig {
|
|
2
|
+
sourceType?: boolean;
|
|
3
|
+
entity?: boolean;
|
|
4
|
+
formType?: boolean;
|
|
5
|
+
fiscalYear?: boolean;
|
|
6
|
+
semantic?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface SearchConfig {
|
|
9
|
+
title: string;
|
|
10
|
+
description: string;
|
|
11
|
+
placeholder: string;
|
|
12
|
+
showFilters?: boolean;
|
|
13
|
+
defaultSourceType?: string;
|
|
14
|
+
filters?: SearchFilterConfig;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type PropsWithChildren } from 'react';
|
|
2
|
+
import type { Entity } from '../types';
|
|
3
|
+
export interface EntityContextValue {
|
|
4
|
+
currentEntity: Entity | null;
|
|
5
|
+
setCurrentEntity: (entity: Entity | null) => void;
|
|
6
|
+
clearEntity: () => void;
|
|
7
|
+
}
|
|
8
|
+
export interface EntityProviderProps extends PropsWithChildren {
|
|
9
|
+
initialEntityCookie?: {
|
|
10
|
+
identifier: string;
|
|
11
|
+
name: string;
|
|
12
|
+
graphId: string;
|
|
13
|
+
} | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* EntityProvider - Manages entity selection for entity-based graphs
|
|
17
|
+
*
|
|
18
|
+
* This provider wraps GraphProvider and adds entity-specific state management.
|
|
19
|
+
* Entity selection persists across page refreshes using cookies.
|
|
20
|
+
*
|
|
21
|
+
* Use this for apps that work with entity-based graphs (RoboLedger, RoboInvestor, etc.)
|
|
22
|
+
*/
|
|
23
|
+
export declare function EntityProvider({ children, initialEntityCookie, }: EntityProviderProps): import("react").JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* Hook to access entity context
|
|
26
|
+
* Must be used within an EntityProvider
|
|
27
|
+
*/
|
|
28
|
+
export declare function useEntity(): EntityContextValue;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useState, } from 'react';
|
|
4
|
+
import { clearEntitySelection, persistEntitySelection, } from '../actions/entity-actions';
|
|
5
|
+
import { useGraphContext } from './graph-context';
|
|
6
|
+
const EntityContext = createContext(null);
|
|
7
|
+
/**
|
|
8
|
+
* EntityProvider - Manages entity selection for entity-based graphs
|
|
9
|
+
*
|
|
10
|
+
* This provider wraps GraphProvider and adds entity-specific state management.
|
|
11
|
+
* Entity selection persists across page refreshes using cookies.
|
|
12
|
+
*
|
|
13
|
+
* Use this for apps that work with entity-based graphs (RoboLedger, RoboInvestor, etc.)
|
|
14
|
+
*/
|
|
15
|
+
export function EntityProvider({ children, initialEntityCookie, }) {
|
|
16
|
+
const { state: graphState } = useGraphContext();
|
|
17
|
+
const [currentEntity, setCurrentEntityState] = useState(() => {
|
|
18
|
+
// Initialize from cookie if available
|
|
19
|
+
if (initialEntityCookie) {
|
|
20
|
+
return {
|
|
21
|
+
identifier: initialEntityCookie.identifier,
|
|
22
|
+
name: initialEntityCookie.name,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
});
|
|
27
|
+
const setCurrentEntity = useCallback(async (entity) => {
|
|
28
|
+
setCurrentEntityState(entity);
|
|
29
|
+
// Persist to cookie
|
|
30
|
+
try {
|
|
31
|
+
if (entity && graphState.currentGraphId) {
|
|
32
|
+
await persistEntitySelection(entity, graphState.currentGraphId);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
await clearEntitySelection();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error('Failed to persist entity selection:', error);
|
|
40
|
+
// Don't throw - we don't want to break the UI if cookie persistence fails
|
|
41
|
+
// The entity state is still updated in memory
|
|
42
|
+
}
|
|
43
|
+
}, [graphState.currentGraphId]);
|
|
44
|
+
// Validate entity cookie against user's actual graphs on load
|
|
45
|
+
// If the cookie's graphId doesn't belong to the current user, clear it
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (currentEntity &&
|
|
48
|
+
(initialEntityCookie === null || initialEntityCookie === void 0 ? void 0 : initialEntityCookie.graphId) &&
|
|
49
|
+
!graphState.isLoading &&
|
|
50
|
+
graphState.graphs.length > 0) {
|
|
51
|
+
const graphExists = graphState.graphs.some((g) => g.graphId === initialEntityCookie.graphId);
|
|
52
|
+
if (!graphExists) {
|
|
53
|
+
setCurrentEntityState(null);
|
|
54
|
+
clearEntitySelection().catch((error) => {
|
|
55
|
+
console.error('Failed to clear stale entity selection:', error);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- intentionally omit currentEntity to avoid re-triggering after clearing
|
|
60
|
+
}, [graphState.isLoading, graphState.graphs, initialEntityCookie]);
|
|
61
|
+
const clearEntity = useCallback(async () => {
|
|
62
|
+
setCurrentEntityState(null);
|
|
63
|
+
try {
|
|
64
|
+
await clearEntitySelection();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.error('Failed to clear entity selection:', error);
|
|
68
|
+
// Don't throw - we don't want to break the UI if cookie clearing fails
|
|
69
|
+
// The entity state is still cleared in memory
|
|
70
|
+
}
|
|
71
|
+
}, []);
|
|
72
|
+
const value = {
|
|
73
|
+
currentEntity,
|
|
74
|
+
setCurrentEntity,
|
|
75
|
+
clearEntity,
|
|
76
|
+
};
|
|
77
|
+
return (_jsx(EntityContext.Provider, { value: value, children: children }));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Hook to access entity context
|
|
81
|
+
* Must be used within an EntityProvider
|
|
82
|
+
*/
|
|
83
|
+
export function useEntity() {
|
|
84
|
+
const context = useContext(EntityContext);
|
|
85
|
+
if (!context) {
|
|
86
|
+
throw new Error('useEntity must be used within an EntityProvider');
|
|
87
|
+
}
|
|
88
|
+
return context;
|
|
89
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { GraphInfo } from '@robosystems/client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export interface GraphState {
|
|
4
|
+
graphs: GraphInfo[];
|
|
5
|
+
currentGraphId: string | null;
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
error: string | null;
|
|
8
|
+
}
|
|
9
|
+
export interface GraphContextValue<T extends GraphState = GraphState> {
|
|
10
|
+
state: T;
|
|
11
|
+
loadGraphs: () => Promise<void>;
|
|
12
|
+
setCurrentGraph: (graphId: string) => Promise<void>;
|
|
13
|
+
refreshGraphs: () => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare function createGraphContext<T extends GraphState = GraphState>(): React.Context<GraphContextValue<T>>;
|
|
16
|
+
export interface GraphProviderProps<T extends GraphState = GraphState> {
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
initialGraphId?: string | null;
|
|
19
|
+
graphFilter?: (graph: GraphInfo) => boolean;
|
|
20
|
+
transformState?: (baseState: GraphState) => T;
|
|
21
|
+
persistGraphSelection: (graphId: string) => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export declare function createGraphProvider<T extends GraphState = GraphState>(Context: React.Context<GraphContextValue<T> | null>): ({ children, initialGraphId, graphFilter, transformState, persistGraphSelection, }: GraphProviderProps<T>) => React.JSX.Element;
|
|
24
|
+
export declare function createUseGraphContext<T extends GraphState = GraphState>(Context: React.Context<GraphContextValue<T> | null>): () => GraphContextValue<T>;
|
|
25
|
+
export declare const GraphContext: React.Context<GraphContextValue<GraphState>>;
|
|
26
|
+
export declare const GraphProvider: ({ children, initialGraphId, graphFilter, transformState, persistGraphSelection, }: GraphProviderProps<GraphState>) => React.JSX.Element;
|
|
27
|
+
export declare const useGraphContext: () => GraphContextValue<GraphState>;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as SDK from '@robosystems/client';
|
|
4
|
+
import { createContext, useCallback, useContext, useEffect, useState, } from 'react';
|
|
5
|
+
// Factory function to create a typed graph context
|
|
6
|
+
export function createGraphContext() {
|
|
7
|
+
return createContext(null);
|
|
8
|
+
}
|
|
9
|
+
// Helper to check if error is 403 Forbidden
|
|
10
|
+
function is403Error(error) {
|
|
11
|
+
var _a;
|
|
12
|
+
return ((error === null || error === void 0 ? void 0 : error.status) === 403 ||
|
|
13
|
+
((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) === 403 ||
|
|
14
|
+
(typeof error === 'object' && 'status' in error && error.status === 403));
|
|
15
|
+
}
|
|
16
|
+
// Generic provider factory
|
|
17
|
+
export function createGraphProvider(Context) {
|
|
18
|
+
return function GraphProvider({ children, initialGraphId, graphFilter, transformState, persistGraphSelection, }) {
|
|
19
|
+
const [baseState, setBaseState] = useState({
|
|
20
|
+
graphs: [],
|
|
21
|
+
currentGraphId: initialGraphId !== null && initialGraphId !== void 0 ? initialGraphId : null,
|
|
22
|
+
isLoading: false,
|
|
23
|
+
error: null,
|
|
24
|
+
});
|
|
25
|
+
// Transform state if needed
|
|
26
|
+
const state = transformState ? transformState(baseState) : baseState;
|
|
27
|
+
// Load all user graphs
|
|
28
|
+
const loadGraphs = useCallback(async () => {
|
|
29
|
+
setBaseState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: true, error: null })));
|
|
30
|
+
try {
|
|
31
|
+
const response = await SDK.getGraphs();
|
|
32
|
+
if (response.data) {
|
|
33
|
+
const graphsData = response.data;
|
|
34
|
+
let graphs = graphsData.graphs || [];
|
|
35
|
+
// Apply optional filter
|
|
36
|
+
if (graphFilter) {
|
|
37
|
+
graphs = graphs.filter(graphFilter);
|
|
38
|
+
}
|
|
39
|
+
const selectedGraphId = graphsData.selectedGraphId || initialGraphId;
|
|
40
|
+
// Validate that selectedGraphId exists in graphs array
|
|
41
|
+
const graphIds = graphs.map((g) => g.graphId);
|
|
42
|
+
const validSelectedId = selectedGraphId && graphIds.includes(selectedGraphId)
|
|
43
|
+
? selectedGraphId
|
|
44
|
+
: null;
|
|
45
|
+
setBaseState((prev) => {
|
|
46
|
+
// Determine which graph should be selected
|
|
47
|
+
let newCurrentGraphId = validSelectedId || (graphs.length > 0 ? graphs[0].graphId : null);
|
|
48
|
+
// IMPORTANT: If we currently have a repository selected, preserve it
|
|
49
|
+
// The API's selectedGraphId only tracks user graphs, not repositories
|
|
50
|
+
if (prev.currentGraphId) {
|
|
51
|
+
const currentGraph = graphs.find((g) => g.graphId === prev.currentGraphId);
|
|
52
|
+
// If current selection is still in the graph list, keep it
|
|
53
|
+
// This prevents loadGraphs from overwriting repository selections
|
|
54
|
+
if (currentGraph) {
|
|
55
|
+
newCurrentGraphId = prev.currentGraphId;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return Object.assign(Object.assign({}, prev), { graphs, currentGraphId: newCurrentGraphId, isLoading: false });
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error('Failed to load graphs:', error);
|
|
64
|
+
setBaseState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, error: 'Failed to load graphs' })));
|
|
65
|
+
}
|
|
66
|
+
}, [initialGraphId, graphFilter]);
|
|
67
|
+
// Set current graph with persistence
|
|
68
|
+
const setCurrentGraph = useCallback(async (graphId) => {
|
|
69
|
+
try {
|
|
70
|
+
// Use functional setState to access current graphs and determine if repository
|
|
71
|
+
let isUserGraph = false;
|
|
72
|
+
setBaseState((prev) => {
|
|
73
|
+
const graph = prev.graphs.find((g) => g.graphId === graphId);
|
|
74
|
+
// Only treat as a user graph if found and NOT a repository
|
|
75
|
+
isUserGraph = graph ? !graph.isRepository : false;
|
|
76
|
+
return Object.assign(Object.assign({}, prev), { currentGraphId: graphId });
|
|
77
|
+
});
|
|
78
|
+
// Only call selectGraph API for user graphs, not repositories
|
|
79
|
+
// Repositories can be accessed but not "selected" in the backend
|
|
80
|
+
// If graph is not found in local state, skip the API call (likely a repository)
|
|
81
|
+
if (isUserGraph) {
|
|
82
|
+
await SDK.selectGraph({
|
|
83
|
+
path: { graph_id: graphId },
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
console.error('Failed to select graph via API:', error);
|
|
89
|
+
// Don't throw - state is already updated, navigation should continue
|
|
90
|
+
}
|
|
91
|
+
// Persist to cookies via server action - fire and forget
|
|
92
|
+
// This can fail in production (e.g. server action issues behind CDN)
|
|
93
|
+
// but shouldn't block graph selection since React state is already set
|
|
94
|
+
persistGraphSelection(graphId).catch((error) => {
|
|
95
|
+
console.warn('Failed to persist graph selection to cookie:', error);
|
|
96
|
+
});
|
|
97
|
+
}, [persistGraphSelection]);
|
|
98
|
+
// Refresh graphs
|
|
99
|
+
const refreshGraphs = useCallback(async () => {
|
|
100
|
+
await loadGraphs();
|
|
101
|
+
}, [loadGraphs]);
|
|
102
|
+
// Initialize on mount
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
loadGraphs();
|
|
105
|
+
}, [loadGraphs]);
|
|
106
|
+
const value = {
|
|
107
|
+
state,
|
|
108
|
+
loadGraphs,
|
|
109
|
+
setCurrentGraph,
|
|
110
|
+
refreshGraphs,
|
|
111
|
+
};
|
|
112
|
+
return _jsx(Context.Provider, { value: value, children: children });
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// Factory for creating a typed hook
|
|
116
|
+
export function createUseGraphContext(Context) {
|
|
117
|
+
return function useGraphContext() {
|
|
118
|
+
const context = useContext(Context);
|
|
119
|
+
if (!context) {
|
|
120
|
+
throw new Error('useGraphContext must be used within a GraphProvider');
|
|
121
|
+
}
|
|
122
|
+
return context;
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// Default implementation for simple use cases
|
|
126
|
+
export const GraphContext = createGraphContext();
|
|
127
|
+
export const GraphProvider = createGraphProvider(GraphContext);
|
|
128
|
+
export const useGraphContext = createUseGraphContext(GraphContext);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { EntityProvider, useEntity, type EntityContextValue, type EntityProviderProps, } from './entity-context';
|
|
2
|
+
export { GraphContext, GraphProvider, createGraphContext, createGraphProvider, createUseGraphContext, useGraphContext, type GraphContextValue, type GraphProviderProps, type GraphState, } from './graph-context';
|
|
3
|
+
export { OrgProvider, useOrg, type OrgContextState, type OrgContextValue, type OrgProviderProps, } from './org-context';
|
|
4
|
+
export { ServiceOfferingsProvider, useServiceOfferings, type ServiceOfferings, } from './service-offerings-context';
|
|
5
|
+
export { SidebarProvider, useSidebarContext } from './sidebar-context';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { EntityProvider, useEntity, } from './entity-context';
|
|
2
|
+
export { GraphContext, GraphProvider, createGraphContext, createGraphProvider, createUseGraphContext, useGraphContext, } from './graph-context';
|
|
3
|
+
export { OrgProvider, useOrg, } from './org-context';
|
|
4
|
+
export { ServiceOfferingsProvider, useServiceOfferings, } from './service-offerings-context';
|
|
5
|
+
export { SidebarProvider, useSidebarContext } from './sidebar-context';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as SDK from '@robosystems/client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export interface OrgContextState {
|
|
4
|
+
currentOrg: SDK.OrgResponse | null;
|
|
5
|
+
orgs: SDK.OrgResponse[];
|
|
6
|
+
loading: boolean;
|
|
7
|
+
error: string | null;
|
|
8
|
+
}
|
|
9
|
+
export interface OrgContextValue extends OrgContextState {
|
|
10
|
+
refreshOrgs: () => Promise<void>;
|
|
11
|
+
setCurrentOrg: (org: SDK.OrgResponse) => void;
|
|
12
|
+
}
|
|
13
|
+
export interface OrgProviderProps {
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Organization context provider
|
|
18
|
+
* Manages the current organization and provides org-related state
|
|
19
|
+
*/
|
|
20
|
+
export declare function OrgProvider({ children }: OrgProviderProps): React.JSX.Element;
|
|
21
|
+
/**
|
|
22
|
+
* Hook to access organization context
|
|
23
|
+
* @throws {Error} If used outside of OrgProvider
|
|
24
|
+
*/
|
|
25
|
+
export declare function useOrg(): OrgContextValue;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as SDK from '@robosystems/client';
|
|
4
|
+
import { createContext, useCallback, useContext, useEffect, useState, } from 'react';
|
|
5
|
+
const OrgContext = createContext(undefined);
|
|
6
|
+
/**
|
|
7
|
+
* Organization context provider
|
|
8
|
+
* Manages the current organization and provides org-related state
|
|
9
|
+
*/
|
|
10
|
+
export function OrgProvider({ children }) {
|
|
11
|
+
const [state, setState] = useState({
|
|
12
|
+
currentOrg: null,
|
|
13
|
+
orgs: [],
|
|
14
|
+
loading: true,
|
|
15
|
+
error: null,
|
|
16
|
+
});
|
|
17
|
+
const refreshOrgs = useCallback(async () => {
|
|
18
|
+
try {
|
|
19
|
+
setState((prev) => (Object.assign(Object.assign({}, prev), { loading: true, error: null })));
|
|
20
|
+
const response = await SDK.listUserOrgs();
|
|
21
|
+
if (response.error) {
|
|
22
|
+
const errorMsg = typeof response.error === 'object' && 'detail' in response.error
|
|
23
|
+
? String(response.error.detail)
|
|
24
|
+
: 'Failed to load organizations';
|
|
25
|
+
throw new Error(errorMsg);
|
|
26
|
+
}
|
|
27
|
+
if (response.data) {
|
|
28
|
+
const orgs = response.data.orgs || [];
|
|
29
|
+
// Since users can only be in one org, set it as current
|
|
30
|
+
const currentOrg = orgs.length > 0 ? orgs[0] : null;
|
|
31
|
+
setState({
|
|
32
|
+
currentOrg,
|
|
33
|
+
orgs,
|
|
34
|
+
loading: false,
|
|
35
|
+
error: null,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error('Failed to load organizations:', error);
|
|
41
|
+
setState((prev) => (Object.assign(Object.assign({}, prev), { loading: false, error: error instanceof Error ? error.message : 'Unknown error' })));
|
|
42
|
+
}
|
|
43
|
+
}, []);
|
|
44
|
+
const setCurrentOrg = useCallback((org) => {
|
|
45
|
+
setState((prev) => (Object.assign(Object.assign({}, prev), { currentOrg: org })));
|
|
46
|
+
}, []);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
refreshOrgs();
|
|
49
|
+
}, [refreshOrgs]);
|
|
50
|
+
const value = Object.assign(Object.assign({}, state), { refreshOrgs,
|
|
51
|
+
setCurrentOrg });
|
|
52
|
+
return _jsx(OrgContext.Provider, { value: value, children: children });
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Hook to access organization context
|
|
56
|
+
* @throws {Error} If used outside of OrgProvider
|
|
57
|
+
*/
|
|
58
|
+
export function useOrg() {
|
|
59
|
+
const context = useContext(OrgContext);
|
|
60
|
+
if (context === undefined) {
|
|
61
|
+
throw new Error('useOrg must be used within an OrgProvider');
|
|
62
|
+
}
|
|
63
|
+
return context;
|
|
64
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ServiceOfferingsResponse } from '@robosystems/client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export type { ServiceOfferingsResponse };
|
|
4
|
+
export interface ServiceOfferings {
|
|
5
|
+
billingEnabled: boolean;
|
|
6
|
+
graphPlans?: {
|
|
7
|
+
[key: string]: {
|
|
8
|
+
name: string;
|
|
9
|
+
displayName: string;
|
|
10
|
+
monthlyPrice: number;
|
|
11
|
+
monthlyCredits: number;
|
|
12
|
+
features: string[];
|
|
13
|
+
instanceStorageLimitGb?: number;
|
|
14
|
+
creditMultiplier: number;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
repositoryPlans?: {
|
|
18
|
+
[repositoryType: string]: {
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
comingSoon?: boolean;
|
|
23
|
+
plans: Array<{
|
|
24
|
+
plan: string;
|
|
25
|
+
name: string;
|
|
26
|
+
monthlyPrice: number;
|
|
27
|
+
monthlyCredits: number;
|
|
28
|
+
features?: string[];
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
features?: {
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
interface ServiceOfferingsContextValue {
|
|
37
|
+
offerings: ServiceOfferings | null;
|
|
38
|
+
isLoading: boolean;
|
|
39
|
+
error: string | null;
|
|
40
|
+
refresh: () => Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
export declare function ServiceOfferingsProvider({ children, }: {
|
|
43
|
+
children: React.ReactNode;
|
|
44
|
+
}): React.JSX.Element;
|
|
45
|
+
export declare function useServiceOfferings(): ServiceOfferingsContextValue;
|