@nocobase/flow-engine 2.0.0-alpha.9 → 2.0.0-beta.2
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 +92 -0
- package/lib/FlowDefinition.d.ts +6 -4
- package/lib/JSRunner.js +3 -0
- package/lib/ViewScopedFlowEngine.js +15 -1
- package/lib/acl/Acl.d.ts +12 -12
- package/lib/acl/Acl.js +78 -30
- package/lib/components/DynamicFlowsEditor.js +2 -4
- package/lib/components/FieldModelRenderer.js +10 -8
- package/lib/components/FieldSkeleton.d.ts +10 -0
- package/lib/components/FieldSkeleton.js +64 -0
- package/lib/components/FlowContextSelector.js +19 -3
- package/lib/components/FlowModelRenderer.d.ts +2 -1
- package/lib/components/FlowModelRenderer.js +34 -12
- package/lib/components/FormItem.js +5 -1
- package/lib/components/MobilePopup.d.ts +20 -0
- package/lib/components/MobilePopup.js +102 -0
- package/lib/components/MobilePopup.style.d.ts +17 -0
- package/lib/components/MobilePopup.style.js +186 -0
- package/lib/components/common/withFlowDesignMode.d.ts +1 -1
- package/lib/components/common/withFlowDesignMode.js +5 -5
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +3 -1
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +71 -53
- package/lib/components/settings/wrappers/component/SelectWithTitle.d.ts +19 -0
- package/lib/components/settings/wrappers/component/SelectWithTitle.js +136 -0
- package/lib/components/settings/wrappers/component/SwitchWithTitle.d.ts +10 -0
- package/lib/components/settings/wrappers/component/SwitchWithTitle.js +110 -0
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +221 -93
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +71 -54
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +2 -2
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +63 -23
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +11 -6
- package/lib/components/settings/wrappers/embedded/FlowSettings.js +42 -28
- package/lib/components/settings/wrappers/embedded/FlowsSettings.js +3 -3
- package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +52 -32
- package/lib/components/subModel/AddSubModelButton.d.ts +7 -0
- package/lib/components/subModel/AddSubModelButton.js +78 -8
- package/lib/components/subModel/LazyDropdown.js +14 -15
- package/lib/components/subModel/utils.d.ts +1 -1
- package/lib/components/subModel/utils.js +21 -11
- package/lib/components/variables/VariableInput.js +5 -3
- package/lib/components/variables/types.d.ts +2 -0
- package/lib/components/variables/utils.js +4 -2
- package/lib/data-source/index.d.ts +43 -4
- package/lib/data-source/index.js +104 -11
- package/lib/data-source/jioToJoiSchema.js +1 -0
- package/lib/emitter.d.ts +6 -0
- package/lib/emitter.js +12 -0
- package/lib/executor/FlowExecutor.js +48 -7
- package/lib/flow-registry/GlobalFlowRegistry.d.ts +1 -0
- package/lib/flow-registry/GlobalFlowRegistry.js +3 -0
- package/lib/flow-registry/InstanceFlowRegistry.d.ts +1 -0
- package/lib/flow-registry/InstanceFlowRegistry.js +3 -0
- package/lib/flowContext.d.ts +6 -0
- package/lib/flowContext.js +111 -30
- package/lib/flowEngine.d.ts +49 -0
- package/lib/flowEngine.js +265 -10
- package/lib/flowSettings.d.ts +4 -3
- package/lib/flowSettings.js +33 -11
- package/lib/hooks/useApplyAutoFlows.d.ts +1 -0
- package/lib/hooks/useApplyAutoFlows.js +2 -2
- package/lib/index.d.ts +4 -2
- package/lib/index.js +11 -5
- package/lib/locale/de-DE.json +62 -0
- package/lib/locale/en-US.json +57 -45
- package/lib/locale/es-ES.json +62 -0
- package/lib/locale/fr-FR.json +62 -0
- package/lib/locale/hu-HU.json +62 -0
- package/lib/locale/id-ID.json +62 -0
- package/lib/locale/index.d.ts +114 -90
- package/lib/locale/it-IT.json +62 -0
- package/lib/locale/ja-JP.json +62 -0
- package/lib/locale/ko-KR.json +62 -0
- package/lib/locale/nl-NL.json +62 -0
- package/lib/locale/pt-BR.json +62 -0
- package/lib/locale/ru-RU.json +62 -0
- package/lib/locale/tr-TR.json +62 -0
- package/lib/locale/uk-UA.json +62 -0
- package/lib/locale/vi-VN.json +62 -0
- package/lib/locale/zh-CN.json +58 -46
- package/lib/locale/zh-TW.json +62 -0
- package/lib/models/CollectionFieldModel.d.ts +6 -2
- package/lib/models/CollectionFieldModel.js +60 -14
- package/lib/models/flowModel.d.ts +43 -4
- package/lib/models/flowModel.js +128 -26
- package/lib/models/forkFlowModel.d.ts +6 -2
- package/lib/models/forkFlowModel.js +9 -2
- package/lib/provider.d.ts +3 -1
- package/lib/provider.js +4 -3
- package/lib/reactive/index.d.ts +10 -0
- package/lib/reactive/index.js +41 -0
- package/lib/reactive/observer.d.ts +19 -0
- package/lib/reactive/observer.js +109 -0
- package/lib/resources/baseRecordResource.d.ts +1 -0
- package/lib/resources/baseRecordResource.js +14 -3
- package/lib/resources/multiRecordResource.d.ts +4 -2
- package/lib/resources/multiRecordResource.js +15 -6
- package/lib/resources/singleRecordResource.js +6 -3
- package/lib/resources/sqlResource.d.ts +1 -0
- package/lib/resources/sqlResource.js +22 -25
- package/lib/runjs-context/contexts/base.js +42 -6
- package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
- package/lib/runjs-context/snippets/index.js +3 -0
- package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.js +65 -0
- package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.js +6 -4
- package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +15 -16
- package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.js +58 -0
- package/lib/runjs-context/snippets/scene/block/render-react.snippet.js +7 -7
- package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +24 -29
- package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +20 -21
- package/lib/scheduler/ModelOperationScheduler.d.ts +51 -0
- package/lib/scheduler/ModelOperationScheduler.js +262 -0
- package/lib/types.d.ts +42 -7
- package/lib/types.js +4 -3
- package/lib/utils/associationObjectVariable.d.ts +32 -0
- package/lib/utils/associationObjectVariable.js +157 -0
- package/lib/utils/createCollectionContextMeta.d.ts +1 -1
- package/lib/utils/createCollectionContextMeta.js +8 -4
- package/lib/utils/createEphemeralContext.d.ts +13 -0
- package/lib/utils/createEphemeralContext.js +140 -0
- package/lib/utils/flows.d.ts +10 -0
- package/lib/utils/flows.js +48 -0
- package/lib/utils/index.d.ts +7 -3
- package/lib/utils/index.js +20 -0
- package/lib/utils/jsxTransform.d.ts +15 -0
- package/lib/utils/jsxTransform.js +68 -0
- package/lib/utils/params-resolvers.js +3 -3
- package/lib/utils/parsePathnameToViewParams.d.ts +1 -1
- package/lib/utils/parsePathnameToViewParams.js +41 -5
- package/lib/utils/pruneFilter.d.ts +21 -0
- package/lib/utils/pruneFilter.js +52 -0
- package/lib/utils/safeGlobals.d.ts +5 -3
- package/lib/utils/safeGlobals.js +42 -1
- package/lib/utils/schema-utils.d.ts +6 -0
- package/lib/utils/schema-utils.js +71 -6
- package/lib/utils/serverContextParams.d.ts +3 -0
- package/lib/utils/serverContextParams.js +2 -0
- package/lib/utils/translation.d.ts +4 -1
- package/lib/utils/translation.js +6 -2
- package/lib/utils/variablesParams.d.ts +21 -5
- package/lib/utils/variablesParams.js +103 -34
- package/lib/views/DialogComponent.js +1 -5
- package/lib/views/DrawerComponent.js +18 -9
- package/lib/views/PageComponent.js +3 -4
- package/lib/views/ViewNavigation.d.ts +11 -15
- package/lib/views/ViewNavigation.js +37 -19
- package/lib/views/createViewMeta.d.ts +3 -2
- package/lib/views/createViewMeta.js +164 -53
- package/lib/views/useDialog.d.ts +2 -1
- package/lib/views/useDialog.js +36 -30
- package/lib/views/useDrawer.d.ts +2 -1
- package/lib/views/useDrawer.js +33 -26
- package/lib/views/usePage.d.ts +2 -1
- package/lib/views/usePage.js +40 -29
- package/package.json +6 -3
- package/src/BlockScopedFlowEngine.ts +88 -0
- package/src/JSRunner.ts +3 -0
- package/src/ViewScopedFlowEngine.ts +16 -0
- package/src/__tests__/JSRunner.test.ts +62 -53
- package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
- package/src/__tests__/createViewMeta.popup.test.ts +142 -0
- package/src/__tests__/flow-engine.test.ts +3 -0
- package/src/__tests__/flowContext.test.ts +70 -0
- package/src/__tests__/flowEngine.destroyModel.test.ts +74 -0
- package/src/__tests__/flowEngine.moveModel.test.ts +43 -0
- package/src/__tests__/flowEngine.removeModel.test.ts +72 -0
- package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
- package/src/__tests__/flowModel.openView.navigation.test.ts +3 -2
- package/src/__tests__/flowSettings.open.test.tsx +2 -0
- package/src/__tests__/flowSettings.test.ts +2 -0
- package/src/__tests__/globalFlowRegistry.test.ts +1 -1
- package/src/__tests__/modelOperationScheduler.test.ts +346 -0
- package/src/__tests__/objectVariable.test.ts +464 -0
- package/src/__tests__/runjsRuntimeFeatures.test.ts +12 -0
- package/src/__tests__/viewScopedFlowEngine.test.ts +98 -0
- package/src/acl/Acl.tsx +85 -31
- package/src/acl/__tests__/Acl.test.tsx +43 -1
- package/src/components/DynamicFlowsEditor.tsx +0 -10
- package/src/components/FieldModelRenderer.tsx +15 -8
- package/src/components/FieldSkeleton.tsx +27 -0
- package/src/components/FlowContextSelector.tsx +20 -2
- package/src/components/FlowModelRenderer.tsx +46 -12
- package/src/components/FormItem.tsx +8 -1
- package/src/components/MobilePopup.style.ts +220 -0
- package/src/components/MobilePopup.tsx +86 -0
- package/src/components/__tests__/FlowModelRenderer.test.tsx +89 -0
- package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +1 -1
- package/src/components/common/withFlowDesignMode.tsx +5 -5
- package/src/components/index.ts +1 -0
- package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +34 -17
- package/src/components/settings/wrappers/component/SelectWithTitle.tsx +110 -0
- package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +82 -0
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +260 -121
- package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +34 -18
- package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +56 -18
- package/src/components/settings/wrappers/contextual/StepSettings.tsx +1 -2
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +12 -6
- package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +565 -0
- package/src/components/settings/wrappers/embedded/FlowSettings.tsx +47 -35
- package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +1 -1
- package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +64 -42
- package/src/components/subModel/AddSubModelButton.tsx +104 -9
- package/src/components/subModel/LazyDropdown.tsx +14 -14
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +168 -7
- package/src/components/subModel/__tests__/utils.test.ts +12 -12
- package/src/components/subModel/utils.ts +25 -6
- package/src/components/variables/VariableInput.tsx +5 -3
- package/src/components/variables/types.ts +2 -0
- package/src/components/variables/utils.ts +7 -3
- package/src/data-source/index.ts +169 -11
- package/src/data-source/jioToJoiSchema.ts +1 -0
- package/src/emitter.ts +14 -0
- package/src/executor/FlowExecutor.ts +56 -8
- package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
- package/src/flow-registry/GlobalFlowRegistry.ts +1 -0
- package/src/flow-registry/InstanceFlowRegistry.ts +1 -0
- package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +54 -0
- package/src/flowContext.ts +144 -29
- package/src/flowEngine.ts +328 -8
- package/src/flowSettings.ts +47 -19
- package/src/hooks/useApplyAutoFlows.ts +3 -3
- package/src/index.ts +4 -2
- package/src/locale/de-DE.json +62 -0
- package/src/locale/en-US.json +57 -45
- package/src/locale/es-ES.json +62 -0
- package/src/locale/fr-FR.json +62 -0
- package/src/locale/hu-HU.json +62 -0
- package/src/locale/id-ID.json +62 -0
- package/src/locale/it-IT.json +62 -0
- package/src/locale/ja-JP.json +62 -0
- package/src/locale/ko-KR.json +62 -0
- package/src/locale/nl-NL.json +62 -0
- package/src/locale/pt-BR.json +62 -0
- package/src/locale/ru-RU.json +62 -0
- package/src/locale/tr-TR.json +62 -0
- package/src/locale/uk-UA.json +62 -0
- package/src/locale/vi-VN.json +62 -0
- package/src/locale/zh-CN.json +58 -46
- package/src/locale/zh-TW.json +62 -0
- package/src/models/CollectionFieldModel.tsx +79 -17
- package/src/models/__tests__/dispatchEvent.behavior.test.ts +169 -0
- package/src/models/__tests__/flowEngine.resolveUse.test.ts +170 -0
- package/src/models/__tests__/flowModel.getFlows.sort.test.ts +29 -5
- package/src/models/__tests__/flowModel.scheduleModelOperation.test.tsx +129 -0
- package/src/models/__tests__/flowModel.test.ts +65 -27
- package/src/models/__tests__/forkFlowModel.test.ts +40 -7
- package/src/models/flowModel.tsx +192 -30
- package/src/models/forkFlowModel.ts +11 -3
- package/src/provider.tsx +5 -5
- package/src/reactive/__tests__/observer.test.tsx +211 -0
- package/src/reactive/index.ts +11 -0
- package/src/reactive/observer.tsx +101 -0
- package/src/resources/baseRecordResource.ts +15 -3
- package/src/resources/multiRecordResource.ts +17 -8
- package/src/resources/singleRecordResource.ts +6 -3
- package/src/resources/sqlResource.ts +22 -26
- package/src/runjs-context/contexts/base.ts +47 -6
- package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
- package/src/runjs-context/snippets/index.ts +3 -0
- package/src/runjs-context/snippets/scene/block/render-antd-icons.snippet.ts +46 -0
- package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +6 -4
- package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +15 -16
- package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
- package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +7 -7
- package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +24 -29
- package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +20 -21
- package/src/scheduler/ModelOperationScheduler.ts +304 -0
- package/src/types.ts +50 -4
- package/src/utils/__tests__/createCollectionContextMeta.test.ts +51 -0
- package/src/utils/__tests__/flows.test.ts +65 -0
- package/src/utils/__tests__/jsxTransform.test.ts +38 -0
- package/src/utils/__tests__/parsePathnameToViewParams.test.ts +25 -0
- package/src/utils/__tests__/pruneFilter.test.ts +38 -0
- package/src/utils/__tests__/safeGlobals.test.ts +23 -1
- package/src/utils/__tests__/utils.test.ts +114 -15
- package/src/utils/__tests__/variablesParams.test.ts +120 -0
- package/src/utils/associationObjectVariable.ts +180 -0
- package/src/utils/createCollectionContextMeta.ts +8 -3
- package/src/utils/createEphemeralContext.ts +142 -0
- package/src/utils/flows.ts +23 -0
- package/src/utils/index.ts +11 -2
- package/src/utils/jsxTransform.ts +39 -0
- package/src/utils/params-resolvers.ts +2 -2
- package/src/utils/parsePathnameToViewParams.ts +50 -6
- package/src/utils/pruneFilter.ts +41 -0
- package/src/utils/safeGlobals.ts +51 -4
- package/src/utils/schema-utils.ts +81 -3
- package/src/utils/serverContextParams.ts +5 -0
- package/src/utils/translation.ts +7 -2
- package/src/utils/variablesParams.ts +125 -42
- package/src/views/DialogComponent.tsx +1 -4
- package/src/views/DrawerComponent.tsx +19 -7
- package/src/views/PageComponent.tsx +2 -4
- package/src/views/ViewNavigation.ts +49 -43
- package/src/views/__tests__/FlowView.usePage.test.tsx +133 -0
- package/src/views/__tests__/ViewNavigation.test.ts +54 -34
- package/src/views/__tests__/useDialog.closeDestroy.test.tsx +132 -0
- package/src/views/createViewMeta.ts +179 -42
- package/src/views/useDialog.tsx +36 -24
- package/src/views/useDrawer.tsx +37 -24
- package/src/views/usePage.tsx +46 -27
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
export * from '@formily/reactive';
|
|
11
|
+
export { observer, getPageActive } from './observer';
|
|
@@ -0,0 +1,101 @@
|
|
|
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 { observer as originalObserver, IObserverOptions, ReactFC } from '@formily/reactive-react';
|
|
11
|
+
import React, { useMemo, useEffect, useRef } from 'react';
|
|
12
|
+
import { useFlowContext } from '../FlowContextProvider';
|
|
13
|
+
import { autorun } from '@formily/reactive';
|
|
14
|
+
import { FlowEngineContext } from '..';
|
|
15
|
+
|
|
16
|
+
type ObserverComponentProps<P, Options extends IObserverOptions> = Options extends {
|
|
17
|
+
forwardRef: true;
|
|
18
|
+
}
|
|
19
|
+
? P & {
|
|
20
|
+
ref?: 'ref' extends keyof P ? P['ref'] : React.RefAttributes<any>;
|
|
21
|
+
}
|
|
22
|
+
: React.PropsWithoutRef<P>;
|
|
23
|
+
|
|
24
|
+
export const observer = <P, Options extends IObserverOptions = IObserverOptions>(
|
|
25
|
+
Component: ReactFC<P>,
|
|
26
|
+
options?: Options,
|
|
27
|
+
): React.MemoExoticComponent<ReactFC<ObserverComponentProps<P, Options>>> => {
|
|
28
|
+
const ComponentWithDefaultScheduler = React.memo((props: any) => {
|
|
29
|
+
const ctx = useFlowContext();
|
|
30
|
+
const ctxRef = useRef(ctx);
|
|
31
|
+
ctxRef.current = ctx;
|
|
32
|
+
|
|
33
|
+
// Store the pending disposer to avoid creating multiple listeners
|
|
34
|
+
const pendingDisposerRef = useRef<(() => void) | null>(null);
|
|
35
|
+
|
|
36
|
+
// Cleanup on unmount
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
return () => {
|
|
39
|
+
if (pendingDisposerRef.current) {
|
|
40
|
+
pendingDisposerRef.current();
|
|
41
|
+
pendingDisposerRef.current = null;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const ObservedComponent = useMemo(
|
|
47
|
+
() =>
|
|
48
|
+
originalObserver(Component, {
|
|
49
|
+
scheduler(updater) {
|
|
50
|
+
const pageActive = getPageActive(ctxRef.current);
|
|
51
|
+
const tabActive = ctxRef.current?.tabActive?.value;
|
|
52
|
+
|
|
53
|
+
if (pageActive === false || tabActive === false) {
|
|
54
|
+
// Avoid stack overflow
|
|
55
|
+
setTimeout(() => {
|
|
56
|
+
// If there is already a pending updater, do nothing
|
|
57
|
+
if (pendingDisposerRef.current) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Delay the update until the page and tab become active
|
|
62
|
+
const disposer = autorun(() => {
|
|
63
|
+
if (
|
|
64
|
+
ctxRef.current?.pageActive?.value &&
|
|
65
|
+
(ctxRef.current?.tabActive?.value === true || ctxRef.current?.tabActive?.value === undefined)
|
|
66
|
+
) {
|
|
67
|
+
updater();
|
|
68
|
+
disposer?.();
|
|
69
|
+
pendingDisposerRef.current = null;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
pendingDisposerRef.current = disposer;
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// If we are updating immediately, clear any pending disposer
|
|
78
|
+
if (pendingDisposerRef.current) {
|
|
79
|
+
pendingDisposerRef.current();
|
|
80
|
+
pendingDisposerRef.current = null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
updater();
|
|
84
|
+
},
|
|
85
|
+
...options,
|
|
86
|
+
}),
|
|
87
|
+
[],
|
|
88
|
+
);
|
|
89
|
+
return <ObservedComponent {...props} />;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
ComponentWithDefaultScheduler.displayName = `ComponentWithDefaultScheduler`;
|
|
93
|
+
|
|
94
|
+
return ComponentWithDefaultScheduler as React.MemoExoticComponent<ReactFC<ObserverComponentProps<P, Options>>>;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export function getPageActive(context: FlowEngineContext): boolean | undefined {
|
|
98
|
+
return typeof context?.pageActive?.value === 'boolean'
|
|
99
|
+
? context?.pageActive?.value
|
|
100
|
+
: context?.view?.inputArgs.pageActive;
|
|
101
|
+
}
|
|
@@ -95,6 +95,7 @@ export abstract class BaseRecordResource<TData = any> extends APIResource<TData>
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
async runAction<TData = any, TMeta = any>(action: string, options: any) {
|
|
98
|
+
const { rawResponse, ...rest } = options;
|
|
98
99
|
const config = this.mergeRequestConfig(
|
|
99
100
|
_.omit(this.request, ['params', 'data', 'method']),
|
|
100
101
|
{
|
|
@@ -102,14 +103,18 @@ export abstract class BaseRecordResource<TData = any> extends APIResource<TData>
|
|
|
102
103
|
url: this.buildURL(action),
|
|
103
104
|
},
|
|
104
105
|
this.runActionOptions?.[action],
|
|
105
|
-
|
|
106
|
+
rest,
|
|
106
107
|
);
|
|
107
108
|
if (['create', 'update', 'firstOrCreate', 'updateOrCreate'].includes(action)) {
|
|
108
109
|
config.params = config.params || {};
|
|
109
110
|
config.params.updateAssociationValues = this.getUpdateAssociationValues();
|
|
110
111
|
}
|
|
111
112
|
try {
|
|
112
|
-
const
|
|
113
|
+
const response = await this.api.request(config);
|
|
114
|
+
if (rawResponse) {
|
|
115
|
+
return response;
|
|
116
|
+
}
|
|
117
|
+
const { data } = response;
|
|
113
118
|
if (!data?.data) {
|
|
114
119
|
return data;
|
|
115
120
|
}
|
|
@@ -227,8 +232,15 @@ export abstract class BaseRecordResource<TData = any> extends APIResource<TData>
|
|
|
227
232
|
return this;
|
|
228
233
|
}
|
|
229
234
|
|
|
235
|
+
jsonStringify(value: any): string {
|
|
236
|
+
if (value !== null && typeof value === 'object') {
|
|
237
|
+
return JSON.stringify(value);
|
|
238
|
+
}
|
|
239
|
+
return value;
|
|
240
|
+
}
|
|
241
|
+
|
|
230
242
|
setFilterByTk(filterByTk: any) {
|
|
231
|
-
return this.addRequestParameter('filterByTk', filterByTk);
|
|
243
|
+
return this.addRequestParameter('filterByTk', this.jsonStringify(filterByTk));
|
|
232
244
|
}
|
|
233
245
|
|
|
234
246
|
getFilterByTk(): any {
|
|
@@ -110,10 +110,14 @@ export class MultiRecordResource<TDataItem = any> extends BaseRecordResource<TDa
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
async create(data: TDataItem, options?: AxiosRequestConfig): Promise<void> {
|
|
113
|
+
async create(data: TDataItem, options?: AxiosRequestConfig & { refresh?: boolean }): Promise<void> {
|
|
114
114
|
const config = this.mergeRequestConfig({ data }, this.createActionOptions, options);
|
|
115
|
-
await this.runAction('create', config);
|
|
116
|
-
|
|
115
|
+
const res = await this.runAction('create', config);
|
|
116
|
+
this.emit('saved', data);
|
|
117
|
+
if (options?.refresh !== false) {
|
|
118
|
+
await this.refresh();
|
|
119
|
+
}
|
|
120
|
+
return res;
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
async get(filterByTk: any): Promise<TDataItem | undefined> {
|
|
@@ -129,17 +133,19 @@ export class MultiRecordResource<TDataItem = any> extends BaseRecordResource<TDa
|
|
|
129
133
|
}
|
|
130
134
|
|
|
131
135
|
async update(filterByTk: string | number, data: Partial<TDataItem>, options?: AxiosRequestConfig): Promise<void> {
|
|
136
|
+
const result = data;
|
|
132
137
|
const config = this.mergeRequestConfig(
|
|
133
138
|
{
|
|
134
139
|
params: {
|
|
135
140
|
filterByTk,
|
|
136
141
|
},
|
|
137
|
-
data,
|
|
142
|
+
data: result,
|
|
138
143
|
},
|
|
139
144
|
this.updateActionOptions,
|
|
140
145
|
options,
|
|
141
146
|
);
|
|
142
147
|
await this.runAction('update', config);
|
|
148
|
+
this.emit('saved', data);
|
|
143
149
|
await this.refresh();
|
|
144
150
|
}
|
|
145
151
|
|
|
@@ -152,20 +158,23 @@ export class MultiRecordResource<TDataItem = any> extends BaseRecordResource<TDa
|
|
|
152
158
|
}
|
|
153
159
|
|
|
154
160
|
async destroy(
|
|
155
|
-
filterByTk: string | number | string[] | number[] | TDataItem | TDataItem[],
|
|
161
|
+
filterByTk: string | number | string[] | number[] | TDataItem | TDataItem[] | object,
|
|
156
162
|
options?: AxiosRequestConfig,
|
|
157
163
|
): Promise<void> {
|
|
158
164
|
const config = this.mergeRequestConfig(
|
|
159
165
|
{
|
|
160
166
|
params: {
|
|
161
|
-
filterByTk:
|
|
162
|
-
return typeof item === 'object' ? item['id'] : item; // TODO: ID 字段还需要根据实际情况更改
|
|
163
|
-
}),
|
|
167
|
+
filterByTk: this.jsonStringify(filterByTk),
|
|
164
168
|
},
|
|
165
169
|
},
|
|
166
170
|
options,
|
|
167
171
|
);
|
|
168
172
|
await this.runAction('destroy', config);
|
|
173
|
+
const currentPage = this.getPage();
|
|
174
|
+
const lastPage = Math.ceil((this.getCount() - _.castArray(filterByTk).length) / this.getPageSize());
|
|
175
|
+
if (currentPage > lastPage) {
|
|
176
|
+
this.setPage(lastPage || 1);
|
|
177
|
+
}
|
|
169
178
|
await this.refresh();
|
|
170
179
|
}
|
|
171
180
|
|
|
@@ -33,26 +33,29 @@ export class SingleRecordResource<TData = any> extends BaseRecordResource<TData>
|
|
|
33
33
|
async save(data: TData, options?: AxiosRequestConfig & { refresh?: boolean }): Promise<void> {
|
|
34
34
|
const config = this.mergeRequestConfig(this.saveActionOptions, _.omit(options, ['refresh']));
|
|
35
35
|
let actionName = 'create';
|
|
36
|
+
const result = data;
|
|
36
37
|
// 如果有 filterByTk,则表示是更新操作
|
|
37
38
|
if (!this.isNewRecord) {
|
|
38
39
|
config.params = config.params || {};
|
|
39
40
|
config.params.filterByTk = this.getFilterByTk();
|
|
40
41
|
actionName = 'update';
|
|
41
42
|
}
|
|
42
|
-
await this.runAction(actionName, {
|
|
43
|
+
const res = await this.runAction(actionName, {
|
|
43
44
|
...config,
|
|
44
|
-
data,
|
|
45
|
+
data: result,
|
|
45
46
|
});
|
|
47
|
+
this.emit('saved', data);
|
|
46
48
|
if (options?.refresh !== false) {
|
|
47
49
|
await this.refresh();
|
|
48
50
|
}
|
|
51
|
+
return res;
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
async destroy(options?: AxiosRequestConfig): Promise<void> {
|
|
52
55
|
const config = this.mergeRequestConfig(
|
|
53
56
|
{
|
|
54
57
|
params: {
|
|
55
|
-
filterByTk: this.request.params.filterByTk,
|
|
58
|
+
filterByTk: this.jsonStringify(this.request.params.filterByTk),
|
|
56
59
|
},
|
|
57
60
|
},
|
|
58
61
|
options,
|
|
@@ -11,6 +11,7 @@ import { observable } from '@formily/reactive';
|
|
|
11
11
|
import _ from 'lodash';
|
|
12
12
|
import { FlowContext, FlowEngineContext } from '../flowContext';
|
|
13
13
|
import { BaseRecordResource } from './baseRecordResource';
|
|
14
|
+
import { parseLiquidContext, transformSQL } from '@nocobase/utils/client';
|
|
14
15
|
|
|
15
16
|
type SQLRunOptions = {
|
|
16
17
|
bind?: Record<string, any>;
|
|
@@ -25,20 +26,6 @@ type SQLSaveOptions = {
|
|
|
25
26
|
dataSourceKey?: string;
|
|
26
27
|
};
|
|
27
28
|
|
|
28
|
-
function transformSQL(template: string) {
|
|
29
|
-
let index = 1;
|
|
30
|
-
const bind = {};
|
|
31
|
-
|
|
32
|
-
const sql = template.replace(/{{\s*([^}]+)\s*}}/g, (_, expr) => {
|
|
33
|
-
const key = `__var${index}`;
|
|
34
|
-
bind[key] = `{{${expr.trim()}}}`;
|
|
35
|
-
index++;
|
|
36
|
-
return `$${key}`;
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
return { sql, bind };
|
|
40
|
-
}
|
|
41
|
-
|
|
42
29
|
export class FlowSQLRepository {
|
|
43
30
|
protected ctx: FlowEngineContext;
|
|
44
31
|
|
|
@@ -56,16 +43,17 @@ export class FlowSQLRepository {
|
|
|
56
43
|
}
|
|
57
44
|
|
|
58
45
|
async run(sql: string, options: SQLRunOptions = {}) {
|
|
59
|
-
const
|
|
60
|
-
const
|
|
46
|
+
const { sql: transformedSQL, bind, liquidContext } = await transformSQL(sql);
|
|
47
|
+
const resolved = await this.ctx.resolveJsonTemplate({ bind, liquidContext });
|
|
48
|
+
const parsedSQL = await parseLiquidContext(transformedSQL, resolved.liquidContext);
|
|
61
49
|
const { data } = await this.ctx.api.request({
|
|
62
50
|
method: 'POST',
|
|
63
51
|
url: 'flowSql:run',
|
|
64
52
|
data: {
|
|
65
|
-
sql:
|
|
53
|
+
sql: parsedSQL,
|
|
66
54
|
...options,
|
|
67
55
|
bind: {
|
|
68
|
-
...bind,
|
|
56
|
+
...resolved.bind,
|
|
69
57
|
...options.bind,
|
|
70
58
|
},
|
|
71
59
|
},
|
|
@@ -91,7 +79,7 @@ export class FlowSQLRepository {
|
|
|
91
79
|
uid,
|
|
92
80
|
},
|
|
93
81
|
});
|
|
94
|
-
const bind = await this.ctx.resolveJsonTemplate(response.data.data || {});
|
|
82
|
+
const { bind, liquidContext } = await this.ctx.resolveJsonTemplate(response.data.data || {});
|
|
95
83
|
const { data } = await this.ctx.api.request({
|
|
96
84
|
method: 'POST',
|
|
97
85
|
url: 'flowSql:runById',
|
|
@@ -100,8 +88,9 @@ export class FlowSQLRepository {
|
|
|
100
88
|
...options,
|
|
101
89
|
bind: {
|
|
102
90
|
...bind,
|
|
103
|
-
...options
|
|
91
|
+
...options?.bind,
|
|
104
92
|
},
|
|
93
|
+
liquidContext,
|
|
105
94
|
},
|
|
106
95
|
});
|
|
107
96
|
return data?.data;
|
|
@@ -233,20 +222,25 @@ export class SQLResource<TData = any> extends BaseRecordResource<TData> {
|
|
|
233
222
|
return this;
|
|
234
223
|
}
|
|
235
224
|
|
|
225
|
+
setLiquidContext(liquidContext: Record<string, any>) {
|
|
226
|
+
this.request.data.liquidContext = liquidContext;
|
|
227
|
+
return this;
|
|
228
|
+
}
|
|
229
|
+
|
|
236
230
|
async run() {
|
|
237
231
|
return this._debugEnabled ? await this.runBySQL() : await this.runById();
|
|
238
232
|
}
|
|
239
233
|
|
|
240
234
|
async runBySQL() {
|
|
241
235
|
const sql = this._sql;
|
|
242
|
-
const
|
|
243
|
-
const
|
|
236
|
+
const { sql: transformedSQL, bind, liquidContext } = await transformSQL(sql);
|
|
237
|
+
const resolved = await this.context.resolveJsonTemplate({ bind, liquidContext });
|
|
244
238
|
const options = _.cloneDeep({
|
|
245
239
|
method: 'post',
|
|
246
240
|
...this.getRefreshRequestOptions(),
|
|
247
241
|
});
|
|
248
|
-
options.data.
|
|
249
|
-
options.data.
|
|
242
|
+
options.data.sql = await parseLiquidContext(transformedSQL, resolved.liquidContext);
|
|
243
|
+
options.data.bind = resolved.bind;
|
|
250
244
|
return await this.runAction<TData, any>('run', options);
|
|
251
245
|
}
|
|
252
246
|
|
|
@@ -257,8 +251,9 @@ export class SQLResource<TData = any> extends BaseRecordResource<TData> {
|
|
|
257
251
|
uid: this.request.data.uid,
|
|
258
252
|
},
|
|
259
253
|
});
|
|
260
|
-
const bind = await this.context.resolveJsonTemplate(data);
|
|
254
|
+
const { bind, liquidContext } = await this.context.resolveJsonTemplate(data);
|
|
261
255
|
this.setBind(bind);
|
|
256
|
+
this.setLiquidContext(liquidContext);
|
|
262
257
|
return await this.runAction<TData, any>('runById', {
|
|
263
258
|
method: 'post',
|
|
264
259
|
...this.getRefreshRequestOptions(),
|
|
@@ -281,10 +276,11 @@ export class SQLResource<TData = any> extends BaseRecordResource<TData> {
|
|
|
281
276
|
try {
|
|
282
277
|
this.clearError();
|
|
283
278
|
this.loading = true;
|
|
279
|
+
this.emit('loading');
|
|
284
280
|
const { data, meta } = await this.run();
|
|
285
281
|
this.setData(data).setMeta(meta);
|
|
286
|
-
this.emit('refresh');
|
|
287
282
|
this.loading = false;
|
|
283
|
+
this.emit('refresh');
|
|
288
284
|
resolve();
|
|
289
285
|
} catch (error) {
|
|
290
286
|
this.setError(error);
|
|
@@ -44,12 +44,33 @@ export function defineBaseContextMeta() {
|
|
|
44
44
|
language: 'Current active language code.',
|
|
45
45
|
},
|
|
46
46
|
},
|
|
47
|
-
React:
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
React:
|
|
48
|
+
'React namespace providing React library functions and hooks (available in RunJS environment). Recommended access path: `ctx.libs.React`.',
|
|
49
|
+
ReactDOM:
|
|
50
|
+
'ReactDOM client API including createRoot for rendering React components. Also available via `ctx.libs.ReactDOM`.',
|
|
51
|
+
antd: 'Ant Design component library. Recommended access path: `ctx.libs.antd`.',
|
|
52
|
+
libs: {
|
|
53
|
+
description: 'Namespace for third-party and shared libraries. Includes React, ReactDOM, Ant Design, and dayjs.',
|
|
54
|
+
detail: 'Libraries namespace',
|
|
55
|
+
properties: {
|
|
56
|
+
React: 'React namespace (same as ctx.React).',
|
|
57
|
+
ReactDOM: 'ReactDOM client API (same as ctx.ReactDOM).',
|
|
58
|
+
antd: 'Ant Design component library (same as ctx.antd).',
|
|
59
|
+
dayjs: 'dayjs date-time utility library.',
|
|
60
|
+
antdIcons: 'Ant Design icons library. Example: `ctx.libs.antdIcons.PlusOutlined`.',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
50
63
|
},
|
|
51
64
|
methods: {
|
|
52
65
|
t: 'Internationalization function for translating text. Parameters: (key: string, variables?: object) => string. Example: `ctx.t("Hello {name}", { name: "World" })`',
|
|
66
|
+
render: {
|
|
67
|
+
description:
|
|
68
|
+
'Render into container. Accepts ReactElement, DOM Node/Fragment, or HTML string. Parameters: (vnode: ReactElement | Node | DocumentFragment | string, container?: HTMLElement|ElementProxy) => Root|null. Example: `ctx.render(<div>Hello</div>)` or `ctx.render("<b>hi</b>")`',
|
|
69
|
+
detail: 'ReactDOM Root',
|
|
70
|
+
completion: {
|
|
71
|
+
insertText: `ctx.render(<div />)`,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
53
74
|
requireAsync:
|
|
54
75
|
'Asynchronously load external libraries from URL. Parameters: (url: string) => Promise<any>. Example: `const lodash = await ctx.requireAsync("https://cdn.jsdelivr.net/npm/lodash")`',
|
|
55
76
|
importAsync:
|
|
@@ -121,12 +142,32 @@ export function defineBaseContextMeta() {
|
|
|
121
142
|
language: '当前激活的语言代码',
|
|
122
143
|
},
|
|
123
144
|
},
|
|
124
|
-
React: 'React 命名空间,提供 React 函数与 hooks(RunJS
|
|
125
|
-
ReactDOM: 'ReactDOM 客户端 API,含 createRoot
|
|
126
|
-
antd: 'Ant Design 组件库(RunJS
|
|
145
|
+
React: 'React 命名空间,提供 React 函数与 hooks(RunJS 环境中可用)。推荐使用 `ctx.libs.React` 访问。',
|
|
146
|
+
ReactDOM: 'ReactDOM 客户端 API,含 createRoot 等渲染方法。推荐通过 `ctx.libs.ReactDOM` 访问。',
|
|
147
|
+
antd: 'Ant Design 组件库(RunJS 环境中可用)。推荐使用 `ctx.libs.antd` 访问。',
|
|
148
|
+
libs: {
|
|
149
|
+
description:
|
|
150
|
+
'第三方/通用库的统一命名空间,包含 React、ReactDOM、Ant Design、dayjs 等。后续新增库会优先挂在此处。',
|
|
151
|
+
detail: '通用库命名空间',
|
|
152
|
+
properties: {
|
|
153
|
+
React: 'React 命名空间(等价于 ctx.React)。',
|
|
154
|
+
ReactDOM: 'ReactDOM 客户端 API(等价于 ctx.ReactDOM)。',
|
|
155
|
+
antd: 'Ant Design 组件库(等价于 ctx.antd)。',
|
|
156
|
+
dayjs: 'dayjs 日期时间工具库。',
|
|
157
|
+
antdIcons: 'Ant Design 图标库。 例如:`ctx.libs.antdIcons.PlusOutlined`。',
|
|
158
|
+
},
|
|
159
|
+
},
|
|
127
160
|
},
|
|
128
161
|
methods: {
|
|
129
162
|
t: '国际化函数,用于翻译文案。参数:(key: string, variables?: object) => string。示例:`ctx.t("你好 {name}", { name: "世界" })`',
|
|
163
|
+
render: {
|
|
164
|
+
description:
|
|
165
|
+
'渲染到容器。vnode 支持 ReactElement、DOM 节点/片段、或 HTML 字符串。参数:(vnode: ReactElement | Node | DocumentFragment | string, container?: HTMLElement|ElementProxy) => Root|null。示例:`ctx.render(<div />)` 或 `ctx.render("<b>hi</b>")`',
|
|
166
|
+
detail: 'ReactDOM Root',
|
|
167
|
+
completion: {
|
|
168
|
+
insertText: `ctx.render(<div />)`,
|
|
169
|
+
},
|
|
170
|
+
},
|
|
130
171
|
requireAsync:
|
|
131
172
|
'按 URL 异步加载外部库。参数:(url: string) => Promise<any>。示例:`const lodash = await ctx.requireAsync("https://cdn.jsdelivr.net/npm/lodash")`',
|
|
132
173
|
importAsync:
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
|
|
12
|
+
const snippet: SnippetModule = {
|
|
13
|
+
contexts: ['*'],
|
|
14
|
+
prefix: 'sn-clipboard-copy',
|
|
15
|
+
label: 'Copy text to clipboard (function)',
|
|
16
|
+
description: 'A reusable function that copies a given string to the clipboard.',
|
|
17
|
+
locales: {
|
|
18
|
+
'zh-CN': {
|
|
19
|
+
label: '复制文本到剪贴板(函数)',
|
|
20
|
+
description: '通用函数:接受一个字符串参数并复制到剪贴板。',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
content: `
|
|
24
|
+
// A general utility function that copies text to clipboard.
|
|
25
|
+
// Usage:
|
|
26
|
+
// const ok = await copyTextToClipboard('Hello');
|
|
27
|
+
// if (ok) { /* success */ } else { /* handle failure */ }
|
|
28
|
+
async function copyTextToClipboard(text) {
|
|
29
|
+
const s = String(text ?? '');
|
|
30
|
+
try {
|
|
31
|
+
if (navigator?.clipboard?.writeText) {
|
|
32
|
+
await navigator.clipboard.writeText(s);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
} catch (_) {
|
|
36
|
+
// Fallback below
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
`,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default snippet;
|
|
@@ -22,10 +22,13 @@ const snippets: Record<string, () => Promise<any>> = {
|
|
|
22
22
|
'global/open-view-drawer': () => import('./global/open-view-drawer.snippet'),
|
|
23
23
|
'global/open-view-dialog': () => import('./global/open-view-dialog.snippet'),
|
|
24
24
|
'global/query-selector': () => import('./global/query-selector.snippet'),
|
|
25
|
+
'global/clipboard-copy-text': () => import('./global/clipboard-copy-text.snippet'),
|
|
25
26
|
// libs
|
|
26
27
|
'scene/block/echarts-init': () => import('./scene/block/echarts-init.snippet'),
|
|
27
28
|
// scene/block
|
|
28
29
|
'scene/block/render-react': () => import('./scene/block/render-react.snippet'),
|
|
30
|
+
'scene/block/render-react-jsx': () => import('./scene/block/render-react-jsx.snippet'),
|
|
31
|
+
'scene/block/render-antd-icons': () => import('./scene/block/render-antd-icons.snippet'),
|
|
29
32
|
'scene/block/render-button-handler': () => import('./scene/block/render-button-handler.snippet'),
|
|
30
33
|
'scene/block/add-event-listener': () => import('./scene/block/add-event-listener.snippet'),
|
|
31
34
|
'scene/block/chartjs-bar': () => import('./scene/block/chartjs-bar.snippet'),
|
|
@@ -0,0 +1,46 @@
|
|
|
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 { JSBlockRunJSContext } from '../../../contexts/JSBlockRunJSContext';
|
|
12
|
+
|
|
13
|
+
const snippet: SnippetModule = {
|
|
14
|
+
contexts: [JSBlockRunJSContext],
|
|
15
|
+
prefix: 'sn-jsb-antd-icons',
|
|
16
|
+
label: 'Render Ant Design icons',
|
|
17
|
+
description: 'Render Ant Design icons with buttons inside the block container',
|
|
18
|
+
locales: {
|
|
19
|
+
'zh-CN': {
|
|
20
|
+
label: '渲染 Ant Design 图标',
|
|
21
|
+
description: '在区块容器中使用 Ant Design 图标与按钮进行渲染',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
content: `
|
|
25
|
+
// Render Ant Design icons with buttons via ctx.libs
|
|
26
|
+
const { React, antd, antdIcons } = ctx.libs;
|
|
27
|
+
const { Button, Space } = antd;
|
|
28
|
+
const { PlusOutlined, EditOutlined, DeleteOutlined } = antdIcons;
|
|
29
|
+
|
|
30
|
+
const IconButtons = () => (
|
|
31
|
+
<Space style={{ padding: 12 }}>
|
|
32
|
+
<Button type="primary" icon={<PlusOutlined />}>
|
|
33
|
+
{ctx.t('Add')}
|
|
34
|
+
</Button>
|
|
35
|
+
<Button icon={<EditOutlined />}>{ctx.t('Edit')}</Button>
|
|
36
|
+
<Button danger icon={<DeleteOutlined />}>
|
|
37
|
+
{ctx.t('Delete')}
|
|
38
|
+
</Button>
|
|
39
|
+
</Space>
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
ctx.render(<IconButtons />);
|
|
43
|
+
`,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default snippet;
|
|
@@ -22,11 +22,13 @@ const snippet: SnippetModule = {
|
|
|
22
22
|
},
|
|
23
23
|
},
|
|
24
24
|
content: `
|
|
25
|
-
const {
|
|
26
|
-
const { Button } = antd;
|
|
25
|
+
const { Button } = ctx.libs.antd;
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
ctx.render(
|
|
28
|
+
<Button type="primary" onClick={() => ctx.message.success(ctx.t('Clicked!'))}>
|
|
29
|
+
{ctx.t('Button')}
|
|
30
|
+
</Button>
|
|
31
|
+
);
|
|
30
32
|
`,
|
|
31
33
|
};
|
|
32
34
|
|
|
@@ -22,29 +22,28 @@ const snippet: SnippetModule = {
|
|
|
22
22
|
},
|
|
23
23
|
},
|
|
24
24
|
content: `
|
|
25
|
-
const { Card, Descriptions, Tag
|
|
26
|
-
const { createElement: h } = ctx.React;
|
|
25
|
+
const { Card, Descriptions, Tag } = ctx.libs.antd;
|
|
27
26
|
|
|
28
27
|
if (!ctx.record) {
|
|
29
|
-
ctx.
|
|
28
|
+
ctx.render('<div style="padding:16px;color:#999;">' + ctx.t('No record data') + '</div>');
|
|
30
29
|
return;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
const record = ctx.record;
|
|
34
33
|
|
|
35
|
-
ctx.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
record.createdAt ? new Date(record.createdAt).toLocaleString() : '-'
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
34
|
+
ctx.render(
|
|
35
|
+
<Card title={ctx.t('Record Details')} bordered style={{ margin: 0 }}>
|
|
36
|
+
<Descriptions column={2} size="small">
|
|
37
|
+
<Descriptions.Item label={ctx.t('ID')}>{record.id || '-'}</Descriptions.Item>
|
|
38
|
+
<Descriptions.Item label={ctx.t('Status')}>
|
|
39
|
+
<Tag color={record.status === 'active' ? 'green' : 'default'}>{record.status || '-'}</Tag>
|
|
40
|
+
</Descriptions.Item>
|
|
41
|
+
<Descriptions.Item label={ctx.t('Title')}>{record.title || '-'}</Descriptions.Item>
|
|
42
|
+
<Descriptions.Item label={ctx.t('Created At')}>
|
|
43
|
+
{record.createdAt ? new Date(record.createdAt).toLocaleString() : '-'}
|
|
44
|
+
</Descriptions.Item>
|
|
45
|
+
</Descriptions>
|
|
46
|
+
</Card>
|
|
48
47
|
);
|
|
49
48
|
|
|
50
49
|
`,
|
|
@@ -0,0 +1,39 @@
|
|
|
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 { JSBlockRunJSContext } from '../../../contexts/JSBlockRunJSContext';
|
|
12
|
+
|
|
13
|
+
const snippet: SnippetModule = {
|
|
14
|
+
contexts: [JSBlockRunJSContext],
|
|
15
|
+
prefix: 'sn-react-jsx',
|
|
16
|
+
label: 'Render React (JSX)',
|
|
17
|
+
description: 'Render a simple React component using JSX syntax',
|
|
18
|
+
locales: {
|
|
19
|
+
'zh-CN': {
|
|
20
|
+
label: '渲染 React(JSX)',
|
|
21
|
+
description: '使用 JSX 语法渲染一个简单的 React 组件',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
content: `
|
|
25
|
+
// Render a React component with JSX
|
|
26
|
+
const { React } = ctx.libs;
|
|
27
|
+
|
|
28
|
+
const App = () => (
|
|
29
|
+
<div style={{ padding: 12 }}>
|
|
30
|
+
<h3 style={{ margin: 0, color: '#1890ff' }}>Hello JSX</h3>
|
|
31
|
+
<div style={{ color: '#555' }}>This block is rendered by JSX.</div>
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
ctx.render(<App />);
|
|
36
|
+
`,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default snippet;
|