@firecms/core 3.0.0-canary.5 → 3.0.0-canary.50
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/README.md +2 -2
- package/dist/components/ClearFilterSortButton.d.ts +5 -0
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +11 -11
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +5 -3
- package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +3 -2
- package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
- package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -3
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
- package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
- package/dist/components/EntityPreview.d.ts +25 -7
- package/dist/components/EntityView.d.ts +11 -0
- package/dist/components/FieldCaption.d.ts +5 -0
- package/dist/components/FireCMSAppBar.d.ts +3 -2
- package/dist/components/HomePage/NavigationCard.d.ts +8 -0
- package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +2 -2
- package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
- package/dist/components/HomePage/index.d.ts +3 -1
- package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +1 -1
- package/dist/components/common/types.d.ts +4 -6
- package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
- package/dist/components/index.d.ts +4 -2
- package/dist/contexts/AuthControllerContext.d.ts +1 -1
- package/dist/core/{EntityView.d.ts → EntityEditView.d.ts} +2 -2
- package/dist/core/NavigationRoutes.d.ts +1 -1
- package/dist/core/Scaffold.d.ts +1 -1
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/components/ErrorFocus.d.ts +1 -1
- package/dist/form/components/StorageItemPreview.d.ts +3 -2
- package/dist/form/components/StorageUploadProgress.d.ts +1 -1
- package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +4 -3
- package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
- package/dist/form/validation.d.ts +1 -1
- package/dist/hooks/data/delete.d.ts +2 -2
- package/dist/hooks/data/save.d.ts +2 -3
- package/dist/hooks/data/useDataSource.d.ts +2 -2
- package/dist/hooks/data/useEntityFetch.d.ts +3 -3
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useBuildNavigationController.d.ts +6 -4
- package/dist/hooks/useProjectLog.d.ts +6 -2
- package/dist/hooks/useStorageSource.d.ts +2 -2
- package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
- package/dist/index.es.js +10402 -9898
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5 -5
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useBuildDataSource.d.ts +1 -12
- package/dist/preview/PropertyPreview.d.ts +1 -1
- package/dist/preview/PropertyPreviewProps.d.ts +1 -4
- package/dist/preview/components/BooleanPreview.d.ts +5 -1
- package/dist/preview/components/EnumValuesChip.d.ts +1 -1
- package/dist/preview/components/ReferencePreview.d.ts +1 -7
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/auth.d.ts +37 -1
- package/dist/types/collections.d.ts +29 -5
- package/dist/types/datasource.d.ts +3 -6
- package/dist/types/entities.d.ts +5 -1
- package/dist/types/entity_actions.d.ts +14 -0
- package/dist/types/entity_callbacks.d.ts +2 -2
- package/dist/types/entity_overrides.d.ts +6 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/navigation.d.ts +14 -13
- package/dist/types/permissions.d.ts +5 -1
- package/dist/types/plugins.d.ts +20 -20
- package/dist/types/properties.d.ts +4 -4
- package/dist/types/property_config.d.ts +2 -2
- package/dist/types/roles.d.ts +31 -0
- package/dist/types/storage.d.ts +11 -3
- package/dist/types/user.d.ts +5 -0
- package/dist/util/collections.d.ts +9 -1
- package/dist/util/entities.d.ts +1 -1
- package/dist/util/icon_synonyms.d.ts +1 -4
- package/dist/util/icons.d.ts +8 -2
- package/dist/util/navigation_utils.d.ts +2 -2
- package/dist/util/permissions.d.ts +4 -4
- package/dist/util/references.d.ts +4 -2
- package/dist/util/resolutions.d.ts +9 -13
- package/dist/util/useTraceUpdate.d.ts +1 -0
- package/package.json +139 -119
- package/src/components/ClearFilterSortButton.tsx +41 -0
- package/src/components/DeleteEntityDialog.tsx +4 -4
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +2 -2
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +275 -278
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +9 -5
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +44 -44
- package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +9 -16
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +3 -3
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +27 -32
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +11 -6
- package/src/components/EntityCollectionTable/internal/default_entity_actions.tsx +9 -5
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -4
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +69 -64
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
- package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
- package/src/components/EntityPreview.tsx +207 -70
- package/src/components/EntityView.tsx +84 -0
- package/src/components/FieldCaption.tsx +14 -0
- package/src/components/FireCMSAppBar.tsx +33 -11
- package/src/components/HomePage/DefaultHomePage.tsx +15 -11
- package/src/components/HomePage/NavigationCard.tsx +69 -0
- package/src/components/HomePage/NavigationCardBinding.tsx +116 -0
- package/src/components/HomePage/SmallNavigationCard.tsx +45 -0
- package/src/components/HomePage/index.tsx +3 -1
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +4 -4
- package/src/components/ReferenceWidget.tsx +4 -4
- package/src/components/SearchIconsView.tsx +4 -4
- package/src/components/SelectableTable/SelectableTable.tsx +1 -1
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +23 -8
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +35 -24
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
- package/src/components/VirtualTable/VirtualTable.tsx +28 -20
- package/src/components/VirtualTable/VirtualTableProps.tsx +1 -1
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
- package/src/components/common/types.tsx +4 -6
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -1
- package/src/components/index.tsx +4 -2
- package/src/contexts/AuthControllerContext.tsx +1 -1
- package/src/core/Drawer.tsx +66 -39
- package/src/core/{EntityView.tsx → EntityEditView.tsx} +21 -40
- package/src/core/EntitySidePanel.tsx +2 -2
- package/src/core/FireCMS.tsx +18 -3
- package/src/core/NavigationRoutes.tsx +11 -4
- package/src/core/Scaffold.tsx +5 -4
- package/src/core/field_configs.tsx +1 -2
- package/src/form/EntityForm.tsx +40 -21
- package/src/form/PropertyFieldBinding.tsx +0 -2
- package/src/form/components/StorageItemPreview.tsx +5 -3
- package/src/form/components/StorageUploadProgress.tsx +7 -6
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +8 -12
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +15 -15
- package/src/form/field_bindings/MapFieldBinding.tsx +15 -15
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -0
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +14 -5
- package/src/form/field_bindings/TextFieldBinding.tsx +7 -5
- package/src/form/validation.ts +3 -4
- package/src/hooks/data/delete.ts +3 -3
- package/src/hooks/data/save.ts +2 -2
- package/src/hooks/data/useCollectionFetch.tsx +1 -1
- package/src/hooks/data/useDataSource.tsx +8 -3
- package/src/hooks/data/useEntityFetch.tsx +4 -4
- package/src/hooks/index.tsx +2 -0
- package/src/hooks/useBuildLocalConfigurationPersistence.tsx +9 -10
- package/src/hooks/useBuildModeController.tsx +11 -5
- package/src/hooks/useBuildNavigationController.tsx +199 -81
- package/src/hooks/useProjectLog.tsx +17 -7
- package/src/hooks/useReferenceDialog.tsx +2 -2
- package/src/hooks/useStorageSource.tsx +7 -2
- package/src/hooks/useValidateAuthenticator.tsx +115 -0
- package/src/internal/useBuildDataSource.ts +42 -44
- package/src/internal/useBuildSideEntityController.tsx +86 -20
- package/src/preview/PropertyPreview.tsx +3 -14
- package/src/preview/PropertyPreviewProps.tsx +1 -11
- package/src/preview/components/BooleanPreview.tsx +19 -4
- package/src/preview/components/EnumValuesChip.tsx +1 -1
- package/src/preview/components/ReferencePreview.tsx +55 -147
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +0 -1
- package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
- package/src/types/analytics.ts +1 -0
- package/src/types/auth.tsx +50 -1
- package/src/types/collections.ts +33 -5
- package/src/types/datasource.ts +8 -5
- package/src/types/entities.ts +9 -1
- package/src/types/entity_actions.tsx +17 -0
- package/src/types/entity_callbacks.ts +2 -2
- package/src/types/entity_overrides.tsx +7 -0
- package/src/types/firecms.tsx +0 -1
- package/src/types/index.ts +2 -1
- package/src/types/navigation.ts +17 -16
- package/src/types/permissions.ts +6 -1
- package/src/types/plugins.tsx +26 -28
- package/src/types/properties.ts +8 -6
- package/src/types/property_config.tsx +2 -2
- package/src/types/roles.ts +41 -0
- package/src/types/side_entity_controller.tsx +1 -0
- package/src/types/storage.ts +12 -3
- package/src/types/user.ts +7 -0
- package/src/util/collections.ts +22 -0
- package/src/util/entities.ts +1 -1
- package/src/util/icon_list.ts +2 -2
- package/src/util/icon_synonyms.ts +1 -4
- package/src/util/icons.tsx +11 -3
- package/src/util/navigation_utils.ts +6 -6
- package/src/util/objects.ts +0 -14
- package/src/util/permissions.ts +11 -8
- package/src/util/references.ts +36 -5
- package/src/util/resolutions.ts +6 -24
- package/src/util/strings.ts +2 -2
- package/src/util/useTraceUpdate.tsx +2 -1
- package/dist/core/SideEntityView.d.ts +0 -7
- package/dist/internal/useLocaleConfig.d.ts +0 -1
- package/dist/types/appcheck.d.ts +0 -26
- package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
- package/src/core/SideEntityView.tsx +0 -38
- package/src/internal/useLocaleConfig.tsx +0 -18
- package/src/types/appcheck.ts +0 -29
|
@@ -252,7 +252,7 @@ export type VirtualTableFilterValues<Key extends string> = Partial<Record<Key, [
|
|
|
252
252
|
|
|
253
253
|
/**
|
|
254
254
|
* Filter conditions in a `Query.where()` clause are specified using the
|
|
255
|
-
* strings
|
|
255
|
+
* strings `<`, `<=`, `==`, `>=`, `>`, `array-contains`, `in`, and `array-contains-any`.
|
|
256
256
|
* @see Table
|
|
257
257
|
* @group Models
|
|
258
258
|
*/
|
|
@@ -25,7 +25,7 @@ export function VirtualTableDateField(props: {
|
|
|
25
25
|
return (
|
|
26
26
|
<DateTimeField
|
|
27
27
|
value={internalValue ?? undefined}
|
|
28
|
-
onChange={(dateValue) => updateValue(dateValue)}
|
|
28
|
+
onChange={(dateValue) => updateValue(dateValue ?? null)}
|
|
29
29
|
size={"medium"}
|
|
30
30
|
invisible={true}
|
|
31
31
|
className={"w-full h-full"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CollectionSize,
|
|
1
|
+
import { CollectionSize, FireCMSContext, ResolvedProperty, SelectedCellProps } from "../../types";
|
|
2
2
|
|
|
3
3
|
export type EntityCollectionTableController<M extends Record<string, any>> = {
|
|
4
4
|
|
|
@@ -31,14 +31,12 @@ export type EntityCollectionTableController<M extends Record<string, any>> = {
|
|
|
31
31
|
* Props passed in a callback when the content of a cell in a table has been edited
|
|
32
32
|
* @group Collection components
|
|
33
33
|
*/
|
|
34
|
-
export interface OnCellValueChangeParams<T = any,
|
|
34
|
+
export interface OnCellValueChangeParams<T = any, D = any> {
|
|
35
35
|
value: T,
|
|
36
36
|
propertyKey: string,
|
|
37
|
-
|
|
37
|
+
data?: D,
|
|
38
38
|
onValueUpdated: () => void
|
|
39
|
-
setError: (e: Error) => void
|
|
40
|
-
fullPath: string
|
|
41
|
-
context: FireCMSContext
|
|
39
|
+
setError: (e: Error | undefined) => void
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
/**
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
User
|
|
13
13
|
} from "../../types";
|
|
14
14
|
import { useDebouncedData } from "./useDebouncedData";
|
|
15
|
+
import equal from "react-fast-compare"
|
|
15
16
|
|
|
16
17
|
const DEFAULT_PAGE_SIZE = 50;
|
|
17
18
|
|
|
@@ -31,6 +32,10 @@ export type DataSourceEntityCollectionTableControllerProps<M extends Record<stri
|
|
|
31
32
|
entitiesDisplayedFirst?: Entity<M>[];
|
|
32
33
|
|
|
33
34
|
lastDeleteTimestamp?: number;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Force filter to be applied to the table.
|
|
38
|
+
*/
|
|
34
39
|
forceFilter?: FilterValues<string>;
|
|
35
40
|
}
|
|
36
41
|
|
|
@@ -65,7 +70,7 @@ export function useDataSourceEntityCollectionTableController<M extends Record<st
|
|
|
65
70
|
|
|
66
71
|
const [popupCell, setPopupCell] = React.useState<SelectedCellProps<M> | undefined>(undefined);
|
|
67
72
|
const navigation = useNavigationController();
|
|
68
|
-
const dataSource = useDataSource();
|
|
73
|
+
const dataSource = useDataSource(collection);
|
|
69
74
|
const resolvedPath = useMemo(() => navigation.resolveAliasesFrom(fullPath), [fullPath, navigation.resolveAliasesFrom]);
|
|
70
75
|
|
|
71
76
|
const forceFilter = forceFilterFromProps ?? forceFilterFromCollection;
|
|
@@ -83,6 +88,12 @@ export function useDataSourceEntityCollectionTableController<M extends Record<st
|
|
|
83
88
|
return initialSort;
|
|
84
89
|
}, [initialSort, forceFilter]);
|
|
85
90
|
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (!equal(forceFilter, filterValues)) {
|
|
93
|
+
setFilterValues(forceFilter)
|
|
94
|
+
}
|
|
95
|
+
}, [forceFilter]);
|
|
96
|
+
|
|
86
97
|
const [filterValues, setFilterValues] = React.useState<FilterValues<Extract<keyof M, string>> | undefined>(forceFilter ?? initialFilter ?? undefined);
|
|
87
98
|
const [sortBy, setSortBy] = React.useState<[Extract<keyof M, string>, "asc" | "desc"] | undefined>(initialSortInternal);
|
|
88
99
|
|
package/src/components/index.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export type { ErrorViewProps } from "./ErrorView";
|
|
2
2
|
export { ErrorView } from "./ErrorView";
|
|
3
3
|
|
|
4
|
-
export type {
|
|
5
|
-
export {
|
|
4
|
+
export type { EntityViewProps } from "./EntityView";
|
|
5
|
+
export { EntityView } from "./EntityView";
|
|
6
6
|
|
|
7
7
|
export type { ReferenceSelectionInnerProps } from "./ReferenceTable/ReferenceSelectionTable";
|
|
8
8
|
export { ReferenceSelectionTable } from "./ReferenceTable/ReferenceSelectionTable";
|
|
@@ -15,6 +15,7 @@ export * from "./HomePage";
|
|
|
15
15
|
export * from "./SelectableTable/SelectableTable";
|
|
16
16
|
export * from "./EntityCollectionView/EntityCollectionView";
|
|
17
17
|
export * from "./EntityCollectionView/EntityCollectionViewActions";
|
|
18
|
+
export * from "./EntityCollectionView/useSelectionController";
|
|
18
19
|
|
|
19
20
|
export * from "./PropertyConfigBadge";
|
|
20
21
|
|
|
@@ -32,3 +33,4 @@ export * from "./FireCMSAppBar";
|
|
|
32
33
|
export * from "./ArrayContainer";
|
|
33
34
|
export * from "./ReferenceWidget";
|
|
34
35
|
export * from "./SearchIconsView";
|
|
36
|
+
export * from "./FieldCaption";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { AuthController } from "../types";
|
|
3
3
|
|
|
4
|
-
export const AuthControllerContext = React.createContext<AuthController
|
|
4
|
+
export const AuthControllerContext = React.createContext<AuthController<any, any>>({} as AuthController<any, any>);
|
package/src/core/Drawer.tsx
CHANGED
|
@@ -2,10 +2,10 @@ import React, { useCallback } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { useLargeLayout, useNavigationController } from "../hooks";
|
|
4
4
|
|
|
5
|
-
import { NavLink } from "react-router-dom";
|
|
5
|
+
import { NavLink, useNavigate } from "react-router-dom";
|
|
6
6
|
import { CMSAnalyticsEvent, TopNavigationEntry, TopNavigationResult } from "../types";
|
|
7
7
|
import { IconForView } from "../util";
|
|
8
|
-
import { cn, Tooltip, Typography } from "@firecms/ui";
|
|
8
|
+
import { cn, IconButton, Menu, MenuItem, MoreVertIcon, Tooltip, Typography } from "@firecms/ui";
|
|
9
9
|
import { useAnalyticsController } from "../hooks/useAnalyticsController";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -33,6 +33,9 @@ export function Drawer({
|
|
|
33
33
|
|
|
34
34
|
const tooltipsOpen = hovered && !drawerOpen;
|
|
35
35
|
const largeLayout = useLargeLayout();
|
|
36
|
+
const navigate = useNavigate();
|
|
37
|
+
|
|
38
|
+
const [adminMenuOpen, setAdminMenuOpen] = React.useState(false);
|
|
36
39
|
|
|
37
40
|
if (!navigation.topLevelNavigation)
|
|
38
41
|
throw Error("Navigation not ready in Drawer");
|
|
@@ -42,7 +45,8 @@ export function Drawer({
|
|
|
42
45
|
groups
|
|
43
46
|
}: TopNavigationResult = navigation.topLevelNavigation;
|
|
44
47
|
|
|
45
|
-
const
|
|
48
|
+
const adminViews = navigationEntries.filter(e => e.type === "admin") ?? [];
|
|
49
|
+
const groupsWithoutAdmin = groups.filter(g => g !== "Admin");
|
|
46
50
|
|
|
47
51
|
const buildGroupHeader = useCallback((group?: string) => {
|
|
48
52
|
if (!drawerOpen) return <div className="h-12 w-full"/>;
|
|
@@ -67,41 +71,64 @@ export function Drawer({
|
|
|
67
71
|
};
|
|
68
72
|
|
|
69
73
|
return (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
74
|
+
<>
|
|
75
|
+
|
|
76
|
+
<div className={"flex-grow overflow-scroll no-scrollbar"}>
|
|
77
|
+
|
|
78
|
+
{groupsWithoutAdmin.map((group) => (
|
|
79
|
+
<React.Fragment
|
|
80
|
+
key={`drawer_group_${group}`}>
|
|
81
|
+
{buildGroupHeader(group)}
|
|
82
|
+
{Object.values(navigationEntries)
|
|
83
|
+
.filter(e => e.group === group)
|
|
84
|
+
.map((view, index) =>
|
|
85
|
+
<DrawerNavigationItem
|
|
86
|
+
key={`navigation_${index}`}
|
|
87
|
+
icon={<IconForView collectionOrView={view.collection ?? view.view}/>}
|
|
88
|
+
tooltipsOpen={tooltipsOpen}
|
|
89
|
+
drawerOpen={drawerOpen}
|
|
90
|
+
onClick={() => onClick(view)}
|
|
91
|
+
url={view.url}
|
|
92
|
+
name={view.name}/>)}
|
|
93
|
+
</React.Fragment>
|
|
94
|
+
))}
|
|
95
|
+
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
{adminViews.length > 0 && <Menu
|
|
99
|
+
open={adminMenuOpen}
|
|
100
|
+
onOpenChange={setAdminMenuOpen}
|
|
101
|
+
trigger={
|
|
102
|
+
<IconButton
|
|
103
|
+
shape={"square"}
|
|
104
|
+
className={"m-4 text-gray-900 dark:text-white w-fit"}>
|
|
105
|
+
<Tooltip title={"Admin"}
|
|
106
|
+
open={tooltipsOpen}
|
|
107
|
+
side={"right"} sideOffset={28}>
|
|
108
|
+
<MoreVertIcon/>
|
|
109
|
+
</Tooltip>
|
|
110
|
+
{drawerOpen && <div
|
|
111
|
+
className={cn(
|
|
112
|
+
drawerOpen ? "opacity-100" : "opacity-0 hidden",
|
|
113
|
+
"mx-4 font-inherit text-inherit"
|
|
114
|
+
)}>
|
|
115
|
+
ADMIN
|
|
116
|
+
</div>}
|
|
117
|
+
</IconButton>}
|
|
118
|
+
>
|
|
119
|
+
{adminViews.map((entry, index) =>
|
|
120
|
+
<MenuItem
|
|
121
|
+
onClick={(event) => {
|
|
122
|
+
event.preventDefault();
|
|
123
|
+
navigate(entry.path);
|
|
124
|
+
}}
|
|
125
|
+
key={`navigation_${index}`}>
|
|
126
|
+
{<IconForView collectionOrView={entry.view}/>}
|
|
127
|
+
{entry.name}
|
|
128
|
+
</MenuItem>)}
|
|
129
|
+
|
|
130
|
+
</Menu>}
|
|
131
|
+
</>
|
|
105
132
|
);
|
|
106
133
|
}
|
|
107
134
|
|
|
@@ -133,7 +160,7 @@ export function DrawerNavigationItem({
|
|
|
133
160
|
transition: drawerOpen ? "width 150ms ease-in" : undefined
|
|
134
161
|
}}
|
|
135
162
|
className={({ isActive }: any) => cn("rounded-r-xl truncate",
|
|
136
|
-
"hover:bg-slate-300 hover:bg-opacity-75 dark:hover:bg-gray-700 dark:hover:bg-opacity-75 text-gray-800 dark:text-gray-200 hover:text-gray-900 hover:dark:text-
|
|
163
|
+
"hover:bg-slate-300 hover:bg-opacity-75 dark:hover:bg-gray-700 dark:hover:bg-opacity-75 text-gray-800 dark:text-gray-200 hover:text-gray-900 hover:dark:text-white",
|
|
137
164
|
"flex flex-row items-center mr-8",
|
|
138
165
|
// "transition-all ease-in-out delay-100 duration-300",
|
|
139
166
|
// drawerOpen ? "w-full" : "w-18",
|
|
@@ -9,10 +9,9 @@ import {
|
|
|
9
9
|
FormContext,
|
|
10
10
|
User
|
|
11
11
|
} from "../types";
|
|
12
|
-
import { CircularProgressCenter, EntityCollectionView,
|
|
12
|
+
import { CircularProgressCenter, EntityCollectionView, EntityView, ErrorBoundary, } from "../components";
|
|
13
13
|
import {
|
|
14
14
|
canEditEntity,
|
|
15
|
-
fullPathToCollectionSegments,
|
|
16
15
|
removeInitialAndTrailingSlashes,
|
|
17
16
|
resolveDefaultSelectedView,
|
|
18
17
|
resolveEntityView,
|
|
@@ -32,12 +31,11 @@ import {
|
|
|
32
31
|
import { EntityForm } from "../form";
|
|
33
32
|
import { CircularProgress, CloseIcon, cn, defaultBorderMixin, IconButton, Tab, Tabs, Typography } from "@firecms/ui";
|
|
34
33
|
import { EntityFormSaveParams } from "../form/EntityForm";
|
|
35
|
-
import { FORM_CONTAINER_WIDTH } from "../internal/common";
|
|
36
34
|
import { useSideDialogContext } from "./index";
|
|
37
35
|
|
|
38
36
|
const MAIN_TAB_VALUE = "main_##Q$SC^#S6";
|
|
39
37
|
|
|
40
|
-
export interface
|
|
38
|
+
export interface EntityEditViewProps<M extends Record<string, any>> {
|
|
41
39
|
path: string;
|
|
42
40
|
collection: EntityCollection<M>;
|
|
43
41
|
entityId?: string;
|
|
@@ -56,18 +54,18 @@ export interface EntityViewProps<M extends Record<string, any>> {
|
|
|
56
54
|
* You probably don't want to use this view directly since it is bound to the
|
|
57
55
|
* side panel. Instead, you might want to use {@link EntityForm} or {@link EntityCollectionView}
|
|
58
56
|
*/
|
|
59
|
-
export function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
57
|
+
export function EntityEditView<M extends Record<string, any>, UserType extends User>({
|
|
58
|
+
path,
|
|
59
|
+
entityId,
|
|
60
|
+
selectedSubPath,
|
|
61
|
+
copy,
|
|
62
|
+
collection,
|
|
63
|
+
parentCollectionIds,
|
|
64
|
+
onValuesAreModified,
|
|
65
|
+
formWidth,
|
|
66
|
+
onUpdate,
|
|
67
|
+
onClose,
|
|
68
|
+
}: EntityEditViewProps<M>) {
|
|
71
69
|
|
|
72
70
|
if (collection.customId && collection.formAutoSave) {
|
|
73
71
|
console.warn(`The collection ${collection.path} has customId and formAutoSave enabled. This is not supported and formAutoSave will be ignored`);
|
|
@@ -92,10 +90,9 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
92
90
|
|
|
93
91
|
// const largeLayout = useLargeLayout();
|
|
94
92
|
// const largeLayoutTabSelected = useRef(!largeLayout);
|
|
93
|
+
// const resolvedFormWidth: string = typeof formWidth === "number" ? `${formWidth}px` : formWidth ?? FORM_CONTAINER_WIDTH;
|
|
95
94
|
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
const dataSource = useDataSource();
|
|
95
|
+
const dataSource = useDataSource(collection);
|
|
99
96
|
const sideDialogContext = useSideDialogContext();
|
|
100
97
|
const sideEntityController = useSideEntityController();
|
|
101
98
|
const snackbarController = useSnackbarController();
|
|
@@ -154,29 +151,12 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
154
151
|
if (status === "new") {
|
|
155
152
|
setReadOnly(false);
|
|
156
153
|
} else {
|
|
157
|
-
const editEnabled = usedEntity ? canEditEntity(collection, authController,
|
|
154
|
+
const editEnabled = usedEntity ? canEditEntity(collection, authController, path, usedEntity ?? null) : false;
|
|
158
155
|
if (usedEntity)
|
|
159
156
|
setReadOnly(!editEnabled);
|
|
160
157
|
}
|
|
161
158
|
}, [authController, usedEntity, status]);
|
|
162
159
|
|
|
163
|
-
// useEffect(() => {
|
|
164
|
-
// if (largeLayoutTabSelected.current === largeLayout)
|
|
165
|
-
// return;
|
|
166
|
-
// // open first tab by default in large layouts
|
|
167
|
-
// if (selectedSubPath !== defaultSelectedView) {
|
|
168
|
-
// console.log("Replacing url 1", defaultSelectedView);
|
|
169
|
-
// sideEntityController.replace({
|
|
170
|
-
// path,
|
|
171
|
-
// entityId,
|
|
172
|
-
// selectedSubPath: defaultSelectedView,
|
|
173
|
-
// updateUrl: true,
|
|
174
|
-
// collection
|
|
175
|
-
// });
|
|
176
|
-
// }
|
|
177
|
-
// largeLayoutTabSelected.current = largeLayout;
|
|
178
|
-
// }, [defaultSelectedView, largeLayout, selectedSubPath]);
|
|
179
|
-
|
|
180
160
|
const onPreSaveHookError = useCallback((e: Error) => {
|
|
181
161
|
setSaving(false);
|
|
182
162
|
snackbarController.open({
|
|
@@ -222,7 +202,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
222
202
|
entityId: updatedEntity.id,
|
|
223
203
|
selectedSubPath: selectedTabRef.current,
|
|
224
204
|
updateUrl: true,
|
|
225
|
-
collection
|
|
205
|
+
collection,
|
|
226
206
|
});
|
|
227
207
|
}
|
|
228
208
|
|
|
@@ -302,6 +282,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
302
282
|
.map(e => resolveEntityView(e, customizationController.entityViews))
|
|
303
283
|
.filter(Boolean) as EntityCustomView[]
|
|
304
284
|
: [];
|
|
285
|
+
|
|
305
286
|
const customViewsView: React.ReactNode[] | undefined = customViews && resolvedEntityViews
|
|
306
287
|
.map(
|
|
307
288
|
(customView, colIndex) => {
|
|
@@ -382,7 +363,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
382
363
|
entityId,
|
|
383
364
|
selectedSubPath: value === MAIN_TAB_VALUE ? undefined : value,
|
|
384
365
|
updateUrl: true,
|
|
385
|
-
collection
|
|
366
|
+
collection,
|
|
386
367
|
});
|
|
387
368
|
};
|
|
388
369
|
|
|
@@ -463,7 +444,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
463
444
|
className={"mt-16 mb-8 mx-8"}
|
|
464
445
|
variant={"h4"}>{collection.singularName ?? collection.name}
|
|
465
446
|
</Typography>
|
|
466
|
-
<
|
|
447
|
+
<EntityView
|
|
467
448
|
className={"px-12"}
|
|
468
449
|
entity={usedEntity as Entity<M>}
|
|
469
450
|
path={path}
|
|
@@ -4,7 +4,7 @@ import { EntitySidePanelProps } from "../types";
|
|
|
4
4
|
import { useNavigationController } from "../hooks";
|
|
5
5
|
|
|
6
6
|
import { ErrorBoundary } from "../components";
|
|
7
|
-
import {
|
|
7
|
+
import { EntityEditView } from "./EntityEditView";
|
|
8
8
|
import { useSideDialogContext } from "./SideDialogs";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -77,7 +77,7 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
77
77
|
return (
|
|
78
78
|
<>
|
|
79
79
|
<ErrorBoundary>
|
|
80
|
-
<
|
|
80
|
+
<EntityEditView
|
|
81
81
|
{...props}
|
|
82
82
|
formWidth={props.width}
|
|
83
83
|
collection={collection}
|
package/src/core/FireCMS.tsx
CHANGED
|
@@ -12,8 +12,7 @@ import { DataSourceContext } from "../contexts/DataSourceContext";
|
|
|
12
12
|
import { SideEntityControllerContext } from "../contexts/SideEntityControllerContext";
|
|
13
13
|
import { NavigationContext } from "../contexts/NavigationContext";
|
|
14
14
|
import { SideDialogsControllerContext } from "../contexts/SideDialogsControllerContext";
|
|
15
|
-
import { useLocaleConfig } from "
|
|
16
|
-
import { CenteredView } from "@firecms/ui";
|
|
15
|
+
import { CenteredView, Typography, useLocaleConfig } from "@firecms/ui";
|
|
17
16
|
import { DialogsProvider } from "../contexts/DialogsProvider";
|
|
18
17
|
import { useBuildDataSource } from "../internal/useBuildDataSource";
|
|
19
18
|
import { useBuildCustomizationController } from "../internal/useBuildCustomizationController";
|
|
@@ -85,7 +84,7 @@ export function FireCMS<UserType extends User, EC extends EntityCollection>(prop
|
|
|
85
84
|
onAnalyticsEvent
|
|
86
85
|
}), []);
|
|
87
86
|
|
|
88
|
-
useProjectLog(authController);
|
|
87
|
+
const accessResponse = useProjectLog(authController, plugins);
|
|
89
88
|
|
|
90
89
|
if (navigationController.navigationLoadingError) {
|
|
91
90
|
return (
|
|
@@ -107,6 +106,22 @@ export function FireCMS<UserType extends User, EC extends EntityCollection>(prop
|
|
|
107
106
|
);
|
|
108
107
|
}
|
|
109
108
|
|
|
109
|
+
if (accessResponse?.blocked) {
|
|
110
|
+
return (
|
|
111
|
+
<CenteredView maxWidth={"md"} fullScreen={true}>
|
|
112
|
+
<Typography variant={"h4"}>
|
|
113
|
+
Access blocked
|
|
114
|
+
</Typography>
|
|
115
|
+
<Typography>
|
|
116
|
+
This app has been blocked. Please reach out at <a
|
|
117
|
+
href={"mailto:hello@firecms.co"}>hello@firecms.co</a> for more information.
|
|
118
|
+
</Typography>
|
|
119
|
+
{accessResponse?.message &&
|
|
120
|
+
<Typography>Response from the server: {accessResponse?.message}</Typography>}
|
|
121
|
+
</CenteredView>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
110
125
|
return (
|
|
111
126
|
<ModeControllerContext.Provider value={modeController}>
|
|
112
127
|
<AnalyticsContext.Provider value={analyticsController}>
|
|
@@ -13,7 +13,7 @@ export type NavigationRoutesProps = {
|
|
|
13
13
|
/**
|
|
14
14
|
* In case you need to override the home page
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
homePage?: React.ReactNode;
|
|
17
17
|
|
|
18
18
|
customRoutes?: React.ReactNode[]
|
|
19
19
|
|
|
@@ -28,10 +28,9 @@ export type NavigationRoutesProps = {
|
|
|
28
28
|
* @constructor
|
|
29
29
|
* @group Components
|
|
30
30
|
*/
|
|
31
|
-
|
|
32
31
|
export const NavigationRoutes = React.memo<NavigationRoutesProps>(
|
|
33
32
|
function NavigationRoutes({
|
|
34
|
-
|
|
33
|
+
homePage = <DefaultHomePage/>,
|
|
35
34
|
customRoutes
|
|
36
35
|
}: NavigationRoutesProps) {
|
|
37
36
|
|
|
@@ -59,6 +58,14 @@ export const NavigationRoutes = React.memo<NavigationRoutesProps>(
|
|
|
59
58
|
cmsViews.push(buildCMSViewRoute(cmsView.path, cmsView));
|
|
60
59
|
});
|
|
61
60
|
}
|
|
61
|
+
if (navigation.adminViews) {
|
|
62
|
+
navigation.adminViews.forEach((cmsView) => {
|
|
63
|
+
if (Array.isArray(cmsView.path))
|
|
64
|
+
cmsViews.push(...cmsView.path.map(path => buildCMSViewRoute(path, cmsView)));
|
|
65
|
+
else
|
|
66
|
+
cmsViews.push(buildCMSViewRoute(cmsView.path, cmsView));
|
|
67
|
+
});
|
|
68
|
+
}
|
|
62
69
|
|
|
63
70
|
// we reorder collections so that nested paths are included first
|
|
64
71
|
const sortedCollections = [...(navigation.collections ?? [])]
|
|
@@ -85,7 +92,7 @@ export const NavigationRoutes = React.memo<NavigationRoutesProps>(
|
|
|
85
92
|
|
|
86
93
|
const homeRoute = (
|
|
87
94
|
<Route path={"/"}
|
|
88
|
-
element={
|
|
95
|
+
element={homePage}/>
|
|
89
96
|
);
|
|
90
97
|
|
|
91
98
|
const notFoundRoute = <Route path={"*"}
|
package/src/core/Scaffold.tsx
CHANGED
|
@@ -17,7 +17,7 @@ export interface ScaffoldProps<ExtraDrawerProps = object, ExtraAppbarProps = obj
|
|
|
17
17
|
/**
|
|
18
18
|
* Name of the app, displayed as the main title and in the tab title
|
|
19
19
|
*/
|
|
20
|
-
name:
|
|
20
|
+
name: React.ReactNode;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Logo to be displayed in the drawer of the CMS
|
|
@@ -112,9 +112,10 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
|
|
|
112
112
|
}}>
|
|
113
113
|
|
|
114
114
|
<FireCMSAppBar title={name}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
includeDrawer={includeDrawer}
|
|
116
|
+
logo={logo}
|
|
117
|
+
drawerOpen={computedDrawerOpen}
|
|
118
|
+
{...fireCMSAppBarProps}/>
|
|
118
119
|
|
|
119
120
|
<StyledDrawer
|
|
120
121
|
displayed={includeDrawer}
|
|
@@ -359,8 +359,7 @@ export function getDefaultFieldId(property: Property | ResolvedProperty) {
|
|
|
359
359
|
} else if (property.dataType === "map") {
|
|
360
360
|
if (property.keyValue)
|
|
361
361
|
return "key_value";
|
|
362
|
-
|
|
363
|
-
return "group";
|
|
362
|
+
return "group";
|
|
364
363
|
} else if (property.dataType === "array") {
|
|
365
364
|
const of = (property as ArrayProperty).of;
|
|
366
365
|
const oneOf = (property as ArrayProperty).oneOf;
|