@firecms/core 3.1.0 → 3.2.0-canary.4c3b8f2
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/EntityCollectionView/CollectionDataErrorBanner.d.ts +4 -0
- package/dist/components/ErrorBoundary.d.ts +3 -1
- 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/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/image-bubble.d.ts +5 -0
- package/dist/editor/components/index.d.ts +16 -0
- package/dist/editor/components/table-bubble.d.ts +5 -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 +13 -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 +12 -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/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 +12898 -2265
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +12877 -2264
- package/dist/index.umd.js.map +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/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 +7 -0
- package/dist/types/storage.d.ts +1 -0
- package/dist/types/translations.d.ts +646 -0
- package/dist/util/useStorageUploadController.d.ts +10 -1
- package/package.json +45 -9
- 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/popup_field/PopupFormField.tsx +3 -2
- package/src/components/EntityCollectionView/BoardSortableList.tsx +3 -1
- package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +16 -43
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +17 -25
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +26 -18
- 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 +11 -8
- 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/VirtualTableHeader.tsx +12 -10
- 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 +14 -10
- 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 +6 -5
- package/src/core/FireCMS.tsx +33 -6
- package/src/editor/components/SlashCommandMenu.tsx +516 -0
- package/src/editor/components/editor-bubble-item.tsx +32 -0
- package/src/editor/components/editor-bubble.tsx +118 -0
- package/src/editor/components/image-bubble.tsx +156 -0
- package/src/editor/components/index.ts +14 -0
- package/src/editor/components/table-bubble.tsx +165 -0
- package/src/editor/editor.tsx +455 -0
- package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
- package/src/editor/extensions/Image/index.ts +133 -0
- package/src/editor/extensions/Image.ts +159 -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 +480 -0
- package/src/editor/hooks/useProseMirror.ts +124 -0
- package/src/editor/hooks/useProseMirrorContext.ts +15 -0
- package/src/editor/index.ts +2 -0
- package/src/editor/markdown.ts +172 -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 +58 -0
- package/src/editor/plugins/inputrules.ts +82 -0
- package/src/editor/plugins/placeholderPlugin.ts +55 -0
- package/src/editor/plugins/slashCommandPlugin.ts +61 -0
- package/src/editor/schema.ts +240 -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 +108 -0
- package/src/editor/utils/remove_classes.ts +17 -0
- package/src/editor/utils/useDebouncedCallback.ts +25 -0
- package/src/form/EntityForm.tsx +16 -3
- package/src/form/EntityFormActions.tsx +19 -12
- package/src/form/PropertyFieldBinding.tsx +3 -2
- package/src/form/components/LocalChangesMenu.tsx +13 -13
- package/src/form/components/StorageItemPreview.tsx +3 -2
- package/src/form/components/StorageUploadProgress.tsx +18 -3
- 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 +33 -19
- package/src/form/field_bindings/RepeatFieldBinding.tsx +3 -1
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +4 -3
- package/src/hooks/index.tsx +1 -0
- package/src/hooks/useBuildNavigationController.tsx +45 -18
- package/src/hooks/useCollapsedGroups.ts +7 -6
- package/src/hooks/useTranslation.ts +31 -0
- package/src/i18n/FireCMSi18nProvider.tsx +160 -0
- package/src/index.ts +4 -0
- 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/components/UrlComponentPreview.tsx +4 -2
- package/src/preview/components/UserPreview.tsx +3 -1
- 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 +8 -0
- package/src/types/properties.ts +1 -0
- package/src/types/storage.ts +2 -1
- package/src/types/translations.ts +725 -0
- package/src/util/useStorageUploadController.tsx +23 -29
|
@@ -20,9 +20,6 @@ import {
|
|
|
20
20
|
DialogActions,
|
|
21
21
|
DialogContent,
|
|
22
22
|
getColorSchemeForSeed,
|
|
23
|
-
IconButton,
|
|
24
|
-
RefreshIcon,
|
|
25
|
-
Tooltip,
|
|
26
23
|
Typography
|
|
27
24
|
} from "@firecms/ui";
|
|
28
25
|
import { getPropertyInPath, resolveCollection, resolveEnumValues } from "../../util";
|
|
@@ -38,6 +35,8 @@ import { useAnalyticsController } from "../../hooks/useAnalyticsController";
|
|
|
38
35
|
import { SaveEntityProps } from "../../types/datasource";
|
|
39
36
|
import { setIn } from "@firecms/formex";
|
|
40
37
|
import { useBoardDataController } from "./useBoardDataController";
|
|
38
|
+
import { CollectionDataErrorBanner } from "./CollectionDataErrorBanner";
|
|
39
|
+
import { useTranslation } from "../../hooks/useTranslation";
|
|
41
40
|
|
|
42
41
|
export type EntityCollectionBoardViewProps<M extends Record<string, any> = any> = {
|
|
43
42
|
collection: EntityCollection<M>;
|
|
@@ -77,6 +76,7 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
77
76
|
const sideEntityController = useSideEntityController();
|
|
78
77
|
const analyticsController = useAnalyticsController();
|
|
79
78
|
const plugins = customizationController.plugins ?? [];
|
|
79
|
+
const { t } = useTranslation();
|
|
80
80
|
|
|
81
81
|
// State for backfill dialog
|
|
82
82
|
const [showBackfillDialog, setShowBackfillDialog] = useState(false);
|
|
@@ -579,19 +579,16 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
579
579
|
|
|
580
580
|
// Check for loading error
|
|
581
581
|
const hasError = Boolean(dataLoadingError);
|
|
582
|
-
const errorMessage = dataLoadingError?.message || "";
|
|
583
|
-
const indexUrl = errorMessage.match(/https:\/\/console\.firebase\.google\.com[^\s]+/)?.[0];
|
|
584
582
|
|
|
585
583
|
// Error: no enum properties available for Kanban columns
|
|
586
584
|
if (!columnProperty || enumColumns.length === 0) {
|
|
587
585
|
return (
|
|
588
586
|
<div className="flex-1 flex flex-col items-center justify-center p-8 gap-4">
|
|
589
587
|
<Typography variant="h6">
|
|
590
|
-
|
|
588
|
+
{t("kanban_view_not_available")}
|
|
591
589
|
</Typography>
|
|
592
590
|
<Typography variant="body2" color="secondary" className="text-center max-w-md">
|
|
593
|
-
|
|
594
|
-
Please add an enum property to your collection schema to use this view.
|
|
591
|
+
{t("kanban_view_requires_enum")}
|
|
595
592
|
</Typography>
|
|
596
593
|
{KanbanSetupComponent && (
|
|
597
594
|
<KanbanSetupComponent
|
|
@@ -612,7 +609,7 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
612
609
|
return (
|
|
613
610
|
<div className="flex-1 flex items-center justify-center p-8">
|
|
614
611
|
<Typography variant="label" color="secondary">
|
|
615
|
-
|
|
612
|
+
{t("no_enum_values_configured", { property: columnProperty })}
|
|
616
613
|
</Typography>
|
|
617
614
|
</div>
|
|
618
615
|
);
|
|
@@ -622,33 +619,10 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
622
619
|
<div className="flex-1 flex flex-col overflow-hidden">
|
|
623
620
|
{/* Error banner - only show when no data loaded */}
|
|
624
621
|
{hasError && allEntities.length === 0 && (
|
|
625
|
-
<
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
{indexUrl
|
|
630
|
-
? "A Firestore index is required for this query."
|
|
631
|
-
: errorMessage}
|
|
632
|
-
</Typography>
|
|
633
|
-
<Tooltip title="Refresh data">
|
|
634
|
-
<IconButton
|
|
635
|
-
size="small"
|
|
636
|
-
onClick={() => boardDataController.refreshAll()}
|
|
637
|
-
>
|
|
638
|
-
<RefreshIcon size="small" />
|
|
639
|
-
</IconButton>
|
|
640
|
-
</Tooltip>
|
|
641
|
-
{indexUrl && (
|
|
642
|
-
<Button
|
|
643
|
-
size="small"
|
|
644
|
-
variant="outlined"
|
|
645
|
-
color="error"
|
|
646
|
-
onClick={() => window.open(indexUrl, "_blank")}
|
|
647
|
-
>
|
|
648
|
-
Create Index
|
|
649
|
-
</Button>
|
|
650
|
-
)}
|
|
651
|
-
</div>
|
|
622
|
+
<CollectionDataErrorBanner
|
|
623
|
+
error={dataLoadingError}
|
|
624
|
+
onRetry={() => boardDataController.refreshAll()}
|
|
625
|
+
/>
|
|
652
626
|
)}
|
|
653
627
|
|
|
654
628
|
{/* Backfill info bar - non-blocking */}
|
|
@@ -656,14 +630,14 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
656
630
|
<div
|
|
657
631
|
className="flex items-center justify-between gap-4 px-4 py-2 bg-amber-50 dark:bg-amber-900/20 border-b border-amber-200 dark:border-amber-800">
|
|
658
632
|
<Typography variant="body2" color="secondary">
|
|
659
|
-
|
|
633
|
+
{t("items_need_backfill")}
|
|
660
634
|
</Typography>
|
|
661
635
|
<Button
|
|
662
636
|
size="small"
|
|
663
637
|
variant="text"
|
|
664
638
|
onClick={() => setShowBackfillDialog(true)}
|
|
665
639
|
>
|
|
666
|
-
|
|
640
|
+
{t("initialize")}
|
|
667
641
|
</Button>
|
|
668
642
|
</div>
|
|
669
643
|
)}
|
|
@@ -713,18 +687,17 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
713
687
|
{/* Backfill dialog */}
|
|
714
688
|
<Dialog open={showBackfillDialog} onOpenChange={setShowBackfillDialog}>
|
|
715
689
|
<DialogContent>
|
|
716
|
-
<Typography variant="h6" className="mb-4">
|
|
690
|
+
<Typography variant="h6" className="mb-4">{t("initialize_kanban_order")}</Typography>
|
|
717
691
|
<Typography variant="body2">
|
|
718
|
-
|
|
719
|
-
Items will maintain their current order within each column.
|
|
692
|
+
{t("initialize_kanban_order_desc")}
|
|
720
693
|
</Typography>
|
|
721
694
|
</DialogContent>
|
|
722
695
|
<DialogActions>
|
|
723
696
|
<Button variant="text" onClick={() => setShowBackfillDialog(false)} disabled={backfillLoading}>
|
|
724
|
-
|
|
697
|
+
{t("cancel")}
|
|
725
698
|
</Button>
|
|
726
699
|
<Button onClick={handleBackfill} disabled={backfillLoading}>
|
|
727
|
-
{backfillLoading ? <CircularProgress size="smallest" /> : "
|
|
700
|
+
{backfillLoading ? <CircularProgress size="smallest" /> : t("initialize")}
|
|
728
701
|
</Button>
|
|
729
702
|
</DialogActions>
|
|
730
703
|
</Dialog>
|
|
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useRef } from "react";
|
|
|
2
2
|
import { CollectionSize, Entity, EntityCollection, EntityTableController, SelectionController } from "../../types";
|
|
3
3
|
import { EntityCard } from "./EntityCard";
|
|
4
4
|
import { CircularProgress, cls, Typography } from "@firecms/ui";
|
|
5
|
-
import { useAuthController, useCustomizationController } from "../../hooks";
|
|
5
|
+
import { useAuthController, useCustomizationController, useTranslation } from "../../hooks";
|
|
6
6
|
|
|
7
7
|
export type EntityCollectionCardViewProps<M extends Record<string, any> = any> = {
|
|
8
8
|
collection: EntityCollection<M>;
|
|
@@ -61,17 +61,18 @@ function getGridColumnsClass(size: CollectionSize): string {
|
|
|
61
61
|
* Alternative to the EntityCollectionTable for visual browsing.
|
|
62
62
|
*/
|
|
63
63
|
export function EntityCollectionCardView<M extends Record<string, any> = any>({
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
collection,
|
|
65
|
+
tableController,
|
|
66
|
+
onEntityClick,
|
|
67
|
+
selectionController,
|
|
68
|
+
selectionEnabled = true,
|
|
69
|
+
highlightedEntities,
|
|
70
|
+
emptyComponent,
|
|
71
|
+
onScroll,
|
|
72
|
+
initialScroll,
|
|
73
|
+
size = "m"
|
|
74
|
+
}: EntityCollectionCardViewProps<M>) {
|
|
75
|
+
const { t } = useTranslation();
|
|
75
76
|
const authController = useAuthController();
|
|
76
77
|
const customizationController = useCustomizationController();
|
|
77
78
|
|
|
@@ -178,23 +179,14 @@ export function EntityCollectionCardView<M extends Record<string, any> = any>({
|
|
|
178
179
|
<div className="flex-1 flex items-center justify-center p-8">
|
|
179
180
|
{emptyComponent ?? (
|
|
180
181
|
<Typography variant="label" color="secondary">
|
|
181
|
-
|
|
182
|
+
{t("no_entries_found")}
|
|
182
183
|
</Typography>
|
|
183
184
|
)}
|
|
184
185
|
</div>
|
|
185
186
|
);
|
|
186
187
|
}
|
|
187
188
|
|
|
188
|
-
|
|
189
|
-
if (dataLoadingError) {
|
|
190
|
-
return (
|
|
191
|
-
<div className="flex-1 flex items-center justify-center p-8">
|
|
192
|
-
<Typography className="text-red-500">
|
|
193
|
-
Error loading data: {dataLoadingError.message}
|
|
194
|
-
</Typography>
|
|
195
|
-
</div>
|
|
196
|
-
);
|
|
197
|
-
}
|
|
189
|
+
|
|
198
190
|
|
|
199
191
|
const gridColumnsClass = getGridColumnsClass(size);
|
|
200
192
|
|
|
@@ -230,11 +222,11 @@ export function EntityCollectionCardView<M extends Record<string, any> = any>({
|
|
|
230
222
|
className="flex items-center justify-center py-8"
|
|
231
223
|
>
|
|
232
224
|
{dataLoading && (
|
|
233
|
-
<CircularProgress size="small"/>
|
|
225
|
+
<CircularProgress size="small" />
|
|
234
226
|
)}
|
|
235
227
|
{!dataLoading && noMoreToLoad && data.length > 0 && (
|
|
236
228
|
<Typography variant="caption" color="secondary">
|
|
237
|
-
|
|
229
|
+
{t("all_entries_loaded", { count: data.length.toString() })}
|
|
238
230
|
</Typography>
|
|
239
231
|
)}
|
|
240
232
|
</div>
|
|
@@ -45,13 +45,15 @@ import {
|
|
|
45
45
|
useFireCMSContext,
|
|
46
46
|
useLargeLayout,
|
|
47
47
|
useNavigationController,
|
|
48
|
-
useSideEntityController
|
|
48
|
+
useSideEntityController,
|
|
49
|
+
useTranslation
|
|
49
50
|
} from "../../hooks";
|
|
50
51
|
import { useBreadcrumbsController } from "../../hooks/useBreadcrumbsController";
|
|
51
52
|
import { useUserConfigurationPersistence } from "../../hooks/useUserConfigurationPersistence";
|
|
52
53
|
import { EntityCollectionViewActions } from "./EntityCollectionViewActions";
|
|
53
54
|
import { EntityCollectionCardView } from "./EntityCollectionCardView";
|
|
54
55
|
import { EntityCollectionBoardView } from "./EntityCollectionBoardView";
|
|
56
|
+
import { CollectionDataErrorBanner } from "./CollectionDataErrorBanner";
|
|
55
57
|
import { ViewModeToggle, KanbanPropertyOption } from "./ViewModeToggle";
|
|
56
58
|
import {
|
|
57
59
|
AddIcon,
|
|
@@ -159,6 +161,7 @@ export const EntityCollectionView = React.memo(
|
|
|
159
161
|
) {
|
|
160
162
|
|
|
161
163
|
const context = useFireCMSContext();
|
|
164
|
+
const { t } = useTranslation();
|
|
162
165
|
const navigation = useNavigationController();
|
|
163
166
|
const breadcrumbs = useBreadcrumbsController();
|
|
164
167
|
const fullPath = fullPathProp ?? collectionProp.path;
|
|
@@ -695,11 +698,13 @@ export const EntityCollectionView = React.memo(
|
|
|
695
698
|
customEntityActions?: EntityAction[]
|
|
696
699
|
}): EntityAction[] => {
|
|
697
700
|
const deleteEnabled = entity ? canDeleteEntity(collection, authController, fullPath, entity) : true;
|
|
698
|
-
const actions: EntityAction[] = [
|
|
701
|
+
const actions: EntityAction[] = [
|
|
702
|
+
{ ...editEntityAction, name: t("edit") }
|
|
703
|
+
];
|
|
699
704
|
if (createEnabled)
|
|
700
|
-
actions.push(copyEntityAction);
|
|
705
|
+
actions.push({ ...copyEntityAction, name: t("copy") });
|
|
701
706
|
if (deleteEnabled)
|
|
702
|
-
actions.push(deleteEntityAction);
|
|
707
|
+
actions.push({ ...deleteEntityAction, name: t("delete") });
|
|
703
708
|
if (customEntityActions)
|
|
704
709
|
return mergeEntityActions(actions, customEntityActions);
|
|
705
710
|
return actions;
|
|
@@ -899,9 +904,11 @@ export const EntityCollectionView = React.memo(
|
|
|
899
904
|
/>
|
|
900
905
|
|
|
901
906
|
{/* View content - only the view-specific content changes */}
|
|
902
|
-
{tableController.dataLoadingError && pluginErrorView
|
|
903
|
-
|
|
904
|
-
|
|
907
|
+
{tableController.dataLoadingError && pluginErrorView}
|
|
908
|
+
{tableController.dataLoadingError && !pluginErrorView && (
|
|
909
|
+
<CollectionDataErrorBanner error={tableController.dataLoadingError} />
|
|
910
|
+
)}
|
|
911
|
+
{viewMode === "kanban" && enabledViews.includes("kanban") ? (
|
|
905
912
|
<EntityCollectionBoardView
|
|
906
913
|
key={`kanban-view-${fullPath}-${selectedKanbanProperty}`}
|
|
907
914
|
collection={collection}
|
|
@@ -916,16 +923,16 @@ export const EntityCollectionView = React.memo(
|
|
|
916
923
|
deletedEntities={deletedEntities}
|
|
917
924
|
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
918
925
|
? <div className="flex flex-col items-center justify-center">
|
|
919
|
-
<Typography variant={"subtitle2"}>
|
|
926
|
+
<Typography variant={"subtitle2"}>{t("so_empty")}</Typography>
|
|
920
927
|
<Button
|
|
921
928
|
onClick={onNewClick}
|
|
922
929
|
className="mt-4"
|
|
923
930
|
>
|
|
924
931
|
<AddIcon />
|
|
925
|
-
|
|
932
|
+
{t("create_your_first_entry")}
|
|
926
933
|
</Button>
|
|
927
934
|
</div>
|
|
928
|
-
: <Typography variant={"label"}>
|
|
935
|
+
: <Typography variant={"label"}>{t("no_results_filter_sort")}</Typography>
|
|
929
936
|
}
|
|
930
937
|
/>
|
|
931
938
|
) : viewMode === "cards" ? (
|
|
@@ -942,16 +949,16 @@ export const EntityCollectionView = React.memo(
|
|
|
942
949
|
size={cardSize}
|
|
943
950
|
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
944
951
|
? <div className="flex flex-col items-center justify-center">
|
|
945
|
-
<Typography variant={"subtitle2"}>
|
|
952
|
+
<Typography variant={"subtitle2"}>{t("so_empty")}</Typography>
|
|
946
953
|
<Button
|
|
947
954
|
onClick={onNewClick}
|
|
948
955
|
className="mt-4"
|
|
949
956
|
>
|
|
950
957
|
<AddIcon />
|
|
951
|
-
|
|
958
|
+
{t("create_your_first_entry")}
|
|
952
959
|
</Button>
|
|
953
960
|
</div>
|
|
954
|
-
: <Typography variant={"label"}>
|
|
961
|
+
: <Typography variant={"label"}>{t("no_results_filter_sort")}</Typography>
|
|
955
962
|
}
|
|
956
963
|
/>
|
|
957
964
|
) : (
|
|
@@ -980,16 +987,16 @@ export const EntityCollectionView = React.memo(
|
|
|
980
987
|
textSearchEnabled={textSearchEnabled}
|
|
981
988
|
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
982
989
|
? <div className="flex flex-col items-center justify-center">
|
|
983
|
-
<Typography variant={"subtitle2"}>
|
|
990
|
+
<Typography variant={"subtitle2"}>{t("so_empty")}</Typography>
|
|
984
991
|
<Button
|
|
985
992
|
onClick={onNewClick}
|
|
986
993
|
className="mt-4"
|
|
987
994
|
>
|
|
988
995
|
<AddIcon />
|
|
989
|
-
|
|
996
|
+
{t("create_your_first_entry")}
|
|
990
997
|
</Button>
|
|
991
998
|
</div>
|
|
992
|
-
: <Typography variant={"label"}>
|
|
999
|
+
: <Typography variant={"label"}>{t("no_results_filter_sort")}</Typography>
|
|
993
1000
|
}
|
|
994
1001
|
hoverRow={hoverRow}
|
|
995
1002
|
inlineEditing={checkInlineEditing()}
|
|
@@ -1160,11 +1167,12 @@ function EntityIdHeaderWidget({
|
|
|
1160
1167
|
const [searchString, setSearchString] = React.useState("");
|
|
1161
1168
|
const [recentIds, setRecentIds] = React.useState<string[]>(getRecentIds(collection.id));
|
|
1162
1169
|
const sideEntityController = useSideEntityController();
|
|
1170
|
+
const { t } = useTranslation();
|
|
1163
1171
|
|
|
1164
1172
|
const openEntityMode = collection?.openEntityMode ?? DEFAULT_ENTITY_OPEN_MODE;
|
|
1165
1173
|
|
|
1166
1174
|
return (
|
|
1167
|
-
<Tooltip title={!openPopup ? "
|
|
1175
|
+
<Tooltip title={!openPopup ? t("find_by_id") : undefined} asChild={false}>
|
|
1168
1176
|
<Popover
|
|
1169
1177
|
open={openPopup}
|
|
1170
1178
|
onOpenChange={setOpenPopup}
|
|
@@ -1200,7 +1208,7 @@ function EntityIdHeaderWidget({
|
|
|
1200
1208
|
<div className="flex p-2 w-full gap-2">
|
|
1201
1209
|
<input
|
|
1202
1210
|
autoFocus={openPopup}
|
|
1203
|
-
placeholder={"
|
|
1211
|
+
placeholder={t("find_entity_by_id")}
|
|
1204
1212
|
// size={"small"}
|
|
1205
1213
|
onChange={(e) => {
|
|
1206
1214
|
setSearchString(e.target.value);
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from "@firecms/ui";
|
|
18
18
|
import { toArray } from "../../util/arrays";
|
|
19
19
|
import { ErrorBoundary } from "../ErrorBoundary";
|
|
20
|
+
import { useTranslation } from "../../hooks/useTranslation";
|
|
20
21
|
|
|
21
22
|
export type EntityCollectionViewActionsProps<M extends Record<string, any>> = {
|
|
22
23
|
collection: EntityCollection<M>;
|
|
@@ -45,9 +46,9 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
|
45
46
|
}: EntityCollectionViewActionsProps<M>) {
|
|
46
47
|
|
|
47
48
|
const context = useFireCMSContext();
|
|
48
|
-
|
|
49
49
|
const customizationController = useCustomizationController();
|
|
50
50
|
const plugins = customizationController.plugins ?? [];
|
|
51
|
+
const { t } = useTranslation();
|
|
51
52
|
|
|
52
53
|
const authController = useAuthController();
|
|
53
54
|
|
|
@@ -63,7 +64,7 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
|
63
64
|
startIcon={<AddIcon size={"small"} />}
|
|
64
65
|
variant="filled"
|
|
65
66
|
color="primary">
|
|
66
|
-
|
|
67
|
+
{t("add")} {collection.singularName ?? collection.name}
|
|
67
68
|
</Button>
|
|
68
69
|
: <Button
|
|
69
70
|
id={`add_entity_${path}`}
|
|
@@ -98,7 +99,7 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
|
98
99
|
</IconButton>;
|
|
99
100
|
multipleDeleteButton =
|
|
100
101
|
<Tooltip
|
|
101
|
-
title={multipleDeleteEnabled ? "
|
|
102
|
+
title={multipleDeleteEnabled ? t("delete_selected") : t("cannot_delete_selected")}>
|
|
102
103
|
{button}
|
|
103
104
|
</Tooltip>
|
|
104
105
|
}
|
|
@@ -12,6 +12,7 @@ import { ErrorBoundary } from "../ErrorBoundary";
|
|
|
12
12
|
import { ClearFilterSortButton } from "../ClearFilterSortButton";
|
|
13
13
|
import { FiltersDialog } from "./FiltersDialog";
|
|
14
14
|
import { Badge, Button, cls, FilterListIcon, IconButton, Tooltip } from "@firecms/ui";
|
|
15
|
+
import { useTranslation } from "../../hooks/useTranslation";
|
|
15
16
|
|
|
16
17
|
export type EntityCollectionViewStartActionsProps<M extends Record<string, any>> = {
|
|
17
18
|
collection: EntityCollection<M>;
|
|
@@ -42,6 +43,7 @@ export function EntityCollectionViewStartActions<M extends Record<string, any>>(
|
|
|
42
43
|
const customizationController = useCustomizationController();
|
|
43
44
|
const plugins = customizationController.plugins ?? [];
|
|
44
45
|
const largeLayout = useLargeLayout();
|
|
46
|
+
const { t } = useTranslation();
|
|
45
47
|
|
|
46
48
|
// Filters dialog state
|
|
47
49
|
const [filtersDialogOpen, setFiltersDialogOpen] = useState(false);
|
|
@@ -66,7 +68,7 @@ export function EntityCollectionViewStartActions<M extends Record<string, any>>(
|
|
|
66
68
|
|
|
67
69
|
// Filters button
|
|
68
70
|
const filtersButton = resolvedProperties && tableController.setFilterValues && (
|
|
69
|
-
<Tooltip title="
|
|
71
|
+
<Tooltip title={t("filters")}
|
|
70
72
|
key={"filters_tooltip"}>
|
|
71
73
|
<Badge
|
|
72
74
|
color="primary"
|
|
@@ -80,7 +82,7 @@ export function EntityCollectionViewStartActions<M extends Record<string, any>>(
|
|
|
80
82
|
startIcon={<FilterListIcon size="small" />}
|
|
81
83
|
className={cls(activeFilterCount > 0 && "text-primary")}
|
|
82
84
|
>
|
|
83
|
-
|
|
85
|
+
{t("filters")}{activeFilterCount > 0 ? ` (${activeFilterCount})` : ""}
|
|
84
86
|
</Button>
|
|
85
87
|
) : (
|
|
86
88
|
<IconButton
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
FilterListIcon,
|
|
16
16
|
Typography
|
|
17
17
|
} from "@firecms/ui";
|
|
18
|
+
import { useTranslation } from "../../hooks/useTranslation";
|
|
18
19
|
import { StringNumberFilterField } from "../SelectableTable/filters/StringNumberFilterField";
|
|
19
20
|
import { BooleanFilterField } from "../SelectableTable/filters/BooleanFilterField";
|
|
20
21
|
import { DateTimeFilterField } from "../SelectableTable/filters/DateTimeFilterField";
|
|
@@ -43,6 +44,8 @@ export function FiltersDialog({
|
|
|
43
44
|
setFilterValues,
|
|
44
45
|
forceFilter
|
|
45
46
|
}: FiltersDialogProps) {
|
|
47
|
+
const { t } = useTranslation();
|
|
48
|
+
|
|
46
49
|
// Local state for filters being edited
|
|
47
50
|
const [localFilters, setLocalFilters] = useState<FilterValues<any>>(filterValues ?? {});
|
|
48
51
|
|
|
@@ -173,7 +176,7 @@ export function FiltersDialog({
|
|
|
173
176
|
containerClassName={isAnyFieldHidden ? "hidden" : undefined}
|
|
174
177
|
>
|
|
175
178
|
<DialogTitle className="flex items-center gap-2">
|
|
176
|
-
<Typography variant="h6">
|
|
179
|
+
<Typography variant="h6">{t("filters")}</Typography>
|
|
177
180
|
{activeFilterCount > 0 && (
|
|
178
181
|
<span className="ml-2 px-2 py-0.5 text-xs rounded-full bg-primary text-white">
|
|
179
182
|
{activeFilterCount}
|
|
@@ -184,7 +187,7 @@ export function FiltersDialog({
|
|
|
184
187
|
<DialogContent >
|
|
185
188
|
{filterableProperties.length === 0 ? (
|
|
186
189
|
<Typography color="secondary" className="py-8 text-center">
|
|
187
|
-
|
|
190
|
+
{t("no_filterable_properties")}
|
|
188
191
|
</Typography>
|
|
189
192
|
) : (
|
|
190
193
|
<table className="w-full border-collapse">
|
|
@@ -228,20 +231,20 @@ export function FiltersDialog({
|
|
|
228
231
|
onClick={handleClearAll}
|
|
229
232
|
disabled={activeFilterCount === 0}
|
|
230
233
|
>
|
|
231
|
-
|
|
234
|
+
{t("clear")}
|
|
232
235
|
</Button>
|
|
233
236
|
<div className="flex-grow" />
|
|
234
237
|
<Button
|
|
235
238
|
variant="text"
|
|
236
239
|
onClick={() => onOpenChange(false)}
|
|
237
240
|
>
|
|
238
|
-
|
|
241
|
+
{t("cancel")}
|
|
239
242
|
</Button>
|
|
240
243
|
<Button
|
|
241
244
|
variant="filled"
|
|
242
245
|
onClick={handleApply}
|
|
243
246
|
>
|
|
244
|
-
|
|
247
|
+
{t("apply_filters")}
|
|
245
248
|
</Button>
|
|
246
249
|
</DialogActions>
|
|
247
250
|
</Dialog>
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
ViewColumnIcon,
|
|
13
13
|
ViewKanbanIcon
|
|
14
14
|
} from "@firecms/ui";
|
|
15
|
+
import { useTranslation } from "../../hooks/useTranslation";
|
|
15
16
|
|
|
16
17
|
export type KanbanPropertyOption = {
|
|
17
18
|
key: string;
|
|
@@ -72,6 +73,8 @@ export function ViewModeToggle({
|
|
|
72
73
|
onKanbanPropertyChange
|
|
73
74
|
}: ViewModeToggleProps) {
|
|
74
75
|
|
|
76
|
+
const { t } = useTranslation();
|
|
77
|
+
|
|
75
78
|
if (!onViewModeChange) {
|
|
76
79
|
return null;
|
|
77
80
|
}
|
|
@@ -84,9 +87,9 @@ export function ViewModeToggle({
|
|
|
84
87
|
};
|
|
85
88
|
|
|
86
89
|
const getViewModeName = () => {
|
|
87
|
-
if (viewMode === "kanban") return "
|
|
88
|
-
if (viewMode === "cards") return "
|
|
89
|
-
return "
|
|
90
|
+
if (viewMode === "kanban") return t("board");
|
|
91
|
+
if (viewMode === "cards") return t("cards");
|
|
92
|
+
return t("list");
|
|
90
93
|
};
|
|
91
94
|
|
|
92
95
|
const showSizeSelector = size && onSizeChanged && (viewMode === "table" || viewMode === "cards");
|
|
@@ -100,17 +103,17 @@ export function ViewModeToggle({
|
|
|
100
103
|
const allOptions: ToggleButtonOption<ViewMode>[] = [
|
|
101
104
|
{
|
|
102
105
|
value: "table",
|
|
103
|
-
label: "
|
|
106
|
+
label: t("list"),
|
|
104
107
|
icon: <ListIcon size="small" />
|
|
105
108
|
},
|
|
106
109
|
{
|
|
107
110
|
value: "cards",
|
|
108
|
-
label: "
|
|
111
|
+
label: t("cards"),
|
|
109
112
|
icon: <AppsIcon size="small" />
|
|
110
113
|
},
|
|
111
114
|
{
|
|
112
115
|
value: "kanban",
|
|
113
|
-
label: "
|
|
116
|
+
label: t("board"),
|
|
114
117
|
icon: <ViewKanbanIcon size="small" />
|
|
115
118
|
}
|
|
116
119
|
];
|
|
@@ -150,7 +153,7 @@ export function ViewModeToggle({
|
|
|
150
153
|
<div className="flex flex-row items-center justify-between gap-2">
|
|
151
154
|
<div className="flex items-center gap-2 text-sm text-surface-600 dark:text-surface-300">
|
|
152
155
|
<ViewColumnIcon size="small" />
|
|
153
|
-
<span>
|
|
156
|
+
<span>{t("size_label")}</span>
|
|
154
157
|
</div>
|
|
155
158
|
<Select
|
|
156
159
|
value={size}
|
|
@@ -173,7 +176,7 @@ export function ViewModeToggle({
|
|
|
173
176
|
<div className="flex flex-row items-center justify-between gap-2">
|
|
174
177
|
<div className="flex items-center gap-2 text-sm text-surface-600 dark:text-surface-300">
|
|
175
178
|
<ViewKanbanIcon size="small" />
|
|
176
|
-
<span>
|
|
179
|
+
<span>{t("group_by")}</span>
|
|
177
180
|
</div>
|
|
178
181
|
<Select
|
|
179
182
|
value={selectedKanbanProperty}
|
|
@@ -4,7 +4,7 @@ import { resolveCollection } from "../util";
|
|
|
4
4
|
import { cls, defaultBorderMixin, IconButton, OpenInNewIcon, Typography } from "@firecms/ui";
|
|
5
5
|
import { CustomizationController } from "../types/customization_controller";
|
|
6
6
|
import { useCustomizationController } from "../hooks/useCustomizationController";
|
|
7
|
-
import { useAuthController } from "../hooks";
|
|
7
|
+
import { useAuthController, useTranslation } from "../hooks";
|
|
8
8
|
import { PropertyCollectionView } from "./PropertyCollectionView";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -26,6 +26,7 @@ export function EntityView<M extends Record<string, any>>(
|
|
|
26
26
|
}: EntityViewProps<M>) {
|
|
27
27
|
|
|
28
28
|
const authController = useAuthController();
|
|
29
|
+
const { t } = useTranslation();
|
|
29
30
|
const customizationController: CustomizationController = useCustomizationController();
|
|
30
31
|
const resolvedCollection: ResolvedEntityCollection<M> = useMemo(() => resolveCollection<M>({
|
|
31
32
|
collection,
|
|
@@ -48,7 +49,7 @@ export function EntityView<M extends Record<string, any>>(
|
|
|
48
49
|
color={"secondary"}
|
|
49
50
|
component={"span"}
|
|
50
51
|
className="break-words">
|
|
51
|
-
|
|
52
|
+
{t("id")}
|
|
52
53
|
</Typography>
|
|
53
54
|
</div>
|
|
54
55
|
<div className="col-span-8">
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import React, { ErrorInfo, PropsWithChildren } from "react";
|
|
2
|
+
import { useTranslation } from "../hooks/useTranslation";
|
|
2
3
|
|
|
3
4
|
import { ErrorIcon, Typography } from "@firecms/ui";
|
|
4
5
|
|
|
5
6
|
export class ErrorBoundary extends React.Component<PropsWithChildren<Record<string, unknown>>, {
|
|
6
|
-
|
|
7
|
+
hasError: boolean,
|
|
8
|
+
error?: Error
|
|
7
9
|
}> {
|
|
8
10
|
constructor(props: any) {
|
|
9
11
|
super(props);
|
|
10
|
-
this.state = {
|
|
12
|
+
this.state = { hasError: false };
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
// eslint-disable-next-line n/handle-callback-err
|
|
14
16
|
static getDerivedStateFromError(error: Error) {
|
|
15
|
-
return { error };
|
|
17
|
+
return { hasError: true, error };
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
|
@@ -21,20 +23,30 @@ export class ErrorBoundary extends React.Component<PropsWithChildren<Record<stri
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
render() {
|
|
24
|
-
if (this.state.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<div className="flex items-center m-2">
|
|
28
|
-
<ErrorIcon color={"error"} size={"small"}/>
|
|
29
|
-
<div className="ml-4">Error</div>
|
|
30
|
-
</div>
|
|
31
|
-
<Typography variant={"caption"}>
|
|
32
|
-
{this.state.error?.message ?? "See the error in the console"}
|
|
33
|
-
</Typography>
|
|
34
|
-
</div>
|
|
35
|
-
);
|
|
26
|
+
if (this.state.hasError) {
|
|
27
|
+
// You can render any custom fallback UI
|
|
28
|
+
return <FallbackView message={this.state.error?.message}/>;
|
|
36
29
|
}
|
|
37
30
|
|
|
38
31
|
return this.props.children;
|
|
39
32
|
}
|
|
40
33
|
}
|
|
34
|
+
|
|
35
|
+
function FallbackView({ message }: { message?: string }) {
|
|
36
|
+
const { t } = useTranslation();
|
|
37
|
+
return (
|
|
38
|
+
<div className="h-full w-full bg-slate-100 flex items-center justify-center p-4">
|
|
39
|
+
<div
|
|
40
|
+
className="flex flex-col items-center justify-center m-4 bg-white dark:bg-gray-800 p-8 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
|
|
41
|
+
<div className="flex items-center mb-4 text-red-500">
|
|
42
|
+
<ErrorIcon/>
|
|
43
|
+
<div className="ml-4">{t("error")}</div>
|
|
44
|
+
</div>
|
|
45
|
+
<div className="flex justify-center text-gray-500 dark:text-gray-400">
|
|
46
|
+
{/* Error message is purposely removed since it's hard to access state here, but typical ErrorBoundary fallback doesn't always show the raw message */}
|
|
47
|
+
{t("see_console_details")}
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|