@firecms/core 3.1.0-canary.1df3b2c → 3.1.0-canary.75005e4
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/dist/components/EntityCollectionTable/internal/popup_field/useDraggable.d.ts +2 -2
- package/dist/components/EntityCollectionView/CollectionDataErrorBanner.d.ts +4 -0
- package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +5 -10
- package/dist/components/ErrorBoundary.d.ts +4 -2
- package/dist/components/HomePage/DefaultHomePage.d.ts +0 -1
- package/dist/components/LanguageToggle.d.ts +1 -0
- package/dist/components/UnsavedChangesDialog.d.ts +1 -0
- package/dist/components/VirtualTable/VirtualTableHeader.d.ts +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/core/DrawerNavigationGroup.d.ts +2 -2
- package/dist/editor/components/SlashCommandMenu.d.ts +6 -0
- package/dist/editor/components/editor-bubble-item.d.ts +8 -0
- package/dist/editor/components/editor-bubble.d.ts +8 -0
- package/dist/editor/components/index.d.ts +14 -0
- package/dist/editor/editor.d.ts +30 -0
- package/dist/editor/extensions/HighlightDecorationExtension.d.ts +24 -0
- package/dist/editor/extensions/Image/index.d.ts +6 -0
- package/dist/editor/extensions/Image.d.ts +6 -0
- package/dist/editor/extensions/TextLoadingDecorationExtension.d.ts +16 -0
- package/dist/editor/extensions/clipboard.d.ts +7 -0
- package/dist/editor/extensions/custom-keymap.d.ts +1 -0
- package/dist/editor/extensions/drag-and-drop.d.ts +9 -0
- package/dist/editor/hooks/useProseMirror.d.ts +14 -0
- package/dist/editor/hooks/useProseMirrorContext.d.ts +9 -0
- package/dist/editor/index.d.ts +2 -0
- package/dist/editor/markdown.d.ts +5 -0
- package/dist/editor/nodeViews/ImageComponent.d.ts +3 -0
- package/dist/editor/nodeViews/ReactNodeView.d.ts +29 -0
- package/dist/editor/nodeViews/TaskItemComponent.d.ts +3 -0
- package/dist/editor/nodeViews/index.d.ts +6 -0
- package/dist/editor/plugins/index.d.ts +2 -0
- package/dist/editor/plugins/inputrules.d.ts +6 -0
- package/dist/editor/plugins/placeholderPlugin.d.ts +3 -0
- package/dist/editor/plugins/slashCommandPlugin.d.ts +11 -0
- package/dist/editor/schema.d.ts +2 -0
- package/dist/editor/selectors/ai-selector.d.ts +0 -0
- package/dist/editor/selectors/color-selector.d.ts +10 -0
- package/dist/editor/selectors/link-selector.d.ts +8 -0
- package/dist/editor/selectors/node-selector.d.ts +15 -0
- package/dist/editor/selectors/text-buttons.d.ts +1 -0
- package/dist/editor/types.d.ts +5 -0
- package/dist/editor/useProseMirror.d.ts +16 -0
- package/dist/editor/utils/prosemirror-utils.d.ts +6 -0
- package/dist/editor/utils/remove_classes.d.ts +1 -0
- package/dist/editor/utils/useDebouncedCallback.d.ts +1 -0
- package/dist/form/components/ErrorFocus.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useBuildNavigationController.d.ts +0 -1
- package/dist/hooks/useCollapsedGroups.d.ts +3 -3
- package/dist/hooks/useTranslation.d.ts +17 -0
- package/dist/i18n/FireCMSi18nProvider.d.ts +33 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.es.js +11441 -2215
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +11423 -2216
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useRestoreScroll.d.ts +1 -1
- 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/types/analytics.d.ts +1 -1
- package/dist/types/collections.d.ts +8 -0
- package/dist/types/customization_controller.d.ts +2 -1
- package/dist/types/firecms.d.ts +2 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/navigation.d.ts +2 -2
- package/dist/types/plugins.d.ts +23 -0
- package/dist/types/translations.d.ts +646 -0
- package/dist/util/entities.d.ts +1 -1
- package/dist/util/resolutions.d.ts +2 -2
- package/package.json +47 -13
- package/src/app/Scaffold.tsx +7 -5
- package/src/components/AIIcon.tsx +3 -1
- package/src/components/ArrayContainer.tsx +6 -4
- package/src/components/ClearFilterSortButton.tsx +6 -3
- package/src/components/ConfirmationDialog.tsx +4 -2
- package/src/components/DeleteEntityDialog.tsx +10 -7
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +6 -3
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -1
- package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -2
- package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +11 -11
- package/src/components/EntityCollectionView/BoardSortableList.tsx +3 -1
- package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
- package/src/components/EntityCollectionView/EntityBoardCard.tsx +1 -1
- package/src/components/EntityCollectionView/EntityCard.tsx +4 -0
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +39 -46
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +17 -25
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +73 -31
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -3
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +4 -2
- package/src/components/EntityCollectionView/FiltersDialog.tsx +8 -5
- package/src/components/EntityCollectionView/ViewModeToggle.tsx +37 -37
- package/src/components/EntityView.tsx +3 -2
- package/src/components/ErrorBoundary.tsx +27 -15
- package/src/components/HomePage/DefaultHomePage.tsx +19 -13
- package/src/components/HomePage/HomePageDnD.tsx +3 -1
- package/src/components/HomePage/NavigationGroup.tsx +3 -1
- package/src/components/HomePage/RenameGroupDialog.tsx +15 -13
- package/src/components/LanguageToggle.tsx +66 -0
- package/src/components/NotFoundPage.tsx +5 -3
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +9 -7
- package/src/components/ReferenceWidget.tsx +3 -2
- package/src/components/SearchIconsView.tsx +3 -1
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +11 -0
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +15 -2
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +11 -0
- package/src/components/UnsavedChangesDialog.tsx +6 -4
- package/src/components/VirtualTable/VirtualTable.performance.test.tsx +1 -0
- package/src/components/VirtualTable/VirtualTable.tsx +116 -113
- package/src/components/VirtualTable/VirtualTableHeader.tsx +54 -52
- package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +1 -1
- package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +3 -3
- package/src/components/common/default_entity_actions.tsx +4 -0
- package/src/components/common/useDataSourceTableController.tsx +12 -4
- package/src/components/index.tsx +1 -0
- package/src/core/DefaultAppBar.tsx +15 -11
- package/src/core/DefaultDrawer.tsx +8 -2
- package/src/core/DrawerNavigationGroup.tsx +5 -3
- package/src/core/EntityEditView.tsx +4 -3
- package/src/core/EntityEditViewFormActions.tsx +24 -17
- package/src/core/EntitySidePanel.tsx +32 -29
- package/src/core/FireCMS.tsx +33 -6
- package/src/core/field_configs.tsx +14 -9
- package/src/editor/components/SlashCommandMenu.tsx +348 -0
- package/src/editor/components/editor-bubble-item.tsx +32 -0
- package/src/editor/components/editor-bubble.tsx +118 -0
- package/src/editor/components/index.ts +12 -0
- package/src/editor/editor.tsx +307 -0
- package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
- package/src/editor/extensions/Image/index.ts +133 -0
- package/src/editor/extensions/Image.ts +144 -0
- package/src/editor/extensions/TextLoadingDecorationExtension.tsx +107 -0
- package/src/editor/extensions/clipboard.ts +72 -0
- package/src/editor/extensions/custom-keymap.ts +24 -0
- package/src/editor/extensions/drag-and-drop.tsx +472 -0
- package/src/editor/hooks/useProseMirror.ts +115 -0
- package/src/editor/hooks/useProseMirrorContext.ts +15 -0
- package/src/editor/index.ts +2 -0
- package/src/editor/markdown.ts +110 -0
- package/src/editor/nodeViews/ImageComponent.tsx +20 -0
- package/src/editor/nodeViews/ReactNodeView.tsx +89 -0
- package/src/editor/nodeViews/TaskItemComponent.tsx +29 -0
- package/src/editor/nodeViews/index.ts +35 -0
- package/src/editor/plugins/index.ts +55 -0
- package/src/editor/plugins/inputrules.ts +82 -0
- package/src/editor/plugins/placeholderPlugin.ts +55 -0
- package/src/editor/plugins/slashCommandPlugin.ts +49 -0
- package/src/editor/schema.ts +228 -0
- package/src/editor/selectors/ai-selector.tsx +111 -0
- package/src/editor/selectors/color-selector.tsx +200 -0
- package/src/editor/selectors/link-selector.tsx +118 -0
- package/src/editor/selectors/node-selector.tsx +157 -0
- package/src/editor/selectors/text-buttons.tsx +86 -0
- package/src/editor/types.ts +6 -0
- package/src/editor/useProseMirror.ts +126 -0
- package/src/editor/utils/prosemirror-utils.ts +78 -0
- package/src/editor/utils/remove_classes.ts +17 -0
- package/src/editor/utils/useDebouncedCallback.ts +25 -0
- package/src/form/EntityForm.tsx +76 -63
- package/src/form/EntityFormActions.tsx +19 -12
- package/src/form/PropertyFieldBinding.tsx +6 -5
- package/src/form/components/ErrorFocus.tsx +3 -3
- package/src/form/components/LocalChangesMenu.tsx +13 -13
- package/src/form/components/StorageItemPreview.tsx +3 -2
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +4 -4
- package/src/form/field_bindings/BlockFieldBinding.tsx +5 -2
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +23 -18
- package/src/form/field_bindings/MapFieldBinding.tsx +4 -3
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +4 -4
- package/src/form/field_bindings/RepeatFieldBinding.tsx +3 -1
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +87 -85
- package/src/hooks/index.tsx +1 -0
- package/src/hooks/useBuildNavigationController.tsx +49 -22
- package/src/hooks/useCollapsedGroups.ts +7 -6
- package/src/hooks/useTranslation.ts +31 -0
- package/src/hooks/useValidateAuthenticator.tsx +1 -1
- package/src/i18n/FireCMSi18nProvider.tsx +160 -0
- package/src/index.ts +4 -0
- package/src/internal/useBuildDataSource.ts +1 -2
- package/src/internal/useBuildSideEntityController.tsx +22 -20
- package/src/locales/de.ts +691 -0
- package/src/locales/en.ts +703 -0
- package/src/locales/es.ts +703 -0
- package/src/locales/fr.ts +691 -0
- package/src/locales/hi.ts +691 -0
- package/src/locales/it.ts +691 -0
- package/src/locales/pt.ts +700 -0
- package/src/preview/PropertyPreview.tsx +1 -0
- package/src/preview/components/UrlComponentPreview.tsx +4 -2
- package/src/preview/components/UserPreview.tsx +3 -1
- package/src/types/analytics.ts +10 -0
- package/src/types/collections.ts +9 -0
- package/src/types/customization_controller.tsx +2 -1
- package/src/types/firecms.tsx +2 -1
- package/src/types/index.ts +1 -0
- package/src/types/navigation.ts +2 -2
- package/src/types/plugins.tsx +26 -0
- package/src/types/translations.ts +725 -0
- package/src/util/entities.ts +1 -1
- package/src/util/join_collections.ts +10 -8
- package/src/util/previews.ts +2 -2
- package/src/util/property_utils.tsx +1 -1
- package/src/util/resolutions.ts +5 -3
|
@@ -2,6 +2,7 @@ import React, { RefObject, useCallback, useEffect, useState } from "react";
|
|
|
2
2
|
import equal from "react-fast-compare";
|
|
3
3
|
|
|
4
4
|
import { VirtualTableColumn, VirtualTableSort, VirtualTableWhereFilterOp } from "./VirtualTableProps";
|
|
5
|
+
import { useTranslation } from "../../hooks";
|
|
5
6
|
import { ErrorBoundary } from "../ErrorBoundary";
|
|
6
7
|
import {
|
|
7
8
|
ArrowUpwardIcon,
|
|
@@ -34,7 +35,7 @@ export type FilterFormFieldProps<CustomProps> = {
|
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
type VirtualTableHeaderProps<M extends Record<string, any>> = {
|
|
37
|
-
resizeHandleRef: RefObject<HTMLDivElement>;
|
|
38
|
+
resizeHandleRef: RefObject<HTMLDivElement | null>;
|
|
38
39
|
columnIndex: number;
|
|
39
40
|
isResizingIndex: number;
|
|
40
41
|
column: VirtualTableColumn<any>;
|
|
@@ -51,20 +52,20 @@ type VirtualTableHeaderProps<M extends Record<string, any>> = {
|
|
|
51
52
|
|
|
52
53
|
export const VirtualTableHeader = React.memo<VirtualTableHeaderProps<any>>(
|
|
53
54
|
function VirtualTableHeader<M extends Record<string, any>>({
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
resizeHandleRef,
|
|
56
|
+
columnIndex,
|
|
57
|
+
isResizingIndex,
|
|
58
|
+
sort,
|
|
59
|
+
onColumnSort,
|
|
60
|
+
onFilterUpdate,
|
|
61
|
+
filter,
|
|
62
|
+
column,
|
|
63
|
+
onClickResizeColumn,
|
|
64
|
+
createFilterField,
|
|
65
|
+
AdditionalHeaderWidget,
|
|
66
|
+
isDragging,
|
|
67
|
+
isDraggable
|
|
68
|
+
}: VirtualTableHeaderProps<M>) {
|
|
68
69
|
|
|
69
70
|
const [onHover, setOnHover] = useState(false);
|
|
70
71
|
|
|
@@ -129,11 +130,11 @@ export const VirtualTableHeader = React.memo<VirtualTableHeaderProps<any>>(
|
|
|
129
130
|
<>
|
|
130
131
|
|
|
131
132
|
{AdditionalHeaderWidget &&
|
|
132
|
-
<AdditionalHeaderWidget onHover={onHover || openFilter}/>}
|
|
133
|
+
<AdditionalHeaderWidget onHover={onHover || openFilter} />}
|
|
133
134
|
|
|
134
135
|
{column.sortable && (sort || hovered || openFilter) &&
|
|
135
136
|
<Badge color="secondary"
|
|
136
|
-
|
|
137
|
+
invisible={!sort}>
|
|
137
138
|
<IconButton
|
|
138
139
|
size={"small"}
|
|
139
140
|
className={onHover || openFilter ? "bg-white dark:bg-surface-950" : undefined}
|
|
@@ -142,11 +143,11 @@ export const VirtualTableHeader = React.memo<VirtualTableHeaderProps<any>>(
|
|
|
142
143
|
}}
|
|
143
144
|
>
|
|
144
145
|
{!sort &&
|
|
145
|
-
<ArrowUpwardIcon/>}
|
|
146
|
+
<ArrowUpwardIcon />}
|
|
146
147
|
{sort === "asc" &&
|
|
147
|
-
<ArrowUpwardIcon/>}
|
|
148
|
+
<ArrowUpwardIcon />}
|
|
148
149
|
{sort === "desc" &&
|
|
149
|
-
<ArrowUpwardIcon className={"rotate-180"}/>}
|
|
150
|
+
<ArrowUpwardIcon className={"rotate-180"} />}
|
|
150
151
|
</IconButton>
|
|
151
152
|
</Badge>
|
|
152
153
|
}
|
|
@@ -154,7 +155,7 @@ export const VirtualTableHeader = React.memo<VirtualTableHeaderProps<any>>(
|
|
|
154
155
|
|
|
155
156
|
{column.filter && createFilterField && <div>
|
|
156
157
|
<Badge color="secondary"
|
|
157
|
-
|
|
158
|
+
invisible={!filter}>
|
|
158
159
|
|
|
159
160
|
<Popover
|
|
160
161
|
open={openFilter}
|
|
@@ -166,16 +167,16 @@ export const VirtualTableHeader = React.memo<VirtualTableHeaderProps<any>>(
|
|
|
166
167
|
className={onHover || openFilter ? "bg-white dark:bg-surface-950" : undefined}
|
|
167
168
|
size={"small"}
|
|
168
169
|
onClick={handleSettingsClick}>
|
|
169
|
-
<FilterListIcon size={"small"}/>
|
|
170
|
+
<FilterListIcon size={"small"} />
|
|
170
171
|
</IconButton>}
|
|
171
172
|
>
|
|
172
173
|
<FilterForm column={column}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
174
|
+
filter={filter}
|
|
175
|
+
onHover={onHover}
|
|
176
|
+
onFilterUpdate={update}
|
|
177
|
+
createFilterField={createFilterField}
|
|
178
|
+
hidden={hidden}
|
|
179
|
+
setHidden={setHidden} />
|
|
179
180
|
|
|
180
181
|
</Popover>
|
|
181
182
|
|
|
@@ -204,14 +205,16 @@ export const VirtualTableHeader = React.memo<VirtualTableHeaderProps<any>>(
|
|
|
204
205
|
}, equal) as React.FunctionComponent<VirtualTableHeaderProps<any>>;
|
|
205
206
|
|
|
206
207
|
function FilterForm<M>({
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
208
|
+
column,
|
|
209
|
+
onFilterUpdate,
|
|
210
|
+
filter,
|
|
211
|
+
onHover,
|
|
212
|
+
createFilterField,
|
|
213
|
+
hidden,
|
|
214
|
+
setHidden
|
|
215
|
+
}: FilterFormProps<M>) {
|
|
216
|
+
|
|
217
|
+
const { t } = useTranslation();
|
|
215
218
|
|
|
216
219
|
const id = column.key;
|
|
217
220
|
|
|
@@ -245,12 +248,12 @@ function FilterForm<M>({
|
|
|
245
248
|
if (!filterField) return null;
|
|
246
249
|
return (
|
|
247
250
|
<form noValidate={true}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
onSubmit={(e) => {
|
|
252
|
+
e.stopPropagation();
|
|
253
|
+
e.preventDefault();
|
|
254
|
+
submit();
|
|
255
|
+
}}
|
|
256
|
+
className={"text-surface-900 dark:text-white"}>
|
|
254
257
|
<div
|
|
255
258
|
className={cls(defaultBorderMixin, "py-4 px-6 typography-label border-b")}>
|
|
256
259
|
{column.title ?? id}
|
|
@@ -258,16 +261,15 @@ function FilterForm<M>({
|
|
|
258
261
|
{filterField && <div className="m-4 w-[400px]">
|
|
259
262
|
{filterField}
|
|
260
263
|
</div>}
|
|
261
|
-
<div className="flex justify-end
|
|
262
|
-
<Button
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
type="submit">Filter</Button>
|
|
264
|
+
<div className="flex justify-end p-4 pt-0 gap-2">
|
|
265
|
+
<Button variant={"text"}
|
|
266
|
+
size={"small"}
|
|
267
|
+
aria-label="filter clear"
|
|
268
|
+
onClick={reset}>{t("clear")}</Button>
|
|
269
|
+
|
|
270
|
+
<Button variant={"outlined"}
|
|
271
|
+
size={"small"}
|
|
272
|
+
type="submit">{t("filter")}</Button>
|
|
271
273
|
</div>
|
|
272
274
|
</form>
|
|
273
275
|
);
|
|
@@ -26,7 +26,7 @@ const SortableColumnHeader = ({
|
|
|
26
26
|
}: {
|
|
27
27
|
column: VirtualTableColumn;
|
|
28
28
|
columnIndex: number;
|
|
29
|
-
columnRefs: React.RefObject<HTMLDivElement>[];
|
|
29
|
+
columnRefs: React.RefObject<HTMLDivElement | null>[];
|
|
30
30
|
isResizing: number;
|
|
31
31
|
onFilterUpdate: any;
|
|
32
32
|
filter: [VirtualTableWhereFilterOp, any] | undefined;
|
|
@@ -79,7 +79,7 @@ export function VirtualTableSelect(props: {
|
|
|
79
79
|
multiple
|
|
80
80
|
? <MultiSelect
|
|
81
81
|
inputRef={ref}
|
|
82
|
-
className="w-full h-full p-0 bg-transparent"
|
|
82
|
+
className="w-full h-full p-0 bg-transparent outline-none"
|
|
83
83
|
position={"item-aligned"}
|
|
84
84
|
disabled={disabled}
|
|
85
85
|
includeClear={false}
|
|
@@ -104,8 +104,8 @@ export function VirtualTableSelect(props: {
|
|
|
104
104
|
inputRef={ref}
|
|
105
105
|
size={"large"}
|
|
106
106
|
fullWidth={true}
|
|
107
|
-
className="w-full h-full p-0 bg-transparent"
|
|
108
|
-
inputClassName="focus:ring-0 focus-visible:ring-0 outline-none focus:outline-none focus-visible:outline-none"
|
|
107
|
+
className="w-full h-full p-0 bg-transparent outline-none [&_button]:ring-0 [&_button]:ring-offset-0"
|
|
108
|
+
inputClassName="ring-0 ring-offset-0 focus:ring-0 focus-visible:ring-0 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-offset-0"
|
|
109
109
|
position={"item-aligned"}
|
|
110
110
|
disabled={disabled}
|
|
111
111
|
padding={false}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Note: entity action 'name' fields (Edit, Copy, Delete) are plain strings defined
|
|
2
|
+
// at module level. They cannot use hooks. Consumers who need to translate these
|
|
3
|
+
// should override the action name by creating their own EntityAction objects or
|
|
4
|
+
// by using the entityActions prop with custom names for their locale.
|
|
1
5
|
import { DeleteIcon, EditIcon, FileCopyIcon } from "@firecms/ui";
|
|
2
6
|
import { EntityAction } from "../../types";
|
|
3
7
|
import { DeleteEntityDialog } from "../DeleteEntityDialog";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { useLocation } from "react-router-dom";
|
|
2
3
|
|
|
3
4
|
import { useDataSource, useFireCMSContext, useNavigationController } from "../../hooks";
|
|
4
5
|
import { useDataOrder } from "../../hooks/data/useDataOrder";
|
|
@@ -94,7 +95,7 @@ export function useDataSourceTableController<M extends Record<string, any> = any
|
|
|
94
95
|
const [searchString, setSearchString] = React.useState<string | undefined>();
|
|
95
96
|
|
|
96
97
|
const checkFilterCombination = useCallback((filterValues: FilterValues<any>,
|
|
97
|
-
|
|
98
|
+
sortBy?: [string, "asc" | "desc"]) => {
|
|
98
99
|
if (!dataSource.isFilterCombinationValid)
|
|
99
100
|
return true;
|
|
100
101
|
return dataSource.isFilterCombinationValid({
|
|
@@ -106,8 +107,8 @@ export function useDataSourceTableController<M extends Record<string, any> = any
|
|
|
106
107
|
}, []);
|
|
107
108
|
|
|
108
109
|
const onScroll = ({
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
scrollOffset
|
|
111
|
+
}: {
|
|
111
112
|
scrollOffset: number
|
|
112
113
|
}) => {
|
|
113
114
|
if (scrollRestoration) {
|
|
@@ -128,10 +129,12 @@ export function useDataSourceTableController<M extends Record<string, any> = any
|
|
|
128
129
|
return initialSort;
|
|
129
130
|
}, [initialSort, forceFilter]);
|
|
130
131
|
|
|
132
|
+
const location = useLocation();
|
|
133
|
+
|
|
131
134
|
const {
|
|
132
135
|
filterValues: initialFilterUrl,
|
|
133
136
|
sortBy: initialSortUrl,
|
|
134
|
-
} = parseFilterAndSort(
|
|
137
|
+
} = parseFilterAndSort(location.search);
|
|
135
138
|
|
|
136
139
|
const [filterValues, setFilterValues] = React.useState<FilterValues<Extract<keyof M, string>> | undefined>(forceFilter ?? (updateUrl ? initialFilterUrl : undefined) ?? initialFilter ?? undefined);
|
|
137
140
|
const [sortBy, setSortBy] = React.useState<[Extract<keyof M, string>, "asc" | "desc"] | undefined>((updateUrl ? initialSortUrl : undefined) ?? initialSortInternal);
|
|
@@ -328,6 +331,11 @@ function encodeFilterAndSort(filterValues?: FilterValues<string>, sortBy?: [stri
|
|
|
328
331
|
} else if (val instanceof EntityReference) {
|
|
329
332
|
encodedValue = encodeRef(val);
|
|
330
333
|
}
|
|
334
|
+
} else if (typeof val === "string") {
|
|
335
|
+
// JSON.stringify wraps the string in quotes (e.g. "4" → '"4"')
|
|
336
|
+
// so that decodeString's JSON.parse restores the string type,
|
|
337
|
+
// not a number. Without this, "4" round-trips as the number 4.
|
|
338
|
+
encodedValue = JSON.stringify(val);
|
|
331
339
|
}
|
|
332
340
|
} catch (e) {
|
|
333
341
|
encodedValue = val;
|
package/src/components/index.tsx
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
import { Link, useNavigate } from "react-router-dom";
|
|
4
|
-
import { ErrorBoundary, FireCMSLogo } from "../components";
|
|
4
|
+
import { ErrorBoundary, FireCMSLogo, LanguageToggle } from "../components";
|
|
5
5
|
import {
|
|
6
6
|
Avatar,
|
|
7
7
|
BrightnessMediumIcon,
|
|
8
|
+
CheckIcon,
|
|
8
9
|
cls,
|
|
9
10
|
DarkModeIcon,
|
|
10
11
|
IconButton,
|
|
@@ -15,7 +16,7 @@ import {
|
|
|
15
16
|
Skeleton,
|
|
16
17
|
Typography
|
|
17
18
|
} from "@firecms/ui";
|
|
18
|
-
import { useAuthController, useLargeLayout, useModeController, useNavigationController } from "../hooks";
|
|
19
|
+
import { useAuthController, useLargeLayout, useModeController, useNavigationController, useTranslation } from "../hooks";
|
|
19
20
|
import { User } from "../types";
|
|
20
21
|
import { useApp } from "../app/useApp";
|
|
21
22
|
import { useBreadcrumbsController } from "../hooks/useBreadcrumbsController";
|
|
@@ -85,6 +86,8 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
85
86
|
mode,
|
|
86
87
|
setMode
|
|
87
88
|
} = useModeController();
|
|
89
|
+
|
|
90
|
+
const { i18n, t } = useTranslation();
|
|
88
91
|
|
|
89
92
|
const navigate = useNavigate();
|
|
90
93
|
|
|
@@ -92,7 +95,7 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
92
95
|
|
|
93
96
|
const user = userProp ?? authController.user;
|
|
94
97
|
|
|
95
|
-
let avatarComponent:
|
|
98
|
+
let avatarComponent: React.ReactElement | null;
|
|
96
99
|
|
|
97
100
|
if (user) {
|
|
98
101
|
const initial = user?.displayName
|
|
@@ -192,18 +195,19 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
192
195
|
<Menu
|
|
193
196
|
trigger={<IconButton
|
|
194
197
|
color="inherit"
|
|
195
|
-
aria-label="Open drawer"
|
|
196
|
-
size="large">
|
|
198
|
+
aria-label="Open drawer">
|
|
197
199
|
{mode === "dark"
|
|
198
|
-
? <DarkModeIcon />
|
|
199
|
-
: <LightModeIcon />}
|
|
200
|
+
? <DarkModeIcon size="small" />
|
|
201
|
+
: <LightModeIcon size="small" />}
|
|
200
202
|
</IconButton>}>
|
|
201
|
-
<MenuItem onClick={() => setMode("dark")}><DarkModeIcon size={"smallest"} />
|
|
202
|
-
<MenuItem onClick={() => setMode("light")}><LightModeIcon size={"smallest"} />
|
|
203
|
+
<MenuItem onClick={() => setMode("dark")}><DarkModeIcon size={"smallest"} /> {t("dark_mode")}</MenuItem>
|
|
204
|
+
<MenuItem onClick={() => setMode("light")}><LightModeIcon size={"smallest"} /> {t("light_mode")}</MenuItem>
|
|
203
205
|
<MenuItem onClick={() => setMode("system")}> <BrightnessMediumIcon
|
|
204
|
-
size={"smallest"} />
|
|
206
|
+
size={"smallest"} />{t("system_mode")}</MenuItem>
|
|
205
207
|
</Menu>}
|
|
206
208
|
|
|
209
|
+
<LanguageToggle />
|
|
210
|
+
|
|
207
211
|
<Menu trigger={avatarComponent}>
|
|
208
212
|
{user && <div className={"px-4 py-2 mb-2"}>
|
|
209
213
|
{user.displayName && <Typography variant={"body1"} color={"secondary"}>
|
|
@@ -222,7 +226,7 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
222
226
|
navigate("/");
|
|
223
227
|
}}>
|
|
224
228
|
<LogoutIcon />
|
|
225
|
-
|
|
229
|
+
{t("log_out")}
|
|
226
230
|
</MenuItem>}
|
|
227
231
|
|
|
228
232
|
</Menu>
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
useCollapsedGroups,
|
|
5
|
+
useLargeLayout,
|
|
6
|
+
useNavigationController,
|
|
7
|
+
useTranslation
|
|
8
|
+
} from "../hooks";
|
|
4
9
|
|
|
5
10
|
import { Link, useNavigate } from "react-router-dom";
|
|
6
11
|
import { CMSAnalyticsEvent, NavigationEntry, NavigationResult } from "../types";
|
|
@@ -34,6 +39,7 @@ export function DefaultDrawer({
|
|
|
34
39
|
|
|
35
40
|
const analyticsController = useAnalyticsController();
|
|
36
41
|
const navigation = useNavigationController();
|
|
42
|
+
const { t } = useTranslation();
|
|
37
43
|
|
|
38
44
|
const tooltipsOpen = drawerHovered && !drawerOpen && !adminMenuOpen;
|
|
39
45
|
const largeLayout = useLargeLayout();
|
|
@@ -122,7 +128,7 @@ export function DefaultDrawer({
|
|
|
122
128
|
}}
|
|
123
129
|
key={entry.id}>
|
|
124
130
|
{<IconForView collectionOrView={entry.view} />}
|
|
125
|
-
{entry.name}
|
|
131
|
+
{t(entry.name as any)}
|
|
126
132
|
</MenuItem>)}
|
|
127
133
|
|
|
128
134
|
</Menu>}
|
|
@@ -3,12 +3,13 @@ import { cls, ExpandMoreIcon, Typography } from "@firecms/ui";
|
|
|
3
3
|
import { NavigationEntry } from "../types";
|
|
4
4
|
import { IconForView } from "../util";
|
|
5
5
|
import { DrawerNavigationItem } from "./DrawerNavigationItem";
|
|
6
|
+
import { useTranslation } from "../hooks/useTranslation";
|
|
6
7
|
|
|
7
8
|
export interface DrawerNavigationGroupProps {
|
|
8
9
|
/**
|
|
9
|
-
* Group name to display in header
|
|
10
|
+
* Group name to display in header. When null, uses the translated default group name.
|
|
10
11
|
*/
|
|
11
|
-
group: string;
|
|
12
|
+
group: string | null;
|
|
12
13
|
/**
|
|
13
14
|
* Navigation entries in this group
|
|
14
15
|
*/
|
|
@@ -58,6 +59,7 @@ export function DrawerNavigationGroup({
|
|
|
58
59
|
headerActions,
|
|
59
60
|
onItemClick
|
|
60
61
|
}: DrawerNavigationGroupProps) {
|
|
62
|
+
const { t } = useTranslation();
|
|
61
63
|
return (
|
|
62
64
|
<div
|
|
63
65
|
className={"bg-surface-50 dark:bg-surface-800/30 my-4 rounded-lg ml-3 mr-1"}
|
|
@@ -81,7 +83,7 @@ export function DrawerNavigationGroup({
|
|
|
81
83
|
color={"secondary"}
|
|
82
84
|
className="font-medium flex-grow line-clamp-1"
|
|
83
85
|
>
|
|
84
|
-
{(group || "
|
|
86
|
+
{(group || t("views_group")).toUpperCase()}
|
|
85
87
|
</Typography>
|
|
86
88
|
{headerActions && (
|
|
87
89
|
<div onClick={(e) => e.stopPropagation()}>
|
|
@@ -32,6 +32,7 @@ import { EntityForm, EntityFormProps } from "../form";
|
|
|
32
32
|
import { EntityEditViewFormActions } from "./EntityEditViewFormActions";
|
|
33
33
|
import { EntityJsonPreview } from "../components/EntityJsonPreview";
|
|
34
34
|
import { createFormexStub } from "../util/createFormexStub";
|
|
35
|
+
import { useTranslation } from "../hooks/useTranslation";
|
|
35
36
|
|
|
36
37
|
export const MAIN_TAB_VALUE = "__main_##Q$SC^#S6";
|
|
37
38
|
export const JSON_TAB_VALUE = "__json";
|
|
@@ -170,6 +171,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
170
171
|
}) {
|
|
171
172
|
|
|
172
173
|
const context = useFireCMSContext();
|
|
174
|
+
const { t } = useTranslation();
|
|
173
175
|
|
|
174
176
|
const [usedEntity, setUsedEntity] = useState<Entity<M> | undefined>(entity);
|
|
175
177
|
|
|
@@ -342,8 +344,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
342
344
|
openEntityMode={layout} />
|
|
343
345
|
: <div className="flex items-center justify-center w-full h-full p-3">
|
|
344
346
|
<Typography variant={"label"}>
|
|
345
|
-
|
|
346
|
-
adding additional collections
|
|
347
|
+
{t("youd_need_to_save_before_additional_collections")}
|
|
347
348
|
</Typography>
|
|
348
349
|
</div>)
|
|
349
350
|
}
|
|
@@ -451,7 +452,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
451
452
|
let result = <div className="relative flex flex-col h-full w-full bg-white dark:bg-surface-900">
|
|
452
453
|
|
|
453
454
|
{shouldShowTopBar && <div
|
|
454
|
-
className={cls("h-14 items-center overflow-
|
|
455
|
+
className={cls("h-14 items-center overflow-hidden w-full border-b pl-2 pr-2 flex gap-2 bg-surface-50 dark:bg-surface-900", defaultBorderMixin)}>
|
|
455
456
|
|
|
456
457
|
{barActions?.({
|
|
457
458
|
path: fullIdPath ?? path,
|
|
@@ -28,7 +28,8 @@ import {
|
|
|
28
28
|
useCustomizationController,
|
|
29
29
|
useFireCMSContext,
|
|
30
30
|
useSideEntityController,
|
|
31
|
-
useSnackbarController
|
|
31
|
+
useSnackbarController,
|
|
32
|
+
useTranslation
|
|
32
33
|
} from "../hooks";
|
|
33
34
|
import { EntityFormActionsProps } from "../form/EntityFormActions";
|
|
34
35
|
import { SideDialogController, useSideDialogContext } from "./SideDialogs";
|
|
@@ -56,6 +57,7 @@ export function EntityEditViewFormActions({
|
|
|
56
57
|
const sideEntityController = useSideEntityController();
|
|
57
58
|
const sideDialogContext = useSideDialogContext();
|
|
58
59
|
const customizationController = useCustomizationController();
|
|
60
|
+
const { t } = useTranslation();
|
|
59
61
|
|
|
60
62
|
const entityActions = useMemo((): EntityAction[] => {
|
|
61
63
|
const customEntityActions = (collection.entityActions ?? [])
|
|
@@ -90,7 +92,8 @@ export function EntityEditViewFormActions({
|
|
|
90
92
|
openEntityMode,
|
|
91
93
|
navigateBack,
|
|
92
94
|
formContext,
|
|
93
|
-
formex
|
|
95
|
+
formex,
|
|
96
|
+
t
|
|
94
97
|
})
|
|
95
98
|
: buildSideActions({
|
|
96
99
|
savingError,
|
|
@@ -106,7 +109,8 @@ export function EntityEditViewFormActions({
|
|
|
106
109
|
openEntityMode,
|
|
107
110
|
navigateBack,
|
|
108
111
|
formContext,
|
|
109
|
-
formex
|
|
112
|
+
formex,
|
|
113
|
+
t
|
|
110
114
|
});
|
|
111
115
|
}
|
|
112
116
|
|
|
@@ -123,8 +127,9 @@ type ActionsViewProps<M extends object> = {
|
|
|
123
127
|
pluginActions?: React.ReactNode[],
|
|
124
128
|
openEntityMode: "side_panel" | "full_screen";
|
|
125
129
|
navigateBack: () => void;
|
|
126
|
-
formContext: FormContext
|
|
130
|
+
formContext: FormContext;
|
|
127
131
|
formex: FormexController<any>;
|
|
132
|
+
t: any;
|
|
128
133
|
};
|
|
129
134
|
|
|
130
135
|
function buildBottomActions<M extends object>({
|
|
@@ -141,7 +146,8 @@ function buildBottomActions<M extends object>({
|
|
|
141
146
|
openEntityMode,
|
|
142
147
|
navigateBack,
|
|
143
148
|
formContext,
|
|
144
|
-
formex
|
|
149
|
+
formex,
|
|
150
|
+
t
|
|
145
151
|
}: ActionsViewProps<M>) {
|
|
146
152
|
|
|
147
153
|
const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
|
|
@@ -191,7 +197,7 @@ function buildBottomActions<M extends object>({
|
|
|
191
197
|
color="primary"
|
|
192
198
|
disabled={disabled || formex.isSubmitting}
|
|
193
199
|
type="reset">
|
|
194
|
-
{status === "existing" ? "
|
|
200
|
+
{status === "existing" ? t("discard") : t("clear")}
|
|
195
201
|
</Button>
|
|
196
202
|
<Button variant={canClose ? "text" : "filled"}
|
|
197
203
|
color="primary"
|
|
@@ -200,9 +206,9 @@ function buildBottomActions<M extends object>({
|
|
|
200
206
|
onClick={() => {
|
|
201
207
|
sideDialogContext.setPendingClose(false);
|
|
202
208
|
}}>
|
|
203
|
-
{status === "existing" && "
|
|
204
|
-
{status === "copy" && "
|
|
205
|
-
{status === "new" && "
|
|
209
|
+
{status === "existing" && t("save")}
|
|
210
|
+
{status === "copy" && t("create_copy")}
|
|
211
|
+
{status === "new" && t("create")}
|
|
206
212
|
</Button>
|
|
207
213
|
{canClose && <LoadingButton variant="filled"
|
|
208
214
|
color="primary"
|
|
@@ -212,9 +218,9 @@ function buildBottomActions<M extends object>({
|
|
|
212
218
|
onClick={() => {
|
|
213
219
|
sideDialogContext.setPendingClose?.(true);
|
|
214
220
|
}}>
|
|
215
|
-
{status === "existing" && "
|
|
216
|
-
{status === "copy" && "
|
|
217
|
-
{status === "new" && "
|
|
221
|
+
{status === "existing" && t("save_and_close")}
|
|
222
|
+
{status === "copy" && t("create_copy_and_close")}
|
|
223
|
+
{status === "new" && t("create_and_close")}
|
|
218
224
|
</LoadingButton>}
|
|
219
225
|
</DialogActions>;
|
|
220
226
|
}
|
|
@@ -233,7 +239,8 @@ function buildSideActions<M extends object>({
|
|
|
233
239
|
openEntityMode,
|
|
234
240
|
navigateBack,
|
|
235
241
|
formContext,
|
|
236
|
-
formex
|
|
242
|
+
formex,
|
|
243
|
+
t
|
|
237
244
|
}: ActionsViewProps<M>) {
|
|
238
245
|
|
|
239
246
|
const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
|
|
@@ -249,13 +256,13 @@ function buildSideActions<M extends object>({
|
|
|
249
256
|
onClick={() => {
|
|
250
257
|
sideDialogContext.setPendingClose?.(false);
|
|
251
258
|
}}>
|
|
252
|
-
{status === "existing" && "
|
|
253
|
-
{status === "copy" && "
|
|
254
|
-
{status === "new" && "
|
|
259
|
+
{status === "existing" && t("save")}
|
|
260
|
+
{status === "copy" && t("create_copy")}
|
|
261
|
+
{status === "new" && t("create")}
|
|
255
262
|
</LoadingButton>
|
|
256
263
|
|
|
257
264
|
<Button fullWidth={true} variant="text" disabled={disabled || formex.isSubmitting} type="reset">
|
|
258
|
-
{status === "existing" ? "
|
|
265
|
+
{status === "existing" ? t("discard") : t("clear")}
|
|
259
266
|
</Button>
|
|
260
267
|
|
|
261
268
|
{pluginActions}
|