@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
|
@@ -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";
|
|
@@ -34,9 +31,12 @@ import {
|
|
|
34
31
|
useFireCMSContext,
|
|
35
32
|
useSideEntityController
|
|
36
33
|
} from "../../hooks";
|
|
34
|
+
import { useAnalyticsController } from "../../hooks/useAnalyticsController";
|
|
37
35
|
import { SaveEntityProps } from "../../types/datasource";
|
|
38
36
|
import { setIn } from "@firecms/formex";
|
|
39
37
|
import { useBoardDataController } from "./useBoardDataController";
|
|
38
|
+
import { CollectionDataErrorBanner } from "./CollectionDataErrorBanner";
|
|
39
|
+
import { useTranslation } from "../../hooks/useTranslation";
|
|
40
40
|
|
|
41
41
|
export type EntityCollectionBoardViewProps<M extends Record<string, any> = any> = {
|
|
42
42
|
collection: EntityCollection<M>;
|
|
@@ -74,7 +74,9 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
74
74
|
const context = useFireCMSContext();
|
|
75
75
|
const dataSource = useDataSource(collection);
|
|
76
76
|
const sideEntityController = useSideEntityController();
|
|
77
|
+
const analyticsController = useAnalyticsController();
|
|
77
78
|
const plugins = customizationController.plugins ?? [];
|
|
79
|
+
const { t } = useTranslation();
|
|
78
80
|
|
|
79
81
|
// State for backfill dialog
|
|
80
82
|
const [showBackfillDialog, setShowBackfillDialog] = useState(false);
|
|
@@ -222,6 +224,10 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
222
224
|
}, [plugins]);
|
|
223
225
|
|
|
224
226
|
const handleColumnReorder = useCallback((newColumns: string[]) => {
|
|
227
|
+
analyticsController.onAnalyticsEvent?.("kanban_column_reorder", {
|
|
228
|
+
path: fullPath,
|
|
229
|
+
columnProperty
|
|
230
|
+
});
|
|
225
231
|
setHasUserReordered(true);
|
|
226
232
|
setLocalColumnsOrder(newColumns);
|
|
227
233
|
plugins
|
|
@@ -235,7 +241,7 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
235
241
|
newColumnsOrder: newColumns
|
|
236
242
|
});
|
|
237
243
|
});
|
|
238
|
-
}, [plugins, fullPath, parentCollectionIds, collection, columnProperty]);
|
|
244
|
+
}, [plugins, fullPath, parentCollectionIds, collection, columnProperty, analyticsController]);
|
|
239
245
|
|
|
240
246
|
// Collection-level count queries to detect missing order property
|
|
241
247
|
// Just TWO counts: total and ordered (for the entire collection, not per column)
|
|
@@ -393,6 +399,13 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
393
399
|
const entity = items.find(item => item.id === moveInfo?.itemId)?.entity;
|
|
394
400
|
if (!entity) return;
|
|
395
401
|
|
|
402
|
+
analyticsController.onAnalyticsEvent?.("kanban_card_moved", {
|
|
403
|
+
path: fullPath,
|
|
404
|
+
entityId: entity.id,
|
|
405
|
+
sourceColumn: moveInfo?.sourceColumn,
|
|
406
|
+
targetColumn: moveInfo?.targetColumn
|
|
407
|
+
});
|
|
408
|
+
|
|
396
409
|
const isColumnChange = moveInfo && moveInfo.sourceColumn !== moveInfo.targetColumn;
|
|
397
410
|
|
|
398
411
|
// If no orderProperty and not a column change, nothing to do
|
|
@@ -440,7 +453,7 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
440
453
|
} catch (e) {
|
|
441
454
|
console.error("Error saving entity:", e);
|
|
442
455
|
}
|
|
443
|
-
}, [collection, columnProperty, orderProperty, context, dataSource, calculateNewOrder, boardDataController]);
|
|
456
|
+
}, [collection, columnProperty, orderProperty, context, dataSource, calculateNewOrder, boardDataController, analyticsController, fullPath]);
|
|
444
457
|
|
|
445
458
|
// Backfill order values for all entities
|
|
446
459
|
const handleBackfill = useCallback(async () => {
|
|
@@ -449,6 +462,9 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
449
462
|
console.log("No orderProperty, returning");
|
|
450
463
|
return;
|
|
451
464
|
}
|
|
465
|
+
analyticsController.onAnalyticsEvent?.("kanban_backfill_order", {
|
|
466
|
+
path: fullPath
|
|
467
|
+
});
|
|
452
468
|
setBackfillLoading(true);
|
|
453
469
|
|
|
454
470
|
try {
|
|
@@ -514,7 +530,7 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
514
530
|
} finally {
|
|
515
531
|
setBackfillLoading(false);
|
|
516
532
|
}
|
|
517
|
-
}, [orderProperty, fullPath, collection, dataSource, context, boardDataController]);
|
|
533
|
+
}, [orderProperty, fullPath, collection, dataSource, context, boardDataController, analyticsController]);
|
|
518
534
|
|
|
519
535
|
const handleEntityClick = useCallback((entity: Entity<M>) => {
|
|
520
536
|
onEntityClick?.(entity);
|
|
@@ -563,19 +579,16 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
563
579
|
|
|
564
580
|
// Check for loading error
|
|
565
581
|
const hasError = Boolean(dataLoadingError);
|
|
566
|
-
const errorMessage = dataLoadingError?.message || "";
|
|
567
|
-
const indexUrl = errorMessage.match(/https:\/\/console\.firebase\.google\.com[^\s]+/)?.[0];
|
|
568
582
|
|
|
569
583
|
// Error: no enum properties available for Kanban columns
|
|
570
584
|
if (!columnProperty || enumColumns.length === 0) {
|
|
571
585
|
return (
|
|
572
586
|
<div className="flex-1 flex flex-col items-center justify-center p-8 gap-4">
|
|
573
587
|
<Typography variant="h6">
|
|
574
|
-
|
|
588
|
+
{t("kanban_view_not_available")}
|
|
575
589
|
</Typography>
|
|
576
590
|
<Typography variant="body2" color="secondary" className="text-center max-w-md">
|
|
577
|
-
|
|
578
|
-
Please add an enum property to your collection schema to use this view.
|
|
591
|
+
{t("kanban_view_requires_enum")}
|
|
579
592
|
</Typography>
|
|
580
593
|
{KanbanSetupComponent && (
|
|
581
594
|
<KanbanSetupComponent
|
|
@@ -596,7 +609,7 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
596
609
|
return (
|
|
597
610
|
<div className="flex-1 flex items-center justify-center p-8">
|
|
598
611
|
<Typography variant="label" color="secondary">
|
|
599
|
-
|
|
612
|
+
{t("no_enum_values_configured", { property: columnProperty })}
|
|
600
613
|
</Typography>
|
|
601
614
|
</div>
|
|
602
615
|
);
|
|
@@ -606,33 +619,10 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
606
619
|
<div className="flex-1 flex flex-col overflow-hidden">
|
|
607
620
|
{/* Error banner - only show when no data loaded */}
|
|
608
621
|
{hasError && allEntities.length === 0 && (
|
|
609
|
-
<
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
{indexUrl
|
|
614
|
-
? "A Firestore index is required for this query."
|
|
615
|
-
: errorMessage}
|
|
616
|
-
</Typography>
|
|
617
|
-
<Tooltip title="Refresh data">
|
|
618
|
-
<IconButton
|
|
619
|
-
size="small"
|
|
620
|
-
onClick={() => boardDataController.refreshAll()}
|
|
621
|
-
>
|
|
622
|
-
<RefreshIcon size="small" />
|
|
623
|
-
</IconButton>
|
|
624
|
-
</Tooltip>
|
|
625
|
-
{indexUrl && (
|
|
626
|
-
<Button
|
|
627
|
-
size="small"
|
|
628
|
-
variant="outlined"
|
|
629
|
-
color="error"
|
|
630
|
-
onClick={() => window.open(indexUrl, "_blank")}
|
|
631
|
-
>
|
|
632
|
-
Create Index
|
|
633
|
-
</Button>
|
|
634
|
-
)}
|
|
635
|
-
</div>
|
|
622
|
+
<CollectionDataErrorBanner
|
|
623
|
+
error={dataLoadingError}
|
|
624
|
+
onRetry={() => boardDataController.refreshAll()}
|
|
625
|
+
/>
|
|
636
626
|
)}
|
|
637
627
|
|
|
638
628
|
{/* Backfill info bar - non-blocking */}
|
|
@@ -640,14 +630,14 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
640
630
|
<div
|
|
641
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">
|
|
642
632
|
<Typography variant="body2" color="secondary">
|
|
643
|
-
|
|
633
|
+
{t("items_need_backfill")}
|
|
644
634
|
</Typography>
|
|
645
635
|
<Button
|
|
646
636
|
size="small"
|
|
647
637
|
variant="text"
|
|
648
638
|
onClick={() => setShowBackfillDialog(true)}
|
|
649
639
|
>
|
|
650
|
-
|
|
640
|
+
{t("initialize")}
|
|
651
641
|
</Button>
|
|
652
642
|
</div>
|
|
653
643
|
)}
|
|
@@ -667,6 +657,10 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
667
657
|
columnLoadingState={columnLoadingState}
|
|
668
658
|
onLoadMoreColumn={(column) => boardDataController.loadMoreColumn(column)}
|
|
669
659
|
onAddItemToColumn={(column) => {
|
|
660
|
+
analyticsController.onAnalyticsEvent?.("kanban_new_entity_in_column", {
|
|
661
|
+
path: fullPath,
|
|
662
|
+
column
|
|
663
|
+
});
|
|
670
664
|
sideEntityController.open({
|
|
671
665
|
path: fullPath,
|
|
672
666
|
collection,
|
|
@@ -693,18 +687,17 @@ export function EntityCollectionBoardView<M extends Record<string, any> = any>({
|
|
|
693
687
|
{/* Backfill dialog */}
|
|
694
688
|
<Dialog open={showBackfillDialog} onOpenChange={setShowBackfillDialog}>
|
|
695
689
|
<DialogContent>
|
|
696
|
-
<Typography variant="h6" className="mb-4">
|
|
690
|
+
<Typography variant="h6" className="mb-4">{t("initialize_kanban_order")}</Typography>
|
|
697
691
|
<Typography variant="body2">
|
|
698
|
-
|
|
699
|
-
Items will maintain their current order within each column.
|
|
692
|
+
{t("initialize_kanban_order_desc")}
|
|
700
693
|
</Typography>
|
|
701
694
|
</DialogContent>
|
|
702
695
|
<DialogActions>
|
|
703
696
|
<Button variant="text" onClick={() => setShowBackfillDialog(false)} disabled={backfillLoading}>
|
|
704
|
-
|
|
697
|
+
{t("cancel")}
|
|
705
698
|
</Button>
|
|
706
699
|
<Button onClick={handleBackfill} disabled={backfillLoading}>
|
|
707
|
-
{backfillLoading ? <CircularProgress size="smallest" /> : "
|
|
700
|
+
{backfillLoading ? <CircularProgress size="smallest" /> : t("initialize")}
|
|
708
701
|
</Button>
|
|
709
702
|
</DialogActions>
|
|
710
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;
|
|
@@ -433,12 +436,17 @@ export const EntityCollectionView = React.memo(
|
|
|
433
436
|
|
|
434
437
|
// View mode change: update URL + save to local persistence
|
|
435
438
|
const onViewModeChange = useCallback((mode: ViewMode) => {
|
|
439
|
+
analyticsController.onAnalyticsEvent?.("view_mode_changed", {
|
|
440
|
+
path: fullPath,
|
|
441
|
+
from: viewMode,
|
|
442
|
+
to: mode
|
|
443
|
+
});
|
|
436
444
|
setViewMode(mode);
|
|
437
445
|
// Save to local persistence for next visit
|
|
438
446
|
if (userConfigPersistence) {
|
|
439
447
|
onCollectionModifiedForUser(fullPath, { defaultViewMode: mode } as PartialEntityCollection<M>);
|
|
440
448
|
}
|
|
441
|
-
}, [setViewMode, userConfigPersistence, onCollectionModifiedForUser, fullPath]);
|
|
449
|
+
}, [setViewMode, userConfigPersistence, onCollectionModifiedForUser, fullPath, analyticsController, viewMode]);
|
|
442
450
|
|
|
443
451
|
const createEnabled = canCreateEntity(collection, authController, fullPath, null);
|
|
444
452
|
|
|
@@ -501,18 +509,24 @@ export const EntityCollectionView = React.memo(
|
|
|
501
509
|
authController,
|
|
502
510
|
}), [collection, fullPath]);
|
|
503
511
|
|
|
504
|
-
// Check if Kanban view is
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
}, [
|
|
512
|
+
// Check if Kanban view is possible (collection has at least one string enum property)
|
|
513
|
+
const hasEnumProperty = useMemo(() => {
|
|
514
|
+
const properties = resolvedCollection.properties;
|
|
515
|
+
return Object.values(properties).some((prop: any) =>
|
|
516
|
+
prop && prop.dataType === "string" && prop.enumValues
|
|
517
|
+
);
|
|
518
|
+
}, [resolvedCollection.properties]);
|
|
511
519
|
|
|
512
|
-
//
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
520
|
+
// Compute the effective enabled views:
|
|
521
|
+
// - Start from collection.enabledViews (defaults to all three)
|
|
522
|
+
// - Filter out kanban if no enum properties exist
|
|
523
|
+
const enabledViews: ViewMode[] = useMemo(() => {
|
|
524
|
+
const configured = collection.enabledViews ?? ["table", "cards", "kanban"];
|
|
525
|
+
if (!hasEnumProperty) {
|
|
526
|
+
return configured.filter(v => v !== "kanban");
|
|
527
|
+
}
|
|
528
|
+
return configured;
|
|
529
|
+
}, [collection.enabledViews, hasEnumProperty]);
|
|
516
530
|
|
|
517
531
|
// Compute available enum properties for kanban column selection
|
|
518
532
|
const kanbanPropertyOptions: KanbanPropertyOption[] = useMemo(() => {
|
|
@@ -562,12 +576,16 @@ export const EntityCollectionView = React.memo(
|
|
|
562
576
|
|
|
563
577
|
// Handle kanban property change
|
|
564
578
|
const onKanbanPropertyChange = useCallback((property: string) => {
|
|
579
|
+
analyticsController.onAnalyticsEvent?.("kanban_property_changed", {
|
|
580
|
+
path: fullPath,
|
|
581
|
+
property
|
|
582
|
+
});
|
|
565
583
|
setSelectedKanbanProperty(property);
|
|
566
584
|
// Save to local persistence
|
|
567
585
|
if (userConfigPersistence) {
|
|
568
586
|
onCollectionModifiedForUser(fullPath, { kanbanColumnProperty: property } as any);
|
|
569
587
|
}
|
|
570
|
-
}, [userConfigPersistence, onCollectionModifiedForUser, fullPath]);
|
|
588
|
+
}, [userConfigPersistence, onCollectionModifiedForUser, fullPath, analyticsController]);
|
|
571
589
|
|
|
572
590
|
const getPropertyFor = useCallback(({
|
|
573
591
|
propertyKey,
|
|
@@ -680,11 +698,13 @@ export const EntityCollectionView = React.memo(
|
|
|
680
698
|
customEntityActions?: EntityAction[]
|
|
681
699
|
}): EntityAction[] => {
|
|
682
700
|
const deleteEnabled = entity ? canDeleteEntity(collection, authController, fullPath, entity) : true;
|
|
683
|
-
const actions: EntityAction[] = [
|
|
701
|
+
const actions: EntityAction[] = [
|
|
702
|
+
{ ...editEntityAction, name: t("edit") }
|
|
703
|
+
];
|
|
684
704
|
if (createEnabled)
|
|
685
|
-
actions.push(copyEntityAction);
|
|
705
|
+
actions.push({ ...copyEntityAction, name: t("copy") });
|
|
686
706
|
if (deleteEnabled)
|
|
687
|
-
actions.push(deleteEntityAction);
|
|
707
|
+
actions.push({ ...deleteEntityAction, name: t("delete") });
|
|
688
708
|
if (customEntityActions)
|
|
689
709
|
return mergeEntityActions(actions, customEntityActions);
|
|
690
710
|
return actions;
|
|
@@ -819,8 +839,7 @@ export const EntityCollectionView = React.memo(
|
|
|
819
839
|
<ViewModeToggle
|
|
820
840
|
viewMode={viewMode}
|
|
821
841
|
onViewModeChange={onViewModeChange}
|
|
822
|
-
|
|
823
|
-
hasKanbanConfigPlugin={hasKanbanConfigPlugin}
|
|
842
|
+
enabledViews={enabledViews}
|
|
824
843
|
size={viewMode === "table" ? tableSize : viewMode === "cards" ? cardSize : undefined}
|
|
825
844
|
onSizeChanged={viewMode === "table" ? onTableSizeChanged : viewMode === "cards" ? setCardSize : undefined}
|
|
826
845
|
open={viewModePopoverOpen}
|
|
@@ -831,6 +850,24 @@ export const EntityCollectionView = React.memo(
|
|
|
831
850
|
/>
|
|
832
851
|
);
|
|
833
852
|
|
|
853
|
+
// Compute plugin-provided error view for collection loading errors
|
|
854
|
+
const pluginErrorView = useMemo(() => {
|
|
855
|
+
const error = tableController.dataLoadingError;
|
|
856
|
+
if (!error || !customizationController.plugins) return null;
|
|
857
|
+
for (const plugin of customizationController.plugins) {
|
|
858
|
+
if (plugin.collectionView?.CollectionError) {
|
|
859
|
+
const CollectionError = plugin.collectionView.CollectionError;
|
|
860
|
+
return <CollectionError
|
|
861
|
+
path={fullPath}
|
|
862
|
+
collection={collection}
|
|
863
|
+
parentCollectionIds={parentCollectionIds}
|
|
864
|
+
error={error}
|
|
865
|
+
/>;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
return null;
|
|
869
|
+
}, [tableController.dataLoadingError, customizationController.plugins, fullPath, collection, parentCollectionIds]);
|
|
870
|
+
|
|
834
871
|
return (
|
|
835
872
|
<div className={cls("overflow-hidden h-full w-full rounded-md flex flex-col", className)}
|
|
836
873
|
ref={containerRef}>
|
|
@@ -867,7 +904,11 @@ export const EntityCollectionView = React.memo(
|
|
|
867
904
|
/>
|
|
868
905
|
|
|
869
906
|
{/* View content - only the view-specific content changes */}
|
|
870
|
-
{
|
|
907
|
+
{tableController.dataLoadingError && pluginErrorView}
|
|
908
|
+
{tableController.dataLoadingError && !pluginErrorView && (
|
|
909
|
+
<CollectionDataErrorBanner error={tableController.dataLoadingError} />
|
|
910
|
+
)}
|
|
911
|
+
{viewMode === "kanban" && enabledViews.includes("kanban") ? (
|
|
871
912
|
<EntityCollectionBoardView
|
|
872
913
|
key={`kanban-view-${fullPath}-${selectedKanbanProperty}`}
|
|
873
914
|
collection={collection}
|
|
@@ -882,16 +923,16 @@ export const EntityCollectionView = React.memo(
|
|
|
882
923
|
deletedEntities={deletedEntities}
|
|
883
924
|
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
884
925
|
? <div className="flex flex-col items-center justify-center">
|
|
885
|
-
<Typography variant={"subtitle2"}>
|
|
926
|
+
<Typography variant={"subtitle2"}>{t("so_empty")}</Typography>
|
|
886
927
|
<Button
|
|
887
928
|
onClick={onNewClick}
|
|
888
929
|
className="mt-4"
|
|
889
930
|
>
|
|
890
931
|
<AddIcon />
|
|
891
|
-
|
|
932
|
+
{t("create_your_first_entry")}
|
|
892
933
|
</Button>
|
|
893
934
|
</div>
|
|
894
|
-
: <Typography variant={"label"}>
|
|
935
|
+
: <Typography variant={"label"}>{t("no_results_filter_sort")}</Typography>
|
|
895
936
|
}
|
|
896
937
|
/>
|
|
897
938
|
) : viewMode === "cards" ? (
|
|
@@ -908,16 +949,16 @@ export const EntityCollectionView = React.memo(
|
|
|
908
949
|
size={cardSize}
|
|
909
950
|
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
910
951
|
? <div className="flex flex-col items-center justify-center">
|
|
911
|
-
<Typography variant={"subtitle2"}>
|
|
952
|
+
<Typography variant={"subtitle2"}>{t("so_empty")}</Typography>
|
|
912
953
|
<Button
|
|
913
954
|
onClick={onNewClick}
|
|
914
955
|
className="mt-4"
|
|
915
956
|
>
|
|
916
957
|
<AddIcon />
|
|
917
|
-
|
|
958
|
+
{t("create_your_first_entry")}
|
|
918
959
|
</Button>
|
|
919
960
|
</div>
|
|
920
|
-
: <Typography variant={"label"}>
|
|
961
|
+
: <Typography variant={"label"}>{t("no_results_filter_sort")}</Typography>
|
|
921
962
|
}
|
|
922
963
|
/>
|
|
923
964
|
) : (
|
|
@@ -946,16 +987,16 @@ export const EntityCollectionView = React.memo(
|
|
|
946
987
|
textSearchEnabled={textSearchEnabled}
|
|
947
988
|
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
948
989
|
? <div className="flex flex-col items-center justify-center">
|
|
949
|
-
<Typography variant={"subtitle2"}>
|
|
990
|
+
<Typography variant={"subtitle2"}>{t("so_empty")}</Typography>
|
|
950
991
|
<Button
|
|
951
992
|
onClick={onNewClick}
|
|
952
993
|
className="mt-4"
|
|
953
994
|
>
|
|
954
995
|
<AddIcon />
|
|
955
|
-
|
|
996
|
+
{t("create_your_first_entry")}
|
|
956
997
|
</Button>
|
|
957
998
|
</div>
|
|
958
|
-
: <Typography variant={"label"}>
|
|
999
|
+
: <Typography variant={"label"}>{t("no_results_filter_sort")}</Typography>
|
|
959
1000
|
}
|
|
960
1001
|
hoverRow={hoverRow}
|
|
961
1002
|
inlineEditing={checkInlineEditing()}
|
|
@@ -1126,11 +1167,12 @@ function EntityIdHeaderWidget({
|
|
|
1126
1167
|
const [searchString, setSearchString] = React.useState("");
|
|
1127
1168
|
const [recentIds, setRecentIds] = React.useState<string[]>(getRecentIds(collection.id));
|
|
1128
1169
|
const sideEntityController = useSideEntityController();
|
|
1170
|
+
const { t } = useTranslation();
|
|
1129
1171
|
|
|
1130
1172
|
const openEntityMode = collection?.openEntityMode ?? DEFAULT_ENTITY_OPEN_MODE;
|
|
1131
1173
|
|
|
1132
1174
|
return (
|
|
1133
|
-
<Tooltip title={!openPopup ? "
|
|
1175
|
+
<Tooltip title={!openPopup ? t("find_by_id") : undefined} asChild={false}>
|
|
1134
1176
|
<Popover
|
|
1135
1177
|
open={openPopup}
|
|
1136
1178
|
onOpenChange={setOpenPopup}
|
|
@@ -1166,7 +1208,7 @@ function EntityIdHeaderWidget({
|
|
|
1166
1208
|
<div className="flex p-2 w-full gap-2">
|
|
1167
1209
|
<input
|
|
1168
1210
|
autoFocus={openPopup}
|
|
1169
|
-
placeholder={"
|
|
1211
|
+
placeholder={t("find_entity_by_id")}
|
|
1170
1212
|
// size={"small"}
|
|
1171
1213
|
onChange={(e) => {
|
|
1172
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
|