mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-01 19:38:16 +08:00
fix: 修复crud 中 drawer 动作后不刷新问题 Close: #6903
This commit is contained in:
parent
06ad5abe50
commit
b337c1590d
83
.vscode/launch.json
vendored
83
.vscode/launch.json
vendored
@ -1,71 +1,18 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Jest All",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
||||
"args": ["--runInBand"],
|
||||
"sourceMaps": true,
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"disableOptimisticBPs": true,
|
||||
"runtimeExecutable": "/usr/local/bin/node",
|
||||
"windows": {
|
||||
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Jest Current File",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
||||
"args": [
|
||||
"--no-cache",
|
||||
"--runInBand",
|
||||
"${relativeFile}"
|
||||
],
|
||||
"sourceMaps": true,
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"disableOptimisticBPs": true,
|
||||
"runtimeExecutable": "/usr/local/bin/node",
|
||||
"windows": {
|
||||
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Jest Current File Specified test",
|
||||
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
||||
"args": [
|
||||
"--no-cache",
|
||||
"--runInBand",
|
||||
"${relativeFile}",
|
||||
"-t",
|
||||
"${input:testName}"
|
||||
],
|
||||
"sourceMaps": true,
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"disableOptimisticBPs": true,
|
||||
"runtimeExecutable": "/usr/local/bin/node",
|
||||
"windows": {
|
||||
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "testName",
|
||||
"type": "promptString",
|
||||
"default": "",
|
||||
"description": "Run only tests with a name that matches the regex pattern."
|
||||
"version": "1.0.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Jest: current file",
|
||||
//"env": { "NODE_ENV": "test" },
|
||||
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
||||
"args": ["${fileBasenameNoExtension}"],
|
||||
"console": "integratedTerminal",
|
||||
"disableOptimisticBPs": true,
|
||||
"windows": {
|
||||
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -160,7 +160,12 @@ export class RootRenderer extends React.Component<RootRendererProps> {
|
||||
window.open(mailto);
|
||||
} else if (action.actionType === 'dialog') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDialog(ctx, undefined, action.callback, delegate);
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
action.callback,
|
||||
delegate || (this.context as any)
|
||||
);
|
||||
} else if (action.actionType === 'drawer') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDrawer(ctx, undefined, undefined, delegate);
|
||||
@ -323,9 +328,14 @@ export class RootRenderer extends React.Component<RootRendererProps> {
|
||||
actionType: 'dialog',
|
||||
dialog: dialog
|
||||
});
|
||||
store.openDialog(ctx, undefined, confirmed => {
|
||||
resolve(confirmed);
|
||||
});
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
confirmed => {
|
||||
resolve(confirmed);
|
||||
},
|
||||
this.context as any
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,8 @@ export interface ScopedComponentType extends React.Component<RendererProps> {
|
||||
}
|
||||
|
||||
export interface IScopedContext {
|
||||
rendererType?: string;
|
||||
component?: ScopedComponentType;
|
||||
parent?: AliasIScopedContext;
|
||||
children?: AliasIScopedContext[];
|
||||
registerComponent: (component: ScopedComponentType) => void;
|
||||
@ -69,6 +71,10 @@ export interface IScopedContext {
|
||||
send: (target: string, ctx: RendererData) => void;
|
||||
close: (target: string) => void;
|
||||
closeById: (target: string) => void;
|
||||
getComponentsByRefPath: (
|
||||
session: string,
|
||||
path: string
|
||||
) => ScopedComponentType[];
|
||||
}
|
||||
type AliasIScopedContext = IScopedContext;
|
||||
|
||||
@ -78,14 +84,18 @@ export const ScopedContext = React.createContext(rootScopedContext);
|
||||
function createScopedTools(
|
||||
path?: string,
|
||||
parent?: AliasIScopedContext,
|
||||
env?: RendererEnv
|
||||
env?: RendererEnv,
|
||||
rendererType?: string
|
||||
): IScopedContext {
|
||||
const components: Array<ScopedComponentType> = [];
|
||||
const self = {
|
||||
const self: IScopedContext = {
|
||||
rendererType,
|
||||
component: undefined,
|
||||
parent,
|
||||
registerComponent(component: ScopedComponentType) {
|
||||
// 不要把自己注册在自己的 Scoped 上,自己的 Scoped 是给子节点们注册的。
|
||||
if (component.props.$path === path && parent) {
|
||||
self.component = component;
|
||||
return parent.registerComponent(component);
|
||||
}
|
||||
|
||||
@ -404,7 +414,8 @@ export function HocScoped<
|
||||
env: RendererEnv;
|
||||
}
|
||||
>(
|
||||
ComposedComponent: React.ComponentType<T>
|
||||
ComposedComponent: React.ComponentType<T>,
|
||||
rendererType?: string
|
||||
): React.ComponentType<
|
||||
T & {
|
||||
scopeRef?: (ref: any) => void;
|
||||
@ -430,7 +441,8 @@ export function HocScoped<
|
||||
this.scoped = createScopedTools(
|
||||
this.props.$path,
|
||||
context,
|
||||
this.props.env
|
||||
this.props.env,
|
||||
rendererType
|
||||
);
|
||||
|
||||
const scopeRef = props.scopeRef;
|
||||
|
@ -186,7 +186,7 @@ export function registerRenderer(config: RendererConfig): RendererConfig {
|
||||
}
|
||||
|
||||
if (config.isolateScope) {
|
||||
config.component = Scoped(config.component);
|
||||
config.component = Scoped(config.component, config.type);
|
||||
}
|
||||
|
||||
const idx = findIndex(
|
||||
|
@ -1133,7 +1133,12 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
action.target &&
|
||||
this.reloadTarget(filterTarget(action.target, values), values);
|
||||
} else if (action.actionType === 'dialog') {
|
||||
store.openDialog(data, undefined, action.callback);
|
||||
store.openDialog(
|
||||
data,
|
||||
undefined,
|
||||
action.callback,
|
||||
delegate || (this.context as any)
|
||||
);
|
||||
} else if (action.actionType === 'drawer') {
|
||||
store.openDrawer(data);
|
||||
} else if (isEffectiveApi(action.api || api, values)) {
|
||||
@ -1259,7 +1264,12 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
this.validate(true);
|
||||
} else if (action.actionType === 'dialog') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDialog(data, undefined, action.callback);
|
||||
store.openDialog(
|
||||
data,
|
||||
undefined,
|
||||
action.callback,
|
||||
delegate || (this.context as any)
|
||||
);
|
||||
} else if (action.actionType === 'drawer') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDrawer(data);
|
||||
@ -1428,9 +1438,14 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
actionType: 'dialog',
|
||||
dialog: dialog
|
||||
});
|
||||
store.openDialog(ctx, undefined, confirmed => {
|
||||
resolve(confirmed);
|
||||
});
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
confirmed => {
|
||||
resolve(confirmed);
|
||||
},
|
||||
this.context as any
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
531
packages/amis/__tests__/renderers/CRUDReload.test.tsx
Normal file
531
packages/amis/__tests__/renderers/CRUDReload.test.tsx
Normal file
@ -0,0 +1,531 @@
|
||||
import {render, fireEvent, waitFor} from '@testing-library/react';
|
||||
import '../../src';
|
||||
import {render as amisRender} from '../../src';
|
||||
import {makeEnv, wait} from '../helper';
|
||||
jest.useRealTimers();
|
||||
|
||||
// 验证 crud 里面的 ajax 动作,结束后是否刷新 crud
|
||||
test('CRUD reload ajax1', async () => {
|
||||
let listApiCalledCount = 0;
|
||||
const mockFetcher = jest.fn().mockImplementation((api: any) => {
|
||||
if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
listApiCalledCount++;
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0,
|
||||
data: {
|
||||
items: [{id: 1, a: 'a1', b: 'b1'}]
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
const {container} = render(
|
||||
amisRender(
|
||||
{
|
||||
type: 'page',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: '/api/mock2/sample',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
label: 'ID'
|
||||
},
|
||||
{
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
label: 'B'
|
||||
},
|
||||
{
|
||||
label: '操作',
|
||||
type: 'operation',
|
||||
buttons: [
|
||||
{
|
||||
label: '保存',
|
||||
type: 'button',
|
||||
actionType: 'ajax',
|
||||
api: '/api/mock2/sample/${id}'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{},
|
||||
makeEnv({fetcher: mockFetcher})
|
||||
)
|
||||
);
|
||||
await wait(200);
|
||||
const saveBtn = container.querySelectorAll('tbody>tr button')[0];
|
||||
expect(saveBtn).toBeTruthy();
|
||||
fireEvent.click(saveBtn);
|
||||
await waitFor(() => {
|
||||
expect(mockFetcher).toBeCalledTimes(3);
|
||||
});
|
||||
expect(listApiCalledCount).toBe(2);
|
||||
});
|
||||
|
||||
// 如果配置了 reload none 则不刷新
|
||||
test('CRUD reload ajax2', async () => {
|
||||
let listApiCalledCount = 0;
|
||||
const mockFetcher = jest.fn().mockImplementation((api: any) => {
|
||||
if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
listApiCalledCount++;
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0,
|
||||
data: {
|
||||
items: [{id: 1, a: 'a1', b: 'b1'}]
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
const {container} = render(
|
||||
amisRender(
|
||||
{
|
||||
type: 'page',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: '/api/mock2/sample',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
label: 'ID'
|
||||
},
|
||||
{
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
label: 'B'
|
||||
},
|
||||
{
|
||||
label: '操作',
|
||||
type: 'operation',
|
||||
buttons: [
|
||||
{
|
||||
label: '保存',
|
||||
type: 'button',
|
||||
actionType: 'ajax',
|
||||
api: '/api/mock2/sample/${id}'
|
||||
},
|
||||
{
|
||||
label: '保存2',
|
||||
type: 'button',
|
||||
actionType: 'ajax',
|
||||
api: '/api/mock2/sample/${id}',
|
||||
reload: 'none'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{},
|
||||
makeEnv({fetcher: mockFetcher})
|
||||
)
|
||||
);
|
||||
await wait(200);
|
||||
const saveBtn1 = container.querySelectorAll('tbody>tr button')[0];
|
||||
const saveBtn2 = container.querySelectorAll('tbody>tr button')[1];
|
||||
expect(saveBtn1).toBeTruthy();
|
||||
expect(saveBtn2).toBeTruthy();
|
||||
fireEvent.click(saveBtn2);
|
||||
await waitFor(() => {
|
||||
expect(mockFetcher).toBeCalledTimes(2);
|
||||
});
|
||||
expect(listApiCalledCount).toBe(1);
|
||||
fireEvent.click(saveBtn1);
|
||||
await waitFor(() => {
|
||||
expect(mockFetcher).toBeCalledTimes(4);
|
||||
});
|
||||
expect(listApiCalledCount).toBe(2);
|
||||
});
|
||||
|
||||
// dialog 提交后应该刷新 crud
|
||||
test('CRUD reload dialog1', async () => {
|
||||
let listApiCalledCount = 0;
|
||||
const mockFetcher = jest.fn().mockImplementation((api: any) => {
|
||||
if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
listApiCalledCount++;
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0,
|
||||
data: {
|
||||
items: [{id: 1, a: 'a1', b: 'b1'}]
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
const {container, getByText}: any = render(
|
||||
amisRender(
|
||||
{
|
||||
type: 'page',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: '/api/mock2/sample',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
label: 'ID'
|
||||
},
|
||||
{
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
label: 'B'
|
||||
},
|
||||
{
|
||||
label: '操作',
|
||||
type: 'operation',
|
||||
buttons: [
|
||||
{
|
||||
label: 'OpenDialog',
|
||||
type: 'button',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
body: {
|
||||
type: 'form',
|
||||
api: '/api/mock2/sample/${id}',
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{},
|
||||
makeEnv({fetcher: mockFetcher, getModalContainer: () => container})
|
||||
)
|
||||
);
|
||||
await wait(200);
|
||||
const saveBtn = container.querySelectorAll('tbody>tr button')[0];
|
||||
expect(saveBtn).toBeTruthy();
|
||||
fireEvent.click(saveBtn);
|
||||
await wait(300);
|
||||
|
||||
expect(getByText('确认')).toBeInTheDocument();
|
||||
fireEvent.click(getByText('取消'));
|
||||
await wait(300);
|
||||
|
||||
fireEvent.click(saveBtn);
|
||||
await wait(300);
|
||||
expect(getByText('确认')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(getByText('确认'));
|
||||
await wait(500);
|
||||
|
||||
expect(mockFetcher).toBeCalledTimes(3);
|
||||
expect(listApiCalledCount).toBe(2);
|
||||
});
|
||||
|
||||
// dialog 提交后如果配置列不刷新,则不刷新
|
||||
test('CRUD reload dialog2', async () => {
|
||||
let listApiCalledCount = 0;
|
||||
const mockFetcher = jest.fn().mockImplementation((api: any) => {
|
||||
if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
listApiCalledCount++;
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0,
|
||||
data: {
|
||||
items: [{id: 1, a: 'a1', b: 'b1'}]
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
const {container, getByText}: any = render(
|
||||
amisRender(
|
||||
{
|
||||
type: 'page',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: '/api/mock2/sample',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
label: 'ID'
|
||||
},
|
||||
{
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
label: 'B'
|
||||
},
|
||||
{
|
||||
label: '操作',
|
||||
type: 'operation',
|
||||
buttons: [
|
||||
{
|
||||
label: 'OpenDialog',
|
||||
type: 'button',
|
||||
actionType: 'dialog',
|
||||
reload: 'none',
|
||||
dialog: {
|
||||
body: {
|
||||
type: 'form',
|
||||
api: '/api/mock2/sample/${id}',
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{},
|
||||
makeEnv({fetcher: mockFetcher, getModalContainer: () => container})
|
||||
)
|
||||
);
|
||||
await wait(200);
|
||||
const saveBtn = container.querySelectorAll('tbody>tr button')[0];
|
||||
expect(saveBtn).toBeTruthy();
|
||||
fireEvent.click(saveBtn);
|
||||
await wait(300);
|
||||
|
||||
fireEvent.click(saveBtn);
|
||||
await wait(300);
|
||||
expect(getByText('确认')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(getByText('确认'));
|
||||
await wait(500);
|
||||
|
||||
expect(mockFetcher).toBeCalledTimes(2);
|
||||
expect(listApiCalledCount).toBe(1);
|
||||
});
|
||||
|
||||
// drawer 提交后应该刷新 crud
|
||||
test('CRUD reload drawer1', async () => {
|
||||
let listApiCalledCount = 0;
|
||||
const mockFetcher = jest.fn().mockImplementation((api: any) => {
|
||||
if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
listApiCalledCount++;
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0,
|
||||
data: {
|
||||
items: [{id: 1, a: 'a1', b: 'b1'}]
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
const {container, getByText}: any = render(
|
||||
amisRender(
|
||||
{
|
||||
type: 'page',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: '/api/mock2/sample',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
label: 'ID'
|
||||
},
|
||||
{
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
label: 'B'
|
||||
},
|
||||
{
|
||||
label: '操作',
|
||||
type: 'operation',
|
||||
buttons: [
|
||||
{
|
||||
label: 'openDrawer',
|
||||
type: 'button',
|
||||
actionType: 'drawer',
|
||||
drawer: {
|
||||
body: {
|
||||
type: 'form',
|
||||
api: '/api/mock2/sample/${id}',
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{},
|
||||
makeEnv({fetcher: mockFetcher, getModalContainer: () => container})
|
||||
)
|
||||
);
|
||||
await wait(200);
|
||||
const saveBtn = container.querySelectorAll('tbody>tr button')[0];
|
||||
expect(saveBtn).toBeTruthy();
|
||||
fireEvent.click(saveBtn);
|
||||
await wait(300);
|
||||
|
||||
expect(getByText('确认')).toBeInTheDocument();
|
||||
fireEvent.click(getByText('取消'));
|
||||
await wait(300);
|
||||
|
||||
fireEvent.click(saveBtn);
|
||||
await wait(300);
|
||||
expect(getByText('确认')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(getByText('确认'));
|
||||
await wait(500);
|
||||
|
||||
expect(mockFetcher).toBeCalledTimes(3);
|
||||
expect(listApiCalledCount).toBe(2);
|
||||
});
|
||||
|
||||
// dialog 提交后如果配置列不刷新,则不刷新
|
||||
test('CRUD reload drawer2', async () => {
|
||||
let listApiCalledCount = 0;
|
||||
const mockFetcher = jest.fn().mockImplementation((api: any) => {
|
||||
if (/^\/api\/mock2\/sample\/\d+/.test(api.url)) {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
listApiCalledCount++;
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
status: 0,
|
||||
data: {
|
||||
items: [{id: 1, a: 'a1', b: 'b1'}]
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
const {container, getByText}: any = render(
|
||||
amisRender(
|
||||
{
|
||||
type: 'page',
|
||||
body: {
|
||||
type: 'crud',
|
||||
api: '/api/mock2/sample',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
label: 'ID'
|
||||
},
|
||||
{
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
label: 'B'
|
||||
},
|
||||
{
|
||||
label: '操作',
|
||||
type: 'operation',
|
||||
buttons: [
|
||||
{
|
||||
label: 'openDrawer',
|
||||
type: 'button',
|
||||
actionType: 'drawer',
|
||||
reload: 'none',
|
||||
drawer: {
|
||||
body: {
|
||||
type: 'form',
|
||||
api: '/api/mock2/sample/${id}',
|
||||
body: [
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'a',
|
||||
label: 'A'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{},
|
||||
makeEnv({fetcher: mockFetcher, getModalContainer: () => container})
|
||||
)
|
||||
);
|
||||
await wait(200);
|
||||
const saveBtn = container.querySelectorAll('tbody>tr button')[0];
|
||||
expect(saveBtn).toBeTruthy();
|
||||
fireEvent.click(saveBtn);
|
||||
await wait(300);
|
||||
|
||||
fireEvent.click(saveBtn);
|
||||
await wait(300);
|
||||
expect(getByText('确认')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(getByText('确认'));
|
||||
await wait(500);
|
||||
|
||||
expect(mockFetcher).toBeCalledTimes(2);
|
||||
expect(listApiCalledCount).toBe(1);
|
||||
});
|
@ -702,7 +702,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
prevIndex: idx - 1,
|
||||
index: idx
|
||||
},
|
||||
action.callback
|
||||
action.callback,
|
||||
delegate || (this.context as any)
|
||||
);
|
||||
} else if (action.actionType === 'ajax') {
|
||||
store.setCurrentAction(action);
|
||||
@ -1130,9 +1131,14 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
||||
actionType: 'dialog',
|
||||
dialog: dialog
|
||||
});
|
||||
store.openDialog(ctx, undefined, confirmed => {
|
||||
resolve(confirmed);
|
||||
});
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
confirmed => {
|
||||
resolve(confirmed);
|
||||
},
|
||||
this.context as any
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -426,9 +426,14 @@ export default class Dialog extends React.Component<DialogProps> {
|
||||
actionType: 'dialog',
|
||||
dialog: dialog
|
||||
});
|
||||
store.openDialog(ctx, undefined, confirmed => {
|
||||
resolve(confirmed);
|
||||
});
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
confirmed => {
|
||||
resolve(confirmed);
|
||||
},
|
||||
this.context as any
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -898,7 +903,12 @@ export class DialogRenderer extends Dialog {
|
||||
}
|
||||
} else if (action.actionType === 'dialog') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDialog(data, undefined, action.callback);
|
||||
store.openDialog(
|
||||
data,
|
||||
undefined,
|
||||
action.callback,
|
||||
delegate || (this.context as any)
|
||||
);
|
||||
} else if (action.actionType === 'drawer') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDrawer(data);
|
||||
@ -1000,16 +1010,18 @@ export class DialogRenderer extends Dialog {
|
||||
...rest: Array<any>
|
||||
) {
|
||||
super.handleDialogConfirm(values, action, ...rest);
|
||||
const scoped = this.context as IScopedContext;
|
||||
const store = this.props.store;
|
||||
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
|
||||
const dialogAction = store.action as ActionObject;
|
||||
const reload = action.reload ?? dialogAction.reload;
|
||||
|
||||
if (reload) {
|
||||
scoped.reload(reload, store.data);
|
||||
} else if (scoped.component?.reload) {
|
||||
scoped.component.reload();
|
||||
} else {
|
||||
// 没有设置,则自动让页面中 crud 刷新。
|
||||
scoped
|
||||
(this.context as IScopedContext)
|
||||
.getComponents()
|
||||
.filter((item: any) => item.props.type === 'crud')
|
||||
.forEach((item: any) => item.reload && item.reload());
|
||||
@ -1022,19 +1034,20 @@ export class DialogRenderer extends Dialog {
|
||||
...rest: Array<any>
|
||||
) {
|
||||
super.handleDrawerConfirm(values, action);
|
||||
const scoped = this.context as IScopedContext;
|
||||
const store = this.props.store;
|
||||
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
|
||||
const drawerAction = store.action as ActionObject;
|
||||
const reload = action.reload ?? drawerAction.reload;
|
||||
|
||||
// 稍等会,等动画结束。
|
||||
setTimeout(() => {
|
||||
if (drawerAction.reload) {
|
||||
scoped.reload(drawerAction.reload, store.data);
|
||||
} else if (action.reload) {
|
||||
scoped.reload(action.reload, store.data);
|
||||
if (reload) {
|
||||
scoped.reload(reload, store.data);
|
||||
} else if (scoped.component?.reload) {
|
||||
scoped.component.reload();
|
||||
} else {
|
||||
// 没有设置,则自动让页面中 crud 刷新。
|
||||
scoped
|
||||
(this.context as IScopedContext)
|
||||
.getComponents()
|
||||
.filter((item: any) => item.props.type === 'crud')
|
||||
.forEach((item: any) => item.reload && item.reload());
|
||||
|
@ -525,9 +525,14 @@ export default class Drawer extends React.Component<DrawerProps> {
|
||||
actionType: 'dialog',
|
||||
dialog: dialog
|
||||
});
|
||||
store.openDialog(ctx, undefined, confirmed => {
|
||||
resolve(confirmed);
|
||||
});
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
confirmed => {
|
||||
resolve(confirmed);
|
||||
},
|
||||
this.context as any
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -827,7 +832,12 @@ export class DrawerRenderer extends Drawer {
|
||||
store.openDrawer(data);
|
||||
} else if (action.actionType === 'dialog') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDialog(data, undefined, action.callback);
|
||||
store.openDialog(
|
||||
data,
|
||||
undefined,
|
||||
action.callback,
|
||||
delegate || (this.context as any)
|
||||
);
|
||||
} else if (action.actionType === 'reload') {
|
||||
store.setCurrentAction(action);
|
||||
action.target && scoped.reload(action.target, data);
|
||||
@ -913,16 +923,19 @@ export class DrawerRenderer extends Drawer {
|
||||
...rest: Array<any>
|
||||
) {
|
||||
super.handleDialogConfirm(values, action, ...rest);
|
||||
const scoped = this.context as IScopedContext;
|
||||
|
||||
const store = this.props.store;
|
||||
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
|
||||
const dialogAction = store.action as ActionObject;
|
||||
const reload = action.reload ?? dialogAction.reload;
|
||||
|
||||
if (reload) {
|
||||
scoped.reload(reload, store.data);
|
||||
} else if (scoped.component?.reload) {
|
||||
scoped.component.reload();
|
||||
} else {
|
||||
// 没有设置,则自动让页面中 crud 刷新。
|
||||
scoped
|
||||
(this.context as IScopedContext)
|
||||
.getComponents()
|
||||
.filter((item: any) => item.props.type === 'crud')
|
||||
.forEach((item: any) => item.reload && item.reload());
|
||||
@ -935,19 +948,20 @@ export class DrawerRenderer extends Drawer {
|
||||
...rest: Array<any>
|
||||
) {
|
||||
super.handleDrawerConfirm(values, action);
|
||||
const scoped = this.context as IScopedContext;
|
||||
const store = this.props.store;
|
||||
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
|
||||
const drawerAction = store.action as ActionObject;
|
||||
const reload = action.reload ?? drawerAction.reload;
|
||||
|
||||
// 稍等会,等动画结束。
|
||||
setTimeout(() => {
|
||||
if (drawerAction.reload) {
|
||||
scoped.reload(drawerAction.reload, store.data);
|
||||
} else if (action.reload) {
|
||||
scoped.reload(action.reload, store.data);
|
||||
if (reload) {
|
||||
scoped.reload(reload, store.data);
|
||||
} else if (scoped.component?.reload) {
|
||||
scoped.component.reload();
|
||||
} else {
|
||||
// 没有设置,则自动让页面中 crud 刷新。
|
||||
scoped
|
||||
(this.context as IScopedContext)
|
||||
.getComponents()
|
||||
.filter((item: any) => item.props.type === 'crud')
|
||||
.forEach((item: any) => item.reload && item.reload());
|
||||
|
@ -484,7 +484,12 @@ export default class Page extends React.Component<PageProps> {
|
||||
|
||||
if (action.actionType === 'dialog') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDialog(ctx, undefined, action.callback, delegate);
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
action.callback,
|
||||
delegate || (this.context as any)
|
||||
);
|
||||
} else if (action.actionType === 'drawer') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDrawer(ctx, undefined, undefined, delegate);
|
||||
@ -664,9 +669,14 @@ export default class Page extends React.Component<PageProps> {
|
||||
actionType: 'dialog',
|
||||
dialog: dialog
|
||||
});
|
||||
store.openDialog(ctx, undefined, confirmed => {
|
||||
resolve(confirmed);
|
||||
});
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
confirmed => {
|
||||
resolve(confirmed);
|
||||
},
|
||||
this.context as any
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1066,9 +1076,11 @@ export class PageRenderer extends Page {
|
||||
|
||||
if (reload) {
|
||||
scoped.reload(reload, store.data);
|
||||
} else if (scoped?.component?.reload) {
|
||||
scoped.component.reload();
|
||||
} else {
|
||||
// 没有设置,则自动让页面中 crud 刷新。
|
||||
scoped
|
||||
(this.context as IScopedContext)
|
||||
.getComponents()
|
||||
.filter((item: any) => item.props.type === 'crud')
|
||||
.forEach((item: any) => item.reload && item.reload());
|
||||
@ -1091,9 +1103,10 @@ export class PageRenderer extends Page {
|
||||
setTimeout(() => {
|
||||
if (reload) {
|
||||
scoped.reload(reload, store.data);
|
||||
} else if (scoped?.component?.reload) {
|
||||
scoped.component.reload();
|
||||
} else {
|
||||
// 没有设置,则自动让页面中 crud 刷新。
|
||||
scoped
|
||||
(this.context as IScopedContext)
|
||||
.getComponents()
|
||||
.filter((item: any) => item.props.type === 'crud')
|
||||
.forEach((item: any) => item.reload && item.reload());
|
||||
|
@ -695,9 +695,14 @@ export default class Service extends React.Component<ServiceProps> {
|
||||
actionType: 'dialog',
|
||||
dialog: dialog
|
||||
});
|
||||
store.openDialog(ctx, undefined, confirmed => {
|
||||
resolve(confirmed);
|
||||
});
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
confirmed => {
|
||||
resolve(confirmed);
|
||||
},
|
||||
this.context as any
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -650,7 +650,12 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
|
||||
this.form.reset();
|
||||
} else if (action.actionType === 'dialog') {
|
||||
store.setCurrentAction(action);
|
||||
store.openDialog(data, undefined, action.callback);
|
||||
store.openDialog(
|
||||
data,
|
||||
undefined,
|
||||
action.callback,
|
||||
delegate || (this.context as any)
|
||||
);
|
||||
} else if (action.actionType === 'ajax') {
|
||||
if (!action.api) {
|
||||
return env.alert(`当 actionType 为 ajax 时,请设置 api 属性`);
|
||||
@ -743,9 +748,14 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
|
||||
actionType: 'dialog',
|
||||
dialog: dialog
|
||||
});
|
||||
store.openDialog(ctx, undefined, confirmed => {
|
||||
resolve(confirmed);
|
||||
});
|
||||
store.openDialog(
|
||||
ctx,
|
||||
undefined,
|
||||
confirmed => {
|
||||
resolve(confirmed);
|
||||
},
|
||||
this.context as any
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user