@rebasepro/admin 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +20 -20
- package/dist/{CollectionEditorDialog-iGgS4rLX.js → CollectionEditorDialog-B-7uW3iJ.js} +15 -15
- package/dist/CollectionEditorDialog-B-7uW3iJ.js.map +1 -0
- package/dist/{PropertyEditView-C9yhLyja.js → PropertyEditView-7KMTcrqi.js} +140 -106
- package/dist/PropertyEditView-7KMTcrqi.js.map +1 -0
- package/dist/{RouterCollectionsStudioView-Dqx27GD8.js → RouterCollectionsStudioView-epqIbZrJ.js} +4 -4
- package/dist/{RouterCollectionsStudioView-Dqx27GD8.js.map → RouterCollectionsStudioView-epqIbZrJ.js.map} +1 -1
- package/dist/collection_editor/_cms_internals.d.ts +4 -4
- package/dist/collection_editor/api/generateCollectionApi.d.ts +7 -6
- package/dist/collection_editor/extensibility_types.d.ts +3 -3
- package/dist/collection_editor/index.d.ts +2 -2
- package/dist/collection_editor/pgColumnToProperty.d.ts +3 -3
- package/dist/collection_editor/serializable_types.d.ts +12 -16
- package/dist/collection_editor/serializable_utils.d.ts +8 -8
- package/dist/collection_editor/types/collection_editor_controller.d.ts +5 -5
- package/dist/collection_editor/types/collection_inference.d.ts +2 -2
- package/dist/collection_editor/types/config_controller.d.ts +7 -7
- package/dist/collection_editor/ui/AddKanbanColumnAction.d.ts +2 -2
- package/dist/collection_editor/ui/CollectionViewHeaderAction.d.ts +2 -2
- package/dist/collection_editor/ui/KanbanSetupAction.d.ts +2 -2
- package/dist/collection_editor/ui/PropertyAddColumnComponent.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.d.ts +3 -3
- package/dist/collection_editor/ui/collection_editor/CollectionDetailsForm.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +4 -5
- package/dist/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/CollectionJsonImportDialog.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +4 -4
- package/dist/collection_editor/ui/collection_editor/CollectionStudioView.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/CollectionsStudioView.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/EntityActionsEditTab.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/GeneralSettingsForm.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/GetCodeDialog.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/PropertyEditView.d.ts +4 -4
- package/dist/collection_editor/ui/collection_editor/SubcollectionsEditTab.d.ts +3 -3
- package/dist/collection_editor/ui/collection_editor/templates/blog_template.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/templates/pages_template.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/templates/products_template.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/templates/users_template.d.ts +2 -2
- package/dist/collection_editor/useLocalCollectionsConfigController.d.ts +2 -2
- package/dist/collection_editor/validateCollectionJson.d.ts +2 -2
- package/dist/collection_editor_ui.js +4 -4
- package/dist/components/CollectionPanel.d.ts +4 -4
- package/dist/components/{EntityCollectionTable/EntityCollectionRowActions.d.ts → CollectionTableBinding/CollectionRowActions.d.ts} +3 -3
- package/dist/components/CollectionTableBinding/CollectionTableBinding.d.ts +28 -0
- package/dist/components/{EntityCollectionTable/EntityCollectionTableProps.d.ts → CollectionTableBinding/CollectionTableBindingProps.d.ts} +1 -1
- package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableMultipleRelationField.d.ts +2 -2
- package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableReferenceField.d.ts +2 -2
- package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableRelationField.d.ts +2 -2
- package/dist/components/CollectionTableBinding/index.d.ts +6 -0
- package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/common.d.ts +2 -2
- package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/PopupFormField.d.ts +2 -2
- package/dist/components/{EntityCollectionView/EntityBoardCard.d.ts → CollectionViewBinding/BoardCardBinding.d.ts} +8 -8
- package/dist/components/{EntityCollectionView/EntityCollectionBoardView.d.ts → CollectionViewBinding/CollectionBoardViewBinding.d.ts} +4 -4
- package/dist/components/{EntityCollectionView/EntityCollectionCardView.d.ts → CollectionViewBinding/CollectionCardViewBinding.d.ts} +5 -5
- package/dist/components/{EntityCollectionView/EntityCollectionListView.d.ts → CollectionViewBinding/CollectionListViewBinding.d.ts} +4 -4
- package/dist/components/{EntityCollectionView/EntityCollectionViewActions.d.ts → CollectionViewBinding/CollectionViewActions.d.ts} +4 -4
- package/dist/components/{EntityCollectionView/EntityCollectionView.d.ts → CollectionViewBinding/CollectionViewBinding.d.ts} +4 -4
- package/dist/components/{EntityCollectionView/EntityCollectionViewStartActions.d.ts → CollectionViewBinding/CollectionViewStartActions.d.ts} +4 -4
- package/dist/components/CollectionViewBinding/EntityCardBinding.d.ts +21 -0
- package/dist/components/{EntityCollectionView → CollectionViewBinding}/SplitListView.d.ts +3 -3
- package/dist/components/{EntityCollectionView → CollectionViewBinding}/hooks/useCollectionInlineEditor.d.ts +2 -2
- package/dist/components/{EntityCollectionView → CollectionViewBinding}/hooks/useKanbanDragAndDrop.d.ts +2 -2
- package/dist/components/{EntityCollectionView → CollectionViewBinding}/useBoardDataController.d.ts +2 -2
- package/dist/components/{EntityCollectionView/useEntityPreviewSlots.d.ts → CollectionViewBinding/usePreviewSlots.d.ts} +5 -5
- package/dist/components/DeleteEntityDialog.d.ts +4 -4
- package/dist/components/{EntityDetailView.d.ts → DetailViewBinding.d.ts} +5 -5
- package/dist/components/EditFormActions.d.ts +3 -0
- package/dist/components/{EntityEditView.d.ts → EditViewBinding.d.ts} +9 -9
- package/dist/components/{EntityPreview.d.ts → EntityPreviewBinding.d.ts} +13 -13
- package/dist/components/EntityViewBinding.d.ts +13 -0
- package/dist/components/{EntityJsonPreview.d.ts → JsonPreviewBinding.d.ts} +1 -1
- package/dist/components/RebaseCMS.d.ts +1 -1
- package/dist/components/RebaseNavigation.d.ts +1 -1
- package/dist/components/ReferenceTable/{EntitySelectionTable.d.ts → SelectionTableBinding.d.ts} +5 -5
- package/dist/components/SelectableTable/SelectableTable.d.ts +5 -5
- package/dist/components/SelectableTable/SelectableTableContext.d.ts +3 -3
- package/dist/components/SelectableTable/SelectionStore.d.ts +13 -22
- package/dist/components/SelectableTable/filters/BooleanFilterField.d.ts +6 -1
- package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +7 -1
- package/dist/components/SelectableTable/filters/FilterFieldBinding.d.ts +40 -0
- package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +7 -1
- package/dist/components/SelectableTable/filters/RelationFilterField.d.ts +7 -1
- package/dist/components/SelectableTable/filters/StringNumberFilterField.d.ts +7 -1
- package/dist/components/SideDialogs.d.ts +1 -1
- package/dist/components/SidePanelBinding.d.ts +11 -0
- package/dist/components/{SideEntityProvider.d.ts → SidePanelProvider.d.ts} +7 -7
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/components/history/EntityHistoryEntry.d.ts +2 -2
- package/dist/components/history/LastEditedByIndicator.d.ts +2 -2
- package/dist/components/index.d.ts +14 -13
- package/dist/contexts/SidePanelControllerContext.d.ts +3 -0
- package/dist/data_export/export/ExportCollectionAction.d.ts +3 -3
- package/dist/data_import/components/ImportSaveInProgress.d.ts +2 -2
- package/dist/editor/editor.d.ts +0 -6
- package/dist/editor.js +1 -3
- package/dist/editor.js.map +1 -1
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/components/StorageUploadProgress.d.ts +6 -1
- package/dist/form/form_utils.d.ts +2 -2
- package/dist/form/index.d.ts +0 -1
- package/dist/{history-ChHgyyvM.js → history-7X5bON_n.js} +4 -4
- package/dist/history-7X5bON_n.js.map +1 -0
- package/dist/hooks/index.d.ts +4 -4
- package/dist/hooks/navigation/contexts/CollectionRegistryContext.d.ts +2 -2
- package/dist/hooks/navigation/useBuildNavigationStateController.d.ts +5 -5
- package/dist/hooks/navigation/useNavigationResolution.d.ts +4 -4
- package/dist/hooks/navigation/useResolvedCollections.d.ts +7 -7
- package/dist/hooks/navigation/useTopLevelNavigation.d.ts +2 -2
- package/dist/hooks/navigation/utils.d.ts +5 -5
- package/dist/hooks/useBuildSidePanel.d.ts +6 -0
- package/dist/hooks/useCMSContext.d.ts +2 -2
- package/dist/hooks/{useEntityHistory.d.ts → useHistory.d.ts} +1 -1
- package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
- package/dist/hooks/{useEntitySelectionDialog.d.ts → useSelectionDialog.d.ts} +2 -2
- package/dist/hooks/useSideDialogsController.d.ts +1 -1
- package/dist/hooks/useSidePanel.d.ts +11 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/preview/components/StorageThumbnail.d.ts +3 -1
- package/dist/{src-DOX2nOyh.js → src-sUZfe29F.js} +904 -1096
- package/dist/src-sUZfe29F.js.map +1 -0
- package/dist/types/components/EntityFormActionsProps.d.ts +2 -2
- package/dist/types/components/EntityFormProps.d.ts +3 -3
- package/dist/types/components/PropertyPreviewProps.d.ts +2 -1
- package/dist/types/fields.d.ts +6 -8
- package/dist/util/dataControllerAdapter.d.ts +2 -5
- package/dist/util/navigation_utils.d.ts +6 -6
- package/dist/util/previews.d.ts +3 -3
- package/dist/util/property_utils.d.ts +2 -2
- package/dist/util/{entity_view_constants.d.ts → view_constants.d.ts} +1 -1
- package/package.json +18 -18
- package/src/collection_editor/ConfigControllerProvider.tsx +10 -10
- package/src/collection_editor/_cms_internals.ts +4 -4
- package/src/collection_editor/api/generateCollectionApi.ts +7 -6
- package/src/collection_editor/extensibility_types.ts +3 -3
- package/src/collection_editor/index.ts +3 -3
- package/src/collection_editor/pgColumnToProperty.ts +4 -4
- package/src/collection_editor/serializable_types.ts +22 -35
- package/src/collection_editor/serializable_utils.ts +40 -52
- package/src/collection_editor/types/collection_editor_controller.tsx +5 -5
- package/src/collection_editor/types/collection_inference.ts +2 -2
- package/src/collection_editor/types/config_controller.tsx +7 -7
- package/src/collection_editor/ui/AddKanbanColumnAction.tsx +2 -2
- package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +2 -2
- package/src/collection_editor/ui/EditorCollectionAction.tsx +2 -2
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +2 -2
- package/src/collection_editor/ui/EditorEntityAction.tsx +2 -2
- package/src/collection_editor/ui/KanbanSetupAction.tsx +2 -2
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +63 -46
- package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +8 -8
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +4 -4
- package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +7 -16
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +45 -36
- package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +35 -1
- package/src/collection_editor/ui/collection_editor/templates/blog_template.ts +3 -3
- package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +2 -2
- package/src/collection_editor/ui/collection_editor/templates/products_template.ts +2 -2
- package/src/collection_editor/ui/collection_editor/templates/users_template.ts +2 -2
- package/src/collection_editor/ui/collection_editor/utils/supported_fields.tsx +0 -1
- package/src/collection_editor/ui/collection_editor/utils/update_property_for_widget.ts +7 -29
- package/src/collection_editor/useJsonCollectionsConfigController.tsx +14 -14
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +4 -4
- package/src/collection_editor/validateCollectionJson.ts +3 -3
- package/src/components/CollectionPanel.tsx +14 -17
- package/src/components/{EntityCollectionTable/EntityCollectionRowActions.tsx → CollectionTableBinding/CollectionRowActions.tsx} +6 -6
- package/src/components/{EntityCollectionTable/EntityCollectionTable.tsx → CollectionTableBinding/CollectionTableBinding.tsx} +19 -17
- package/src/components/{EntityCollectionTable/EntityCollectionTableProps.tsx → CollectionTableBinding/CollectionTableBindingProps.tsx} +1 -1
- package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableMultipleRelationField.tsx +7 -6
- package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableReferenceField.tsx +10 -10
- package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableRelationField.tsx +7 -6
- package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableStorageUpload.tsx +23 -20
- package/src/components/CollectionTableBinding/index.tsx +14 -0
- package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/common.tsx +2 -2
- package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/PopupFormField.tsx +2 -2
- package/src/components/{EntityCollectionTable → CollectionTableBinding}/table_bindings.tsx +24 -44
- package/src/components/{EntityCollectionView/EntityBoardCard.tsx → CollectionViewBinding/BoardCardBinding.tsx} +15 -15
- package/src/components/{EntityCollectionView/EntityCollectionBoardView.tsx → CollectionViewBinding/CollectionBoardViewBinding.tsx} +15 -14
- package/src/components/{EntityCollectionView/EntityCollectionCardView.tsx → CollectionViewBinding/CollectionCardViewBinding.tsx} +8 -8
- package/src/components/{EntityCollectionView/EntityCollectionListView.tsx → CollectionViewBinding/CollectionListViewBinding.tsx} +24 -13
- package/src/components/{EntityCollectionView/EntityCollectionViewActions.tsx → CollectionViewBinding/CollectionViewActions.tsx} +5 -5
- package/src/components/{EntityCollectionView/EntityCollectionView.tsx → CollectionViewBinding/CollectionViewBinding.tsx} +112 -114
- package/src/components/{EntityCollectionView/EntityCollectionViewStartActions.tsx → CollectionViewBinding/CollectionViewStartActions.tsx} +5 -5
- package/src/components/{EntityCollectionView/EntityCard.tsx → CollectionViewBinding/EntityCardBinding.tsx} +9 -9
- package/src/components/{EntityCollectionView → CollectionViewBinding}/FiltersDialog.tsx +31 -72
- package/src/components/{EntityCollectionView → CollectionViewBinding}/SplitListView.tsx +9 -9
- package/src/components/{EntityCollectionView → CollectionViewBinding}/hooks/useCollectionInlineEditor.ts +6 -6
- package/src/components/{EntityCollectionView → CollectionViewBinding}/hooks/useKanbanDragAndDrop.ts +4 -4
- package/src/components/{EntityCollectionView → CollectionViewBinding}/useBoardDataController.tsx +28 -50
- package/src/components/{EntityCollectionView/useEntityPreviewSlots.ts → CollectionViewBinding/usePreviewSlots.ts} +11 -11
- package/src/components/DefaultDrawer.tsx +1 -1
- package/src/components/DeleteEntityDialog.tsx +6 -6
- package/src/components/{EntityDetailView.tsx → DetailViewBinding.tsx} +28 -31
- package/src/components/{EntityEditViewFormActions.tsx → EditFormActions.tsx} +15 -15
- package/src/components/{EntityEditView.tsx → EditViewBinding.tsx} +31 -34
- package/src/components/{EntityPreview.tsx → EntityPreviewBinding.tsx} +27 -27
- package/src/components/{EntityView.tsx → EntityViewBinding.tsx} +5 -5
- package/src/components/HomePage/ContentHomePage.tsx +1 -1
- package/src/components/HomePage/NavigationCardBinding.tsx +1 -1
- package/src/components/{EntityJsonPreview.tsx → JsonPreviewBinding.tsx} +1 -1
- package/src/components/RebaseCMS.tsx +4 -4
- package/src/components/RebaseNavigation.tsx +20 -10
- package/src/components/ReferenceTable/{EntitySelectionTable.tsx → SelectionTableBinding.tsx} +22 -19
- package/src/components/ReferenceWidget.tsx +4 -4
- package/src/components/RelationSelector.tsx +16 -14
- package/src/components/SelectableTable/SelectableTable.tsx +44 -89
- package/src/components/SelectableTable/SelectableTableContext.tsx +3 -3
- package/src/components/SelectableTable/SelectionStore.ts +22 -52
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +9 -1
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +33 -12
- package/src/components/SelectableTable/filters/FilterFieldBinding.tsx +187 -0
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +21 -7
- package/src/components/SelectableTable/filters/RelationFilterField.tsx +17 -3
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +66 -12
- package/src/components/SideDialogs.tsx +3 -3
- package/src/components/{EntitySidePanel.tsx → SidePanelBinding.tsx} +19 -19
- package/src/components/{SideEntityProvider.tsx → SidePanelProvider.tsx} +16 -16
- package/src/components/common/default_entity_actions.tsx +24 -13
- package/src/components/field_configs.tsx +0 -14
- package/src/components/history/EntityHistoryEntry.tsx +2 -2
- package/src/components/history/EntityHistoryView.tsx +3 -3
- package/src/components/history/LastEditedByIndicator.tsx +2 -2
- package/src/components/index.ts +15 -14
- package/src/contexts/SidePanelControllerContext.tsx +5 -0
- package/src/data_export/export/ExportCollectionAction.tsx +4 -4
- package/src/data_import/components/ImportSaveInProgress.tsx +3 -3
- package/src/data_import/import/ImportCollectionAction.tsx +4 -4
- package/src/data_import/utils/data.ts +2 -2
- package/src/editor/editor.tsx +4 -7
- package/src/form/EntityForm.tsx +2 -2
- package/src/form/EntityFormActions.tsx +4 -4
- package/src/form/EntityFormBinding.tsx +7 -7
- package/src/form/PropertyFieldBinding.tsx +4 -4
- package/src/form/components/StorageUploadProgress.tsx +9 -2
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +4 -4
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +19 -19
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +12 -1
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +6 -6
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +5 -5
- package/src/form/field_bindings/RelationFieldBinding.tsx +8 -10
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +19 -15
- package/src/form/form_utils.ts +2 -2
- package/src/form/index.tsx +0 -1
- package/src/hooks/index.ts +4 -4
- package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +2 -2
- package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +11 -11
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +5 -5
- package/src/hooks/navigation/useNavigationResolution.ts +10 -10
- package/src/hooks/navigation/useResolvedCollections.ts +8 -8
- package/src/hooks/navigation/useTopLevelNavigation.ts +2 -2
- package/src/hooks/navigation/utils.ts +5 -5
- package/src/hooks/{useBuildSideEntityController.tsx → useBuildSidePanel.tsx} +28 -28
- package/src/hooks/useCMSContext.tsx +6 -6
- package/src/hooks/{useEntityHistory.ts → useHistory.ts} +1 -1
- package/src/hooks/useResolvedNavigationFrom.tsx +8 -5
- package/src/hooks/{useEntitySelectionDialog.tsx → useSelectionDialog.tsx} +7 -7
- package/src/hooks/useSideDialogsController.tsx +1 -1
- package/src/hooks/useSidePanel.tsx +13 -0
- package/src/index.ts +13 -13
- package/src/preview/PropertyPreview.tsx +1 -16
- package/src/preview/components/ReferencePreview.tsx +10 -10
- package/src/preview/components/RelationPreview.tsx +13 -12
- package/src/preview/components/StorageThumbnail.tsx +24 -7
- package/src/routes/RebaseRoute.tsx +10 -10
- package/src/types/components/EntityFormActionsProps.tsx +2 -2
- package/src/types/components/EntityFormProps.tsx +3 -3
- package/src/types/components/PropertyPreviewProps.tsx +1 -1
- package/src/types/fields.tsx +4 -9
- package/src/util/dataControllerAdapter.ts +9 -15
- package/src/util/navigation_utils.ts +7 -7
- package/src/util/previews.ts +23 -3
- package/src/util/propertyConfigMapper.ts +3 -3
- package/src/util/property_utils.tsx +2 -3
- package/src/util/{entity_view_constants.ts → view_constants.ts} +1 -1
- package/dist/CollectionEditorDialog-iGgS4rLX.js.map +0 -1
- package/dist/PropertyEditView-C9yhLyja.js.map +0 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +0 -28
- package/dist/components/EntityCollectionTable/fields/VirtualTableDateField.d.ts +0 -12
- package/dist/components/EntityCollectionTable/fields/VirtualTableInput.d.ts +0 -10
- package/dist/components/EntityCollectionTable/fields/VirtualTableNumberInput.d.ts +0 -9
- package/dist/components/EntityCollectionTable/fields/VirtualTableSwitch.d.ts +0 -8
- package/dist/components/EntityCollectionTable/index.d.ts +0 -6
- package/dist/components/EntityCollectionView/EntityCard.d.ts +0 -21
- package/dist/components/EntityEditViewFormActions.d.ts +0 -3
- package/dist/components/EntitySidePanel.d.ts +0 -11
- package/dist/components/EntityView.d.ts +0 -13
- package/dist/contexts/SideEntityControllerContext.d.ts +0 -3
- package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +0 -11
- package/dist/history-ChHgyyvM.js.map +0 -1
- package/dist/hooks/useBuildSideEntityController.d.ts +0 -6
- package/dist/hooks/useSideEntityController.d.ts +0 -11
- package/dist/src-DOX2nOyh.js.map +0 -1
- package/src/components/EntityCollectionTable/fields/VirtualTableDateField.tsx +0 -39
- package/src/components/EntityCollectionTable/fields/VirtualTableInput.tsx +0 -90
- package/src/components/EntityCollectionTable/fields/VirtualTableNumberInput.tsx +0 -83
- package/src/components/EntityCollectionTable/fields/VirtualTableSwitch.tsx +0 -32
- package/src/components/EntityCollectionTable/index.tsx +0 -14
- package/src/contexts/SideEntityControllerContext.tsx +0 -5
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +0 -141
- package/src/hooks/useSideEntityController.tsx +0 -13
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/PropertyTableCell.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/column_utils.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableRelationSelectorField.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableStorageUpload.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/VirtualTableSelect.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/VirtualTableUserSelect.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/CollectionTableToolbar.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/EntityTableCell.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/EntityTableCellActions.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/useDraggable.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/useWindowSize.d.ts +0 -0
- /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/table_bindings.d.ts +0 -0
- /package/dist/components/{EntityCollectionView → CollectionViewBinding}/FilterPresetsButton.d.ts +0 -0
- /package/dist/components/{EntityCollectionView → CollectionViewBinding}/FiltersDialog.d.ts +0 -0
- /package/dist/components/{EntityCollectionView → CollectionViewBinding}/ViewModeToggle.d.ts +0 -0
- /package/dist/components/{EntityCollectionView → CollectionViewBinding}/useSelectionController.d.ts +0 -0
- /package/dist/components/{EntityCollectionView → CollectionViewBinding}/utils.d.ts +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/PropertyTableCell.tsx +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/column_utils.tsx +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableRelationSelectorField.tsx +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/VirtualTableSelect.tsx +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/VirtualTableUserSelect.tsx +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/CollectionTableToolbar.tsx +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/EntityTableCell.tsx +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/EntityTableCellActions.tsx +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/useDraggable.tsx +0 -0
- /package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/useWindowSize.tsx +0 -0
- /package/src/components/{EntityCollectionView → CollectionViewBinding}/FilterPresetsButton.tsx +0 -0
- /package/src/components/{EntityCollectionView → CollectionViewBinding}/ViewModeToggle.tsx +0 -0
- /package/src/components/{EntityCollectionView → CollectionViewBinding}/useSelectionController.tsx +0 -0
- /package/src/components/{EntityCollectionView → CollectionViewBinding}/utils.ts +0 -0
|
@@ -1,67 +1,37 @@
|
|
|
1
1
|
import { useSyncExternalStore, useCallback, useRef } from "react";
|
|
2
2
|
import { SelectedCellProps } from "@rebasepro/types";
|
|
3
|
+
import {
|
|
4
|
+
createVirtualTableSelectionStore,
|
|
5
|
+
VirtualTableSelectionStore,
|
|
6
|
+
SelectedCell
|
|
7
|
+
} from "@rebasepro/ui";
|
|
8
|
+
|
|
9
|
+
export interface AdminSelectedCell extends SelectedCell {
|
|
10
|
+
entityPath: string;
|
|
11
|
+
entityId: string | number;
|
|
12
|
+
propertyKey: string;
|
|
13
|
+
cellRect: DOMRect;
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
}
|
|
3
17
|
|
|
4
|
-
/**
|
|
5
|
-
* A ref-based selection store that avoids React context re-renders.
|
|
6
|
-
*
|
|
7
|
-
* The problem with putting `selectedCell` in a React context value is that
|
|
8
|
-
* ANY cell selection change triggers a context value change, which forces
|
|
9
|
-
* ALL consumers (every PropertyTableCell in the table) to re-render.
|
|
10
|
-
* This causes the DOM to be replaced between mousedown and click events,
|
|
11
|
-
* breaking `alwaysInteractive` cells (like relation selectors) where the
|
|
12
|
-
* user needs to click a button on the very first interaction.
|
|
13
|
-
*
|
|
14
|
-
* This store uses `useSyncExternalStore` so only cells whose `selected`
|
|
15
|
-
* derivation actually changed will re-render.
|
|
16
|
-
*/
|
|
17
18
|
export function createSelectionStore() {
|
|
18
|
-
|
|
19
|
-
const listeners = new Set<() => void>();
|
|
20
|
-
|
|
21
|
-
function getSnapshot(): SelectedCellProps | undefined {
|
|
22
|
-
return selectedCell;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function subscribe(listener: () => void): () => void {
|
|
26
|
-
listeners.add(listener);
|
|
27
|
-
return () => listeners.delete(listener);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function select(cell: SelectedCellProps | undefined) {
|
|
31
|
-
selectedCell = cell;
|
|
32
|
-
listeners.forEach(l => l());
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return { getSnapshot,
|
|
36
|
-
subscribe,
|
|
37
|
-
select };
|
|
19
|
+
return createVirtualTableSelectionStore<AdminSelectedCell>();
|
|
38
20
|
}
|
|
39
21
|
|
|
40
|
-
export type SelectionStore =
|
|
22
|
+
export type SelectionStore = VirtualTableSelectionStore<AdminSelectedCell>;
|
|
41
23
|
|
|
42
|
-
/**
|
|
43
|
-
* Hook that subscribes a cell to the selection store and returns
|
|
44
|
-
* whether THIS cell is selected. Only re-renders when the cell's
|
|
45
|
-
* `selected` boolean actually changes (not on every store update).
|
|
46
|
-
*/
|
|
47
24
|
export function useCellSelected(
|
|
48
|
-
store: {
|
|
25
|
+
store: { getEntity: () => SelectedCellProps | undefined; subscribe: (listener: () => void) => () => void },
|
|
49
26
|
propertyKey: string,
|
|
50
27
|
entityPath: string,
|
|
51
28
|
entityId: string | number
|
|
52
29
|
): boolean {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// React only re-renders when the returned value !== the previous one.
|
|
56
|
-
const selectorRef = useRef({ propertyKey,
|
|
57
|
-
entityPath,
|
|
58
|
-
entityId });
|
|
59
|
-
selectorRef.current = { propertyKey,
|
|
60
|
-
entityPath,
|
|
61
|
-
entityId };
|
|
30
|
+
const selectorRef = useRef({ propertyKey, entityPath, entityId });
|
|
31
|
+
selectorRef.current = { propertyKey, entityPath, entityId };
|
|
62
32
|
|
|
63
|
-
const
|
|
64
|
-
const cell = store.
|
|
33
|
+
const getEntity = useCallback(() => {
|
|
34
|
+
const cell = store.getEntity();
|
|
65
35
|
if (!cell) return false;
|
|
66
36
|
const s = selectorRef.current;
|
|
67
37
|
return cell.propertyKey === s.propertyKey &&
|
|
@@ -69,5 +39,5 @@ entityId };
|
|
|
69
39
|
cell.entityId === s.entityId;
|
|
70
40
|
}, [store]);
|
|
71
41
|
|
|
72
|
-
return useSyncExternalStore(store.subscribe,
|
|
42
|
+
return useSyncExternalStore(store.subscribe, getEntity, getEntity);
|
|
73
43
|
}
|
|
@@ -8,16 +8,24 @@ interface BooleanFieldProps {
|
|
|
8
8
|
value?: [op: VirtualTableWhereFilterOp, fieldValue: unknown];
|
|
9
9
|
setValue: (value?: [op: VirtualTableWhereFilterOp, newValue: unknown]) => void;
|
|
10
10
|
title?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Restrict the offered operators. This field only ever emits `["==", …]`,
|
|
13
|
+
* so it renders nothing when `==` is not allowed.
|
|
14
|
+
*/
|
|
15
|
+
operators?: readonly VirtualTableWhereFilterOp[];
|
|
11
16
|
}
|
|
12
17
|
|
|
13
18
|
export function BooleanFilterField({
|
|
14
19
|
name,
|
|
15
20
|
title,
|
|
16
21
|
value,
|
|
17
|
-
setValue
|
|
22
|
+
setValue,
|
|
23
|
+
operators
|
|
18
24
|
}: BooleanFieldProps) {
|
|
19
25
|
const { t } = useTranslation();
|
|
20
26
|
|
|
27
|
+
if (operators && !operators.includes("==")) return null;
|
|
28
|
+
|
|
21
29
|
function updateFilter(val?: boolean) {
|
|
22
30
|
if (val !== undefined) {
|
|
23
31
|
setValue(
|
|
@@ -11,9 +11,15 @@ interface DateTimeFilterFieldProps {
|
|
|
11
11
|
isArray?: boolean;
|
|
12
12
|
title?: string;
|
|
13
13
|
timezone?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Restrict the offered operators (already resolved against engine
|
|
16
|
+
* capabilities and property config). When omitted, all operators this
|
|
17
|
+
* field can render are offered.
|
|
18
|
+
*/
|
|
19
|
+
operators?: readonly VirtualTableWhereFilterOp[];
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
const operationLabels: Record<VirtualTableWhereFilterOp
|
|
22
|
+
const operationLabels: Partial<Record<VirtualTableWhereFilterOp, string>> = {
|
|
17
23
|
"==": "==",
|
|
18
24
|
"!=": "!=",
|
|
19
25
|
">": ">",
|
|
@@ -24,7 +30,8 @@ const operationLabels: Record<VirtualTableWhereFilterOp | "is-null", string> = {
|
|
|
24
30
|
in: "in",
|
|
25
31
|
"array-contains": "Contains",
|
|
26
32
|
"array-contains-any": "Any",
|
|
27
|
-
"is-null": "Is null"
|
|
33
|
+
"is-null": "Is null",
|
|
34
|
+
"is-not-null": "Is not null"
|
|
28
35
|
};
|
|
29
36
|
|
|
30
37
|
const multipleSelectOperations = ["array-contains-any", "in"];
|
|
@@ -36,26 +43,40 @@ export function DateTimeFilterField({
|
|
|
36
43
|
value,
|
|
37
44
|
setValue,
|
|
38
45
|
title,
|
|
39
|
-
timezone
|
|
46
|
+
timezone,
|
|
47
|
+
operators
|
|
40
48
|
}: DateTimeFilterFieldProps) {
|
|
41
49
|
|
|
42
50
|
const { locale } = useCustomizationController();
|
|
43
|
-
|
|
51
|
+
let possibleOperations: (keyof typeof operationLabels)[] = isArray
|
|
44
52
|
? ["array-contains"]
|
|
45
|
-
: ["==", "!=", ">", "<", ">=", "<=", "is-null"];
|
|
53
|
+
: ["==", "!=", ">", "<", ">=", "<=", "is-null", "is-not-null"];
|
|
54
|
+
|
|
55
|
+
if (operators) {
|
|
56
|
+
possibleOperations = possibleOperations.filter(op => (operators as readonly string[]).includes(op));
|
|
57
|
+
}
|
|
46
58
|
|
|
47
59
|
const [fieldOperation, fieldValue] = value || [possibleOperations[0], undefined];
|
|
48
|
-
|
|
60
|
+
// Read back both the canonical null operators and the legacy `["==", null]` /
|
|
61
|
+
// `["!=", null]` form saved by older filter presets.
|
|
62
|
+
const [operation, setOperation] = useState<VirtualTableWhereFilterOp>(
|
|
63
|
+
fieldOperation === "==" && fieldValue === null ? "is-null"
|
|
64
|
+
: fieldOperation === "!=" && fieldValue === null ? "is-not-null"
|
|
65
|
+
: fieldOperation
|
|
66
|
+
);
|
|
49
67
|
const [internalValue, setInternalValue] = useState<Date | null | undefined>(fieldValue as Date | null | undefined);
|
|
50
68
|
|
|
51
|
-
const isNullOperation = operation === "is-null";
|
|
69
|
+
const isNullOperation = operation === "is-null" || operation === "is-not-null";
|
|
70
|
+
|
|
71
|
+
// All renderable operators were filtered out (engine/property narrowing).
|
|
72
|
+
if (possibleOperations.length === 0) return null;
|
|
52
73
|
|
|
53
|
-
function updateFilter(op: VirtualTableWhereFilterOp
|
|
54
|
-
//
|
|
55
|
-
if (op === "is-null") {
|
|
74
|
+
function updateFilter(op: VirtualTableWhereFilterOp, val: Date | undefined | null) {
|
|
75
|
+
// Null-testing operators ignore their value.
|
|
76
|
+
if (op === "is-null" || op === "is-not-null") {
|
|
56
77
|
setOperation(op);
|
|
57
78
|
setInternalValue(null);
|
|
58
|
-
setValue([
|
|
79
|
+
setValue([op, null]);
|
|
59
80
|
return;
|
|
60
81
|
}
|
|
61
82
|
|
|
@@ -91,7 +112,7 @@ export function DateTimeFilterField({
|
|
|
91
112
|
size={"medium"}
|
|
92
113
|
fullWidth={true}
|
|
93
114
|
onValueChange={(value) => {
|
|
94
|
-
updateFilter(value as VirtualTableWhereFilterOp
|
|
115
|
+
updateFilter(value as VirtualTableWhereFilterOp, internalValue);
|
|
95
116
|
}}
|
|
96
117
|
renderValue={(op) => operationLabels[op as keyof typeof operationLabels]}>
|
|
97
118
|
{possibleOperations.map((op) => (
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import React, { Suspense } from "react";
|
|
2
|
+
import {
|
|
3
|
+
ArrayProperty,
|
|
4
|
+
FilterFieldBindingProps,
|
|
5
|
+
Property,
|
|
6
|
+
ReferenceProperty,
|
|
7
|
+
RelationProperty,
|
|
8
|
+
WhereFilterOp
|
|
9
|
+
} from "@rebasepro/types";
|
|
10
|
+
import { enumToObjectEntries, resolveFilterOperators } from "@rebasepro/common";
|
|
11
|
+
import { useCollectionScope, useComponentOverride, useResolvedComponent } from "@rebasepro/core";
|
|
12
|
+
import { StringNumberFilterField } from "./StringNumberFilterField";
|
|
13
|
+
import { BooleanFilterField } from "./BooleanFilterField";
|
|
14
|
+
import { DateTimeFilterField } from "./DateTimeFilterField";
|
|
15
|
+
import { ReferenceFilterField } from "./ReferenceFilterField";
|
|
16
|
+
import { RelationFilterField } from "./RelationFilterField";
|
|
17
|
+
|
|
18
|
+
export interface FilterFieldBindingInput {
|
|
19
|
+
/** Key of the property being filtered (the column id). */
|
|
20
|
+
propertyKey: string;
|
|
21
|
+
/** The raw property — array properties are unwrapped internally. */
|
|
22
|
+
property: Property;
|
|
23
|
+
/**
|
|
24
|
+
* Engine backing the collection (`collection.engine`). Drives which
|
|
25
|
+
* operators the engine can execute. Usually omitted — it is read from
|
|
26
|
+
* the surrounding {@link CollectionScopeProvider}; pass it explicitly
|
|
27
|
+
* only when rendering outside any collection scope.
|
|
28
|
+
*/
|
|
29
|
+
engine?: string;
|
|
30
|
+
value?: [WhereFilterOp, unknown];
|
|
31
|
+
setValue: (value?: [WhereFilterOp, unknown]) => void;
|
|
32
|
+
/** Coordination flags for fields that open their own dialogs. */
|
|
33
|
+
hidden?: boolean;
|
|
34
|
+
setHidden?: (hidden: boolean) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The single entry point for rendering a collection filter field.
|
|
39
|
+
* Used by both the table header filters ({@link SelectableTable}) and the
|
|
40
|
+
* Filters dialog.
|
|
41
|
+
*
|
|
42
|
+
* Resolution order:
|
|
43
|
+
* 1. `property.ui.Filter` — per-property replacement (rendered even when the
|
|
44
|
+
* resolved operator list is empty; the component owns filterability).
|
|
45
|
+
* 2. `components["Collection.FilterField"]` — collection-level or app-level
|
|
46
|
+
* override (wrap mode supported via `OriginalComponent`).
|
|
47
|
+
* 3. Built-in field dispatched by property type.
|
|
48
|
+
*
|
|
49
|
+
* The operators handed to the field are the intersection of the engine's
|
|
50
|
+
* capabilities, the property-type defaults, and `property.ui.filterOperators`
|
|
51
|
+
* (see `resolveFilterOperators`). When that intersection is empty and no
|
|
52
|
+
* per-property `Filter` is set, nothing is rendered.
|
|
53
|
+
*
|
|
54
|
+
* @group Components
|
|
55
|
+
*/
|
|
56
|
+
export function FilterFieldBinding({
|
|
57
|
+
propertyKey,
|
|
58
|
+
property,
|
|
59
|
+
engine,
|
|
60
|
+
value,
|
|
61
|
+
setValue,
|
|
62
|
+
hidden,
|
|
63
|
+
setHidden
|
|
64
|
+
}: FilterFieldBindingInput): React.ReactNode {
|
|
65
|
+
|
|
66
|
+
const isArray = property.type === "array";
|
|
67
|
+
const ofVal = isArray ? (property as ArrayProperty).of : undefined;
|
|
68
|
+
const baseProperty: Property | undefined = isArray
|
|
69
|
+
? (Array.isArray(ofVal) ? ofVal[0] : ofVal) as Property | undefined
|
|
70
|
+
: property;
|
|
71
|
+
|
|
72
|
+
// Hooks must run unconditionally — before any early return.
|
|
73
|
+
const scopeCollection = useCollectionScope();
|
|
74
|
+
const ResolvedFilterField = useComponentOverride<FilterFieldBindingProps>("Collection.FilterField", DefaultFilterField);
|
|
75
|
+
const PropertyFilter = useResolvedComponent<FilterFieldBindingProps>(baseProperty?.ui?.Filter);
|
|
76
|
+
|
|
77
|
+
if (!baseProperty) return null;
|
|
78
|
+
|
|
79
|
+
const operators = resolveFilterOperators({
|
|
80
|
+
property: baseProperty,
|
|
81
|
+
isArray,
|
|
82
|
+
engine: engine ?? scopeCollection?.engine
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const bindingProps: FilterFieldBindingProps = {
|
|
86
|
+
propertyKey,
|
|
87
|
+
property: baseProperty,
|
|
88
|
+
isArray,
|
|
89
|
+
operators,
|
|
90
|
+
value,
|
|
91
|
+
setValue,
|
|
92
|
+
title: property.name,
|
|
93
|
+
hidden,
|
|
94
|
+
setHidden
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// 1. Per-property replacement — always rendered, the dev owns filterability.
|
|
98
|
+
if (PropertyFilter) {
|
|
99
|
+
return (
|
|
100
|
+
<Suspense fallback={null}>
|
|
101
|
+
<PropertyFilter {...bindingProps}/>
|
|
102
|
+
</Suspense>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 2/3. Override or built-in — only when the property is filterable here.
|
|
107
|
+
if (operators.length === 0) return null;
|
|
108
|
+
|
|
109
|
+
return <ResolvedFilterField {...bindingProps}/>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Built-in filter field dispatch by property type. This is the
|
|
114
|
+
* `OriginalComponent` received by `"Collection.FilterField"` overrides in
|
|
115
|
+
* wrap mode.
|
|
116
|
+
*/
|
|
117
|
+
function DefaultFilterField({
|
|
118
|
+
propertyKey,
|
|
119
|
+
property,
|
|
120
|
+
isArray,
|
|
121
|
+
operators,
|
|
122
|
+
value,
|
|
123
|
+
setValue,
|
|
124
|
+
title,
|
|
125
|
+
hidden,
|
|
126
|
+
setHidden
|
|
127
|
+
}: FilterFieldBindingProps): React.ReactNode {
|
|
128
|
+
|
|
129
|
+
if (property.type === "reference") {
|
|
130
|
+
const referenceProperty = property as ReferenceProperty;
|
|
131
|
+
return <ReferenceFilterField value={value}
|
|
132
|
+
setValue={setValue}
|
|
133
|
+
name={propertyKey}
|
|
134
|
+
isArray={isArray}
|
|
135
|
+
operators={operators}
|
|
136
|
+
path={referenceProperty.path}
|
|
137
|
+
title={title}
|
|
138
|
+
includeId={referenceProperty.includeId}
|
|
139
|
+
previewProperties={referenceProperty.ui?.previewProperties}
|
|
140
|
+
hidden={hidden ?? false}
|
|
141
|
+
setHidden={setHidden ?? (() => undefined)}/>;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (property.type === "relation") {
|
|
145
|
+
const relation = (property as RelationProperty).relation;
|
|
146
|
+
if (!relation) return null;
|
|
147
|
+
return <RelationFilterField value={value as never}
|
|
148
|
+
setValue={setValue}
|
|
149
|
+
name={propertyKey}
|
|
150
|
+
operators={operators}
|
|
151
|
+
relation={relation}
|
|
152
|
+
hidden={hidden ?? false}
|
|
153
|
+
setHidden={setHidden ?? (() => undefined)}/>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (property.type === "number" || property.type === "string") {
|
|
157
|
+
const enumValues = property.enum ? enumToObjectEntries(property.enum) : undefined;
|
|
158
|
+
return <StringNumberFilterField value={value}
|
|
159
|
+
setValue={setValue}
|
|
160
|
+
name={propertyKey}
|
|
161
|
+
type={property.type}
|
|
162
|
+
isArray={isArray}
|
|
163
|
+
operators={operators}
|
|
164
|
+
enumValues={enumValues}
|
|
165
|
+
title={title}/>;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (property.type === "boolean") {
|
|
169
|
+
return <BooleanFilterField value={value}
|
|
170
|
+
setValue={setValue}
|
|
171
|
+
name={propertyKey}
|
|
172
|
+
operators={operators}
|
|
173
|
+
title={title}/>;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (property.type === "date") {
|
|
177
|
+
return <DateTimeFilterField value={value}
|
|
178
|
+
setValue={setValue}
|
|
179
|
+
name={propertyKey}
|
|
180
|
+
mode={property.mode}
|
|
181
|
+
isArray={isArray}
|
|
182
|
+
operators={operators}
|
|
183
|
+
title={title}/>;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
1
|
+
import { useSelectionDialog } from "../../../hooks/useSelectionDialog";
|
|
2
|
+
import type { CollectionConfig } from "@rebasepro/types";
|
|
3
3
|
import React, { useMemo, useState } from "react";
|
|
4
4
|
import { VirtualTableWhereFilterOp } from "@rebasepro/ui";
|
|
5
5
|
import { Entity, EntityReference } from "@rebasepro/types";
|
|
@@ -20,6 +20,12 @@ interface ReferenceFilterFieldProps {
|
|
|
20
20
|
previewProperties?: string[];
|
|
21
21
|
hidden: boolean;
|
|
22
22
|
setHidden: (hidden: boolean) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Restrict the offered operators (already resolved against engine
|
|
25
|
+
* capabilities and property config). When omitted, all operators this
|
|
26
|
+
* field can render are offered.
|
|
27
|
+
*/
|
|
28
|
+
operators?: readonly VirtualTableWhereFilterOp[];
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
const operationLabels = {
|
|
@@ -44,11 +50,12 @@ export function ReferenceFilterField({
|
|
|
44
50
|
path,
|
|
45
51
|
includeId = true,
|
|
46
52
|
previewProperties,
|
|
47
|
-
setHidden
|
|
53
|
+
setHidden,
|
|
54
|
+
operators
|
|
48
55
|
}: ReferenceFilterFieldProps) {
|
|
49
56
|
const { t } = useTranslation();
|
|
50
57
|
|
|
51
|
-
|
|
58
|
+
let possibleOperations: (keyof typeof operationLabels)[] = isArray
|
|
52
59
|
? ["array-contains"]
|
|
53
60
|
: ["==", "!=", ">", "<", ">=", "<="];
|
|
54
61
|
|
|
@@ -58,6 +65,10 @@ export function ReferenceFilterField({
|
|
|
58
65
|
possibleOperations.push("in", "not-in");
|
|
59
66
|
}
|
|
60
67
|
|
|
68
|
+
if (operators) {
|
|
69
|
+
possibleOperations = possibleOperations.filter(op => (operators as readonly string[]).includes(op));
|
|
70
|
+
}
|
|
71
|
+
|
|
61
72
|
const [fieldOperation, fieldValue] = value || [possibleOperations[0], undefined];
|
|
62
73
|
const [operation, setOperation] = useState<VirtualTableWhereFilterOp>(fieldOperation);
|
|
63
74
|
const [internalValue, setInternalValue] = useState<EntityReference | EntityReference[] | undefined | null>(fieldValue as EntityReference | EntityReference[] | undefined | null);
|
|
@@ -100,7 +111,7 @@ export function ReferenceFilterField({
|
|
|
100
111
|
}
|
|
101
112
|
|
|
102
113
|
const collectionRegistryController = useCollectionRegistryController();
|
|
103
|
-
const collection:
|
|
114
|
+
const collection: CollectionConfig | undefined = useMemo(() => {
|
|
104
115
|
return path ? collectionRegistryController.getCollection(path) : undefined;
|
|
105
116
|
}, [path]);
|
|
106
117
|
|
|
@@ -114,7 +125,7 @@ export function ReferenceFilterField({
|
|
|
114
125
|
|
|
115
126
|
const multiple = multipleSelectOperations.includes(operation);
|
|
116
127
|
|
|
117
|
-
const referenceDialogController =
|
|
128
|
+
const referenceDialogController = useSelectionDialog({
|
|
118
129
|
multiselect: multiple,
|
|
119
130
|
path,
|
|
120
131
|
collection,
|
|
@@ -147,6 +158,9 @@ export function ReferenceFilterField({
|
|
|
147
158
|
);
|
|
148
159
|
};
|
|
149
160
|
|
|
161
|
+
// All renderable operators were filtered out (engine/property narrowing).
|
|
162
|
+
if (possibleOperations.length === 0) return null;
|
|
163
|
+
|
|
150
164
|
return (
|
|
151
165
|
|
|
152
166
|
<div className="flex w-full flex-row">
|
|
@@ -157,7 +171,7 @@ export function ReferenceFilterField({
|
|
|
157
171
|
onValueChange={(value) => {
|
|
158
172
|
updateFilter(value as VirtualTableWhereFilterOp, internalValue);
|
|
159
173
|
}}
|
|
160
|
-
renderValue={(op) => operationLabels[op as
|
|
174
|
+
renderValue={(op) => operationLabels[op as keyof typeof operationLabels]}>
|
|
161
175
|
{possibleOperations.map((op) => (
|
|
162
176
|
<SelectItem key={op} value={op}>
|
|
163
177
|
{operationLabels[op]}
|
|
@@ -11,6 +11,12 @@ interface RelationFilterFieldProps {
|
|
|
11
11
|
relation: Relation; // relation config provided externally
|
|
12
12
|
hidden: boolean;
|
|
13
13
|
setHidden: (value: boolean) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Restrict the offered operators (already resolved against engine
|
|
16
|
+
* capabilities and property config). When omitted, all operators this
|
|
17
|
+
* field can render are offered.
|
|
18
|
+
*/
|
|
19
|
+
operators?: readonly VirtualTableWhereFilterOp[];
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
const operationLabels = {
|
|
@@ -34,15 +40,20 @@ export function RelationFilterField({
|
|
|
34
40
|
relation,
|
|
35
41
|
name: _name,
|
|
36
42
|
hidden: _hidden,
|
|
37
|
-
setHidden: _setHidden
|
|
43
|
+
setHidden: _setHidden,
|
|
44
|
+
operators
|
|
38
45
|
}: RelationFilterFieldProps) {
|
|
39
46
|
|
|
40
47
|
const manyRelation = relation.cardinality === "many";
|
|
41
48
|
|
|
42
|
-
|
|
49
|
+
let possibleOperations: (keyof typeof operationLabels)[] = manyRelation
|
|
43
50
|
? ["array-contains", "array-contains-any"]
|
|
44
51
|
: ["==", "!=", ">", "<", ">=", "<=", "in", "not-in"];
|
|
45
52
|
|
|
53
|
+
if (operators) {
|
|
54
|
+
possibleOperations = possibleOperations.filter(op => (operators as readonly string[]).includes(op));
|
|
55
|
+
}
|
|
56
|
+
|
|
46
57
|
const [fieldOperation, fieldValue] = value || [possibleOperations[0], undefined];
|
|
47
58
|
const [operation, setOperation] = useState<VirtualTableWhereFilterOp>(fieldOperation);
|
|
48
59
|
const [internalValue, setInternalValue] = useState<EntityRelation | EntityRelation[] | undefined | null>(fieldValue);
|
|
@@ -89,6 +100,9 @@ export function RelationFilterField({
|
|
|
89
100
|
updateFilter(operation, newVal);
|
|
90
101
|
};
|
|
91
102
|
|
|
103
|
+
// All renderable operators were filtered out (engine/property narrowing).
|
|
104
|
+
if (possibleOperations.length === 0) return null;
|
|
105
|
+
|
|
92
106
|
return (
|
|
93
107
|
<div className="flex flex-row">
|
|
94
108
|
<div className="">
|
|
@@ -98,7 +112,7 @@ export function RelationFilterField({
|
|
|
98
112
|
onValueChange={(newOp) => {
|
|
99
113
|
updateFilter(newOp as VirtualTableWhereFilterOp, internalValue);
|
|
100
114
|
}}
|
|
101
|
-
renderValue={(op) => operationLabels[op as
|
|
115
|
+
renderValue={(op) => operationLabels[op as keyof typeof operationLabels]}
|
|
102
116
|
>
|
|
103
117
|
{possibleOperations.map((op) => (
|
|
104
118
|
<SelectItem key={op} value={op}>
|
|
@@ -21,6 +21,12 @@ interface StringNumberFilterFieldProps {
|
|
|
21
21
|
isArray?: boolean;
|
|
22
22
|
enumValues?: EnumValueConfig[];
|
|
23
23
|
title?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Restrict the offered operators (already resolved against engine
|
|
26
|
+
* capabilities and property config). When omitted, all operators this
|
|
27
|
+
* field can render are offered.
|
|
28
|
+
*/
|
|
29
|
+
operators?: readonly VirtualTableWhereFilterOp[];
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
const operationLabels = {
|
|
@@ -34,11 +40,23 @@ const operationLabels = {
|
|
|
34
40
|
"not-in": "Not in",
|
|
35
41
|
"array-contains": "Contains",
|
|
36
42
|
"array-contains-any": "Any",
|
|
37
|
-
"
|
|
43
|
+
"ilike": "Contains",
|
|
44
|
+
"not-ilike": "Not contains",
|
|
45
|
+
"is-null": "Is null",
|
|
46
|
+
"is-not-null": "Is not null"
|
|
38
47
|
};
|
|
39
48
|
|
|
40
49
|
const multipleSelectOperations = ["array-contains-any", "in", "not-in"];
|
|
41
50
|
|
|
51
|
+
/** Operators that match a substring, wrapped in SQL wildcards (`%value%`). */
|
|
52
|
+
const containsOperations = ["ilike", "not-ilike"];
|
|
53
|
+
|
|
54
|
+
/** Strip the surrounding `%` wildcards a contains-filter adds, for display. */
|
|
55
|
+
function unwrapContains(value: unknown): string {
|
|
56
|
+
if (typeof value !== "string") return "";
|
|
57
|
+
return value.replace(/^%/, "").replace(/%$/, "");
|
|
58
|
+
}
|
|
59
|
+
|
|
42
60
|
export function StringNumberFilterField({
|
|
43
61
|
name,
|
|
44
62
|
value,
|
|
@@ -46,13 +64,20 @@ export function StringNumberFilterField({
|
|
|
46
64
|
type,
|
|
47
65
|
isArray,
|
|
48
66
|
enumValues,
|
|
49
|
-
title
|
|
67
|
+
title,
|
|
68
|
+
operators
|
|
50
69
|
}: StringNumberFilterFieldProps) {
|
|
51
70
|
const { t } = useTranslation();
|
|
52
71
|
|
|
53
|
-
|
|
72
|
+
let possibleOperations: (keyof typeof operationLabels)[] = isArray
|
|
54
73
|
? ["array-contains"]
|
|
55
|
-
: ["==", "!=", ">", "<", ">=", "<=", "is-null"];
|
|
74
|
+
: ["==", "!=", ">", "<", ">=", "<=", "is-null", "is-not-null"];
|
|
75
|
+
|
|
76
|
+
// Case-insensitive substring matching is only meaningful for free-text
|
|
77
|
+
// string columns (not numbers, arrays, or enums).
|
|
78
|
+
if (!isArray && !enumValues && type === "string") {
|
|
79
|
+
possibleOperations.push("ilike", "not-ilike");
|
|
80
|
+
}
|
|
56
81
|
|
|
57
82
|
if (enumValues) {
|
|
58
83
|
if (isArray) {
|
|
@@ -62,18 +87,47 @@ export function StringNumberFilterField({
|
|
|
62
87
|
}
|
|
63
88
|
}
|
|
64
89
|
|
|
90
|
+
if (operators) {
|
|
91
|
+
possibleOperations = possibleOperations.filter(op => (operators as readonly string[]).includes(op));
|
|
92
|
+
}
|
|
93
|
+
|
|
65
94
|
const [fieldOperation, fieldValue] = value || [possibleOperations[0], undefined];
|
|
66
|
-
|
|
67
|
-
|
|
95
|
+
// Read back both the canonical null operators and the legacy `["==", null]` /
|
|
96
|
+
// `["!=", null]` form saved by older filter presets.
|
|
97
|
+
const [operation, setOperation] = useState<VirtualTableWhereFilterOp>(
|
|
98
|
+
fieldOperation === "==" && fieldValue === null ? "is-null"
|
|
99
|
+
: fieldOperation === "!=" && fieldValue === null ? "is-not-null"
|
|
100
|
+
: fieldOperation
|
|
101
|
+
);
|
|
102
|
+
const [internalValue, setInternalValue] = useState<string | number | string[] | number[] | null | undefined>(
|
|
103
|
+
containsOperations.includes(fieldOperation) ? unwrapContains(fieldValue) : (fieldValue as string | number | string[] | number[] | null | undefined)
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const isNullOperation = operation === "is-null" || operation === "is-not-null";
|
|
68
107
|
|
|
69
|
-
|
|
108
|
+
// All renderable operators were filtered out (engine/property narrowing).
|
|
109
|
+
if (possibleOperations.length === 0) return null;
|
|
70
110
|
|
|
71
|
-
function updateFilter(op: VirtualTableWhereFilterOp
|
|
72
|
-
//
|
|
73
|
-
if (op === "is-null") {
|
|
111
|
+
function updateFilter(op: VirtualTableWhereFilterOp, val: string | number | string[] | number[] | null | undefined) {
|
|
112
|
+
// Null-testing operators ignore their value.
|
|
113
|
+
if (op === "is-null" || op === "is-not-null") {
|
|
74
114
|
setOperation(op);
|
|
75
115
|
setInternalValue(null);
|
|
76
|
-
setValue([
|
|
116
|
+
setValue([op, null]);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Substring matching: keep the raw text in the field, emit it wrapped
|
|
121
|
+
// in SQL wildcards so the backend runs `column ILIKE '%value%'`.
|
|
122
|
+
if (op === "ilike" || op === "not-ilike") {
|
|
123
|
+
const raw = typeof val === "string" ? val : "";
|
|
124
|
+
setOperation(op);
|
|
125
|
+
setInternalValue(raw);
|
|
126
|
+
if (raw.length > 0) {
|
|
127
|
+
setValue([op, `%${raw}%`]);
|
|
128
|
+
} else {
|
|
129
|
+
setValue(undefined);
|
|
130
|
+
}
|
|
77
131
|
return;
|
|
78
132
|
}
|
|
79
133
|
|
|
@@ -121,7 +175,7 @@ export function StringNumberFilterField({
|
|
|
121
175
|
fullWidth={true}
|
|
122
176
|
position={"item-aligned"}
|
|
123
177
|
onValueChange={(value) => {
|
|
124
|
-
updateFilter(value as VirtualTableWhereFilterOp
|
|
178
|
+
updateFilter(value as VirtualTableWhereFilterOp, internalValue);
|
|
125
179
|
}}
|
|
126
180
|
renderValue={(op) => operationLabels[op as keyof typeof operationLabels]}>
|
|
127
181
|
{possibleOperations.map((op) => (
|