@rebasepro/app 0.0.1-canary.4829d6e
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 +174 -0
- package/dist/auth/api.d.ts +66 -0
- package/dist/auth/index.d.ts +13 -0
- package/dist/auth/types.d.ts +127 -0
- package/dist/auth/useRebaseAuthController.d.ts +13 -0
- package/dist/components/AIIcon.d.ts +17 -0
- package/dist/components/AuthSimulationMenu.d.ts +0 -0
- package/dist/components/ConfirmationDialog.d.ts +9 -0
- package/dist/components/Debug/UIReferenceView.d.ts +13 -0
- package/dist/components/Debug/UIStyleGuide.d.ts +2 -0
- package/dist/components/Debug/collection-views/CardViewDemo.d.ts +2 -0
- package/dist/components/Debug/collection-views/CollectionTableDemo.d.ts +2 -0
- package/dist/components/Debug/collection-views/KanbanBoardDemo.d.ts +2 -0
- package/dist/components/Debug/collection-views/index.d.ts +3 -0
- package/dist/components/Debug/collection-views/sample_data.d.ts +23 -0
- package/dist/components/Debug/crm-dashboard/CalendarWidget.d.ts +22 -0
- package/dist/components/Debug/crm-dashboard/CrmDashboardDemo.d.ts +2 -0
- package/dist/components/Debug/crm-dashboard/DashboardMetrics.d.ts +15 -0
- package/dist/components/Debug/crm-dashboard/PipelineOverview.d.ts +34 -0
- package/dist/components/Debug/crm-dashboard/RecentActivity.d.ts +19 -0
- package/dist/components/Debug/crm-dashboard/TaskFilters.d.ts +30 -0
- package/dist/components/Debug/crm-dashboard/TaskTable.d.ts +50 -0
- package/dist/components/Debug/crm-dashboard/TasksView.d.ts +41 -0
- package/dist/components/ErrorTooltip.d.ts +3 -0
- package/dist/components/ErrorView.d.ts +21 -0
- package/dist/components/LanguageToggle.d.ts +2 -0
- package/dist/components/LoginView/LoginView.d.ts +113 -0
- package/dist/components/LoginView/index.d.ts +2 -0
- package/dist/components/NotFoundPage.d.ts +2 -0
- package/dist/components/RebaseAuth.d.ts +10 -0
- package/dist/components/RebaseLogo.d.ts +7 -0
- package/dist/components/SchemaDriftBanner.d.ts +27 -0
- package/dist/components/UnsavedChangesDialog.d.ts +9 -0
- package/dist/components/UserDisplay.d.ts +7 -0
- package/dist/components/UserSelectPopover.d.ts +63 -0
- package/dist/components/UserSettingsView.d.ts +2 -0
- package/dist/components/common/index.d.ts +6 -0
- package/dist/components/common/table_height.d.ts +5 -0
- package/dist/components/common/types.d.ts +66 -0
- package/dist/components/common/useColumnsIds.d.ts +9 -0
- package/dist/components/common/useDataTableController.d.ts +45 -0
- package/dist/components/common/useDebouncedData.d.ts +9 -0
- package/dist/components/common/useScrollRestoration.d.ts +14 -0
- package/dist/components/index.d.ts +18 -0
- package/dist/contexts/AdminModeController.d.ts +4 -0
- package/dist/contexts/AnalyticsContext.d.ts +3 -0
- package/dist/contexts/AuthControllerContext.d.ts +3 -0
- package/dist/contexts/CollectionScopeContext.d.ts +50 -0
- package/dist/contexts/ComponentOverrideContext.d.ts +42 -0
- package/dist/contexts/CustomizationControllerContext.d.ts +3 -0
- package/dist/contexts/DataDriverContext.d.ts +3 -0
- package/dist/contexts/DataSourcesContext.d.ts +31 -0
- package/dist/contexts/DatabaseAdminContext.d.ts +3 -0
- package/dist/contexts/DialogsProvider.d.ts +4 -0
- package/dist/contexts/EffectiveRoleController.d.ts +4 -0
- package/dist/contexts/ModeController.d.ts +4 -0
- package/dist/contexts/RebaseClientInstanceContext.d.ts +6 -0
- package/dist/contexts/RebaseDataContext.d.ts +3 -0
- package/dist/contexts/SnackbarProvider.d.ts +2 -0
- package/dist/contexts/StorageSourceContext.d.ts +3 -0
- package/dist/contexts/StorageSourcesContext.d.ts +25 -0
- package/dist/contexts/UserConfigurationPersistenceContext.d.ts +3 -0
- package/dist/contexts/index.d.ts +17 -0
- package/dist/core/PluginLifecycleManager.d.ts +17 -0
- package/dist/core/PluginProviderStack.d.ts +21 -0
- package/dist/core/Rebase.d.ts +15 -0
- package/dist/core/RebaseProps.d.ts +291 -0
- package/dist/core/RebaseRouter.d.ts +4 -0
- package/dist/core/RebaseRoutes.d.ts +17 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/hooks/ApiConfigContext.d.ts +24 -0
- package/dist/hooks/data/delete.d.ts +33 -0
- package/dist/hooks/data/save.d.ts +40 -0
- package/dist/hooks/data/useCollection.d.ts +62 -0
- package/dist/hooks/data/useData.d.ts +13 -0
- package/dist/hooks/data/useDataOrder.d.ts +12 -0
- package/dist/hooks/data/useFetch.d.ts +43 -0
- package/dist/hooks/data/useRelationSelector.d.ts +52 -0
- package/dist/hooks/index.d.ts +36 -0
- package/dist/hooks/useAdminModeController.d.ts +19 -0
- package/dist/hooks/useAnalyticsController.d.ts +5 -0
- package/dist/hooks/useAuthController.d.ts +11 -0
- package/dist/hooks/useAuthSubscription.d.ts +2 -0
- package/dist/hooks/useBackendStorageSource.d.ts +30 -0
- package/dist/hooks/useBridgeRegistration.d.ts +18 -0
- package/dist/hooks/useBrowserTitleAndIcon.d.ts +6 -0
- package/dist/hooks/useBuildAdminModeController.d.ts +6 -0
- package/dist/hooks/useBuildEffectiveRoleController.d.ts +8 -0
- package/dist/hooks/useBuildLocalConfigurationPersistence.d.ts +2 -0
- package/dist/hooks/useBuildModeController.d.ts +6 -0
- package/dist/hooks/useClipboard.d.ts +57 -0
- package/dist/hooks/useCollapsedGroups.d.ts +27 -0
- package/dist/hooks/useComponentOverride.d.ts +32 -0
- package/dist/hooks/useCustomizationController.d.ts +11 -0
- package/dist/hooks/useDialogsController.d.ts +11 -0
- package/dist/hooks/useEffectiveRoleController.d.ts +7 -0
- package/dist/hooks/useLargeLayout.d.ts +1 -0
- package/dist/hooks/useModeController.d.ts +19 -0
- package/dist/hooks/usePermissions.d.ts +12 -0
- package/dist/hooks/useRebaseClient.d.ts +5 -0
- package/dist/hooks/useRebaseContext.d.ts +11 -0
- package/dist/hooks/useRebaseRegistry.d.ts +34 -0
- package/dist/hooks/useResolvedComponent.d.ts +47 -0
- package/dist/hooks/useSlot.d.ts +18 -0
- package/dist/hooks/useSnackbarController.d.ts +20 -0
- package/dist/hooks/useStorageSource.d.ts +6 -0
- package/dist/hooks/useStudioBridge.d.ts +79 -0
- package/dist/hooks/useTranslation.d.ts +17 -0
- package/dist/hooks/useUnsavedChangesDialog.d.ts +12 -0
- package/dist/hooks/useUserConfigurationPersistence.d.ts +8 -0
- package/dist/i18n/RebaseI18nProvider.d.ts +33 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.es.js +16843 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +17021 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/internal/common.d.ts +14 -0
- package/dist/internal/useRestoreScroll.d.ts +15 -0
- package/dist/locales/de.d.ts +2 -0
- package/dist/locales/en.d.ts +10 -0
- package/dist/locales/es.d.ts +10 -0
- package/dist/locales/fr.d.ts +2 -0
- package/dist/locales/hi.d.ts +2 -0
- package/dist/locales/it.d.ts +2 -0
- package/dist/locales/pt.d.ts +7 -0
- package/dist/util/constants.d.ts +1 -0
- package/dist/util/createFormexStub.d.ts +2 -0
- package/dist/util/entity_cache.d.ts +22 -0
- package/dist/util/enums.d.ts +5 -0
- package/dist/util/icon_list.d.ts +5 -0
- package/dist/util/icons.d.ts +20 -0
- package/dist/util/index.d.ts +8 -0
- package/dist/util/previews.d.ts +4 -0
- package/dist/util/useStorageUploadController.d.ts +44 -0
- package/dist/vitePlugin.d.ts +60 -0
- package/dist/vitePlugin.js +113 -0
- package/package.json +145 -0
- package/src/auth/api.ts +148 -0
- package/src/auth/index.ts +25 -0
- package/src/auth/types.ts +115 -0
- package/src/auth/useRebaseAuthController.ts +328 -0
- package/src/components/AIIcon.tsx +47 -0
- package/src/components/AuthSimulationMenu.tsx +0 -0
- package/src/components/ConfirmationDialog.tsx +48 -0
- package/src/components/Debug/UIReferenceView.tsx +958 -0
- package/src/components/Debug/UIStyleGuide.tsx +156 -0
- package/src/components/Debug/collection-views/CardViewDemo.tsx +85 -0
- package/src/components/Debug/collection-views/CollectionTableDemo.tsx +107 -0
- package/src/components/Debug/collection-views/KanbanBoardDemo.tsx +90 -0
- package/src/components/Debug/collection-views/index.ts +3 -0
- package/src/components/Debug/collection-views/sample_data.ts +42 -0
- package/src/components/Debug/crm-dashboard/CalendarWidget.tsx +389 -0
- package/src/components/Debug/crm-dashboard/CrmDashboardDemo.tsx +1102 -0
- package/src/components/Debug/crm-dashboard/DashboardMetrics.tsx +133 -0
- package/src/components/Debug/crm-dashboard/PipelineOverview.tsx +290 -0
- package/src/components/Debug/crm-dashboard/RecentActivity.tsx +215 -0
- package/src/components/Debug/crm-dashboard/TaskFilters.tsx +184 -0
- package/src/components/Debug/crm-dashboard/TaskTable.tsx +427 -0
- package/src/components/Debug/crm-dashboard/TasksView.tsx +234 -0
- package/src/components/ErrorTooltip.tsx +12 -0
- package/src/components/ErrorView.tsx +94 -0
- package/src/components/LanguageToggle.tsx +59 -0
- package/src/components/LoginView/LoginView.tsx +932 -0
- package/src/components/LoginView/index.ts +2 -0
- package/src/components/NotFoundPage.tsx +27 -0
- package/src/components/RebaseAuth.tsx +27 -0
- package/src/components/RebaseLogo.tsx +29 -0
- package/src/components/SchemaDriftBanner.tsx +102 -0
- package/src/components/UnsavedChangesDialog.tsx +46 -0
- package/src/components/UserDisplay.tsx +54 -0
- package/src/components/UserSelectPopover.tsx +399 -0
- package/src/components/UserSettingsView.tsx +318 -0
- package/src/components/common/index.ts +6 -0
- package/src/components/common/table_height.tsx +21 -0
- package/src/components/common/types.tsx +66 -0
- package/src/components/common/useColumnsIds.tsx +222 -0
- package/src/components/common/useDataTableController.tsx +514 -0
- package/src/components/common/useDebouncedData.ts +49 -0
- package/src/components/common/useScrollRestoration.tsx +68 -0
- package/src/components/index.tsx +26 -0
- package/src/contexts/AdminModeController.tsx +11 -0
- package/src/contexts/AnalyticsContext.tsx +4 -0
- package/src/contexts/AuthControllerContext.tsx +4 -0
- package/src/contexts/CollectionScopeContext.tsx +67 -0
- package/src/contexts/ComponentOverrideContext.tsx +81 -0
- package/src/contexts/CustomizationControllerContext.tsx +4 -0
- package/src/contexts/DataDriverContext.tsx +4 -0
- package/src/contexts/DataSourcesContext.tsx +36 -0
- package/src/contexts/DatabaseAdminContext.tsx +4 -0
- package/src/contexts/DialogsProvider.tsx +56 -0
- package/src/contexts/EffectiveRoleController.tsx +12 -0
- package/src/contexts/ModeController.tsx +11 -0
- package/src/contexts/RebaseClientInstanceContext.tsx +7 -0
- package/src/contexts/RebaseDataContext.tsx +4 -0
- package/src/contexts/SnackbarProvider.tsx +15 -0
- package/src/contexts/StorageSourceContext.tsx +4 -0
- package/src/contexts/StorageSourcesContext.tsx +30 -0
- package/src/contexts/UserConfigurationPersistenceContext.tsx +4 -0
- package/src/contexts/index.ts +17 -0
- package/src/core/PluginLifecycleManager.tsx +95 -0
- package/src/core/PluginProviderStack.tsx +40 -0
- package/src/core/Rebase.tsx +439 -0
- package/src/core/RebaseProps.tsx +320 -0
- package/src/core/RebaseRouter.tsx +17 -0
- package/src/core/RebaseRoutes.tsx +24 -0
- package/src/core/index.tsx +5 -0
- package/src/hooks/ApiConfigContext.tsx +41 -0
- package/src/hooks/data/delete.ts +55 -0
- package/src/hooks/data/save.ts +77 -0
- package/src/hooks/data/useCollection.tsx +176 -0
- package/src/hooks/data/useData.tsx +18 -0
- package/src/hooks/data/useDataOrder.ts +26 -0
- package/src/hooks/data/useFetch.tsx +140 -0
- package/src/hooks/data/useRelationSelector.tsx +234 -0
- package/src/hooks/index.tsx +45 -0
- package/src/hooks/useAdminModeController.tsx +23 -0
- package/src/hooks/useAnalyticsController.tsx +8 -0
- package/src/hooks/useAuthController.tsx +14 -0
- package/src/hooks/useAuthSubscription.ts +87 -0
- package/src/hooks/useBackendStorageSource.ts +288 -0
- package/src/hooks/useBridgeRegistration.tsx +32 -0
- package/src/hooks/useBrowserTitleAndIcon.tsx +23 -0
- package/src/hooks/useBuildAdminModeController.tsx +24 -0
- package/src/hooks/useBuildEffectiveRoleController.tsx +31 -0
- package/src/hooks/useBuildLocalConfigurationPersistence.tsx +75 -0
- package/src/hooks/useBuildModeController.tsx +71 -0
- package/src/hooks/useClipboard.tsx +158 -0
- package/src/hooks/useCollapsedGroups.ts +116 -0
- package/src/hooks/useComponentOverride.tsx +59 -0
- package/src/hooks/useCustomizationController.tsx +14 -0
- package/src/hooks/useDialogsController.tsx +15 -0
- package/src/hooks/useEffectiveRoleController.tsx +10 -0
- package/src/hooks/useLargeLayout.tsx +65 -0
- package/src/hooks/useModeController.tsx +23 -0
- package/src/hooks/usePermissions.ts +44 -0
- package/src/hooks/useRebaseClient.tsx +10 -0
- package/src/hooks/useRebaseContext.tsx +83 -0
- package/src/hooks/useRebaseRegistry.tsx +91 -0
- package/src/hooks/useResolvedComponent.tsx +159 -0
- package/src/hooks/useSlot.tsx +64 -0
- package/src/hooks/useSnackbarController.tsx +52 -0
- package/src/hooks/useStorageSource.tsx +11 -0
- package/src/hooks/useStudioBridge.tsx +209 -0
- package/src/hooks/useTranslation.ts +33 -0
- package/src/hooks/useUnsavedChangesDialog.tsx +64 -0
- package/src/hooks/useUserConfigurationPersistence.tsx +11 -0
- package/src/i18n/RebaseI18nProvider.tsx +160 -0
- package/src/index.ts +25 -0
- package/src/internal/common.tsx +16 -0
- package/src/internal/useRestoreScroll.tsx +69 -0
- package/src/locales/de.ts +902 -0
- package/src/locales/en.ts +980 -0
- package/src/locales/es.ts +922 -0
- package/src/locales/fr.ts +901 -0
- package/src/locales/hi.ts +901 -0
- package/src/locales/it.ts +901 -0
- package/src/locales/pt.ts +909 -0
- package/src/util/constants.ts +7 -0
- package/src/util/createFormexStub.tsx +66 -0
- package/src/util/entity_cache.ts +239 -0
- package/src/util/enums.ts +32 -0
- package/src/util/icon_list.ts +22 -0
- package/src/util/icons.tsx +149 -0
- package/src/util/index.ts +12 -0
- package/src/util/previews.ts +105 -0
- package/src/util/useStorageUploadController.tsx +350 -0
- package/src/vitePlugin.ts +196 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import type { CollectionConfig } from "@rebasepro/types";
|
|
2
|
+
import { useEffect, useState, useMemo } from "react";
|
|
3
|
+
import { Entity, FilterValues, User } from "@rebasepro/types";
|
|
4
|
+
import { useData } from "./useData";
|
|
5
|
+
import { isSchemaDriftError, useSchemaDriftContext } from "../../components/SchemaDriftBanner";
|
|
6
|
+
/**
|
|
7
|
+
* @group Hooks and utilities
|
|
8
|
+
*/
|
|
9
|
+
export interface CollectionProps<M extends Record<string, any>> {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Absolute collection path
|
|
13
|
+
*/
|
|
14
|
+
path: string;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* collection of the entity displayed by this collection
|
|
18
|
+
*/
|
|
19
|
+
collection: CollectionConfig<M>
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Number of entities to fetch
|
|
23
|
+
*/
|
|
24
|
+
itemCount?: number;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Number of items to skip
|
|
28
|
+
*/
|
|
29
|
+
offset?: number;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Page number (1-indexed), alternative to offset
|
|
33
|
+
*/
|
|
34
|
+
page?: number;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Filter the fetched data by the property
|
|
38
|
+
*/
|
|
39
|
+
filterValues?: FilterValues<Extract<keyof M, string>>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Sort the results by
|
|
43
|
+
*/
|
|
44
|
+
sortBy?: [Extract<keyof M, string>, "asc" | "desc"];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Search string
|
|
48
|
+
*/
|
|
49
|
+
searchString?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @group Hooks and utilities
|
|
54
|
+
*/
|
|
55
|
+
export interface CollectionResult<M extends Record<string, any>> {
|
|
56
|
+
data: Entity<M>[];
|
|
57
|
+
dataLoading: boolean;
|
|
58
|
+
noMoreToLoad: boolean;
|
|
59
|
+
dataLoadingError?: Error;
|
|
60
|
+
totalCount?: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* This hook is used to fetch collections using a given collection
|
|
65
|
+
* @param path
|
|
66
|
+
* @param collection
|
|
67
|
+
* @param filterValues
|
|
68
|
+
* @param sortBy
|
|
69
|
+
* @param itemCount
|
|
70
|
+
* @param offset
|
|
71
|
+
* @param page
|
|
72
|
+
* @param searchString
|
|
73
|
+
* @group Hooks and utilities
|
|
74
|
+
*/
|
|
75
|
+
export function useCollection<M extends Record<string, any>, USER extends User>(
|
|
76
|
+
{
|
|
77
|
+
path,
|
|
78
|
+
collection,
|
|
79
|
+
filterValues,
|
|
80
|
+
sortBy,
|
|
81
|
+
itemCount,
|
|
82
|
+
offset,
|
|
83
|
+
page,
|
|
84
|
+
searchString
|
|
85
|
+
}: CollectionProps<M>): CollectionResult<M> {
|
|
86
|
+
const dataClient = useData();
|
|
87
|
+
const { reportSchemaDrift } = useSchemaDriftContext();
|
|
88
|
+
|
|
89
|
+
const sortByProperty = sortBy ? sortBy[0] : undefined;
|
|
90
|
+
const currentSort = sortBy ? sortBy[1] : undefined;
|
|
91
|
+
// Map to PostgREST format for orderBy
|
|
92
|
+
const orderByParams: [string, "asc" | "desc"] | undefined = sortBy ? [String(sortBy[0]), sortBy[1]] : undefined;
|
|
93
|
+
|
|
94
|
+
// filterValues is already FilterValues — pass directly
|
|
95
|
+
const whereParams = filterValues && Object.keys(filterValues).length > 0 ? filterValues : undefined;
|
|
96
|
+
|
|
97
|
+
const [data, setData] = useState<Entity<M>[]>([]);
|
|
98
|
+
|
|
99
|
+
const [dataLoading, setDataLoading] = useState<boolean>(false);
|
|
100
|
+
const [dataLoadingError, setDataLoadingError] = useState<Error | undefined>();
|
|
101
|
+
const [noMoreToLoad, setNoMoreToLoad] = useState<boolean>(false);
|
|
102
|
+
const [totalCount, setTotalCount] = useState<number | undefined>();
|
|
103
|
+
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
|
|
106
|
+
setDataLoading(true);
|
|
107
|
+
|
|
108
|
+
const onEntitiesUpdate = async (res: { data: Entity<M>[], meta: { hasMore: boolean; total?: number } }) => {
|
|
109
|
+
const entities = res.data;
|
|
110
|
+
setDataLoading(false);
|
|
111
|
+
setDataLoadingError(undefined);
|
|
112
|
+
setData(entities.map(e => ({
|
|
113
|
+
...e
|
|
114
|
+
})));
|
|
115
|
+
setNoMoreToLoad(!res.meta.hasMore);
|
|
116
|
+
setTotalCount(res.meta.total);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const onError = (error: Error) => {
|
|
120
|
+
console.error("ERROR", error);
|
|
121
|
+
setDataLoading(false);
|
|
122
|
+
setData([]);
|
|
123
|
+
setDataLoadingError(error);
|
|
124
|
+
setTotalCount(undefined);
|
|
125
|
+
// Report schema drift to the global banner context
|
|
126
|
+
if (isSchemaDriftError(error)) {
|
|
127
|
+
reportSchemaDrift(error.message);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const accessor = dataClient.collection(path);
|
|
132
|
+
|
|
133
|
+
// Eagerly include relations to avoid N+1 fetches.
|
|
134
|
+
const hasRelations = collection.properties && Object.values(collection.properties).some(
|
|
135
|
+
(p) => p.type === "relation" || p.type === "reference"
|
|
136
|
+
);
|
|
137
|
+
const includeParams = hasRelations ? ["*"] : undefined;
|
|
138
|
+
|
|
139
|
+
if (accessor.listen) {
|
|
140
|
+
return accessor.listen({
|
|
141
|
+
where: whereParams,
|
|
142
|
+
limit: itemCount,
|
|
143
|
+
offset,
|
|
144
|
+
page,
|
|
145
|
+
orderBy: orderByParams,
|
|
146
|
+
searchString,
|
|
147
|
+
include: includeParams
|
|
148
|
+
}, (res) => onEntitiesUpdate({ data: res.data as Entity<M>[],
|
|
149
|
+
meta: res.meta }), onError);
|
|
150
|
+
} else {
|
|
151
|
+
accessor.find({
|
|
152
|
+
where: whereParams,
|
|
153
|
+
limit: itemCount,
|
|
154
|
+
offset,
|
|
155
|
+
page,
|
|
156
|
+
orderBy: orderByParams,
|
|
157
|
+
searchString,
|
|
158
|
+
include: includeParams
|
|
159
|
+
})
|
|
160
|
+
.then((res) => onEntitiesUpdate({ data: res.data as Entity<M>[],
|
|
161
|
+
meta: res.meta }))
|
|
162
|
+
.catch(onError);
|
|
163
|
+
return () => {
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}, [path, itemCount, offset, page, currentSort, sortByProperty, filterValues, searchString, dataClient, collection]);
|
|
167
|
+
|
|
168
|
+
return useMemo(() => ({
|
|
169
|
+
data,
|
|
170
|
+
dataLoading,
|
|
171
|
+
dataLoadingError,
|
|
172
|
+
noMoreToLoad,
|
|
173
|
+
totalCount
|
|
174
|
+
}), [data, dataLoading, dataLoadingError, noMoreToLoad, totalCount]);
|
|
175
|
+
|
|
176
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { RebaseData } from "@rebasepro/types";
|
|
3
|
+
import { RebaseDataContext } from "../../contexts/RebaseDataContext";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Use this hook to access the unified data API.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* const data = useData();
|
|
10
|
+
* const { data: products } = await data.products.find({ where: { status: ["==", "published"] } });
|
|
11
|
+
* await data.products.create({ name: "Camera", price: 299 });
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* @group Hooks and utilities
|
|
15
|
+
*/
|
|
16
|
+
export const useData = (): RebaseData => {
|
|
17
|
+
return useContext(RebaseDataContext);
|
|
18
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Entity } from "@rebasepro/types";
|
|
2
|
+
|
|
3
|
+
export interface DataOrderProps<M extends Record<string, any>> {
|
|
4
|
+
data: Entity<M>[];
|
|
5
|
+
entitiesDisplayedFirst?: Entity<M>[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* This hook is used to have some entities at the beginning of data.
|
|
10
|
+
* @param path
|
|
11
|
+
* @param entitiesDisplayedFirst
|
|
12
|
+
* @group Hooks and utilities
|
|
13
|
+
*/
|
|
14
|
+
export function useDataOrder<M extends Record<string, any>>(
|
|
15
|
+
{
|
|
16
|
+
data,
|
|
17
|
+
entitiesDisplayedFirst
|
|
18
|
+
}: DataOrderProps<M>): Entity<M>[] {
|
|
19
|
+
|
|
20
|
+
if (!entitiesDisplayedFirst)
|
|
21
|
+
return data;
|
|
22
|
+
|
|
23
|
+
const displayedFirstId = new Set(entitiesDisplayedFirst.map((e) => e.id));
|
|
24
|
+
return [...entitiesDisplayedFirst, ...data.filter((e) => !displayedFirstId.has(e.id))];
|
|
25
|
+
|
|
26
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { CollectionConfig } from "@rebasepro/types";
|
|
2
|
+
import { useEffect, useState, useMemo } from "react";
|
|
3
|
+
import { Entity, RebaseContext, User } from "@rebasepro/types";
|
|
4
|
+
import { useData } from "./useData";
|
|
5
|
+
import { useRebaseContext } from "../useRebaseContext";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @group Hooks and utilities
|
|
9
|
+
*/
|
|
10
|
+
export interface FetchProps<M extends Record<string, any>, USER extends User = User> {
|
|
11
|
+
path: string;
|
|
12
|
+
entityId?: string | number;
|
|
13
|
+
databaseId?: string;
|
|
14
|
+
collection: CollectionConfig<M, USER>;
|
|
15
|
+
useCache?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @group Hooks and utilities
|
|
20
|
+
*/
|
|
21
|
+
export interface FetchResult<M extends Record<string, any>> {
|
|
22
|
+
entity?: Entity<M>,
|
|
23
|
+
dataLoading: boolean,
|
|
24
|
+
dataLoadingError?: Error
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const CACHE: Record<string, Entity<any> | undefined> = {};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Pre-populate the entity fetch cache with entities loaded from a collection.
|
|
31
|
+
* This allows entity detail views to render instantly using cached data,
|
|
32
|
+
* while the background fetch/listener brings in fresh data.
|
|
33
|
+
* @param path - The collection path (e.g. "products")
|
|
34
|
+
* @param entities - Array of entities to cache
|
|
35
|
+
*/
|
|
36
|
+
export function populateFetchCache<M extends Record<string, any>>(path: string, entities: Entity<M>[]): void {
|
|
37
|
+
for (const entity of entities) {
|
|
38
|
+
CACHE[`${path}/${entity.id}`] = entity;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Clear the entity fetch cache. Call this on auth state changes (e.g. logout)
|
|
44
|
+
* to prevent stale data from a previous session leaking into the next.
|
|
45
|
+
*/
|
|
46
|
+
export function clearFetchCache(): void {
|
|
47
|
+
for (const key of Object.keys(CACHE)) {
|
|
48
|
+
delete CACHE[key];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* This hook is used to fetch a entity.
|
|
54
|
+
* It gives real time updates if the driver supports it.
|
|
55
|
+
* @param path
|
|
56
|
+
* @param collection
|
|
57
|
+
* @param entityId
|
|
58
|
+
* @param useCache
|
|
59
|
+
* @group Hooks and utilities
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
export function useFetch<M extends Record<string, any>, USER extends User = User>(
|
|
63
|
+
{
|
|
64
|
+
path,
|
|
65
|
+
entityId,
|
|
66
|
+
collection,
|
|
67
|
+
databaseId,
|
|
68
|
+
useCache = false
|
|
69
|
+
}: FetchProps<M, USER>): FetchResult<M> {
|
|
70
|
+
|
|
71
|
+
const dataClient = useData();
|
|
72
|
+
|
|
73
|
+
const context: RebaseContext<USER> = useRebaseContext();
|
|
74
|
+
|
|
75
|
+
// Seed initial state from the cache to avoid skeleton flashes.
|
|
76
|
+
// Even when useCache is false, we show cached data instantly while
|
|
77
|
+
// the background fetch/listener brings in fresh data.
|
|
78
|
+
const cacheKey = entityId ? `${path}/${entityId}` : undefined;
|
|
79
|
+
const cachedEntity = cacheKey ? CACHE[cacheKey] as Entity<M> | undefined : undefined;
|
|
80
|
+
|
|
81
|
+
const [entity, setEntity] = useState<Entity<M> | undefined>(cachedEntity);
|
|
82
|
+
const [dataLoading, setDataLoading] = useState<boolean>(!cachedEntity);
|
|
83
|
+
const [dataLoadingError, setDataLoadingError] = useState<Error | undefined>();
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
|
|
87
|
+
// Only show loading state if we have no cached entity to display
|
|
88
|
+
if (!CACHE[`${path}/${entityId}`]) {
|
|
89
|
+
setDataLoading(true);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const onEntityUpdate = async (updatedEntity?: Entity<M> | null) => {
|
|
93
|
+
CACHE[`${path}/${entityId}`] = updatedEntity ?? undefined;
|
|
94
|
+
setEntity(updatedEntity ?? undefined);
|
|
95
|
+
setDataLoading(false);
|
|
96
|
+
setDataLoadingError(undefined);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const onError = (error: Error) => {
|
|
100
|
+
console.error("ERROR fetching entity", error);
|
|
101
|
+
setDataLoading(false);
|
|
102
|
+
setEntity(undefined);
|
|
103
|
+
setDataLoadingError(error);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
if (entityId && useCache && CACHE[`${path}/${entityId}`]) {
|
|
107
|
+
setEntity(CACHE[`${path}/${entityId}`]);
|
|
108
|
+
setDataLoading(false);
|
|
109
|
+
setDataLoadingError(undefined);
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
111
|
+
return () => {
|
|
112
|
+
};
|
|
113
|
+
} else if (entityId && path && collection) {
|
|
114
|
+
const accessor = dataClient.collection(path);
|
|
115
|
+
|
|
116
|
+
if (accessor.listenById) {
|
|
117
|
+
return accessor.listenById(entityId, (entity) => onEntityUpdate(entity as Entity<M> | undefined), onError);
|
|
118
|
+
} else {
|
|
119
|
+
accessor.findById(entityId)
|
|
120
|
+
.then((entity) => onEntityUpdate(entity as Entity<M> | undefined))
|
|
121
|
+
.catch(onError);
|
|
122
|
+
return () => {
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// if no entityId is provided we do nothing
|
|
127
|
+
else {
|
|
128
|
+
onEntityUpdate(undefined);
|
|
129
|
+
return () => {
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}, [entityId, path, dataClient, collection, useCache, databaseId]);
|
|
133
|
+
|
|
134
|
+
return useMemo(() => ({
|
|
135
|
+
entity,
|
|
136
|
+
dataLoading,
|
|
137
|
+
dataLoadingError
|
|
138
|
+
}), [entity, dataLoading, dataLoadingError]);
|
|
139
|
+
|
|
140
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import type { CollectionConfig } from "@rebasepro/types";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState, useMemo } from "react";
|
|
3
|
+
import { useData } from "./useData";
|
|
4
|
+
import { Entity, EntityRelation, FilterValues } from "@rebasepro/types";
|
|
5
|
+
export interface RelationItem {
|
|
6
|
+
id: string | number;
|
|
7
|
+
label: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
data: Entity<any>;
|
|
10
|
+
relation: EntityRelation;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface UseRelationSelectorProps<M extends Record<string, any> = any> {
|
|
14
|
+
/**
|
|
15
|
+
* Full path where the relation data is located
|
|
16
|
+
*/
|
|
17
|
+
path: string;
|
|
18
|
+
/**
|
|
19
|
+
* The collection that represents the relation entities
|
|
20
|
+
*/
|
|
21
|
+
collection: CollectionConfig<M>;
|
|
22
|
+
/**
|
|
23
|
+
* Force filter to be applied to the relation search
|
|
24
|
+
*/
|
|
25
|
+
fixedFilter?: FilterValues<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Page size for pagination
|
|
28
|
+
*/
|
|
29
|
+
pageSize?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Function to extract the label from a entity
|
|
32
|
+
*/
|
|
33
|
+
getLabelFromEntity?: (entity: Entity<M>) => string;
|
|
34
|
+
/**
|
|
35
|
+
* Function to extract the description from a entity
|
|
36
|
+
*/
|
|
37
|
+
getDescriptionFromEntity?: (entity: Entity<M>) => string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Property name to use as the secondary display field
|
|
40
|
+
*/
|
|
41
|
+
descriptionProperty?: keyof M;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface RelationSelectorController {
|
|
45
|
+
items: RelationItem[];
|
|
46
|
+
isLoading: boolean;
|
|
47
|
+
error: Error | undefined;
|
|
48
|
+
search: (searchString: string) => void;
|
|
49
|
+
loadMore: () => void;
|
|
50
|
+
hasMore: boolean;
|
|
51
|
+
entityToRelationItem: (entity: Entity<any>, relation: EntityRelation) => RelationItem;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const DEFAULT_PAGE_SIZE = 10;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Hook to manage relation selection with data fetching from Rebase data source
|
|
58
|
+
*/
|
|
59
|
+
export function useRelationSelector<M extends Record<string, any> = any>(
|
|
60
|
+
{
|
|
61
|
+
path,
|
|
62
|
+
collection,
|
|
63
|
+
fixedFilter,
|
|
64
|
+
pageSize = DEFAULT_PAGE_SIZE,
|
|
65
|
+
getLabelFromEntity,
|
|
66
|
+
getDescriptionFromEntity,
|
|
67
|
+
descriptionProperty
|
|
68
|
+
}: UseRelationSelectorProps<M>
|
|
69
|
+
): RelationSelectorController {
|
|
70
|
+
|
|
71
|
+
const dataClient = useData();
|
|
72
|
+
|
|
73
|
+
const [items, setItems] = useState<RelationItem[]>([]);
|
|
74
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
75
|
+
const isLoadingRef = useRef(false);
|
|
76
|
+
const [error, setError] = useState<Error | undefined>();
|
|
77
|
+
const [hasMore, setHasMore] = useState(true);
|
|
78
|
+
const [currentSearch, setCurrentSearch] = useState<string>("");
|
|
79
|
+
const [limit, setLimit] = useState<number>(pageSize);
|
|
80
|
+
|
|
81
|
+
const unsubscribeRef = useRef<(() => void) | null>(null);
|
|
82
|
+
const searchTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
83
|
+
|
|
84
|
+
const setLoading = useCallback((loading: boolean) => {
|
|
85
|
+
isLoadingRef.current = loading;
|
|
86
|
+
setIsLoading(loading);
|
|
87
|
+
}, []);
|
|
88
|
+
|
|
89
|
+
// Function to convert entity to RelationItem
|
|
90
|
+
const entityToRelationItem = useCallback((entity: Entity<M>, relation?: EntityRelation): RelationItem => {
|
|
91
|
+
let label: string;
|
|
92
|
+
let description: string | undefined;
|
|
93
|
+
|
|
94
|
+
if (getLabelFromEntity) {
|
|
95
|
+
label = getLabelFromEntity(entity);
|
|
96
|
+
} else {
|
|
97
|
+
// Fallback: try common label properties
|
|
98
|
+
const commonLabelProps = ["name", "title", "label", "displayName"];
|
|
99
|
+
let foundProp: string | undefined;
|
|
100
|
+
|
|
101
|
+
if (entity.values) {
|
|
102
|
+
foundProp = commonLabelProps.find(prop => entity.values[prop] != null && entity.values[prop] !== "");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (foundProp && entity.values[foundProp]) {
|
|
106
|
+
label = String(entity.values[foundProp]);
|
|
107
|
+
} else {
|
|
108
|
+
// Ultimate fallback: use entity ID
|
|
109
|
+
label = String(entity.id);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (getDescriptionFromEntity) {
|
|
114
|
+
description = getDescriptionFromEntity(entity);
|
|
115
|
+
} else if (descriptionProperty && entity.values && entity.values[descriptionProperty]) {
|
|
116
|
+
description = String(entity.values[descriptionProperty]);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
id: entity.id,
|
|
121
|
+
label,
|
|
122
|
+
description,
|
|
123
|
+
data: entity,
|
|
124
|
+
relation: relation ? relation : new EntityRelation(entity.id, path)
|
|
125
|
+
};
|
|
126
|
+
}, [getLabelFromEntity, getDescriptionFromEntity, descriptionProperty]);
|
|
127
|
+
|
|
128
|
+
// Clean up any existing subscription
|
|
129
|
+
const cleanupSubscription = useCallback(() => {
|
|
130
|
+
if (unsubscribeRef.current) {
|
|
131
|
+
unsubscribeRef.current();
|
|
132
|
+
unsubscribeRef.current = null;
|
|
133
|
+
}
|
|
134
|
+
}, []);
|
|
135
|
+
|
|
136
|
+
const fetchData = useCallback(() => {
|
|
137
|
+
cleanupSubscription();
|
|
138
|
+
setError(undefined);
|
|
139
|
+
setLoading(true);
|
|
140
|
+
|
|
141
|
+
// fixedFilter is already FilterValues — pass directly
|
|
142
|
+
const whereParams = fixedFilter && Object.keys(fixedFilter).length > 0 ? fixedFilter : undefined;
|
|
143
|
+
|
|
144
|
+
const onEntitiesUpdate = (res: { data: Entity<M>[], meta: { hasMore: boolean } }) => {
|
|
145
|
+
const newItems = res.data.map((e) => entityToRelationItem(e));
|
|
146
|
+
setItems(newItems);
|
|
147
|
+
setHasMore(res.meta.hasMore);
|
|
148
|
+
setLoading(false);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const onErrorUpdate = (fetchError: Error) => {
|
|
152
|
+
console.error("useRelationSelector: Error fetching data:", fetchError);
|
|
153
|
+
setError(fetchError);
|
|
154
|
+
setLoading(false);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const accessor = dataClient.collection(path);
|
|
158
|
+
|
|
159
|
+
let unsubscribe: (() => void) | undefined;
|
|
160
|
+
|
|
161
|
+
if (accessor.listen) {
|
|
162
|
+
unsubscribe = accessor.listen({
|
|
163
|
+
where: whereParams,
|
|
164
|
+
limit: limit,
|
|
165
|
+
orderBy: undefined,
|
|
166
|
+
searchString: currentSearch
|
|
167
|
+
}, (res) => onEntitiesUpdate({ data: res.data as Entity<M>[],
|
|
168
|
+
meta: res.meta }), onErrorUpdate);
|
|
169
|
+
} else {
|
|
170
|
+
accessor.find({
|
|
171
|
+
where: whereParams,
|
|
172
|
+
limit: limit,
|
|
173
|
+
offset: 0,
|
|
174
|
+
orderBy: undefined,
|
|
175
|
+
searchString: currentSearch
|
|
176
|
+
})
|
|
177
|
+
.then((res) => onEntitiesUpdate({ data: res.data as Entity<M>[],
|
|
178
|
+
meta: res.meta }))
|
|
179
|
+
.catch(onErrorUpdate);
|
|
180
|
+
unsubscribe = () => {};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
unsubscribeRef.current = unsubscribe || null;
|
|
184
|
+
}, [dataClient, path, fixedFilter, limit, currentSearch, entityToRelationItem, cleanupSubscription, setLoading]);
|
|
185
|
+
|
|
186
|
+
// Search function with debouncing
|
|
187
|
+
const search = useCallback((searchString: string) => {
|
|
188
|
+
// Clear existing timeout
|
|
189
|
+
if (searchTimeoutRef.current) {
|
|
190
|
+
clearTimeout(searchTimeoutRef.current);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Debounce search
|
|
194
|
+
searchTimeoutRef.current = setTimeout(() => {
|
|
195
|
+
setLimit(pageSize);
|
|
196
|
+
setCurrentSearch(searchString);
|
|
197
|
+
}, searchString.trim() ? 300 : 0);
|
|
198
|
+
}, [pageSize]);
|
|
199
|
+
|
|
200
|
+
// Load more function
|
|
201
|
+
const loadMore = useCallback(() => {
|
|
202
|
+
if (!isLoadingRef.current && hasMore && items.length > 0) {
|
|
203
|
+
setLoading(true);
|
|
204
|
+
setLimit(prev => prev + pageSize);
|
|
205
|
+
}
|
|
206
|
+
}, [hasMore, items.length, pageSize, setLoading]);
|
|
207
|
+
|
|
208
|
+
// Load initial data and update upon changes
|
|
209
|
+
useEffect(() => {
|
|
210
|
+
fetchData();
|
|
211
|
+
|
|
212
|
+
return () => {
|
|
213
|
+
cleanupSubscription();
|
|
214
|
+
};
|
|
215
|
+
}, [fetchData]);
|
|
216
|
+
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
return () => {
|
|
219
|
+
if (searchTimeoutRef.current) {
|
|
220
|
+
clearTimeout(searchTimeoutRef.current);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}, []);
|
|
224
|
+
|
|
225
|
+
return useMemo(() => ({
|
|
226
|
+
items,
|
|
227
|
+
isLoading,
|
|
228
|
+
error,
|
|
229
|
+
search,
|
|
230
|
+
loadMore,
|
|
231
|
+
hasMore,
|
|
232
|
+
entityToRelationItem
|
|
233
|
+
}), [items, isLoading, error, search, loadMore, hasMore, entityToRelationItem]);
|
|
234
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export * from "./data/useData";
|
|
2
|
+
export * from "./data/useCollection";
|
|
3
|
+
export * from "./data/useFetch";
|
|
4
|
+
export * from "./data/useRelationSelector";
|
|
5
|
+
export * from "./data/save";
|
|
6
|
+
export * from "./data/delete";
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export * from "./useUnsavedChangesDialog";
|
|
10
|
+
|
|
11
|
+
export * from "./useStorageSource";
|
|
12
|
+
export * from "./useAuthController";
|
|
13
|
+
export * from "./useAuthSubscription";
|
|
14
|
+
export * from "./useDialogsController";
|
|
15
|
+
export * from "./useAdminModeController";
|
|
16
|
+
export * from "./useBuildAdminModeController";
|
|
17
|
+
export * from "./useEffectiveRoleController";
|
|
18
|
+
export * from "./useBuildEffectiveRoleController";
|
|
19
|
+
export * from "./useRebaseContext";
|
|
20
|
+
export * from "./useSnackbarController";
|
|
21
|
+
export * from "./useModeController";
|
|
22
|
+
export * from "./useClipboard";
|
|
23
|
+
export * from "./useLargeLayout";
|
|
24
|
+
export * from "./useCollapsedGroups";
|
|
25
|
+
|
|
26
|
+
export * from "./useBrowserTitleAndIcon";
|
|
27
|
+
export * from "./useSlot";
|
|
28
|
+
export * from "./useCustomizationController";
|
|
29
|
+
|
|
30
|
+
export * from "./useBuildLocalConfigurationPersistence";
|
|
31
|
+
export * from "./useBuildModeController";
|
|
32
|
+
|
|
33
|
+
export * from "./useRebaseRegistry";
|
|
34
|
+
export * from "./useBackendStorageSource";
|
|
35
|
+
export * from "./usePermissions";
|
|
36
|
+
|
|
37
|
+
export * from "./ApiConfigContext";
|
|
38
|
+
|
|
39
|
+
export * from "./useTranslation";
|
|
40
|
+
export * from "./useRebaseClient";
|
|
41
|
+
|
|
42
|
+
export * from "./useAnalyticsController";
|
|
43
|
+
export * from "./useUserConfigurationPersistence";
|
|
44
|
+
export * from "./useResolvedComponent";
|
|
45
|
+
export * from "./useComponentOverride";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AdminModeControllerContext } from "../contexts/AdminModeController";
|
|
2
|
+
import { useContext } from "react";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Use this controller to change the admin mode (developer vs editor)
|
|
6
|
+
* @group Hooks and utilities
|
|
7
|
+
*/
|
|
8
|
+
export interface AdminModeController {
|
|
9
|
+
mode: "content" | "studio" | "settings";
|
|
10
|
+
setMode: (mode: "content" | "studio" | "settings") => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Hook to retrieve the current admin mode ("developer" | "editor"), and `setMode`
|
|
15
|
+
* to change it.
|
|
16
|
+
*
|
|
17
|
+
* Consider that in order to use this hook you need to have a parent
|
|
18
|
+
* `Rebase`
|
|
19
|
+
*
|
|
20
|
+
* @see AdminModeController
|
|
21
|
+
* @group Hooks and utilities
|
|
22
|
+
*/
|
|
23
|
+
export const useAdminModeController = () => useContext(AdminModeControllerContext);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { AnalyticsController } from "@rebasepro/types";
|
|
3
|
+
import { AnalyticsContext } from "../contexts/AnalyticsContext";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @group Hooks and utilities
|
|
7
|
+
*/
|
|
8
|
+
export const useAnalyticsController = (): AnalyticsController => useContext(AnalyticsContext);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AuthController, User } from "@rebasepro/types";
|
|
2
|
+
import { useContext } from "react";
|
|
3
|
+
import { AuthControllerContext } from "../contexts/AuthControllerContext";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hook to retrieve the AuthContext.
|
|
7
|
+
*
|
|
8
|
+
* Consider that in order to use this hook you need to have a parent
|
|
9
|
+
* `Rebase`
|
|
10
|
+
*
|
|
11
|
+
* @see AuthController
|
|
12
|
+
* @group Hooks and utilities
|
|
13
|
+
*/
|
|
14
|
+
export const useAuthController = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): AuthControllerType => useContext(AuthControllerContext) as AuthControllerType;
|