@nocobase/flow-engine 2.0.0-alpha.2 → 2.0.0-alpha.20
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/lib/BlockScopedFlowEngine.d.ts +23 -0
- package/lib/BlockScopedFlowEngine.js +90 -0
- package/lib/FlowContextProvider.d.ts +2 -2
- package/lib/FlowContextProvider.js +3 -3
- package/lib/FlowDefinition.d.ts +2 -2
- package/lib/JSRunner.js +3 -0
- package/lib/ViewScopedFlowEngine.d.ts +1 -1
- package/lib/components/FieldModelRenderer.js +10 -4
- package/lib/components/FieldSkeleton.d.ts +10 -0
- package/lib/components/FieldSkeleton.js +64 -0
- package/lib/components/FlowContextSelector.js +7 -2
- package/lib/components/FlowModelRenderer.d.ts +2 -5
- package/lib/components/FlowModelRenderer.js +16 -47
- package/lib/components/FormItem.js +5 -1
- package/lib/{runjs-context/snippets/global/requireAsync.snippet.d.ts → components/dnd/findModelUidPosition.d.ts} +4 -7
- package/lib/{runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js → components/dnd/findModelUidPosition.js} +23 -19
- package/lib/components/dnd/gridDragPlanner.d.ts +130 -0
- package/lib/components/dnd/gridDragPlanner.js +497 -0
- package/lib/components/dnd/index.d.ts +2 -2
- package/lib/components/dnd/index.js +5 -5
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +7 -1
- package/lib/components/variables/VariableInput.js +16 -2
- package/lib/components/variables/VariableTag.js +43 -2
- package/lib/components/variables/types.d.ts +2 -0
- package/lib/data-source/index.d.ts +12 -4
- package/lib/data-source/index.js +18 -12
- package/lib/data-source/sortCollectionsByInherits.d.ts +10 -0
- package/lib/data-source/sortCollectionsByInherits.js +71 -0
- package/lib/executor/FlowExecutor.d.ts +4 -5
- package/lib/executor/FlowExecutor.js +122 -94
- package/lib/flowContext.d.ts +33 -5
- package/lib/flowContext.js +145 -74
- package/lib/flowEngine.d.ts +8 -1
- package/lib/flowEngine.js +12 -2
- package/lib/flowSettings.d.ts +2 -1
- package/lib/flowSettings.js +7 -3
- package/lib/hooks/useApplyAutoFlows.js +2 -1
- package/lib/index.d.ts +6 -1
- package/lib/index.js +29 -3
- package/lib/models/CollectionFieldModel.d.ts +2 -0
- package/lib/models/CollectionFieldModel.js +43 -3
- package/lib/models/flowModel.d.ts +28 -29
- package/lib/models/flowModel.js +110 -88
- package/lib/models/forkFlowModel.d.ts +2 -2
- package/lib/models/forkFlowModel.js +29 -6
- package/lib/provider.d.ts +3 -1
- package/lib/provider.js +7 -5
- package/lib/resources/multiRecordResource.js +2 -0
- package/lib/resources/singleRecordResource.js +1 -0
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +27 -20
- package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
- package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
- package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
- package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
- package/lib/runjs-context/contexts/JSItemRunJSContext.js +24 -20
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
- package/lib/runjs-context/contexts/base.d.ts +9 -0
- package/lib/runjs-context/contexts/base.js +169 -0
- package/lib/runjs-context/helpers.d.ts +5 -2
- package/lib/runjs-context/helpers.js +36 -27
- package/lib/runjs-context/registry.d.ts +7 -4
- package/lib/runjs-context/registry.js +10 -42
- package/lib/runjs-context/setup.d.ts +9 -0
- package/lib/runjs-context/setup.js +82 -0
- package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
- package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
- package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
- package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
- package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
- package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
- package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
- package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
- package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
- package/lib/runjs-context/snippets/index.d.ts +14 -3
- package/lib/runjs-context/snippets/index.js +160 -40
- package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
- package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
- package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
- package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +12 -6
- package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
- package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +72 -0
- package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +12 -11
- package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +100 -0
- package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +85 -0
- package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
- package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
- package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
- package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
- package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
- package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
- package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
- package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
- package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
- package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
- package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
- package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
- package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
- package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
- package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
- package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
- package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
- package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
- package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
- package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
- package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
- package/lib/runjs-context/snippets/types.d.ts +9 -1
- package/lib/types.d.ts +15 -3
- package/lib/types.js +4 -3
- package/lib/utils/buildSettingsViewInputArgs.d.ts +19 -0
- package/lib/utils/buildSettingsViewInputArgs.js +75 -0
- package/lib/utils/index.d.ts +3 -2
- package/lib/utils/index.js +5 -2
- package/lib/utils/params-resolvers.js +2 -2
- package/lib/utils/safeGlobals.d.ts +5 -3
- package/lib/utils/safeGlobals.js +40 -0
- package/lib/utils/serverContextParams.d.ts +1 -0
- package/lib/utils/variablesParams.d.ts +9 -5
- package/lib/utils/variablesParams.js +47 -36
- package/lib/views/PageComponent.js +2 -1
- package/lib/views/createViewMeta.d.ts +29 -1
- package/lib/views/createViewMeta.js +321 -72
- package/lib/views/index.d.ts +1 -0
- package/lib/views/index.js +3 -0
- package/lib/views/useDialog.d.ts +8 -8
- package/lib/views/useDialog.js +8 -7
- package/lib/views/useDrawer.d.ts +8 -8
- package/lib/views/useDrawer.js +40 -26
- package/lib/views/usePage.d.ts +8 -8
- package/lib/views/usePage.js +8 -7
- package/package.json +4 -3
- package/src/BlockScopedFlowEngine.ts +86 -0
- package/src/FlowContextProvider.tsx +4 -2
- package/src/JSRunner.ts +3 -0
- package/src/ViewScopedFlowEngine.ts +1 -1
- package/src/__tests__/JSRunner.test.ts +62 -53
- package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
- package/src/__tests__/flow-engine.test.ts +3 -0
- package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
- package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
- package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
- package/src/__tests__/globalFlowRegistry.test.ts +1 -1
- package/src/__tests__/runjsContext.test.ts +216 -35
- package/src/__tests__/runjsContextImplementations.test.ts +217 -0
- package/src/__tests__/runjsContextRuntime.test.ts +269 -0
- package/src/__tests__/runjsEdgeCases.test.ts +281 -0
- package/src/__tests__/runjsLocales.test.ts +36 -0
- package/src/__tests__/runjsRuntimeFeatures.test.ts +449 -0
- package/src/__tests__/runjsSnippets.test.ts +140 -0
- package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
- package/src/components/DynamicFlowsEditor.tsx +3 -4
- package/src/components/FieldModelRenderer.tsx +16 -5
- package/src/components/FieldSkeleton.tsx +27 -0
- package/src/components/FlowContextSelector.tsx +6 -2
- package/src/components/FlowModelRenderer.tsx +30 -78
- package/src/components/FormItem.tsx +8 -1
- package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +5 -5
- package/src/components/__tests__/gridDragPlanner.test.ts +494 -0
- package/src/components/dnd/README.md +149 -0
- package/src/components/dnd/findModelUidPosition.ts +26 -0
- package/src/components/dnd/gridDragPlanner.ts +659 -0
- package/src/components/dnd/index.tsx +3 -3
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +14 -1
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +1 -0
- package/src/components/variables/VariableInput.tsx +22 -2
- package/src/components/variables/VariableTag.tsx +54 -2
- package/src/components/variables/types.ts +2 -0
- package/src/data-source/__tests__/sortCollectionsByInherits.test.ts +125 -0
- package/src/data-source/index.ts +16 -10
- package/src/data-source/sortCollectionsByInherits.ts +61 -0
- package/src/executor/FlowExecutor.ts +160 -114
- package/src/executor/__tests__/flowExecutor.test.ts +151 -5
- package/src/flowContext.ts +196 -93
- package/src/flowEngine.ts +13 -2
- package/src/flowSettings.ts +8 -3
- package/src/hooks/useApplyAutoFlows.ts +3 -1
- package/src/index.ts +11 -1
- package/src/models/CollectionFieldModel.tsx +43 -4
- package/src/models/__tests__/flowModel.getFlows.sort.test.ts +4 -4
- package/src/models/__tests__/flowModel.test.ts +218 -95
- package/src/models/flowModel.tsx +146 -122
- package/src/models/forkFlowModel.ts +37 -5
- package/src/provider.tsx +10 -7
- package/src/resources/multiRecordResource.ts +2 -0
- package/src/resources/singleRecordResource.ts +1 -0
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +28 -21
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +46 -34
- package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
- package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
- package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +25 -21
- package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
- package/src/runjs-context/contexts/base.ts +155 -0
- package/src/runjs-context/helpers.ts +32 -30
- package/src/runjs-context/registry.ts +16 -47
- package/src/runjs-context/setup.ts +51 -0
- package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
- package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
- package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
- package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
- package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
- package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
- package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
- package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
- package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
- package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
- package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
- package/src/runjs-context/snippets/index.ts +176 -39
- package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
- package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
- package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
- package/src/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.ts +15 -6
- package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +53 -0
- package/src/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.ts +15 -11
- package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +81 -0
- package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +66 -0
- package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
- package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
- package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
- package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
- package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
- package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
- package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
- package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
- package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
- package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
- package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
- package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
- package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
- package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
- package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
- package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
- package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
- package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
- package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
- package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
- package/src/runjs-context/snippets/types.ts +5 -1
- package/src/types.ts +13 -0
- package/src/utils/__tests__/safeGlobals.test.ts +22 -1
- package/src/utils/buildSettingsViewInputArgs.ts +72 -0
- package/src/utils/index.ts +2 -2
- package/src/utils/params-resolvers.ts +1 -1
- package/src/utils/safeGlobals.ts +49 -3
- package/src/utils/serverContextParams.ts +1 -0
- package/src/utils/variablesParams.ts +50 -38
- package/src/views/PageComponent.tsx +1 -1
- package/src/views/createViewMeta.ts +372 -70
- package/src/views/index.tsx +1 -0
- package/src/views/useDialog.tsx +12 -10
- package/src/views/useDrawer.tsx +60 -36
- package/src/views/usePage.tsx +13 -10
- package/lib/components/dnd/getMousePositionOnElement.d.ts +0 -50
- package/lib/components/dnd/getMousePositionOnElement.js +0 -95
- package/lib/components/dnd/moveBlock.d.ts +0 -33
- package/lib/components/dnd/moveBlock.js +0 -302
- package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
- package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
- package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
- package/lib/runjs-context/index.d.ts +0 -19
- package/lib/runjs-context/index.js +0 -57
- package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
- package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/api-request-post.snippet.js +0 -42
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +0 -41
- package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +0 -44
- package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
- package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
- package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.js +0 -45
- package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
- package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
- package/src/components/dnd/getMousePositionOnElement.ts +0 -115
- package/src/components/dnd/moveBlock.ts +0 -379
- package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
- package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
- package/src/runjs-context/index.ts +0 -20
- package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
- package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
- package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
- package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
- package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
- package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
- package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
- package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
- package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
- package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
- package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
- package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
- package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
- package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
- package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
- package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
- /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
- /package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.d.ts → block/echarts-init.snippet.d.ts} +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { SnippetModule } from '../../types';
|
|
11
|
+
import { JSColumnRunJSContext } from '../../../contexts/JSColumnRunJSContext';
|
|
12
|
+
|
|
13
|
+
const snippet: SnippetModule = {
|
|
14
|
+
contexts: [JSColumnRunJSContext],
|
|
15
|
+
prefix: 'sn-col-open-dialog',
|
|
16
|
+
label: 'Cell dialog with row data',
|
|
17
|
+
description: 'Render a button in cell to open dialog via ctx.openView with current row context',
|
|
18
|
+
locales: {
|
|
19
|
+
'zh-CN': {
|
|
20
|
+
label: '单元格对话框(显示行数据)',
|
|
21
|
+
description: '在单元格渲染按钮,点击后通过 ctx.openView 打开弹窗并传入当前行上下文',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
content: `
|
|
25
|
+
// Render a button inside the cell
|
|
26
|
+
ctx.element.innerHTML = '<button class="nb-cell-btn" style="padding:4px 8px">' + ctx.t('View') + '</button>';
|
|
27
|
+
|
|
28
|
+
const button = ctx.element.querySelector('.nb-cell-btn');
|
|
29
|
+
const popupUid = ctx.model.uid + '-1'; // popupUid should be stable and better bound to ctx.model.uid
|
|
30
|
+
const primaryKey = ctx.collection?.primaryKey || 'id';
|
|
31
|
+
|
|
32
|
+
button?.addEventListener('click', async () => {
|
|
33
|
+
await ctx.openView(popupUid, {
|
|
34
|
+
mode: 'dialog',
|
|
35
|
+
title: ctx.t('Row detail'),
|
|
36
|
+
params: {
|
|
37
|
+
filterByTk: ctx.record?.[primaryKey],
|
|
38
|
+
record: ctx.record,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
`,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default snippet;
|
package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts
RENAMED
|
@@ -7,10 +7,20 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
import type { SnippetModule } from '../../types';
|
|
11
|
+
import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
|
|
12
|
+
|
|
13
|
+
const snippet: SnippetModule = {
|
|
14
|
+
contexts: [JSCollectionActionRunJSContext],
|
|
12
15
|
prefix: 'sn-act-selected-count',
|
|
13
16
|
label: 'Selected count',
|
|
17
|
+
description: 'Show number of selected rows in list action',
|
|
18
|
+
locales: {
|
|
19
|
+
'zh-CN': {
|
|
20
|
+
label: '选中数量',
|
|
21
|
+
description: '提示当前选中行的数量',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
14
24
|
content: `
|
|
15
25
|
const rows = ctx.resource?.getSelectedRows?.() || [];
|
|
16
26
|
if (!rows.length) {
|
|
@@ -20,3 +30,5 @@ if (!rows.length) {
|
|
|
20
30
|
}
|
|
21
31
|
`,
|
|
22
32
|
};
|
|
33
|
+
|
|
34
|
+
export default snippet;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { SnippetModule } from '../../types';
|
|
11
|
+
import { JSColumnRunJSContext } from '../../../contexts/JSColumnRunJSContext';
|
|
12
|
+
|
|
13
|
+
const snippet: SnippetModule = {
|
|
14
|
+
contexts: [JSColumnRunJSContext],
|
|
15
|
+
prefix: 'sn-col-concat',
|
|
16
|
+
label: 'Concat two fields',
|
|
17
|
+
description: 'Combine two field values into the current column cell',
|
|
18
|
+
locales: {
|
|
19
|
+
'zh-CN': {
|
|
20
|
+
label: '拼接两个字段值',
|
|
21
|
+
description: '在自定义列中拼接两个字段的值作为显示内容',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
content: `
|
|
25
|
+
// Demo helper: infer previous columns' dataIndex values based on the current column position
|
|
26
|
+
// In production, hardcode field names to avoid surprises when columns are reordered
|
|
27
|
+
function resolvePreviousDataIndexes() {
|
|
28
|
+
const parent = ctx.model?.parent;
|
|
29
|
+
const list = parent?.subModels?.columns;
|
|
30
|
+
if (!Array.isArray(list)) return [];
|
|
31
|
+
const currentUid = ctx.model?.uid;
|
|
32
|
+
const currentIndex = list.findIndex((item) => item?.uid === currentUid);
|
|
33
|
+
if (currentIndex <= 0) return [];
|
|
34
|
+
return list
|
|
35
|
+
.slice(Math.max(0, currentIndex - 2), currentIndex)
|
|
36
|
+
.map((item) => (item && item.props ? item.props.dataIndex : undefined))
|
|
37
|
+
.filter((key) => typeof key === 'string' && key.length > 0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const [autoFieldA, autoFieldB] = resolvePreviousDataIndexes();
|
|
41
|
+
|
|
42
|
+
// Fallback: manually specify field keys when auto detection is not enough
|
|
43
|
+
const fieldA = autoFieldA || 'firstName';
|
|
44
|
+
const fieldB = autoFieldB || 'lastName';
|
|
45
|
+
|
|
46
|
+
const normalize = (value) => {
|
|
47
|
+
if (value === undefined || value === null) return '';
|
|
48
|
+
return String(value).trim();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const valueA = normalize(ctx.record?.[fieldA]);
|
|
52
|
+
const valueB = normalize(ctx.record?.[fieldB]);
|
|
53
|
+
|
|
54
|
+
const parts = [valueA, valueB].filter((item) => item.length > 0);
|
|
55
|
+
|
|
56
|
+
ctx.element.textContent = parts.length ? parts.join(' / ') : ctx.t('N/A');
|
|
57
|
+
`,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default snippet;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { SnippetModule } from '../../types';
|
|
11
|
+
import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
|
|
12
|
+
|
|
13
|
+
const snippet: SnippetModule = {
|
|
14
|
+
contexts: [JSCollectionActionRunJSContext],
|
|
15
|
+
prefix: 'sn-act-destroy-selected',
|
|
16
|
+
label: 'Destroy selected rows',
|
|
17
|
+
description: 'Delete selected rows via resource.destroySelectedRows()',
|
|
18
|
+
locales: {
|
|
19
|
+
'zh-CN': {
|
|
20
|
+
label: '删除选中行',
|
|
21
|
+
description: '通过 resource.destroySelectedRows() 删除选中行',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
content: `
|
|
25
|
+
const rows = ctx.resource?.getSelectedRows?.() || [];
|
|
26
|
+
if (!rows.length) {
|
|
27
|
+
ctx.message.warning(ctx.t('Please select data'));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
await ctx.resource.destroySelectedRows();
|
|
32
|
+
ctx.message.success(ctx.t('Deleted {{count}} rows', { count: rows.length }));
|
|
33
|
+
`,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default snippet;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { SnippetModule } from '../../types';
|
|
11
|
+
import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
|
|
12
|
+
|
|
13
|
+
const snippet: SnippetModule = {
|
|
14
|
+
contexts: [JSCollectionActionRunJSContext],
|
|
15
|
+
prefix: 'sn-act-export',
|
|
16
|
+
label: 'Export selected rows as JSON',
|
|
17
|
+
description: 'Download selected rows as a JSON file',
|
|
18
|
+
locales: {
|
|
19
|
+
'zh-CN': {
|
|
20
|
+
label: '导出选中行为 JSON',
|
|
21
|
+
description: '将选中的行导出为 JSON 文件下载',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
content: `
|
|
25
|
+
const rows = ctx.resource?.getSelectedRows?.() || [];
|
|
26
|
+
if (!rows.length) {
|
|
27
|
+
ctx.message.warning(ctx.t('Please select at least one row'));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Create JSON file and download
|
|
32
|
+
const jsonStr = JSON.stringify(rows, null, 2);
|
|
33
|
+
const blob = new Blob([jsonStr], { type: 'application/json' });
|
|
34
|
+
const url = URL.createObjectURL(blob);
|
|
35
|
+
const link = document.createElement('a');
|
|
36
|
+
link.href = url;
|
|
37
|
+
link.download = \`export-\${new Date().toISOString().split('T')[0]}.json\`;
|
|
38
|
+
link.click();
|
|
39
|
+
URL.revokeObjectURL(url);
|
|
40
|
+
|
|
41
|
+
ctx.message.success(ctx.t('Exported {{count}} records', { count: rows.length }));
|
|
42
|
+
`,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default snippet;
|
|
@@ -7,10 +7,20 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
import type { SnippetModule } from '../../types';
|
|
11
|
+
import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
|
|
12
|
+
|
|
13
|
+
const snippet: SnippetModule = {
|
|
14
|
+
contexts: [JSCollectionActionRunJSContext],
|
|
12
15
|
prefix: 'sn-act-iterate',
|
|
13
16
|
label: 'Iterate selected rows',
|
|
17
|
+
description: 'Loop through selected rows and process each record',
|
|
18
|
+
locales: {
|
|
19
|
+
'zh-CN': {
|
|
20
|
+
label: '遍历选中行',
|
|
21
|
+
description: '遍历选中行并处理每条记录',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
14
24
|
content: `
|
|
15
25
|
const rows = ctx.resource?.getSelectedRows?.() || [];
|
|
16
26
|
for (const row of rows) {
|
|
@@ -19,3 +29,5 @@ for (const row of rows) {
|
|
|
19
29
|
ctx.message.success(ctx.t('Processed {{count}} rows', { count: rows.length }));
|
|
20
30
|
`,
|
|
21
31
|
};
|
|
32
|
+
|
|
33
|
+
export default snippet;
|
|
@@ -7,11 +7,15 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
export type SnippetContextSpecifier = string | { name: string } | (new (...args: any[]) => any);
|
|
11
|
+
|
|
10
12
|
export type SnippetModule = {
|
|
11
13
|
content: string;
|
|
12
|
-
contexts?:
|
|
14
|
+
contexts?: SnippetContextSpecifier[]; // e.g., [JSBlockRunJSContext] or ['*']
|
|
13
15
|
versions?: string[]; // e.g., ['v1'] or ['*']
|
|
16
|
+
scenes?: string[]; // logical placement hints like ['form', 'table']
|
|
14
17
|
prefix?: string; // completion trigger text
|
|
15
18
|
label?: string; // display name in snippets list
|
|
16
19
|
description?: string; // optional longer description
|
|
20
|
+
locales?: Record<string, { label?: string; description?: string }>;
|
|
17
21
|
};
|
package/src/types.ts
CHANGED
|
@@ -134,6 +134,8 @@ export enum ActionScene {
|
|
|
134
134
|
BLOCK_LINKAGE_RULES = 1,
|
|
135
135
|
/** 表单字段级联动规则可用 */
|
|
136
136
|
FIELD_LINKAGE_RULES,
|
|
137
|
+
/** 子表单字段级联动规则可用 */
|
|
138
|
+
SUB_FORM_FIELD_LINKAGE_RULES,
|
|
137
139
|
/** 详情字段级联动规则可用 */
|
|
138
140
|
DETAILS_FIELD_LINKAGE_RULES,
|
|
139
141
|
/** 按钮级联动规则可用 */
|
|
@@ -185,6 +187,16 @@ export type FlowEvent<TModel extends FlowModel = FlowModel> =
|
|
|
185
187
|
| FlowEventName
|
|
186
188
|
| { eventName: FlowEventName; defaultParams?: Record<string, any> };
|
|
187
189
|
|
|
190
|
+
/**
|
|
191
|
+
* 事件分发选项。
|
|
192
|
+
*/
|
|
193
|
+
export interface DispatchEventOptions {
|
|
194
|
+
/** 是否顺序执行(默认并行) */
|
|
195
|
+
sequential?: boolean;
|
|
196
|
+
/** 是否使用缓存(默认 false;beforeRender 的默认值为 true,可覆盖) */
|
|
197
|
+
useCache?: boolean;
|
|
198
|
+
}
|
|
199
|
+
|
|
188
200
|
/**
|
|
189
201
|
* 事件定义:用于事件注册表(全局/模型类级)。
|
|
190
202
|
*/
|
|
@@ -300,6 +312,7 @@ export interface IFlowModelRepository<T extends FlowModel = FlowModel> {
|
|
|
300
312
|
save(model: T, options?: { onlyStepParams?: boolean }): Promise<Record<string, any>>;
|
|
301
313
|
destroy(uid: string): Promise<boolean>;
|
|
302
314
|
move(sourceId: string, targetId: string, position: 'before' | 'after'): Promise<void>;
|
|
315
|
+
duplicate(uid: string): Promise<Record<string, any> | null>;
|
|
303
316
|
}
|
|
304
317
|
|
|
305
318
|
/**
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { describe, expect, it } from 'vitest';
|
|
11
|
-
import { createSafeDocument, createSafeWindow } from '../safeGlobals';
|
|
11
|
+
import { createSafeDocument, createSafeWindow, createSafeNavigator } from '../safeGlobals';
|
|
12
12
|
|
|
13
13
|
describe('safeGlobals', () => {
|
|
14
14
|
it('createSafeWindow exposes only allowed globals and extras', () => {
|
|
@@ -26,4 +26,25 @@ describe('safeGlobals', () => {
|
|
|
26
26
|
expect(doc.bar).toBe(true);
|
|
27
27
|
expect(() => doc.cookie).toThrow(/not allowed/);
|
|
28
28
|
});
|
|
29
|
+
|
|
30
|
+
it('createSafeNavigator exposes limited props and guards others', () => {
|
|
31
|
+
const nav: any = createSafeNavigator();
|
|
32
|
+
// clipboard object should always exist
|
|
33
|
+
expect(typeof nav.clipboard).toBe('object');
|
|
34
|
+
// writeText may or may not exist depending on environment
|
|
35
|
+
if (typeof navigator !== 'undefined' && (navigator as any).clipboard?.writeText) {
|
|
36
|
+
expect(typeof nav.clipboard.writeText).toBe('function');
|
|
37
|
+
} else {
|
|
38
|
+
expect(typeof nav.clipboard.writeText === 'undefined' || typeof nav.clipboard.writeText === 'function').toBe(
|
|
39
|
+
true,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
// readable properties
|
|
43
|
+
expect(() => void nav.onLine).not.toThrow();
|
|
44
|
+
expect(() => void nav.language).not.toThrow();
|
|
45
|
+
expect(() => void nav.languages).not.toThrow();
|
|
46
|
+
// blocked properties
|
|
47
|
+
expect(() => (nav as any).geolocation).toThrow(/not allowed/);
|
|
48
|
+
expect(() => (nav as any).userAgent).toThrow(/not allowed/);
|
|
49
|
+
});
|
|
29
50
|
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { FlowModel } from '../models';
|
|
11
|
+
import { inferRecordRef } from './variablesParams';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 统一构造设置弹窗 openView 的 inputArgs:
|
|
15
|
+
* - collectionName/dataSourceKey/filterByTk:优先从 model.context 推断;否则回退父视图 inputArgs
|
|
16
|
+
* - sourceId:优先从 resource.getSourceId();否则回退父视图 inputArgs
|
|
17
|
+
* - associationName:来自 association.resourceName 或 resource.getResourceName()
|
|
18
|
+
* - navigation:父视图 navigation 或传入的 navigationOverride
|
|
19
|
+
*/
|
|
20
|
+
export function buildSettingsViewInputArgs(
|
|
21
|
+
model: FlowModel,
|
|
22
|
+
extra?: Record<string, any>,
|
|
23
|
+
options?: { navigationOverride?: any },
|
|
24
|
+
): Record<string, any> {
|
|
25
|
+
const defaults: Record<string, any> = {};
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// 1) 当前记录/集合
|
|
29
|
+
const ref = inferRecordRef((model as any).context);
|
|
30
|
+
if (ref?.collection) {
|
|
31
|
+
defaults.collectionName = ref.collection;
|
|
32
|
+
defaults.dataSourceKey = ref.dataSourceKey || 'main';
|
|
33
|
+
defaults.filterByTk = ref.filterByTk;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 2) 回退父视图 inputArgs(如在抽屉/页面中)
|
|
37
|
+
const parentArgs = (model as any)?.context?.view?.inputArgs || {};
|
|
38
|
+
if (!defaults.collectionName && parentArgs?.collectionName) {
|
|
39
|
+
defaults.collectionName = parentArgs.collectionName;
|
|
40
|
+
defaults.dataSourceKey = parentArgs.dataSourceKey || defaults.dataSourceKey || 'main';
|
|
41
|
+
}
|
|
42
|
+
if (defaults.filterByTk == null && parentArgs?.filterByTk != null) {
|
|
43
|
+
defaults.filterByTk = parentArgs.filterByTk;
|
|
44
|
+
}
|
|
45
|
+
if (defaults.sourceId == null && parentArgs?.sourceId != null) {
|
|
46
|
+
defaults.sourceId = parentArgs.sourceId;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 3) 导航(用于推断“上级弹窗”)
|
|
50
|
+
const nav = options?.navigationOverride ?? (model as any)?.context?.view?.navigation;
|
|
51
|
+
if (nav) {
|
|
52
|
+
defaults.navigation = nav;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 4) 直接从资源读取 sourceId(优先级高于父视图)
|
|
56
|
+
const sid = (model as any)?.context?.resource?.getSourceId?.();
|
|
57
|
+
if (sid !== undefined && sid !== null && String(sid) !== '') {
|
|
58
|
+
defaults.sourceId = sid;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 5) 关联名(用于“上级记录”)
|
|
62
|
+
const assocName =
|
|
63
|
+
(model as any)?.context?.association?.resourceName || (model as any)?.context?.resource?.getResourceName?.();
|
|
64
|
+
if (typeof assocName === 'string' && assocName) {
|
|
65
|
+
defaults.associationName = assocName;
|
|
66
|
+
}
|
|
67
|
+
} catch (_) {
|
|
68
|
+
// 忽略推断异常
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return { ...defaults, ...(extra || {}) };
|
|
72
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -48,7 +48,6 @@ export {
|
|
|
48
48
|
createRecordMetaFactory,
|
|
49
49
|
extractUsedVariableNames,
|
|
50
50
|
extractUsedVariablePaths,
|
|
51
|
-
inferParentRecordRef,
|
|
52
51
|
inferRecordRef,
|
|
53
52
|
type RecordParamsBuilder,
|
|
54
53
|
} from './variablesParams';
|
|
@@ -58,6 +57,7 @@ export { extractPropertyPath, formatPathToVariable, isVariableExpression } from
|
|
|
58
57
|
|
|
59
58
|
export { clearAutoFlowError, getAutoFlowError, setAutoFlowError, type AutoFlowError } from './autoFlowError';
|
|
60
59
|
export { parsePathnameToViewParams, type ViewParam } from './parsePathnameToViewParams';
|
|
60
|
+
export { buildSettingsViewInputArgs } from './buildSettingsViewInputArgs';
|
|
61
61
|
|
|
62
62
|
// 安全全局对象(window/document)
|
|
63
|
-
export { createSafeDocument, createSafeWindow } from './safeGlobals';
|
|
63
|
+
export { createSafeDocument, createSafeWindow, createSafeNavigator } from './safeGlobals';
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { getValuesByPath } from '@nocobase/shared';
|
|
10
11
|
import _ from 'lodash';
|
|
11
12
|
import { FlowContext, FlowModelContext, FlowRuntimeContext } from '../flowContext';
|
|
12
|
-
import { getValuesByPath } from '@nocobase/utils/client';
|
|
13
13
|
import type { FlowModel } from '../models';
|
|
14
14
|
import type { ServerContextParams } from './serverContextParams';
|
|
15
15
|
|
package/src/utils/safeGlobals.ts
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* 统一的安全全局对象代理:window/document
|
|
12
|
-
* -
|
|
13
|
-
* - document
|
|
11
|
+
* 统一的安全全局对象代理:window/document/navigator
|
|
12
|
+
* - window:仅允许常用的定时器、console、Math、Date、addEventListener、open(安全包装)、location(安全代理)
|
|
13
|
+
* - document:仅允许 createElement/querySelector/querySelectorAll
|
|
14
|
+
* - navigator:仅提供极少量低风险能力(clipboard.writeText、onLine、language、languages)
|
|
14
15
|
* - 不允许随意访问未声明的属性,最小权限原则
|
|
15
16
|
*/
|
|
16
17
|
|
|
@@ -186,3 +187,48 @@ export function createSafeDocument(extra?: Record<string, any>) {
|
|
|
186
187
|
},
|
|
187
188
|
);
|
|
188
189
|
}
|
|
190
|
+
|
|
191
|
+
export function createSafeNavigator(extra?: Record<string, any>) {
|
|
192
|
+
const nav: any = (typeof window !== 'undefined' && window.navigator) || undefined;
|
|
193
|
+
|
|
194
|
+
// 始终提供 clipboard 对象,避免可选链访问时抛错
|
|
195
|
+
const clipboard: Record<string, any> = {};
|
|
196
|
+
const writeText = nav?.clipboard?.writeText;
|
|
197
|
+
if (typeof writeText === 'function') {
|
|
198
|
+
clipboard.writeText = writeText.bind(nav.clipboard);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const allowed: Record<string, any> = {
|
|
202
|
+
clipboard,
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// 只读常用标识,避免泄露更多指纹信息
|
|
206
|
+
Object.defineProperty(allowed, 'onLine', {
|
|
207
|
+
get: () => !!nav?.onLine,
|
|
208
|
+
enumerable: true,
|
|
209
|
+
configurable: false,
|
|
210
|
+
});
|
|
211
|
+
Object.defineProperty(allowed, 'language', {
|
|
212
|
+
get: () => nav?.language,
|
|
213
|
+
enumerable: true,
|
|
214
|
+
configurable: false,
|
|
215
|
+
});
|
|
216
|
+
Object.defineProperty(allowed, 'languages', {
|
|
217
|
+
get: () => (nav?.languages ? [...nav.languages] : undefined),
|
|
218
|
+
enumerable: true,
|
|
219
|
+
configurable: false,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// 允许额外注入(例如自定义能力的受控暴露)
|
|
223
|
+
Object.assign(allowed, extra || {});
|
|
224
|
+
|
|
225
|
+
return new Proxy(
|
|
226
|
+
{},
|
|
227
|
+
{
|
|
228
|
+
get(_t, prop: string) {
|
|
229
|
+
if (prop in allowed) return (allowed as any)[prop];
|
|
230
|
+
throw new Error(`Access to navigator property "${String(prop)}" is not allowed.`);
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
);
|
|
234
|
+
}
|
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import type { FlowContext, PropertyMeta, PropertyMetaFactory } from '../flowContext';
|
|
11
|
-
import type { JSONValue } from './params-resolvers';
|
|
12
|
-
import type { Collection } from '../data-source';
|
|
13
|
-
import { createCollectionContextMeta } from './createCollectionContextMeta';
|
|
14
|
-
import { buildServerContextParams, type RecordRef, type ServerContextParams } from '../utils/serverContextParams';
|
|
15
10
|
import {
|
|
16
11
|
extractUsedVariableNames as _extractUsedVariableNames,
|
|
17
12
|
extractUsedVariablePaths as _extractUsedVariablePaths,
|
|
18
|
-
} from '@nocobase/
|
|
13
|
+
} from '@nocobase/shared';
|
|
14
|
+
import type { Collection } from '../data-source';
|
|
15
|
+
import type { FlowContext, PropertyMeta, PropertyMetaFactory } from '../flowContext';
|
|
16
|
+
import { buildServerContextParams, type RecordRef, type ServerContextParams } from '../utils/serverContextParams';
|
|
17
|
+
import { createCollectionContextMeta } from './createCollectionContextMeta';
|
|
18
|
+
import type { JSONValue } from './params-resolvers';
|
|
19
19
|
|
|
20
20
|
// Narrowest resource shape we rely on for inference
|
|
21
21
|
type ResourceLike = {
|
|
@@ -45,6 +45,7 @@ function getCollection(ctx: FlowContext): CollectionShape | undefined {
|
|
|
45
45
|
return undefined;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
// 从 FlowContext 中推断当前记录的 context params 信息
|
|
48
49
|
export function inferRecordRef(ctx: FlowContext): RecordRef | undefined {
|
|
49
50
|
const resource = getResource(ctx);
|
|
50
51
|
const collectionObj = getCollection(ctx);
|
|
@@ -59,13 +60,26 @@ export function inferRecordRef(ctx: FlowContext): RecordRef | undefined {
|
|
|
59
60
|
return { collection, dataSourceKey, filterByTk };
|
|
60
61
|
}
|
|
61
62
|
|
|
63
|
+
// 从 FlowContext.view 中推断记录的 context params 信息
|
|
64
|
+
export function inferViewRecordRef(ctx: FlowContext): RecordRef | undefined {
|
|
65
|
+
const view = ctx.view;
|
|
66
|
+
if (!view) return undefined;
|
|
67
|
+
const inputArgs = (view as any)?.inputArgs || {};
|
|
68
|
+
const collection = inputArgs?.collectionName || (view as any)?.record?.collection;
|
|
69
|
+
const dataSourceKey = inputArgs?.dataSourceKey || (view as any)?.record?.dataSourceKey || 'main';
|
|
70
|
+
const filterByTk = inputArgs?.filterByTk || (view as any)?.record?.filterByTk;
|
|
71
|
+
const sourceId = inputArgs?.sourceId;
|
|
72
|
+
if (!collection || typeof filterByTk === 'undefined' || filterByTk === null) return undefined;
|
|
73
|
+
return { collection, dataSourceKey, filterByTk, sourceId };
|
|
74
|
+
}
|
|
75
|
+
|
|
62
76
|
export function inferParentRecordRef(ctx: FlowContext): RecordRef | undefined {
|
|
63
77
|
const resource = getResource(ctx);
|
|
64
78
|
const dataSourceKey = getCollection(ctx)?.dataSourceKey || resource?.getDataSourceKey?.();
|
|
65
|
-
const
|
|
79
|
+
const resourceName = resource?.getResourceName?.();
|
|
66
80
|
const sourceId = resource?.getSourceId?.();
|
|
67
|
-
if (!
|
|
68
|
-
const parts = String(
|
|
81
|
+
if (!resourceName || typeof sourceId === 'undefined' || sourceId === null) return undefined;
|
|
82
|
+
const parts = String(resourceName).split('.');
|
|
69
83
|
if (parts.length < 2) return undefined;
|
|
70
84
|
return { collection: parts[0], dataSourceKey, filterByTk: sourceId };
|
|
71
85
|
}
|
|
@@ -110,8 +124,11 @@ export function createRecordMetaFactory(
|
|
|
110
124
|
export function createCurrentRecordMetaFactory(
|
|
111
125
|
ctx: FlowContext,
|
|
112
126
|
collectionAccessor: () => Collection | null,
|
|
127
|
+
options?: { title?: string },
|
|
113
128
|
): PropertyMetaFactory {
|
|
114
|
-
const title =
|
|
129
|
+
const title = options?.title
|
|
130
|
+
? ctx.t?.(options.title) || options.title
|
|
131
|
+
: ctx.t?.('Current record') || 'Current record';
|
|
115
132
|
return createRecordMetaFactory(collectionAccessor, title, (c) => inferRecordRef(c));
|
|
116
133
|
}
|
|
117
134
|
|
|
@@ -141,35 +158,30 @@ export async function collectContextParamsForTemplate(
|
|
|
141
158
|
ctx: FlowContext,
|
|
142
159
|
template: JSONValue,
|
|
143
160
|
): Promise<ServerContextParams | undefined> {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
built = await builder(ctx);
|
|
160
|
-
}
|
|
161
|
-
} catch (err) {
|
|
162
|
-
// 忽略构建变量参数时的异常,继续处理其他变量
|
|
163
|
-
// 使用 void 引用以避免 no-unused-vars,同时避免空代码块触发 no-empty
|
|
164
|
-
void err;
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
if (built) {
|
|
168
|
-
input[key] = built;
|
|
161
|
+
const usage = _extractUsedVariablePaths(template) || {};
|
|
162
|
+
const varNames = Object.keys(usage);
|
|
163
|
+
if (!varNames.length) return undefined;
|
|
164
|
+
|
|
165
|
+
const input: Record<string, any> = {};
|
|
166
|
+
for (const key of varNames) {
|
|
167
|
+
const opt = ctx.getPropertyOptions?.(key);
|
|
168
|
+
const meta: PropertyMeta | (() => Promise<PropertyMeta | null> | PropertyMeta | null) | undefined = opt?.meta;
|
|
169
|
+
if (!meta) continue;
|
|
170
|
+
let built: any;
|
|
171
|
+
try {
|
|
172
|
+
const resolvedMeta = typeof meta === 'function' ? await (meta as any)() : (meta as any);
|
|
173
|
+
const builder = resolvedMeta?.buildVariablesParams;
|
|
174
|
+
if (typeof builder === 'function') {
|
|
175
|
+
built = await builder(ctx);
|
|
169
176
|
}
|
|
177
|
+
} catch (err) {
|
|
178
|
+
// 忽略构建变量参数时的异常,继续处理其他变量
|
|
179
|
+
void err;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (built) {
|
|
183
|
+
input[key] = built;
|
|
170
184
|
}
|
|
171
|
-
return buildServerContextParams(ctx, input);
|
|
172
|
-
} catch (_) {
|
|
173
|
-
return undefined;
|
|
174
185
|
}
|
|
186
|
+
return buildServerContextParams(ctx, input);
|
|
175
187
|
}
|