mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
fix: 修复crud 中 drawer 动作后不刷新问题 Close: #6903
This commit is contained in:
parent
06ad5abe50
commit
b337c1590d
85
.vscode/launch.json
vendored
85
.vscode/launch.json
vendored
@ -1,71 +1,18 @@
|
|||||||
{
|
{
|
||||||
// 使用 IntelliSense 了解相关属性。
|
"version": "1.0.0",
|
||||||
// 悬停以查看现有属性的描述。
|
"configurations": [
|
||||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
{
|
||||||
"version": "0.2.0",
|
"type": "node",
|
||||||
"configurations": [
|
"request": "launch",
|
||||||
{
|
"name": "Jest: current file",
|
||||||
"type": "node",
|
//"env": { "NODE_ENV": "test" },
|
||||||
"request": "launch",
|
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
||||||
"name": "Jest All",
|
"args": ["${fileBasenameNoExtension}"],
|
||||||
"program": "${workspaceFolder}/node_modules/.bin/jest",
|
"console": "integratedTerminal",
|
||||||
"args": ["--runInBand"],
|
"disableOptimisticBPs": true,
|
||||||
"sourceMaps": true,
|
"windows": {
|
||||||
"console": "integratedTerminal",
|
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
|
||||||
"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."
|
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
]
|
||||||
|
}
|
||||||
|
@ -160,7 +160,12 @@ export class RootRenderer extends React.Component<RootRendererProps> {
|
|||||||
window.open(mailto);
|
window.open(mailto);
|
||||||
} else if (action.actionType === 'dialog') {
|
} else if (action.actionType === 'dialog') {
|
||||||
store.setCurrentAction(action);
|
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') {
|
} else if (action.actionType === 'drawer') {
|
||||||
store.setCurrentAction(action);
|
store.setCurrentAction(action);
|
||||||
store.openDrawer(ctx, undefined, undefined, delegate);
|
store.openDrawer(ctx, undefined, undefined, delegate);
|
||||||
@ -323,9 +328,14 @@ export class RootRenderer extends React.Component<RootRendererProps> {
|
|||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: dialog
|
dialog: dialog
|
||||||
});
|
});
|
||||||
store.openDialog(ctx, undefined, confirmed => {
|
store.openDialog(
|
||||||
resolve(confirmed);
|
ctx,
|
||||||
});
|
undefined,
|
||||||
|
confirmed => {
|
||||||
|
resolve(confirmed);
|
||||||
|
},
|
||||||
|
this.context as any
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,8 @@ export interface ScopedComponentType extends React.Component<RendererProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IScopedContext {
|
export interface IScopedContext {
|
||||||
|
rendererType?: string;
|
||||||
|
component?: ScopedComponentType;
|
||||||
parent?: AliasIScopedContext;
|
parent?: AliasIScopedContext;
|
||||||
children?: AliasIScopedContext[];
|
children?: AliasIScopedContext[];
|
||||||
registerComponent: (component: ScopedComponentType) => void;
|
registerComponent: (component: ScopedComponentType) => void;
|
||||||
@ -69,6 +71,10 @@ export interface IScopedContext {
|
|||||||
send: (target: string, ctx: RendererData) => void;
|
send: (target: string, ctx: RendererData) => void;
|
||||||
close: (target: string) => void;
|
close: (target: string) => void;
|
||||||
closeById: (target: string) => void;
|
closeById: (target: string) => void;
|
||||||
|
getComponentsByRefPath: (
|
||||||
|
session: string,
|
||||||
|
path: string
|
||||||
|
) => ScopedComponentType[];
|
||||||
}
|
}
|
||||||
type AliasIScopedContext = IScopedContext;
|
type AliasIScopedContext = IScopedContext;
|
||||||
|
|
||||||
@ -78,14 +84,18 @@ export const ScopedContext = React.createContext(rootScopedContext);
|
|||||||
function createScopedTools(
|
function createScopedTools(
|
||||||
path?: string,
|
path?: string,
|
||||||
parent?: AliasIScopedContext,
|
parent?: AliasIScopedContext,
|
||||||
env?: RendererEnv
|
env?: RendererEnv,
|
||||||
|
rendererType?: string
|
||||||
): IScopedContext {
|
): IScopedContext {
|
||||||
const components: Array<ScopedComponentType> = [];
|
const components: Array<ScopedComponentType> = [];
|
||||||
const self = {
|
const self: IScopedContext = {
|
||||||
|
rendererType,
|
||||||
|
component: undefined,
|
||||||
parent,
|
parent,
|
||||||
registerComponent(component: ScopedComponentType) {
|
registerComponent(component: ScopedComponentType) {
|
||||||
// 不要把自己注册在自己的 Scoped 上,自己的 Scoped 是给子节点们注册的。
|
// 不要把自己注册在自己的 Scoped 上,自己的 Scoped 是给子节点们注册的。
|
||||||
if (component.props.$path === path && parent) {
|
if (component.props.$path === path && parent) {
|
||||||
|
self.component = component;
|
||||||
return parent.registerComponent(component);
|
return parent.registerComponent(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +414,8 @@ export function HocScoped<
|
|||||||
env: RendererEnv;
|
env: RendererEnv;
|
||||||
}
|
}
|
||||||
>(
|
>(
|
||||||
ComposedComponent: React.ComponentType<T>
|
ComposedComponent: React.ComponentType<T>,
|
||||||
|
rendererType?: string
|
||||||
): React.ComponentType<
|
): React.ComponentType<
|
||||||
T & {
|
T & {
|
||||||
scopeRef?: (ref: any) => void;
|
scopeRef?: (ref: any) => void;
|
||||||
@ -430,7 +441,8 @@ export function HocScoped<
|
|||||||
this.scoped = createScopedTools(
|
this.scoped = createScopedTools(
|
||||||
this.props.$path,
|
this.props.$path,
|
||||||
context,
|
context,
|
||||||
this.props.env
|
this.props.env,
|
||||||
|
rendererType
|
||||||
);
|
);
|
||||||
|
|
||||||
const scopeRef = props.scopeRef;
|
const scopeRef = props.scopeRef;
|
||||||
|
@ -186,7 +186,7 @@ export function registerRenderer(config: RendererConfig): RendererConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.isolateScope) {
|
if (config.isolateScope) {
|
||||||
config.component = Scoped(config.component);
|
config.component = Scoped(config.component, config.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
const idx = findIndex(
|
const idx = findIndex(
|
||||||
|
@ -1133,7 +1133,12 @@ export default class Form extends React.Component<FormProps, object> {
|
|||||||
action.target &&
|
action.target &&
|
||||||
this.reloadTarget(filterTarget(action.target, values), values);
|
this.reloadTarget(filterTarget(action.target, values), values);
|
||||||
} else if (action.actionType === 'dialog') {
|
} 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') {
|
} else if (action.actionType === 'drawer') {
|
||||||
store.openDrawer(data);
|
store.openDrawer(data);
|
||||||
} else if (isEffectiveApi(action.api || api, values)) {
|
} else if (isEffectiveApi(action.api || api, values)) {
|
||||||
@ -1259,7 +1264,12 @@ export default class Form extends React.Component<FormProps, object> {
|
|||||||
this.validate(true);
|
this.validate(true);
|
||||||
} else if (action.actionType === 'dialog') {
|
} else if (action.actionType === 'dialog') {
|
||||||
store.setCurrentAction(action);
|
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') {
|
} else if (action.actionType === 'drawer') {
|
||||||
store.setCurrentAction(action);
|
store.setCurrentAction(action);
|
||||||
store.openDrawer(data);
|
store.openDrawer(data);
|
||||||
@ -1428,9 +1438,14 @@ export default class Form extends React.Component<FormProps, object> {
|
|||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: dialog
|
dialog: dialog
|
||||||
});
|
});
|
||||||
store.openDialog(ctx, undefined, confirmed => {
|
store.openDialog(
|
||||||
resolve(confirmed);
|
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,
|
prevIndex: idx - 1,
|
||||||
index: idx
|
index: idx
|
||||||
},
|
},
|
||||||
action.callback
|
action.callback,
|
||||||
|
delegate || (this.context as any)
|
||||||
);
|
);
|
||||||
} else if (action.actionType === 'ajax') {
|
} else if (action.actionType === 'ajax') {
|
||||||
store.setCurrentAction(action);
|
store.setCurrentAction(action);
|
||||||
@ -1130,9 +1131,14 @@ export default class CRUD extends React.Component<CRUDProps, any> {
|
|||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: dialog
|
dialog: dialog
|
||||||
});
|
});
|
||||||
store.openDialog(ctx, undefined, confirmed => {
|
store.openDialog(
|
||||||
resolve(confirmed);
|
ctx,
|
||||||
});
|
undefined,
|
||||||
|
confirmed => {
|
||||||
|
resolve(confirmed);
|
||||||
|
},
|
||||||
|
this.context as any
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,9 +426,14 @@ export default class Dialog extends React.Component<DialogProps> {
|
|||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: dialog
|
dialog: dialog
|
||||||
});
|
});
|
||||||
store.openDialog(ctx, undefined, confirmed => {
|
store.openDialog(
|
||||||
resolve(confirmed);
|
ctx,
|
||||||
});
|
undefined,
|
||||||
|
confirmed => {
|
||||||
|
resolve(confirmed);
|
||||||
|
},
|
||||||
|
this.context as any
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -898,7 +903,12 @@ export class DialogRenderer extends Dialog {
|
|||||||
}
|
}
|
||||||
} else if (action.actionType === 'dialog') {
|
} else if (action.actionType === 'dialog') {
|
||||||
store.setCurrentAction(action);
|
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') {
|
} else if (action.actionType === 'drawer') {
|
||||||
store.setCurrentAction(action);
|
store.setCurrentAction(action);
|
||||||
store.openDrawer(data);
|
store.openDrawer(data);
|
||||||
@ -1000,16 +1010,18 @@ export class DialogRenderer extends Dialog {
|
|||||||
...rest: Array<any>
|
...rest: Array<any>
|
||||||
) {
|
) {
|
||||||
super.handleDialogConfirm(values, action, ...rest);
|
super.handleDialogConfirm(values, action, ...rest);
|
||||||
const scoped = this.context as IScopedContext;
|
|
||||||
const store = this.props.store;
|
const store = this.props.store;
|
||||||
|
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
|
||||||
const dialogAction = store.action as ActionObject;
|
const dialogAction = store.action as ActionObject;
|
||||||
const reload = action.reload ?? dialogAction.reload;
|
const reload = action.reload ?? dialogAction.reload;
|
||||||
|
|
||||||
if (reload) {
|
if (reload) {
|
||||||
scoped.reload(reload, store.data);
|
scoped.reload(reload, store.data);
|
||||||
|
} else if (scoped.component?.reload) {
|
||||||
|
scoped.component.reload();
|
||||||
} else {
|
} else {
|
||||||
// 没有设置,则自动让页面中 crud 刷新。
|
// 没有设置,则自动让页面中 crud 刷新。
|
||||||
scoped
|
(this.context as IScopedContext)
|
||||||
.getComponents()
|
.getComponents()
|
||||||
.filter((item: any) => item.props.type === 'crud')
|
.filter((item: any) => item.props.type === 'crud')
|
||||||
.forEach((item: any) => item.reload && item.reload());
|
.forEach((item: any) => item.reload && item.reload());
|
||||||
@ -1022,19 +1034,20 @@ export class DialogRenderer extends Dialog {
|
|||||||
...rest: Array<any>
|
...rest: Array<any>
|
||||||
) {
|
) {
|
||||||
super.handleDrawerConfirm(values, action);
|
super.handleDrawerConfirm(values, action);
|
||||||
const scoped = this.context as IScopedContext;
|
|
||||||
const store = this.props.store;
|
const store = this.props.store;
|
||||||
|
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
|
||||||
const drawerAction = store.action as ActionObject;
|
const drawerAction = store.action as ActionObject;
|
||||||
|
const reload = action.reload ?? drawerAction.reload;
|
||||||
|
|
||||||
// 稍等会,等动画结束。
|
// 稍等会,等动画结束。
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (drawerAction.reload) {
|
if (reload) {
|
||||||
scoped.reload(drawerAction.reload, store.data);
|
scoped.reload(reload, store.data);
|
||||||
} else if (action.reload) {
|
} else if (scoped.component?.reload) {
|
||||||
scoped.reload(action.reload, store.data);
|
scoped.component.reload();
|
||||||
} else {
|
} else {
|
||||||
// 没有设置,则自动让页面中 crud 刷新。
|
// 没有设置,则自动让页面中 crud 刷新。
|
||||||
scoped
|
(this.context as IScopedContext)
|
||||||
.getComponents()
|
.getComponents()
|
||||||
.filter((item: any) => item.props.type === 'crud')
|
.filter((item: any) => item.props.type === 'crud')
|
||||||
.forEach((item: any) => item.reload && item.reload());
|
.forEach((item: any) => item.reload && item.reload());
|
||||||
|
@ -525,9 +525,14 @@ export default class Drawer extends React.Component<DrawerProps> {
|
|||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: dialog
|
dialog: dialog
|
||||||
});
|
});
|
||||||
store.openDialog(ctx, undefined, confirmed => {
|
store.openDialog(
|
||||||
resolve(confirmed);
|
ctx,
|
||||||
});
|
undefined,
|
||||||
|
confirmed => {
|
||||||
|
resolve(confirmed);
|
||||||
|
},
|
||||||
|
this.context as any
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -827,7 +832,12 @@ export class DrawerRenderer extends Drawer {
|
|||||||
store.openDrawer(data);
|
store.openDrawer(data);
|
||||||
} else if (action.actionType === 'dialog') {
|
} else if (action.actionType === 'dialog') {
|
||||||
store.setCurrentAction(action);
|
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') {
|
} else if (action.actionType === 'reload') {
|
||||||
store.setCurrentAction(action);
|
store.setCurrentAction(action);
|
||||||
action.target && scoped.reload(action.target, data);
|
action.target && scoped.reload(action.target, data);
|
||||||
@ -913,16 +923,19 @@ export class DrawerRenderer extends Drawer {
|
|||||||
...rest: Array<any>
|
...rest: Array<any>
|
||||||
) {
|
) {
|
||||||
super.handleDialogConfirm(values, action, ...rest);
|
super.handleDialogConfirm(values, action, ...rest);
|
||||||
const scoped = this.context as IScopedContext;
|
|
||||||
const store = this.props.store;
|
const store = this.props.store;
|
||||||
|
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
|
||||||
const dialogAction = store.action as ActionObject;
|
const dialogAction = store.action as ActionObject;
|
||||||
const reload = action.reload ?? dialogAction.reload;
|
const reload = action.reload ?? dialogAction.reload;
|
||||||
|
|
||||||
if (reload) {
|
if (reload) {
|
||||||
scoped.reload(reload, store.data);
|
scoped.reload(reload, store.data);
|
||||||
|
} else if (scoped.component?.reload) {
|
||||||
|
scoped.component.reload();
|
||||||
} else {
|
} else {
|
||||||
// 没有设置,则自动让页面中 crud 刷新。
|
// 没有设置,则自动让页面中 crud 刷新。
|
||||||
scoped
|
(this.context as IScopedContext)
|
||||||
.getComponents()
|
.getComponents()
|
||||||
.filter((item: any) => item.props.type === 'crud')
|
.filter((item: any) => item.props.type === 'crud')
|
||||||
.forEach((item: any) => item.reload && item.reload());
|
.forEach((item: any) => item.reload && item.reload());
|
||||||
@ -935,19 +948,20 @@ export class DrawerRenderer extends Drawer {
|
|||||||
...rest: Array<any>
|
...rest: Array<any>
|
||||||
) {
|
) {
|
||||||
super.handleDrawerConfirm(values, action);
|
super.handleDrawerConfirm(values, action);
|
||||||
const scoped = this.context as IScopedContext;
|
|
||||||
const store = this.props.store;
|
const store = this.props.store;
|
||||||
|
const scoped = store.getDialogScoped() || (this.context as IScopedContext);
|
||||||
const drawerAction = store.action as ActionObject;
|
const drawerAction = store.action as ActionObject;
|
||||||
|
const reload = action.reload ?? drawerAction.reload;
|
||||||
|
|
||||||
// 稍等会,等动画结束。
|
// 稍等会,等动画结束。
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (drawerAction.reload) {
|
if (reload) {
|
||||||
scoped.reload(drawerAction.reload, store.data);
|
scoped.reload(reload, store.data);
|
||||||
} else if (action.reload) {
|
} else if (scoped.component?.reload) {
|
||||||
scoped.reload(action.reload, store.data);
|
scoped.component.reload();
|
||||||
} else {
|
} else {
|
||||||
// 没有设置,则自动让页面中 crud 刷新。
|
// 没有设置,则自动让页面中 crud 刷新。
|
||||||
scoped
|
(this.context as IScopedContext)
|
||||||
.getComponents()
|
.getComponents()
|
||||||
.filter((item: any) => item.props.type === 'crud')
|
.filter((item: any) => item.props.type === 'crud')
|
||||||
.forEach((item: any) => item.reload && item.reload());
|
.forEach((item: any) => item.reload && item.reload());
|
||||||
|
@ -484,7 +484,12 @@ export default class Page extends React.Component<PageProps> {
|
|||||||
|
|
||||||
if (action.actionType === 'dialog') {
|
if (action.actionType === 'dialog') {
|
||||||
store.setCurrentAction(action);
|
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') {
|
} else if (action.actionType === 'drawer') {
|
||||||
store.setCurrentAction(action);
|
store.setCurrentAction(action);
|
||||||
store.openDrawer(ctx, undefined, undefined, delegate);
|
store.openDrawer(ctx, undefined, undefined, delegate);
|
||||||
@ -664,9 +669,14 @@ export default class Page extends React.Component<PageProps> {
|
|||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: dialog
|
dialog: dialog
|
||||||
});
|
});
|
||||||
store.openDialog(ctx, undefined, confirmed => {
|
store.openDialog(
|
||||||
resolve(confirmed);
|
ctx,
|
||||||
});
|
undefined,
|
||||||
|
confirmed => {
|
||||||
|
resolve(confirmed);
|
||||||
|
},
|
||||||
|
this.context as any
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1066,9 +1076,11 @@ export class PageRenderer extends Page {
|
|||||||
|
|
||||||
if (reload) {
|
if (reload) {
|
||||||
scoped.reload(reload, store.data);
|
scoped.reload(reload, store.data);
|
||||||
|
} else if (scoped?.component?.reload) {
|
||||||
|
scoped.component.reload();
|
||||||
} else {
|
} else {
|
||||||
// 没有设置,则自动让页面中 crud 刷新。
|
// 没有设置,则自动让页面中 crud 刷新。
|
||||||
scoped
|
(this.context as IScopedContext)
|
||||||
.getComponents()
|
.getComponents()
|
||||||
.filter((item: any) => item.props.type === 'crud')
|
.filter((item: any) => item.props.type === 'crud')
|
||||||
.forEach((item: any) => item.reload && item.reload());
|
.forEach((item: any) => item.reload && item.reload());
|
||||||
@ -1091,9 +1103,10 @@ export class PageRenderer extends Page {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (reload) {
|
if (reload) {
|
||||||
scoped.reload(reload, store.data);
|
scoped.reload(reload, store.data);
|
||||||
|
} else if (scoped?.component?.reload) {
|
||||||
|
scoped.component.reload();
|
||||||
} else {
|
} else {
|
||||||
// 没有设置,则自动让页面中 crud 刷新。
|
(this.context as IScopedContext)
|
||||||
scoped
|
|
||||||
.getComponents()
|
.getComponents()
|
||||||
.filter((item: any) => item.props.type === 'crud')
|
.filter((item: any) => item.props.type === 'crud')
|
||||||
.forEach((item: any) => item.reload && item.reload());
|
.forEach((item: any) => item.reload && item.reload());
|
||||||
|
@ -695,9 +695,14 @@ export default class Service extends React.Component<ServiceProps> {
|
|||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: dialog
|
dialog: dialog
|
||||||
});
|
});
|
||||||
store.openDialog(ctx, undefined, confirmed => {
|
store.openDialog(
|
||||||
resolve(confirmed);
|
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();
|
this.form.reset();
|
||||||
} else if (action.actionType === 'dialog') {
|
} else if (action.actionType === 'dialog') {
|
||||||
store.setCurrentAction(action);
|
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') {
|
} else if (action.actionType === 'ajax') {
|
||||||
if (!action.api) {
|
if (!action.api) {
|
||||||
return env.alert(`当 actionType 为 ajax 时,请设置 api 属性`);
|
return env.alert(`当 actionType 为 ajax 时,请设置 api 属性`);
|
||||||
@ -743,9 +748,14 @@ export default class Wizard extends React.Component<WizardProps, WizardState> {
|
|||||||
actionType: 'dialog',
|
actionType: 'dialog',
|
||||||
dialog: dialog
|
dialog: dialog
|
||||||
});
|
});
|
||||||
store.openDialog(ctx, undefined, confirmed => {
|
store.openDialog(
|
||||||
resolve(confirmed);
|
ctx,
|
||||||
});
|
undefined,
|
||||||
|
confirmed => {
|
||||||
|
resolve(confirmed);
|
||||||
|
},
|
||||||
|
this.context as any
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user