@rebasepro/admin 0.16.0 → 0.16.1-canary.g2d1aec8
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/{CollectionEditorDialog-D2Vf4C3-.js → CollectionEditorDialog-Cec5jU6R.js} +7 -3
- package/dist/{CollectionEditorDialog-D2Vf4C3-.js.map → CollectionEditorDialog-Cec5jU6R.js.map} +1 -1
- package/dist/{PropertyEditView-D3NBsK9_.js → PropertyEditView-BuSPZwnQ.js} +2 -2
- package/dist/{PropertyEditView-D3NBsK9_.js.map → PropertyEditView-BuSPZwnQ.js.map} +1 -1
- package/dist/{RouterCollectionsStudioView-hPB54l3Q.js → RouterCollectionsStudioView-BiNFpEii.js} +4 -4
- package/dist/{RouterCollectionsStudioView-hPB54l3Q.js.map → RouterCollectionsStudioView-BiNFpEii.js.map} +1 -1
- package/dist/SchemaChangeDialog-WKIbzS6P.js +327 -0
- package/dist/SchemaChangeDialog-WKIbzS6P.js.map +1 -0
- package/dist/collection_editor/ConfigControllerProvider.d.ts +4 -4
- package/dist/collection_editor/_cms_internals.d.ts +23 -23
- package/dist/collection_editor/api/index.d.ts +1 -1
- package/dist/collection_editor/extensibility_types.d.ts +1 -1
- package/dist/collection_editor/index.d.ts +21 -21
- package/dist/collection_editor/liveSchemaClient.d.ts +170 -0
- package/dist/collection_editor/serializable_utils.d.ts +1 -1
- package/dist/collection_editor/types/collection_editor_controller.d.ts +1 -1
- package/dist/collection_editor/types/config_controller.d.ts +11 -0
- package/dist/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/AIModifiedPathsContext.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +4 -4
- package/dist/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/CollectionStudioView.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/CollectionsStudioView.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/GeneralSettingsForm.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/PropertyEditView.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/RouterCollectionStudioView.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/RouterCollectionsStudioView.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/SchemaChangeDialog.d.ts +66 -0
- package/dist/collection_editor/ui/collection_editor/SubcollectionsEditTab.d.ts +2 -2
- package/dist/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/import/clean_import_data.d.ts +1 -1
- package/dist/collection_editor/ui/collection_editor/properties/conditions/index.d.ts +6 -6
- package/dist/collection_editor/useCollectionEditorController.d.ts +1 -1
- package/dist/collection_editor/useCollectionsConfigController.d.ts +1 -1
- package/dist/collection_editor/useJsonCollectionsConfigController.d.ts +2 -2
- package/dist/collection_editor/useLiveSchemaEditing.d.ts +71 -0
- package/dist/collection_editor/useLocalCollectionsConfigController.d.ts +1 -1
- package/dist/collection_editor_ui.d.ts +12 -12
- package/dist/collection_editor_ui.js +4 -4
- package/dist/components/CollectionTableBinding/CollectionTableBinding.d.ts +1 -1
- package/dist/components/CollectionTableBinding/PropertyTableCell.d.ts +1 -1
- package/dist/components/CollectionTableBinding/fields/TableStorageUpload.d.ts +1 -1
- package/dist/components/CollectionTableBinding/index.d.ts +5 -5
- package/dist/components/CollectionTableBinding/internal/popup_field/PopupFormField.d.ts +1 -1
- package/dist/components/CollectionViewBinding/SlotValue.d.ts +2 -2
- package/dist/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.d.ts +1 -1
- package/dist/components/EditFormActions.d.ts +1 -1
- package/dist/components/EditViewBinding.d.ts +3 -3
- package/dist/components/EntityInspector.d.ts +1 -1
- package/dist/components/EntityPreviewBinding.d.ts +1 -1
- package/dist/components/EntityViewBinding.d.ts +1 -1
- package/dist/components/HomePage/index.d.ts +4 -4
- package/dist/components/PropertyCollectionView.d.ts +1 -1
- package/dist/components/ReferenceWidget.d.ts +1 -1
- package/dist/components/admin/index.d.ts +1 -1
- package/dist/components/app/AppBar.d.ts +1 -1
- package/dist/components/app/index.d.ts +4 -4
- package/dist/components/common/index.d.ts +1 -1
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/components/history/EntityHistoryEntry.d.ts +2 -2
- package/dist/components/history/index.d.ts +5 -5
- package/dist/components/index.d.ts +45 -45
- package/dist/data_export/export/index.d.ts +4 -4
- package/dist/data_export/index.d.ts +1 -1
- package/dist/data_import/components/DataNewPropertiesMapping.d.ts +1 -1
- package/dist/data_import/components/ImportSaveInProgress.d.ts +1 -1
- package/dist/data_import/components/index.d.ts +4 -4
- package/dist/data_import/hooks/index.d.ts +1 -1
- package/dist/data_import/hooks/useImportConfig.d.ts +1 -1
- package/dist/data_import/import/ImportCollectionAction.d.ts +1 -1
- package/dist/data_import/import/index.d.ts +1 -1
- package/dist/data_import/index.d.ts +5 -5
- package/dist/data_import/types/index.d.ts +1 -1
- package/dist/data_import/utils/file_to_json.d.ts +1 -1
- package/dist/data_import/utils/index.d.ts +5 -5
- package/dist/editor/components/SlashCommandMenu.d.ts +2 -2
- package/dist/editor/components/index.d.ts +5 -5
- package/dist/editor/editor.d.ts +2 -2
- package/dist/editor/index.d.ts +2 -2
- package/dist/editor/nodeViews/ImageComponent.d.ts +1 -1
- package/dist/editor/nodeViews/TaskItemComponent.d.ts +1 -1
- package/dist/editor/types.d.ts +1 -1
- package/dist/{export-oauWlxuu.js → export-BItpoIu0.js} +2 -2
- package/dist/{export-oauWlxuu.js.map → export-BItpoIu0.js.map} +1 -1
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/EntityFormActions.d.ts +1 -1
- package/dist/form/EntityFormBinding.d.ts +1 -1
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/components/StorageItemPreview.d.ts +1 -1
- package/dist/form/components/index.d.ts +6 -6
- package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/BinaryFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/DateTimeFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/GeopointFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +2 -2
- package/dist/form/field_bindings/MultiSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MultipleRelationFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/UserSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/VectorFieldBinding.d.ts +1 -1
- package/dist/form/index.d.ts +24 -24
- package/dist/{history-C2cqc0bw.js → history-C7WF14VR.js} +2 -2
- package/dist/{history-C2cqc0bw.js.map → history-C7WF14VR.js.map} +1 -1
- package/dist/hooks/index.d.ts +16 -16
- package/dist/hooks/navigation/contexts/index.d.ts +3 -3
- package/dist/hooks/useBuildSideDialogsController.d.ts +1 -1
- package/dist/hooks/useSelectionDialog.d.ts +1 -1
- package/dist/{import-Bxv5JPm-.js → import-CZgNAlcd.js} +2 -2
- package/dist/{import-Bxv5JPm-.js.map → import-CZgNAlcd.js.map} +1 -1
- package/dist/index.d.ts +17 -15
- package/dist/index.js +238 -21
- package/dist/index.js.map +1 -1
- package/dist/preview/PropertyPreview.d.ts +1 -1
- package/dist/preview/components/ArrayEnumPreview.d.ts +1 -1
- package/dist/preview/components/BooleanPreview.d.ts +1 -1
- package/dist/preview/components/ImagePreview.d.ts +1 -1
- package/dist/preview/components/ReferencePreview.d.ts +1 -1
- package/dist/preview/components/RelationPreview.d.ts +1 -1
- package/dist/preview/components/StorageThumbnail.d.ts +1 -1
- package/dist/preview/components/UrlComponentPreview.d.ts +2 -2
- package/dist/preview/components/UserPreview.d.ts +1 -1
- package/dist/preview/index.d.ts +24 -24
- package/dist/preview/property_previews/ArrayOfMapsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfReferencesPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfRelationsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOneOfPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayPropertyEnumPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayPropertyPreview.d.ts +1 -1
- package/dist/preview/property_previews/MapPropertyPreview.d.ts +1 -1
- package/dist/preview/property_previews/NumberPropertyPreview.d.ts +1 -1
- package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
- package/dist/preview/property_previews/StringPropertyPreview.d.ts +1 -1
- package/dist/preview/util.d.ts +1 -1
- package/dist/routes/index.d.ts +2 -2
- package/dist/types/components/EntityFormActionsProps.d.ts +2 -2
- package/dist/types/components/EntityFormProps.d.ts +3 -3
- package/dist/types/components/index.d.ts +3 -3
- package/dist/types/fields.d.ts +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/util/index.d.ts +5 -5
- package/dist/{util-C4qsI1QV.js → util-wrBH4QSB.js} +130 -7
- package/dist/util-wrBH4QSB.js.map +1 -0
- package/package.json +10 -10
- package/src/collection_editor/ConfigControllerProvider.tsx +5 -0
- package/src/collection_editor/liveSchemaClient.ts +272 -0
- package/src/collection_editor/types/config_controller.tsx +11 -0
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +10 -0
- package/src/collection_editor/ui/collection_editor/SchemaChangeDialog.tsx +368 -0
- package/src/collection_editor/useLiveSchemaEditing.tsx +285 -0
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +109 -10
- package/src/index.ts +6 -0
- package/dist/util-C4qsI1QV.js.map +0 -1
package/dist/{RouterCollectionsStudioView-hPB54l3Q.js → RouterCollectionsStudioView-BiNFpEii.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import {
|
|
3
|
-
import { t as CollectionEditor } from "./CollectionEditorDialog-
|
|
4
|
-
import { s as AIModifiedPathsProvider } from "./PropertyEditView-
|
|
2
|
+
import { hn as useUrlController } from "./util-wrBH4QSB.js";
|
|
3
|
+
import { t as CollectionEditor } from "./CollectionEditorDialog-Cec5jU6R.js";
|
|
4
|
+
import { s as AIModifiedPathsProvider } from "./PropertyEditView-BuSPZwnQ.js";
|
|
5
5
|
import { useEffect, useState } from "react";
|
|
6
6
|
import { Button, IconButton, PlusIcon, ResizablePanels, Tooltip, Typography, cls, defaultBorderMixin, iconSize } from "@rebasepro/ui";
|
|
7
7
|
import { IconForView, UnsavedChangesDialog, useUnsavedChangesDialog } from "@rebasepro/app";
|
|
@@ -185,4 +185,4 @@ function RouterCollectionsStudioView(props) {
|
|
|
185
185
|
//#endregion
|
|
186
186
|
export { CollectionStudioView as i, RouterCollectionsStudioView_exports as n, CollectionsStudioView as r, RouterCollectionsStudioView as t };
|
|
187
187
|
|
|
188
|
-
//# sourceMappingURL=RouterCollectionsStudioView-
|
|
188
|
+
//# sourceMappingURL=RouterCollectionsStudioView-BiNFpEii.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouterCollectionsStudioView-hPB54l3Q.js","names":[],"sources":["../src/collection_editor/ui/collection_editor/CollectionStudioView.tsx","../src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx","../src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx"],"sourcesContent":["\nimport { useUnsavedChangesDialog, UnsavedChangesDialog } from \"@rebasepro/app\";\nimport * as React from \"react\";\nimport { useState } from \"react\";\nimport { Button, PlusIcon, Typography } from \"@rebasepro/ui\";\nimport { CollectionEditorDialogProps } from \"./CollectionEditorDialog\";\nimport { AIModifiedPathsProvider } from \"./AIModifiedPathsContext\";\nimport { CollectionEditor } from \"./CollectionEditorDialog\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\n\nexport type CollectionStudioViewProps = Omit<CollectionEditorDialogProps, \"open\" | \"isNewCollection\" | \"editedCollectionId\" | \"handleClose\" | \"handleCancel\"> & {\n collectionId?: string | \"new\";\n\n /**\n * Called after a successful save.\n * Receives the saved collection (or undefined if dismissed without saving).\n * When not provided, save completes silently.\n */\n onSave?: (collection?: AdminCollection) => void;\n\n /**\n * Called when the user cancels editing.\n * When not provided, cancel is a no-op.\n */\n onCancel?: () => void;\n};\n\nexport function CollectionStudioView({ collectionId, onSave, onCancel, ...props }: CollectionStudioViewProps) {\n\n // Form state from the editor\n const [formDirty, setFormDirty] = useState<boolean>(false);\n const [cancelRequested, setCancelRequested] = useState<boolean>(false);\n\n const { dialogProps, triggerDialog } = useUnsavedChangesDialog(\n formDirty,\n () => setFormDirty(false)\n );\n\n const activeCollectionId = collectionId;\n\n const handleCancelClick = () => {\n if (!formDirty) {\n onCancel?.();\n } else {\n setCancelRequested(true);\n triggerDialog();\n }\n };\n\n return (\n <div className=\"flex-grow flex flex-col h-full w-full bg-surface-50 dark:bg-surface-800\">\n <AIModifiedPathsProvider>\n {activeCollectionId ? (\n <CollectionEditor\n key={activeCollectionId}\n {...props}\n fullScreen={true}\n open={true}\n isNewCollection={activeCollectionId === \"new\"}\n editedCollectionId={activeCollectionId !== \"new\" ? activeCollectionId : undefined}\n handleCancel={handleCancelClick}\n handleClose={(savedCollection) => {\n setFormDirty(false);\n if (savedCollection) {\n setTimeout(() => {\n onSave?.(savedCollection);\n }, 0);\n }\n }}\n setFormDirty={setFormDirty}\n />\n ) : (\n <div className=\"flex-grow flex flex-col items-center justify-center h-full gap-4\">\n <Typography variant=\"label\">\n Select a collection or create a new one\n </Typography>\n <Button\n disabled={props.configController?.readOnly}\n onClick={() => onSave?.()}\n >\n <PlusIcon/>\n Add new collection\n </Button>\n </div>\n )}\n\n <UnsavedChangesDialog\n {...dialogProps}\n handleOk={() => {\n dialogProps.handleOk();\n if (cancelRequested) {\n onCancel?.();\n setCancelRequested(false);\n }\n }}\n handleCancel={() => {\n dialogProps.handleCancel();\n setCancelRequested(false);\n }}\n />\n </AIModifiedPathsProvider>\n </div>\n );\n}\n","\nimport { IconForView } from \"@rebasepro/app\";\nimport React, { useState, useEffect } from \"react\";\nimport {\n Button,\n cls,\n defaultBorderMixin,\n IconButton,\n iconSize,\n PlusIcon,\n ResizablePanels,\n Tooltip,\n Typography\n} from \"@rebasepro/ui\";\n\nimport { CollectionsConfigController } from \"../../types/config_controller\";\nimport { CollectionStudioView } from \"./CollectionStudioView\";\nimport type { CollectionEditorExtensionProps } from \"../../extensibility_types\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\nimport { readStoredString, writeStoredString } from \"@rebasepro/utils\";\n\nexport interface CollectionsStudioViewProps extends CollectionEditorExtensionProps {\n configController: CollectionsConfigController;\n\n /**\n * Collections to show in the sidebar.\n * When provided, overrides the collections from `configController`.\n * Use this to control exactly which collections the editor displays.\n */\n collections?: AdminCollection[];\n\n /**\n * Controlled active collection ID.\n * When provided together with `onActiveCollectionChange`,\n * navigation is fully external — no internal state is used.\n */\n activeCollectionId?: string;\n\n /**\n * Called when the user clicks a collection, \"new\", or navigates.\n * When provided, the component is fully controlled (no internal state).\n * When not provided, the component manages selection via internal state.\n *\n * Pass `\"new\"` to create a new collection. Pass `undefined` to deselect.\n */\n onActiveCollectionChange?: (collectionId: string | undefined) => void;\n}\n\nexport function CollectionsStudioView({\n configController,\n collections: collectionsProp,\n activeCollectionId: controlledActiveId,\n onActiveCollectionChange,\n propertyTypePresets,\n hiddenPropertyTypes,\n renderExtraPropertyFields,\n renderExtraCollectionFields,\n visibleTabs,\n standalone,\n}: CollectionsStudioViewProps) {\n\n // ── Navigation state ────────────────────────────────────────────────\n // If onActiveCollectionChange is provided, the component is controlled.\n // Otherwise, use internal state.\n const [internalActiveId, setInternalActiveId] = useState<string | undefined>(undefined);\n const isControlled = onActiveCollectionChange !== undefined;\n const activeCollectionId = isControlled ? controlledActiveId : internalActiveId;\n\n const setActiveCollectionId = (id: string | undefined) => {\n if (isControlled) {\n onActiveCollectionChange?.(id);\n } else {\n setInternalActiveId(id);\n }\n };\n\n // ── Collections list ────────────────────────────────────────────────\n const collections = collectionsProp ?? configController.collections ?? [];\n\n // ── Sidebar sizing ──────────────────────────────────────────────────\n // Checked, not just parsed: `parseFloat` answers NaN for anything it cannot\n // read, and a NaN pane size lays the sidebar out to nothing — with the bad\n // value still in storage on reload. `SplitListView.getSavedPanelSize` is the\n // same read, done this way.\n const [sidebarSize, setSidebarSize] = useState(() => {\n const saved = readStoredString(\"rebase_collections_editor_sidebar_size\");\n const parsed = saved === null ? NaN : parseFloat(saved);\n return Number.isFinite(parsed) && parsed > 0 && parsed < 100 ? parsed : 25;\n });\n\n useEffect(() => {\n writeStoredString(\"rebase_collections_editor_sidebar_size\", sidebarSize.toString());\n }, [sidebarSize]);\n\n return (\n <div className=\"flex h-full w-full bg-surface-50 dark:bg-surface-800 overflow-hidden text-text-primary dark:text-text-primary-dark\">\n <ResizablePanels\n orientation=\"horizontal\"\n panelSizePercent={sidebarSize}\n onPanelSizeChange={setSidebarSize}\n minPanelSizePx={220}\n firstPanel={\n <div className={cls(\"flex flex-col h-full w-full bg-surface-50 dark:bg-surface-800 border-r\", defaultBorderMixin)}>\n <div className={cls(\"flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"font-semibold text-[11px] uppercase tracking-wider text-surface-400 dark:text-surface-400\">\n Collections\n </Typography>\n <Tooltip title={configController.readOnly ? configController.readOnlyReason || \"Read only\" : \"Add collection\"}>\n <div>\n <IconButton\n size=\"small\"\n disabled={configController.readOnly}\n onClick={() => setActiveCollectionId(\"new\")}\n className={activeCollectionId === \"new\" ? \"text-primary dark:text-primary-dark\" : \"text-text-secondary dark:text-text-secondary-dark\"}\n >\n <PlusIcon size={iconSize.smallest}/>\n </IconButton>\n </div>\n </Tooltip>\n </div>\n\n <div className=\"flex-grow overflow-y-auto w-full no-scrollbar p-2 space-y-0.5\">\n {collections.length === 0 && (\n <div className=\"p-4 text-center\">\n <Typography variant=\"caption\" className=\"text-text-disabled dark:text-text-disabled-dark italic\">\n No collections yet.\n </Typography>\n </div>\n )}\n {collections.map((collection) => {\n const collectionKey = collection.slug;\n const isSelected = activeCollectionId === collectionKey;\n return (\n <div\n key={collectionKey}\n onClick={() => setActiveCollectionId(collectionKey)}\n className={cls(\n \"flex items-center gap-2.5 px-3 h-[30px] cursor-pointer rounded-lg text-[13px] font-medium transition-colors\",\n isSelected\n ? \"bg-primary/8 text-primary dark:bg-primary/10 dark:text-primary-light font-semibold\"\n : \"hover:bg-primary/5 dark:hover:bg-primary/5 text-surface-700 dark:text-surface-300 hover:text-surface-900 dark:hover:text-white\"\n )}\n >\n <IconForView collectionOrView={collection} size={\"smallest\"} className={cls(\n isSelected\n ? \"text-primary dark:text-primary-light\"\n : \"text-surface-500 dark:text-text-secondary-dark\"\n )}/>\n <span className=\"truncate flex-1\">\n {collection.name || collection.slug}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n }\n secondPanel={\n <div className=\"flex-grow flex flex-col min-w-0 h-full w-full\">\n {/* We use key to force unmount when switching collections, preventing stale state */}\n {activeCollectionId ? (\n <CollectionStudioView\n key={activeCollectionId}\n configController={configController}\n collectionId={activeCollectionId}\n onSave={(savedCollection) => {\n // After creating a new collection, switch to it\n if (activeCollectionId === \"new\" && savedCollection?.slug) {\n setActiveCollectionId(savedCollection.slug);\n }\n }}\n onCancel={() => setActiveCollectionId(undefined)}\n propertyTypePresets={propertyTypePresets}\n hiddenPropertyTypes={hiddenPropertyTypes}\n renderExtraPropertyFields={renderExtraPropertyFields}\n renderExtraCollectionFields={renderExtraCollectionFields}\n visibleTabs={visibleTabs}\n standalone={standalone}\n />\n ) : (\n <div className=\"flex flex-col items-center justify-center h-full gap-4\">\n <Typography variant=\"label\">\n Select a collection or create a new one to start editing\n </Typography>\n <Button\n disabled={configController.readOnly}\n onClick={() => setActiveCollectionId(\"new\")}\n >\n <PlusIcon/>\n Add new collection\n </Button>\n </div>\n )}\n </div>\n }\n />\n </div>\n );\n}\n","/**\n * Router-aware wrapper around CollectionsStudioView.\n *\n * This component provides the react-router-based navigation behavior\n * that Rebase Studio expects: the active collection is derived from the\n * URL, and clicking a collection navigates via react-router.\n *\n * External consumers should use `CollectionsStudioView` directly\n * (which has no react-router dependency).\n */\nimport React from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\nimport { useUrlController } from \"../../_cms_internals\";\nimport { CollectionsStudioView, CollectionsStudioViewProps } from \"./CollectionsStudioView\";\n\nexport type RouterCollectionsStudioViewProps = Omit<CollectionsStudioViewProps, \"activeCollectionId\" | \"onActiveCollectionChange\">;\n\nexport function RouterCollectionsStudioView(props: RouterCollectionsStudioViewProps) {\n const navigate = useNavigate();\n const urlController = useUrlController();\n const location = useLocation();\n\n // Determine the active collection from the URL segment after \"schema/\"\n const basePath = urlController.buildAppUrlPath(\"schema\");\n const relativePath = location.pathname.replace(basePath, \"\").replace(/^\\//, \"\");\n const activeCollectionId = relativePath.split(\"/\")[0] || undefined;\n\n return (\n <CollectionsStudioView\n {...props}\n activeCollectionId={activeCollectionId}\n onActiveCollectionChange={(id) => {\n if (id) {\n navigate(urlController.buildAppUrlPath(`schema/${id}`));\n } else {\n navigate(urlController.buildAppUrlPath(\"schema\"));\n }\n }}\n />\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RouterCollectionsStudioView-BiNFpEii.js","names":[],"sources":["../src/collection_editor/ui/collection_editor/CollectionStudioView.tsx","../src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx","../src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx"],"sourcesContent":["\nimport { useUnsavedChangesDialog, UnsavedChangesDialog } from \"@rebasepro/app\";\nimport * as React from \"react\";\nimport { useState } from \"react\";\nimport { Button, PlusIcon, Typography } from \"@rebasepro/ui\";\nimport { CollectionEditorDialogProps } from \"./CollectionEditorDialog\";\nimport { AIModifiedPathsProvider } from \"./AIModifiedPathsContext\";\nimport { CollectionEditor } from \"./CollectionEditorDialog\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\n\nexport type CollectionStudioViewProps = Omit<CollectionEditorDialogProps, \"open\" | \"isNewCollection\" | \"editedCollectionId\" | \"handleClose\" | \"handleCancel\"> & {\n collectionId?: string | \"new\";\n\n /**\n * Called after a successful save.\n * Receives the saved collection (or undefined if dismissed without saving).\n * When not provided, save completes silently.\n */\n onSave?: (collection?: AdminCollection) => void;\n\n /**\n * Called when the user cancels editing.\n * When not provided, cancel is a no-op.\n */\n onCancel?: () => void;\n};\n\nexport function CollectionStudioView({ collectionId, onSave, onCancel, ...props }: CollectionStudioViewProps) {\n\n // Form state from the editor\n const [formDirty, setFormDirty] = useState<boolean>(false);\n const [cancelRequested, setCancelRequested] = useState<boolean>(false);\n\n const { dialogProps, triggerDialog } = useUnsavedChangesDialog(\n formDirty,\n () => setFormDirty(false)\n );\n\n const activeCollectionId = collectionId;\n\n const handleCancelClick = () => {\n if (!formDirty) {\n onCancel?.();\n } else {\n setCancelRequested(true);\n triggerDialog();\n }\n };\n\n return (\n <div className=\"flex-grow flex flex-col h-full w-full bg-surface-50 dark:bg-surface-800\">\n <AIModifiedPathsProvider>\n {activeCollectionId ? (\n <CollectionEditor\n key={activeCollectionId}\n {...props}\n fullScreen={true}\n open={true}\n isNewCollection={activeCollectionId === \"new\"}\n editedCollectionId={activeCollectionId !== \"new\" ? activeCollectionId : undefined}\n handleCancel={handleCancelClick}\n handleClose={(savedCollection) => {\n setFormDirty(false);\n if (savedCollection) {\n setTimeout(() => {\n onSave?.(savedCollection);\n }, 0);\n }\n }}\n setFormDirty={setFormDirty}\n />\n ) : (\n <div className=\"flex-grow flex flex-col items-center justify-center h-full gap-4\">\n <Typography variant=\"label\">\n Select a collection or create a new one\n </Typography>\n <Button\n disabled={props.configController?.readOnly}\n onClick={() => onSave?.()}\n >\n <PlusIcon/>\n Add new collection\n </Button>\n </div>\n )}\n\n <UnsavedChangesDialog\n {...dialogProps}\n handleOk={() => {\n dialogProps.handleOk();\n if (cancelRequested) {\n onCancel?.();\n setCancelRequested(false);\n }\n }}\n handleCancel={() => {\n dialogProps.handleCancel();\n setCancelRequested(false);\n }}\n />\n </AIModifiedPathsProvider>\n </div>\n );\n}\n","\nimport { IconForView } from \"@rebasepro/app\";\nimport React, { useState, useEffect } from \"react\";\nimport {\n Button,\n cls,\n defaultBorderMixin,\n IconButton,\n iconSize,\n PlusIcon,\n ResizablePanels,\n Tooltip,\n Typography\n} from \"@rebasepro/ui\";\n\nimport { CollectionsConfigController } from \"../../types/config_controller\";\nimport { CollectionStudioView } from \"./CollectionStudioView\";\nimport type { CollectionEditorExtensionProps } from \"../../extensibility_types\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\nimport { readStoredString, writeStoredString } from \"@rebasepro/utils\";\n\nexport interface CollectionsStudioViewProps extends CollectionEditorExtensionProps {\n configController: CollectionsConfigController;\n\n /**\n * Collections to show in the sidebar.\n * When provided, overrides the collections from `configController`.\n * Use this to control exactly which collections the editor displays.\n */\n collections?: AdminCollection[];\n\n /**\n * Controlled active collection ID.\n * When provided together with `onActiveCollectionChange`,\n * navigation is fully external — no internal state is used.\n */\n activeCollectionId?: string;\n\n /**\n * Called when the user clicks a collection, \"new\", or navigates.\n * When provided, the component is fully controlled (no internal state).\n * When not provided, the component manages selection via internal state.\n *\n * Pass `\"new\"` to create a new collection. Pass `undefined` to deselect.\n */\n onActiveCollectionChange?: (collectionId: string | undefined) => void;\n}\n\nexport function CollectionsStudioView({\n configController,\n collections: collectionsProp,\n activeCollectionId: controlledActiveId,\n onActiveCollectionChange,\n propertyTypePresets,\n hiddenPropertyTypes,\n renderExtraPropertyFields,\n renderExtraCollectionFields,\n visibleTabs,\n standalone,\n}: CollectionsStudioViewProps) {\n\n // ── Navigation state ────────────────────────────────────────────────\n // If onActiveCollectionChange is provided, the component is controlled.\n // Otherwise, use internal state.\n const [internalActiveId, setInternalActiveId] = useState<string | undefined>(undefined);\n const isControlled = onActiveCollectionChange !== undefined;\n const activeCollectionId = isControlled ? controlledActiveId : internalActiveId;\n\n const setActiveCollectionId = (id: string | undefined) => {\n if (isControlled) {\n onActiveCollectionChange?.(id);\n } else {\n setInternalActiveId(id);\n }\n };\n\n // ── Collections list ────────────────────────────────────────────────\n const collections = collectionsProp ?? configController.collections ?? [];\n\n // ── Sidebar sizing ──────────────────────────────────────────────────\n // Checked, not just parsed: `parseFloat` answers NaN for anything it cannot\n // read, and a NaN pane size lays the sidebar out to nothing — with the bad\n // value still in storage on reload. `SplitListView.getSavedPanelSize` is the\n // same read, done this way.\n const [sidebarSize, setSidebarSize] = useState(() => {\n const saved = readStoredString(\"rebase_collections_editor_sidebar_size\");\n const parsed = saved === null ? NaN : parseFloat(saved);\n return Number.isFinite(parsed) && parsed > 0 && parsed < 100 ? parsed : 25;\n });\n\n useEffect(() => {\n writeStoredString(\"rebase_collections_editor_sidebar_size\", sidebarSize.toString());\n }, [sidebarSize]);\n\n return (\n <div className=\"flex h-full w-full bg-surface-50 dark:bg-surface-800 overflow-hidden text-text-primary dark:text-text-primary-dark\">\n <ResizablePanels\n orientation=\"horizontal\"\n panelSizePercent={sidebarSize}\n onPanelSizeChange={setSidebarSize}\n minPanelSizePx={220}\n firstPanel={\n <div className={cls(\"flex flex-col h-full w-full bg-surface-50 dark:bg-surface-800 border-r\", defaultBorderMixin)}>\n <div className={cls(\"flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"font-semibold text-[11px] uppercase tracking-wider text-surface-400 dark:text-surface-400\">\n Collections\n </Typography>\n <Tooltip title={configController.readOnly ? configController.readOnlyReason || \"Read only\" : \"Add collection\"}>\n <div>\n <IconButton\n size=\"small\"\n disabled={configController.readOnly}\n onClick={() => setActiveCollectionId(\"new\")}\n className={activeCollectionId === \"new\" ? \"text-primary dark:text-primary-dark\" : \"text-text-secondary dark:text-text-secondary-dark\"}\n >\n <PlusIcon size={iconSize.smallest}/>\n </IconButton>\n </div>\n </Tooltip>\n </div>\n\n <div className=\"flex-grow overflow-y-auto w-full no-scrollbar p-2 space-y-0.5\">\n {collections.length === 0 && (\n <div className=\"p-4 text-center\">\n <Typography variant=\"caption\" className=\"text-text-disabled dark:text-text-disabled-dark italic\">\n No collections yet.\n </Typography>\n </div>\n )}\n {collections.map((collection) => {\n const collectionKey = collection.slug;\n const isSelected = activeCollectionId === collectionKey;\n return (\n <div\n key={collectionKey}\n onClick={() => setActiveCollectionId(collectionKey)}\n className={cls(\n \"flex items-center gap-2.5 px-3 h-[30px] cursor-pointer rounded-lg text-[13px] font-medium transition-colors\",\n isSelected\n ? \"bg-primary/8 text-primary dark:bg-primary/10 dark:text-primary-light font-semibold\"\n : \"hover:bg-primary/5 dark:hover:bg-primary/5 text-surface-700 dark:text-surface-300 hover:text-surface-900 dark:hover:text-white\"\n )}\n >\n <IconForView collectionOrView={collection} size={\"smallest\"} className={cls(\n isSelected\n ? \"text-primary dark:text-primary-light\"\n : \"text-surface-500 dark:text-text-secondary-dark\"\n )}/>\n <span className=\"truncate flex-1\">\n {collection.name || collection.slug}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n }\n secondPanel={\n <div className=\"flex-grow flex flex-col min-w-0 h-full w-full\">\n {/* We use key to force unmount when switching collections, preventing stale state */}\n {activeCollectionId ? (\n <CollectionStudioView\n key={activeCollectionId}\n configController={configController}\n collectionId={activeCollectionId}\n onSave={(savedCollection) => {\n // After creating a new collection, switch to it\n if (activeCollectionId === \"new\" && savedCollection?.slug) {\n setActiveCollectionId(savedCollection.slug);\n }\n }}\n onCancel={() => setActiveCollectionId(undefined)}\n propertyTypePresets={propertyTypePresets}\n hiddenPropertyTypes={hiddenPropertyTypes}\n renderExtraPropertyFields={renderExtraPropertyFields}\n renderExtraCollectionFields={renderExtraCollectionFields}\n visibleTabs={visibleTabs}\n standalone={standalone}\n />\n ) : (\n <div className=\"flex flex-col items-center justify-center h-full gap-4\">\n <Typography variant=\"label\">\n Select a collection or create a new one to start editing\n </Typography>\n <Button\n disabled={configController.readOnly}\n onClick={() => setActiveCollectionId(\"new\")}\n >\n <PlusIcon/>\n Add new collection\n </Button>\n </div>\n )}\n </div>\n }\n />\n </div>\n );\n}\n","/**\n * Router-aware wrapper around CollectionsStudioView.\n *\n * This component provides the react-router-based navigation behavior\n * that Rebase Studio expects: the active collection is derived from the\n * URL, and clicking a collection navigates via react-router.\n *\n * External consumers should use `CollectionsStudioView` directly\n * (which has no react-router dependency).\n */\nimport React from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\nimport { useUrlController } from \"../../_cms_internals\";\nimport { CollectionsStudioView, CollectionsStudioViewProps } from \"./CollectionsStudioView\";\n\nexport type RouterCollectionsStudioViewProps = Omit<CollectionsStudioViewProps, \"activeCollectionId\" | \"onActiveCollectionChange\">;\n\nexport function RouterCollectionsStudioView(props: RouterCollectionsStudioViewProps) {\n const navigate = useNavigate();\n const urlController = useUrlController();\n const location = useLocation();\n\n // Determine the active collection from the URL segment after \"schema/\"\n const basePath = urlController.buildAppUrlPath(\"schema\");\n const relativePath = location.pathname.replace(basePath, \"\").replace(/^\\//, \"\");\n const activeCollectionId = relativePath.split(\"/\")[0] || undefined;\n\n return (\n <CollectionsStudioView\n {...props}\n activeCollectionId={activeCollectionId}\n onActiveCollectionChange={(id) => {\n if (id) {\n navigate(urlController.buildAppUrlPath(`schema/${id}`));\n } else {\n navigate(urlController.buildAppUrlPath(\"schema\"));\n }\n }}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { Alert, Button, Chip, CircularProgress, Dialog, DialogActions, DialogContent, DialogTitle, Typography, cls } from "@rebasepro/ui";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/collection_editor/ui/collection_editor/SchemaChangeDialog.tsx
|
|
5
|
+
/**
|
|
6
|
+
* What a schema change would do, before it does it.
|
|
7
|
+
*
|
|
8
|
+
* The dialog exists because a schema change has three possible verdicts and two
|
|
9
|
+
* of them are refusals. Without a preview, the only way to discover that a
|
|
10
|
+
* change is refused is to press a button on a live database and read what comes
|
|
11
|
+
* back — which is a fine way to learn and a poor way to work.
|
|
12
|
+
*
|
|
13
|
+
* ## What it shows, in the order somebody reads it
|
|
14
|
+
*
|
|
15
|
+
* The verdict first, in a sentence, because it decides whether the rest is
|
|
16
|
+
* worth reading. Then the changes, each with what it does and — when it is
|
|
17
|
+
* refused — what to do instead. Then the things that are easy to skip past and
|
|
18
|
+
* expensive to have skipped: constraints the change asks for that the database
|
|
19
|
+
* will not end up enforcing. The SQL and the file list come last, collapsed,
|
|
20
|
+
* for the reader who wants them; they are the evidence, not the summary.
|
|
21
|
+
*
|
|
22
|
+
* ## Why the button says "Commit and apply"
|
|
23
|
+
*
|
|
24
|
+
* Because that is the order, and the order is the feature. The commit lands
|
|
25
|
+
* first, so a failed apply leaves the repository ahead of the database — the
|
|
26
|
+
* ordinary state of every project between an edit and a deploy, which the next
|
|
27
|
+
* boot reconciles. A button labelled "Save" would be describing a different,
|
|
28
|
+
* worse thing.
|
|
29
|
+
*/
|
|
30
|
+
/** What the verdict means, in the words the reader needs rather than the enum's. */
|
|
31
|
+
var VERDICT_COPY = {
|
|
32
|
+
safe: {
|
|
33
|
+
title: "Ready to apply",
|
|
34
|
+
body: "Every change here can be made against the running database.",
|
|
35
|
+
color: "info"
|
|
36
|
+
},
|
|
37
|
+
diverges: {
|
|
38
|
+
title: "This would leave the database out of step",
|
|
39
|
+
body: "The change can be written, but the database will not end up matching it. The details below say which part, and what would make it applicable.",
|
|
40
|
+
color: "warning"
|
|
41
|
+
},
|
|
42
|
+
"needs-migration": {
|
|
43
|
+
title: "This needs a migration",
|
|
44
|
+
body: "Some of this cannot be done to a running database at all — it drops or rewrites something, and that belongs in a migration somebody has read.",
|
|
45
|
+
color: "error"
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var VERDICT_CHIP = {
|
|
49
|
+
safe: {
|
|
50
|
+
label: "safe",
|
|
51
|
+
scheme: "greenLighter"
|
|
52
|
+
},
|
|
53
|
+
diverges: {
|
|
54
|
+
label: "diverges",
|
|
55
|
+
scheme: "orangeLighter"
|
|
56
|
+
},
|
|
57
|
+
"needs-migration": {
|
|
58
|
+
label: "needs migration",
|
|
59
|
+
scheme: "redLighter"
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
var codeBlock = cls("font-mono text-xs leading-relaxed", "bg-surface-100 dark:bg-surface-800 rounded-md p-3 overflow-x-auto whitespace-pre");
|
|
63
|
+
/** A disclosure that starts closed. The evidence, for the reader who wants it. */
|
|
64
|
+
function Details({ summary, count, children }) {
|
|
65
|
+
const [open, setOpen] = useState(false);
|
|
66
|
+
if (count === 0) return null;
|
|
67
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("button", {
|
|
68
|
+
type: "button",
|
|
69
|
+
onClick: () => setOpen((o) => !o),
|
|
70
|
+
className: "flex items-center gap-2 text-sm text-text-secondary dark:text-text-secondary-dark hover:underline",
|
|
71
|
+
children: [
|
|
72
|
+
/* @__PURE__ */ jsx("span", {
|
|
73
|
+
className: cls("transition-transform", open && "rotate-90"),
|
|
74
|
+
children: "›"
|
|
75
|
+
}),
|
|
76
|
+
summary,
|
|
77
|
+
" (",
|
|
78
|
+
count,
|
|
79
|
+
")"
|
|
80
|
+
]
|
|
81
|
+
}), open && /* @__PURE__ */ jsx("div", {
|
|
82
|
+
className: "mt-2",
|
|
83
|
+
children
|
|
84
|
+
})] });
|
|
85
|
+
}
|
|
86
|
+
function WithheldConstraints({ constraints }) {
|
|
87
|
+
if (constraints.length === 0) return null;
|
|
88
|
+
return /* @__PURE__ */ jsxs(Alert, {
|
|
89
|
+
color: "warning",
|
|
90
|
+
children: [/* @__PURE__ */ jsx(Typography, {
|
|
91
|
+
variant: "body2",
|
|
92
|
+
className: "font-medium mb-1",
|
|
93
|
+
children: constraints.length === 1 ? "One constraint will not be enforced" : `${constraints.length} constraints will not be enforced`
|
|
94
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
95
|
+
className: "space-y-2",
|
|
96
|
+
children: constraints.map((constraint) => /* @__PURE__ */ jsxs("li", {
|
|
97
|
+
className: "text-sm",
|
|
98
|
+
children: [
|
|
99
|
+
/* @__PURE__ */ jsx("code", {
|
|
100
|
+
className: "bg-surface-200 dark:bg-surface-700 px-1 rounded",
|
|
101
|
+
children: constraint.target
|
|
102
|
+
}),
|
|
103
|
+
/* @__PURE__ */ jsx("div", {
|
|
104
|
+
className: "mt-1",
|
|
105
|
+
children: constraint.reason
|
|
106
|
+
}),
|
|
107
|
+
/* @__PURE__ */ jsx("div", {
|
|
108
|
+
className: "mt-1 text-text-secondary dark:text-text-secondary-dark",
|
|
109
|
+
children: constraint.remedy
|
|
110
|
+
})
|
|
111
|
+
]
|
|
112
|
+
}, constraint.target))
|
|
113
|
+
})]
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/** The receipt. Shown in place of the plan once the change has been applied. */
|
|
117
|
+
function Applied({ result }) {
|
|
118
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
119
|
+
className: "flex flex-col gap-4",
|
|
120
|
+
children: [
|
|
121
|
+
/* @__PURE__ */ jsx(Alert, {
|
|
122
|
+
color: result.applied ? "success" : "warning",
|
|
123
|
+
children: /* @__PURE__ */ jsx(Typography, {
|
|
124
|
+
variant: "body2",
|
|
125
|
+
children: result.summary
|
|
126
|
+
})
|
|
127
|
+
}),
|
|
128
|
+
!result.applied && result.applyError && /* @__PURE__ */ jsxs(Alert, {
|
|
129
|
+
color: "warning",
|
|
130
|
+
children: [
|
|
131
|
+
/* @__PURE__ */ jsx(Typography, {
|
|
132
|
+
variant: "body2",
|
|
133
|
+
className: "font-medium mb-1",
|
|
134
|
+
children: "The database was not changed"
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ jsx(Typography, {
|
|
137
|
+
variant: "body2",
|
|
138
|
+
children: result.applyError
|
|
139
|
+
}),
|
|
140
|
+
/* @__PURE__ */ jsxs(Typography, {
|
|
141
|
+
variant: "body2",
|
|
142
|
+
className: "mt-2",
|
|
143
|
+
children: [
|
|
144
|
+
"The commit is on ",
|
|
145
|
+
/* @__PURE__ */ jsx("code", { children: result.committed.branch }),
|
|
146
|
+
" either way, so the change will be applied on the next boot."
|
|
147
|
+
]
|
|
148
|
+
})
|
|
149
|
+
]
|
|
150
|
+
}),
|
|
151
|
+
/* @__PURE__ */ jsx(WithheldConstraints, { constraints: result.withheldConstraints ?? [] }),
|
|
152
|
+
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
|
|
153
|
+
variant: "label",
|
|
154
|
+
color: "secondary",
|
|
155
|
+
children: "Committed"
|
|
156
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
157
|
+
className: cls(codeBlock, "mt-1"),
|
|
158
|
+
children: [
|
|
159
|
+
result.committed.sha.slice(0, 9),
|
|
160
|
+
" on ",
|
|
161
|
+
result.committed.branch,
|
|
162
|
+
"\n",
|
|
163
|
+
result.committed.files.map((file) => ` ${file}`).join("\n")
|
|
164
|
+
]
|
|
165
|
+
})] })
|
|
166
|
+
]
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function SchemaChangeDialog({ open, collectionId, plan, planError, result, applying, applyError, onConfirm, onSourceOnly, onClose, applyRefusedBecause }) {
|
|
170
|
+
const verdict = plan?.verdict;
|
|
171
|
+
const copy = verdict ? VERDICT_COPY[verdict] : void 0;
|
|
172
|
+
return /* @__PURE__ */ jsxs(Dialog, {
|
|
173
|
+
open,
|
|
174
|
+
onOpenChange: (value) => {
|
|
175
|
+
if (!value) onClose();
|
|
176
|
+
},
|
|
177
|
+
maxWidth: "3xl",
|
|
178
|
+
children: [
|
|
179
|
+
/* @__PURE__ */ jsxs(DialogTitle, {
|
|
180
|
+
className: "flex items-center gap-2",
|
|
181
|
+
children: [result ? "Schema change applied" : "Review schema change", /* @__PURE__ */ jsx("code", {
|
|
182
|
+
className: "text-sm font-normal text-text-secondary dark:text-text-secondary-dark",
|
|
183
|
+
children: collectionId
|
|
184
|
+
})]
|
|
185
|
+
}),
|
|
186
|
+
/* @__PURE__ */ jsxs(DialogContent, {
|
|
187
|
+
className: "flex flex-col gap-4",
|
|
188
|
+
children: [
|
|
189
|
+
planError && /* @__PURE__ */ jsxs(Alert, {
|
|
190
|
+
color: "error",
|
|
191
|
+
children: [/* @__PURE__ */ jsx(Typography, {
|
|
192
|
+
variant: "body2",
|
|
193
|
+
className: "font-medium mb-1",
|
|
194
|
+
children: "The change could not be planned"
|
|
195
|
+
}), /* @__PURE__ */ jsx(Typography, {
|
|
196
|
+
variant: "body2",
|
|
197
|
+
children: planError
|
|
198
|
+
})]
|
|
199
|
+
}),
|
|
200
|
+
!plan && !planError && !result && /* @__PURE__ */ jsxs("div", {
|
|
201
|
+
className: "flex items-center gap-3 py-6",
|
|
202
|
+
children: [/* @__PURE__ */ jsx(CircularProgress, { size: "small" }), /* @__PURE__ */ jsx(Typography, {
|
|
203
|
+
variant: "body2",
|
|
204
|
+
color: "secondary",
|
|
205
|
+
children: "Working out what this change would do…"
|
|
206
|
+
})]
|
|
207
|
+
}),
|
|
208
|
+
result && /* @__PURE__ */ jsx(Applied, { result }),
|
|
209
|
+
plan && !result && copy && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
210
|
+
/* @__PURE__ */ jsxs(Alert, {
|
|
211
|
+
color: copy.color,
|
|
212
|
+
children: [/* @__PURE__ */ jsx(Typography, {
|
|
213
|
+
variant: "body2",
|
|
214
|
+
className: "font-medium mb-1",
|
|
215
|
+
children: copy.title
|
|
216
|
+
}), /* @__PURE__ */ jsx(Typography, {
|
|
217
|
+
variant: "body2",
|
|
218
|
+
children: copy.body
|
|
219
|
+
})]
|
|
220
|
+
}),
|
|
221
|
+
applyError && /* @__PURE__ */ jsx(Alert, {
|
|
222
|
+
color: "error",
|
|
223
|
+
children: /* @__PURE__ */ jsx(Typography, {
|
|
224
|
+
variant: "body2",
|
|
225
|
+
children: applyError
|
|
226
|
+
})
|
|
227
|
+
}),
|
|
228
|
+
plan.changes.length === 0 && /* @__PURE__ */ jsx(Typography, {
|
|
229
|
+
variant: "body2",
|
|
230
|
+
color: "secondary",
|
|
231
|
+
children: "Nothing about the database changes. The collection source is still rewritten and committed."
|
|
232
|
+
}),
|
|
233
|
+
!plan.applicable && onSourceOnly && /* @__PURE__ */ jsx(Typography, {
|
|
234
|
+
variant: "body2",
|
|
235
|
+
color: "secondary",
|
|
236
|
+
children: "You can still write the change to your collection source and leave the database as it is — the editor’s behaviour before this preview existed. The column stays, holding whatever is in it, and nothing serves it."
|
|
237
|
+
}),
|
|
238
|
+
plan.changes.length > 0 && /* @__PURE__ */ jsx("ul", {
|
|
239
|
+
className: "flex flex-col gap-3",
|
|
240
|
+
children: plan.changes.map((change, index) => /* @__PURE__ */ jsxs("li", {
|
|
241
|
+
className: "flex gap-3",
|
|
242
|
+
children: [/* @__PURE__ */ jsx(Chip, {
|
|
243
|
+
size: "smallest",
|
|
244
|
+
colorScheme: VERDICT_CHIP[change.verdict].scheme,
|
|
245
|
+
className: "shrink-0 mt-0.5",
|
|
246
|
+
children: VERDICT_CHIP[change.verdict].label
|
|
247
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
248
|
+
className: "min-w-0",
|
|
249
|
+
children: [/* @__PURE__ */ jsx(Typography, {
|
|
250
|
+
variant: "body2",
|
|
251
|
+
children: change.detail
|
|
252
|
+
}), change.remedy && /* @__PURE__ */ jsx(Typography, {
|
|
253
|
+
variant: "body2",
|
|
254
|
+
color: "secondary",
|
|
255
|
+
className: "mt-1",
|
|
256
|
+
children: change.remedy
|
|
257
|
+
})]
|
|
258
|
+
})]
|
|
259
|
+
}, `${change.collection}.${change.property ?? ""}.${index}`))
|
|
260
|
+
}),
|
|
261
|
+
/* @__PURE__ */ jsx(WithheldConstraints, { constraints: plan.withheldConstraints ?? [] }),
|
|
262
|
+
applyRefusedBecause && /* @__PURE__ */ jsxs(Alert, {
|
|
263
|
+
color: "info",
|
|
264
|
+
children: [/* @__PURE__ */ jsx(Typography, {
|
|
265
|
+
variant: "body2",
|
|
266
|
+
className: "font-medium mb-1",
|
|
267
|
+
children: "You can preview this change, but not apply it"
|
|
268
|
+
}), /* @__PURE__ */ jsx(Typography, {
|
|
269
|
+
variant: "body2",
|
|
270
|
+
children: applyRefusedBecause
|
|
271
|
+
})]
|
|
272
|
+
}),
|
|
273
|
+
/* @__PURE__ */ jsx(Details, {
|
|
274
|
+
summary: "SQL that will run",
|
|
275
|
+
count: plan.statements.length,
|
|
276
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
277
|
+
className: codeBlock,
|
|
278
|
+
children: plan.statements.join("\n")
|
|
279
|
+
})
|
|
280
|
+
}),
|
|
281
|
+
/* @__PURE__ */ jsx(Details, {
|
|
282
|
+
summary: "Files that will be committed",
|
|
283
|
+
count: plan.files.length,
|
|
284
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
285
|
+
className: codeBlock,
|
|
286
|
+
children: plan.files.join("\n")
|
|
287
|
+
})
|
|
288
|
+
}),
|
|
289
|
+
/* @__PURE__ */ jsx(Details, {
|
|
290
|
+
summary: "Commit message",
|
|
291
|
+
count: plan.message ? 1 : 0,
|
|
292
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
293
|
+
className: codeBlock,
|
|
294
|
+
children: plan.message
|
|
295
|
+
})
|
|
296
|
+
})
|
|
297
|
+
] })
|
|
298
|
+
]
|
|
299
|
+
}),
|
|
300
|
+
/* @__PURE__ */ jsxs(DialogActions, { children: [
|
|
301
|
+
/* @__PURE__ */ jsx(Button, {
|
|
302
|
+
variant: "text",
|
|
303
|
+
onClick: onClose,
|
|
304
|
+
disabled: applying,
|
|
305
|
+
children: result ? "Close" : "Cancel"
|
|
306
|
+
}),
|
|
307
|
+
!result && plan && !plan.applicable && onSourceOnly && /* @__PURE__ */ jsx(Button, {
|
|
308
|
+
variant: "outlined",
|
|
309
|
+
onClick: onSourceOnly,
|
|
310
|
+
disabled: applying,
|
|
311
|
+
children: "Edit source only"
|
|
312
|
+
}),
|
|
313
|
+
!result && /* @__PURE__ */ jsx(Button, {
|
|
314
|
+
variant: "filled",
|
|
315
|
+
color: "primary",
|
|
316
|
+
onClick: onConfirm,
|
|
317
|
+
disabled: !plan?.applicable || applying || Boolean(applyRefusedBecause),
|
|
318
|
+
children: applying ? "Applying…" : "Commit and apply"
|
|
319
|
+
})
|
|
320
|
+
] })
|
|
321
|
+
]
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
//#endregion
|
|
325
|
+
export { SchemaChangeDialog };
|
|
326
|
+
|
|
327
|
+
//# sourceMappingURL=SchemaChangeDialog-WKIbzS6P.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaChangeDialog-WKIbzS6P.js","names":[],"sources":["../src/collection_editor/ui/collection_editor/SchemaChangeDialog.tsx"],"sourcesContent":["/**\n * What a schema change would do, before it does it.\n *\n * The dialog exists because a schema change has three possible verdicts and two\n * of them are refusals. Without a preview, the only way to discover that a\n * change is refused is to press a button on a live database and read what comes\n * back — which is a fine way to learn and a poor way to work.\n *\n * ## What it shows, in the order somebody reads it\n *\n * The verdict first, in a sentence, because it decides whether the rest is\n * worth reading. Then the changes, each with what it does and — when it is\n * refused — what to do instead. Then the things that are easy to skip past and\n * expensive to have skipped: constraints the change asks for that the database\n * will not end up enforcing. The SQL and the file list come last, collapsed,\n * for the reader who wants them; they are the evidence, not the summary.\n *\n * ## Why the button says \"Commit and apply\"\n *\n * Because that is the order, and the order is the feature. The commit lands\n * first, so a failed apply leaves the repository ahead of the database — the\n * ordinary state of every project between an edit and a deploy, which the next\n * boot reconciles. A button labelled \"Save\" would be describing a different,\n * worse thing.\n */\nimport React, { useState } from \"react\";\nimport {\n Alert,\n Button,\n Chip,\n CircularProgress,\n cls,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Typography\n} from \"@rebasepro/ui\";\n\nimport type { LiveSchemaPlan, LiveSchemaResult, WithheldConstraint } from \"../../liveSchemaClient\";\n\nexport interface SchemaChangeDialogProps {\n open: boolean;\n /** The collection being changed, for the title. */\n collectionId: string;\n /** `undefined` while the plan is still being fetched. */\n plan?: LiveSchemaPlan;\n /** Set when planning itself failed — a network error, a refusal, a 500. */\n planError?: string;\n /** Set once the change has been applied, which turns this into a receipt. */\n result?: LiveSchemaResult;\n applying: boolean;\n /** Set when the apply threw rather than returning a result. */\n applyError?: string;\n onConfirm: () => void;\n /**\n * Write the collection source and leave the database alone.\n *\n * Offered only when the change is refused, and it is what keeps the editor\n * usable while it is. Removing a property is the ordinary case: the ensure\n * path has no `DROP COLUMN`, so a removal can never be applied — and\n * refusing the whole save over it would mean a dev could no longer delete a\n * field from a collection they are still designing.\n *\n * This is exactly what the editor did before live editing existed, so it is\n * not a new hazard; the difference is that it now says what it leaves\n * behind instead of reporting success.\n */\n onSourceOnly?: () => void;\n onClose: () => void;\n /**\n * Why this caller may preview but not apply, when that is the case.\n *\n * A person signed in with an API key, most often. Shown next to a disabled\n * button so the refusal arrives while they are deciding rather than after\n * they have decided.\n */\n applyRefusedBecause?: string;\n}\n\ntype Verdict = LiveSchemaPlan[\"verdict\"];\n\n/** What the verdict means, in the words the reader needs rather than the enum's. */\nconst VERDICT_COPY: Record<Verdict, { title: string; body: string; color: \"info\" | \"warning\" | \"error\" }> = {\n safe: {\n title: \"Ready to apply\",\n body: \"Every change here can be made against the running database.\",\n color: \"info\"\n },\n diverges: {\n title: \"This would leave the database out of step\",\n body: \"The change can be written, but the database will not end up matching it. \" +\n \"The details below say which part, and what would make it applicable.\",\n color: \"warning\"\n },\n \"needs-migration\": {\n title: \"This needs a migration\",\n body: \"Some of this cannot be done to a running database at all — it drops or rewrites \" +\n \"something, and that belongs in a migration somebody has read.\",\n color: \"error\"\n }\n};\n\nconst VERDICT_CHIP: Record<Verdict, { label: string; scheme: \"greenLighter\" | \"orangeLighter\" | \"redLighter\" }> = {\n safe: { label: \"safe\", scheme: \"greenLighter\" },\n diverges: { label: \"diverges\", scheme: \"orangeLighter\" },\n \"needs-migration\": { label: \"needs migration\", scheme: \"redLighter\" }\n};\n\nconst monospace = \"font-mono text-xs leading-relaxed\";\nconst codeBlock = cls(\n monospace,\n \"bg-surface-100 dark:bg-surface-800 rounded-md p-3 overflow-x-auto whitespace-pre\"\n);\n\n/** A disclosure that starts closed. The evidence, for the reader who wants it. */\nfunction Details({ summary, count, children }: {\n summary: string;\n count: number;\n children: React.ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n if (count === 0) return null;\n return (\n <div>\n <button\n type=\"button\"\n onClick={() => setOpen(o => !o)}\n className=\"flex items-center gap-2 text-sm text-text-secondary dark:text-text-secondary-dark hover:underline\"\n >\n <span className={cls(\"transition-transform\", open && \"rotate-90\")}>›</span>\n {summary} ({count})\n </button>\n {open && <div className=\"mt-2\">{children}</div>}\n </div>\n );\n}\n\nfunction WithheldConstraints({ constraints }: { constraints: WithheldConstraint[] }) {\n if (constraints.length === 0) return null;\n return (\n <Alert color=\"warning\">\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n {constraints.length === 1\n ? \"One constraint will not be enforced\"\n : `${constraints.length} constraints will not be enforced`}\n </Typography>\n <ul className=\"space-y-2\">\n {constraints.map(constraint => (\n <li key={constraint.target} className=\"text-sm\">\n <code className=\"bg-surface-200 dark:bg-surface-700 px-1 rounded\">\n {constraint.target}\n </code>\n <div className=\"mt-1\">{constraint.reason}</div>\n <div className=\"mt-1 text-text-secondary dark:text-text-secondary-dark\">\n {constraint.remedy}\n </div>\n </li>\n ))}\n </ul>\n </Alert>\n );\n}\n\n/** The receipt. Shown in place of the plan once the change has been applied. */\nfunction Applied({ result }: { result: LiveSchemaResult }) {\n return (\n <div className=\"flex flex-col gap-4\">\n <Alert color={result.applied ? \"success\" : \"warning\"}>\n <Typography variant=\"body2\">{result.summary}</Typography>\n </Alert>\n\n {!result.applied && result.applyError && (\n // Deliberately not an error state. The commit landed, which is\n // the durable half; the database is now behind the repository,\n // which is where every project sits between an edit and a\n // deploy, and boot reconciles it.\n <Alert color=\"warning\">\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n The database was not changed\n </Typography>\n <Typography variant=\"body2\">{result.applyError}</Typography>\n <Typography variant=\"body2\" className=\"mt-2\">\n The commit is on <code>{result.committed.branch}</code> either way, so the\n change will be applied on the next boot.\n </Typography>\n </Alert>\n )}\n\n <WithheldConstraints constraints={result.withheldConstraints ?? []}/>\n\n <div>\n <Typography variant=\"label\" color=\"secondary\">Committed</Typography>\n <div className={cls(codeBlock, \"mt-1\")}>\n {result.committed.sha.slice(0, 9)} on {result.committed.branch}\n {\"\\n\"}\n {result.committed.files.map(file => ` ${file}`).join(\"\\n\")}\n </div>\n </div>\n </div>\n );\n}\n\nexport function SchemaChangeDialog({\n open,\n collectionId,\n plan,\n planError,\n result,\n applying,\n applyError,\n onConfirm,\n onSourceOnly,\n onClose,\n applyRefusedBecause\n}: SchemaChangeDialogProps) {\n\n const verdict = plan?.verdict;\n const copy = verdict ? VERDICT_COPY[verdict] : undefined;\n\n return (\n <Dialog open={open} onOpenChange={value => { if (!value) onClose(); }} maxWidth=\"3xl\">\n <DialogTitle className=\"flex items-center gap-2\">\n {result ? \"Schema change applied\" : \"Review schema change\"}\n <code className=\"text-sm font-normal text-text-secondary dark:text-text-secondary-dark\">\n {collectionId}\n </code>\n </DialogTitle>\n\n <DialogContent className=\"flex flex-col gap-4\">\n {planError && (\n <Alert color=\"error\">\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n The change could not be planned\n </Typography>\n <Typography variant=\"body2\">{planError}</Typography>\n </Alert>\n )}\n\n {!plan && !planError && !result && (\n <div className=\"flex items-center gap-3 py-6\">\n <CircularProgress size=\"small\"/>\n <Typography variant=\"body2\" color=\"secondary\">\n Working out what this change would do…\n </Typography>\n </div>\n )}\n\n {result && <Applied result={result}/>}\n\n {plan && !result && copy && (\n <>\n <Alert color={copy.color}>\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n {copy.title}\n </Typography>\n <Typography variant=\"body2\">{copy.body}</Typography>\n </Alert>\n\n {applyError && (\n <Alert color=\"error\">\n <Typography variant=\"body2\">{applyError}</Typography>\n </Alert>\n )}\n\n {plan.changes.length === 0 && (\n <Typography variant=\"body2\" color=\"secondary\">\n Nothing about the database changes. The collection source is still\n rewritten and committed.\n </Typography>\n )}\n\n {!plan.applicable && onSourceOnly && (\n <Typography variant=\"body2\" color=\"secondary\">\n You can still write the change to your collection source and leave\n the database as it is — the editor’s behaviour before this preview\n existed. The column stays, holding whatever is in it, and nothing\n serves it.\n </Typography>\n )}\n\n {plan.changes.length > 0 && (\n <ul className=\"flex flex-col gap-3\">\n {plan.changes.map((change, index) => (\n <li\n key={`${change.collection}.${change.property ?? \"\"}.${index}`}\n className=\"flex gap-3\"\n >\n <Chip\n size=\"smallest\"\n colorScheme={VERDICT_CHIP[change.verdict].scheme}\n className=\"shrink-0 mt-0.5\"\n >\n {VERDICT_CHIP[change.verdict].label}\n </Chip>\n <div className=\"min-w-0\">\n <Typography variant=\"body2\">{change.detail}</Typography>\n {change.remedy && (\n <Typography\n variant=\"body2\"\n color=\"secondary\"\n className=\"mt-1\"\n >\n {change.remedy}\n </Typography>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n\n <WithheldConstraints constraints={plan.withheldConstraints ?? []}/>\n\n {applyRefusedBecause && (\n <Alert color=\"info\">\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n You can preview this change, but not apply it\n </Typography>\n <Typography variant=\"body2\">{applyRefusedBecause}</Typography>\n </Alert>\n )}\n\n <Details summary=\"SQL that will run\" count={plan.statements.length}>\n <div className={codeBlock}>{plan.statements.join(\"\\n\")}</div>\n </Details>\n\n <Details summary=\"Files that will be committed\" count={plan.files.length}>\n <div className={codeBlock}>{plan.files.join(\"\\n\")}</div>\n </Details>\n\n <Details summary=\"Commit message\" count={plan.message ? 1 : 0}>\n <div className={codeBlock}>{plan.message}</div>\n </Details>\n </>\n )}\n </DialogContent>\n\n <DialogActions>\n <Button variant=\"text\" onClick={onClose} disabled={applying}>\n {result ? \"Close\" : \"Cancel\"}\n </Button>\n {!result && plan && !plan.applicable && onSourceOnly && (\n <Button variant=\"outlined\" onClick={onSourceOnly} disabled={applying}>\n Edit source only\n </Button>\n )}\n {!result && (\n <Button\n variant=\"filled\"\n color=\"primary\"\n onClick={onConfirm}\n // `applicable` is the server's word, not a\n // re-derivation from the verdicts on screen:\n // `applySchemaChange` re-checks it before it writes\n // anything, so a button that disagreed would only\n // produce the same refusal one click later. The same\n // goes for the permission — `/apply` checks it too, and\n // this only saves somebody the round trip.\n disabled={!plan?.applicable || applying || Boolean(applyRefusedBecause)}\n >\n {applying ? \"Applying…\" : \"Commit and apply\"}\n </Button>\n )}\n </DialogActions>\n </Dialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { User } from "@rebasepro/types";
|
|
3
|
-
import { CollectionsConfigController } from "./types/config_controller";
|
|
4
|
-
import { CollectionEditorController } from "./types/collection_editor_controller";
|
|
5
|
-
import { CollectionInference } from "./types/collection_inference";
|
|
6
|
-
import { CollectionGenerationCallback } from "./api/generateCollectionApi";
|
|
3
|
+
import { CollectionsConfigController } from "./types/config_controller.js";
|
|
4
|
+
import { CollectionEditorController } from "./types/collection_editor_controller.js";
|
|
5
|
+
import { CollectionInference } from "./types/collection_inference.js";
|
|
6
|
+
import { CollectionGenerationCallback } from "./api/generateCollectionApi.js";
|
|
7
7
|
export declare const ConfigControllerContext: React.Context<CollectionsConfigController>;
|
|
8
8
|
export declare const CollectionEditorContext: React.Context<CollectionEditorController>;
|
|
9
9
|
export interface ConfigControllerProviderProps {
|
|
@@ -3,27 +3,27 @@
|
|
|
3
3
|
* This avoids circular imports by pointing directly at source files
|
|
4
4
|
* rather than going through the admin barrel (index.ts).
|
|
5
5
|
*/
|
|
6
|
-
export { useCollectionRegistryController } from "../hooks/navigation/contexts/CollectionRegistryContext";
|
|
7
|
-
export { useNavigationStateController } from "../hooks/navigation/contexts/NavigationStateContext";
|
|
8
|
-
export { useUrlController } from "../hooks/navigation/contexts/UrlContext";
|
|
9
|
-
export { useSidePanel } from "../hooks/useSidePanel";
|
|
10
|
-
export { useBreadcrumbsController } from "../hooks/useBreadcrumbsController";
|
|
11
|
-
export { FieldCaption } from "../components/FieldCaption";
|
|
12
|
-
export { SearchIconsView } from "../components/SearchIconsView";
|
|
13
|
-
export { PropertyConfigBadge } from "../components/PropertyConfigBadge";
|
|
14
|
-
export { CollectionTableBinding } from "../components/CollectionTableBinding";
|
|
6
|
+
export { useCollectionRegistryController } from "../hooks/navigation/contexts/CollectionRegistryContext.js";
|
|
7
|
+
export { useNavigationStateController } from "../hooks/navigation/contexts/NavigationStateContext.js";
|
|
8
|
+
export { useUrlController } from "../hooks/navigation/contexts/UrlContext.js";
|
|
9
|
+
export { useSidePanel } from "../hooks/useSidePanel.js";
|
|
10
|
+
export { useBreadcrumbsController } from "../hooks/useBreadcrumbsController.js";
|
|
11
|
+
export { FieldCaption } from "../components/FieldCaption.js";
|
|
12
|
+
export { SearchIconsView } from "../components/SearchIconsView.js";
|
|
13
|
+
export { PropertyConfigBadge } from "../components/PropertyConfigBadge.js";
|
|
14
|
+
export { CollectionTableBinding } from "../components/CollectionTableBinding/index.js";
|
|
15
15
|
export { VirtualTableInput } from "@rebasepro/ui";
|
|
16
|
-
export { ArrayContainer } from "../components/ArrayContainer";
|
|
17
|
-
export type { ArrayEntryParams } from "../components/ArrayContainer";
|
|
18
|
-
export { useSelectionController } from "../components/CollectionViewBinding/useSelectionController";
|
|
19
|
-
export { ImportFileUpload } from "../data_import/components/ImportFileUpload";
|
|
20
|
-
export { ImportSaveInProgress } from "../data_import/components/ImportSaveInProgress";
|
|
21
|
-
export { useImportConfig } from "../data_import/hooks/useImportConfig";
|
|
22
|
-
export { getInferenceType } from "../data_import/utils/get_import_inference_type";
|
|
23
|
-
export { convertDataToEntity } from "../data_import/utils/data";
|
|
24
|
-
export type { ImportConfig } from "../data_import/types";
|
|
25
|
-
export { DataNewPropertiesMapping } from "../data_import/components/DataNewPropertiesMapping";
|
|
26
|
-
export { ImportNewPropertyFieldPreview } from "../data_import/components/ImportNewPropertyFieldPreview";
|
|
27
|
-
export { getFieldConfig, getFieldId, getDefaultFieldConfig, getDefaultFieldId, DEFAULT_FIELD_CONFIGS } from "../components/field_configs";
|
|
28
|
-
export { getPropertyInPath, getResolvedPropertyInPath, getDefaultPropertiesOrder, getPropertiesWithPropertiesOrder } from "../util/property_utils";
|
|
29
|
-
export { resolveEntityAction, resolveEntityView } from "../util/resolutions";
|
|
16
|
+
export { ArrayContainer } from "../components/ArrayContainer.js";
|
|
17
|
+
export type { ArrayEntryParams } from "../components/ArrayContainer.js";
|
|
18
|
+
export { useSelectionController } from "../components/CollectionViewBinding/useSelectionController.js";
|
|
19
|
+
export { ImportFileUpload } from "../data_import/components/ImportFileUpload.js";
|
|
20
|
+
export { ImportSaveInProgress } from "../data_import/components/ImportSaveInProgress.js";
|
|
21
|
+
export { useImportConfig } from "../data_import/hooks/useImportConfig.js";
|
|
22
|
+
export { getInferenceType } from "../data_import/utils/get_import_inference_type.js";
|
|
23
|
+
export { convertDataToEntity } from "../data_import/utils/data.js";
|
|
24
|
+
export type { ImportConfig } from "../data_import/types/index.js";
|
|
25
|
+
export { DataNewPropertiesMapping } from "../data_import/components/DataNewPropertiesMapping.js";
|
|
26
|
+
export { ImportNewPropertyFieldPreview } from "../data_import/components/ImportNewPropertyFieldPreview.js";
|
|
27
|
+
export { getFieldConfig, getFieldId, getDefaultFieldConfig, getDefaultFieldId, DEFAULT_FIELD_CONFIGS } from "../components/field_configs.js";
|
|
28
|
+
export { getPropertyInPath, getResolvedPropertyInPath, getDefaultPropertiesOrder, getPropertiesWithPropertiesOrder } from "../util/property_utils.js";
|
|
29
|
+
export { resolveEntityAction, resolveEntityView } from "../util/resolutions.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./generateCollectionApi";
|
|
1
|
+
export * from "./generateCollectionApi.js";
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* @module
|
|
12
12
|
*/
|
|
13
13
|
import type React from "react";
|
|
14
|
-
import type { SerializableProperty, SerializableCollectionConfig } from "./serializable_types";
|
|
14
|
+
import type { SerializableProperty, SerializableCollectionConfig } from "./serializable_types.js";
|
|
15
15
|
/**
|
|
16
16
|
* The base property data types supported by Rebase.
|
|
17
17
|
* Derived from the `type` discriminant on `SerializableProperty`.
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
export { useCollectionEditorController } from "./useCollectionEditorController";
|
|
2
|
-
export { useCollectionsConfigController } from "./useCollectionsConfigController";
|
|
3
|
-
export { useLocalCollectionsConfigController } from "./useLocalCollectionsConfigController";
|
|
4
|
-
export { useJsonCollectionsConfigController, type UseJsonCollectionsConfigControllerOptions, } from "./useJsonCollectionsConfigController";
|
|
5
|
-
export { toSerializableCollectionConfig, toSerializableProperty, toSerializableProperties, fromSerializableCollectionConfig, fromSerializableCollectionConfigs, fromSerializableProperty, fromSerializableProperties, } from "./serializable_utils";
|
|
6
|
-
export type { SerializableCollectionConfig, SerializableProperty, SerializableProperties, SerializableBaseProperty, SerializableStringProperty, SerializableNumberProperty, SerializableBooleanProperty, SerializableDateProperty, SerializableGeopointProperty, SerializableReferenceProperty, SerializableRelationProperty, SerializableArrayProperty, SerializableMapProperty, SerializableVectorProperty, SerializableBinaryProperty, SerializableStorageConfig, SerializableStringValidation, SerializableDateValidation, JsonCollectionStore, } from "./serializable_types";
|
|
7
|
-
export type { PropertyTypePreset, PropertyType, CollectionEditorTab, CollectionEditorExtensionProps, ExtraPropertyFieldsParams, ExtraCollectionFieldsParams, } from "./extensibility_types";
|
|
8
|
-
export { validateCollectionJson, type CollectionValidationError, type CollectionValidationResult } from "./validateCollectionJson";
|
|
9
|
-
export type { CollectionsConfigController, DeleteCollectionParams, SaveCollectionParams, UpdateCollectionParams, CollectionsSetupInfo, UpdatePropertiesOrderParams, UpdateKanbanColumnsOrderParams } from "./types/config_controller";
|
|
10
|
-
export type { CollectionEditorController } from "./types/collection_editor_controller";
|
|
11
|
-
export type { CollectionInference } from "./types/collection_inference";
|
|
12
|
-
export { buildCollectionGenerationCallback, CollectionGenerationApiError, DEFAULT_COLLECTION_GENERATION_ENDPOINT } from "./api/generateCollectionApi";
|
|
13
|
-
export type { CollectionGenerationCallback, GenerateCollectionRequest, GenerateCollectionResult, CollectionOperation, CollectionOperationType, BuildCollectionGenerationCallbackProps } from "./api/generateCollectionApi";
|
|
14
|
-
export { MissingReferenceWidget } from "./ui/MissingReferenceWidget";
|
|
15
|
-
export * from "./ui/collection_editor/util";
|
|
16
|
-
export type { CollectionEditorDialogProps } from "./ui/collection_editor/CollectionEditorDialog";
|
|
17
|
-
export type { CollectionStudioViewProps } from "./ui/collection_editor/CollectionStudioView";
|
|
18
|
-
export type { CollectionsStudioViewProps } from "./ui/collection_editor/CollectionsStudioView";
|
|
19
|
-
export type { RouterCollectionStudioViewProps } from "./ui/collection_editor/RouterCollectionStudioView";
|
|
20
|
-
export type { RouterCollectionsStudioViewProps } from "./ui/collection_editor/RouterCollectionsStudioView";
|
|
21
|
-
export type { PropertyFormProps, OnPropertyChangedParams } from "./ui/collection_editor/PropertyEditView";
|
|
1
|
+
export { useCollectionEditorController } from "./useCollectionEditorController.js";
|
|
2
|
+
export { useCollectionsConfigController } from "./useCollectionsConfigController.js";
|
|
3
|
+
export { useLocalCollectionsConfigController } from "./useLocalCollectionsConfigController.js";
|
|
4
|
+
export { useJsonCollectionsConfigController, type UseJsonCollectionsConfigControllerOptions, } from "./useJsonCollectionsConfigController.js";
|
|
5
|
+
export { toSerializableCollectionConfig, toSerializableProperty, toSerializableProperties, fromSerializableCollectionConfig, fromSerializableCollectionConfigs, fromSerializableProperty, fromSerializableProperties, } from "./serializable_utils.js";
|
|
6
|
+
export type { SerializableCollectionConfig, SerializableProperty, SerializableProperties, SerializableBaseProperty, SerializableStringProperty, SerializableNumberProperty, SerializableBooleanProperty, SerializableDateProperty, SerializableGeopointProperty, SerializableReferenceProperty, SerializableRelationProperty, SerializableArrayProperty, SerializableMapProperty, SerializableVectorProperty, SerializableBinaryProperty, SerializableStorageConfig, SerializableStringValidation, SerializableDateValidation, JsonCollectionStore, } from "./serializable_types.js";
|
|
7
|
+
export type { PropertyTypePreset, PropertyType, CollectionEditorTab, CollectionEditorExtensionProps, ExtraPropertyFieldsParams, ExtraCollectionFieldsParams, } from "./extensibility_types.js";
|
|
8
|
+
export { validateCollectionJson, type CollectionValidationError, type CollectionValidationResult } from "./validateCollectionJson.js";
|
|
9
|
+
export type { CollectionsConfigController, DeleteCollectionParams, SaveCollectionParams, UpdateCollectionParams, CollectionsSetupInfo, UpdatePropertiesOrderParams, UpdateKanbanColumnsOrderParams } from "./types/config_controller.js";
|
|
10
|
+
export type { CollectionEditorController } from "./types/collection_editor_controller.js";
|
|
11
|
+
export type { CollectionInference } from "./types/collection_inference.js";
|
|
12
|
+
export { buildCollectionGenerationCallback, CollectionGenerationApiError, DEFAULT_COLLECTION_GENERATION_ENDPOINT } from "./api/generateCollectionApi.js";
|
|
13
|
+
export type { CollectionGenerationCallback, GenerateCollectionRequest, GenerateCollectionResult, CollectionOperation, CollectionOperationType, BuildCollectionGenerationCallbackProps } from "./api/generateCollectionApi.js";
|
|
14
|
+
export { MissingReferenceWidget } from "./ui/MissingReferenceWidget.js";
|
|
15
|
+
export * from "./ui/collection_editor/util.js";
|
|
16
|
+
export type { CollectionEditorDialogProps } from "./ui/collection_editor/CollectionEditorDialog.js";
|
|
17
|
+
export type { CollectionStudioViewProps } from "./ui/collection_editor/CollectionStudioView.js";
|
|
18
|
+
export type { CollectionsStudioViewProps } from "./ui/collection_editor/CollectionsStudioView.js";
|
|
19
|
+
export type { RouterCollectionStudioViewProps } from "./ui/collection_editor/RouterCollectionStudioView.js";
|
|
20
|
+
export type { RouterCollectionsStudioViewProps } from "./ui/collection_editor/RouterCollectionsStudioView.js";
|
|
21
|
+
export type { PropertyFormProps, OnPropertyChangedParams } from "./ui/collection_editor/PropertyEditView.js";
|