feat: drawer close with confirm
This commit is contained in:
parent
388dbc5ef4
commit
bb5aa17106
@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Space, Button, Popconfirm, Popover } from 'antd';
|
||||
import { FilterOutlined, PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import { FilterOutlined, PlusOutlined, SelectOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import Drawer from '@/components/pages/AdminLoader/Drawer';
|
||||
import View from '@/components/pages/AdminLoader/View';
|
||||
import get from 'lodash/get';
|
||||
@ -8,7 +8,7 @@ import set from 'lodash/set';
|
||||
|
||||
export function Create(props) {
|
||||
const { size, onFinish, schema = {}, associatedKey, ...restProps } = props;
|
||||
const { title, viewName } = schema;
|
||||
const { title, viewName, transform } = schema;
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
@ -16,19 +16,32 @@ export function Create(props) {
|
||||
onClick={() => {
|
||||
Drawer.open({
|
||||
title: title,
|
||||
content: ({resolve}) => (
|
||||
content: ({resolve, closeWithConfirm}) => (
|
||||
<div>
|
||||
<View
|
||||
{...restProps}
|
||||
onValueChange={() => {
|
||||
closeWithConfirm && closeWithConfirm(true);
|
||||
}}
|
||||
associatedKey={associatedKey}
|
||||
viewName={viewName}
|
||||
onReset={resolve}
|
||||
onDraft={async (values) => {
|
||||
onDraft={async (item) => {
|
||||
const values = transform ? {} : item;
|
||||
for (const [sourceKey, targetKey] of Object.entries<string>(transform)) {
|
||||
const value = get({ data: item }, sourceKey);
|
||||
set(values, targetKey, value);
|
||||
}
|
||||
await resolve();
|
||||
console.log('onFinish', values);
|
||||
onFinish && await onFinish(values);
|
||||
}}
|
||||
onFinish={async (values) => {
|
||||
onFinish={async (item) => {
|
||||
const values = transform ? {} : item;
|
||||
for (const [sourceKey, targetKey] of Object.entries<string>(transform)) {
|
||||
const value = get({ data: item }, sourceKey);
|
||||
set(values, targetKey, value);
|
||||
}
|
||||
await resolve();
|
||||
console.log('onFinish', values);
|
||||
onFinish && await onFinish(values);
|
||||
@ -54,7 +67,7 @@ export function Update(props) {
|
||||
onClick={() => {
|
||||
Drawer.open({
|
||||
title: title,
|
||||
content: ({resolve}) => (
|
||||
content: ({resolve, closeWithConfirm}) => (
|
||||
<div>
|
||||
<View
|
||||
{...restProps}
|
||||
@ -66,6 +79,9 @@ export function Update(props) {
|
||||
await resolve();
|
||||
onFinish && await onFinish(values);
|
||||
}}
|
||||
onValueChange={() => {
|
||||
closeWithConfirm && closeWithConfirm(true);
|
||||
}}
|
||||
onFinish={async (values) => {
|
||||
await resolve();
|
||||
onFinish && await onFinish(values);
|
||||
@ -85,7 +101,7 @@ export function Update(props) {
|
||||
export function Add(props) {
|
||||
const { size, onFinish, schema = {}, associatedKey, ...restProps } = props;
|
||||
console.log({associatedKey}, 'add');
|
||||
const { filter, title, viewName, transform } = schema;
|
||||
const { filter, title, viewName, transform, componentProps = {} } = schema;
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
@ -132,8 +148,8 @@ export function Add(props) {
|
||||
},
|
||||
});
|
||||
}}
|
||||
icon={<PlusOutlined />}
|
||||
type={'primary'}
|
||||
icon={<SelectOutlined />}
|
||||
{...componentProps}
|
||||
>{ title }</Button>
|
||||
</>
|
||||
)
|
||||
|
@ -3,7 +3,7 @@ import ReactDOM, { createPortal } from 'react-dom'
|
||||
import { createForm } from '@formily/core'
|
||||
// import { FormProvider } from '@formily/react'
|
||||
import { isNum, isStr, isBool, isFn } from '@formily/shared'
|
||||
import { Drawer } from 'antd'
|
||||
import { Modal, Drawer } from 'antd'
|
||||
import { DrawerProps } from 'antd/lib/drawer'
|
||||
import { useContext } from 'react'
|
||||
import { ConfigProvider } from 'antd'
|
||||
@ -77,7 +77,7 @@ export function FormDrawer(title: any, content: any): IFormDrawer {
|
||||
width: '75%',
|
||||
...props,
|
||||
onClose: (e: any) => {
|
||||
props?.onClose?.(e)
|
||||
props?.onClose?.(e);
|
||||
formDrawer.close()
|
||||
},
|
||||
afterVisibleChange: (visible: boolean) => {
|
||||
@ -88,25 +88,13 @@ export function FormDrawer(title: any, content: any): IFormDrawer {
|
||||
env.root = undefined
|
||||
},
|
||||
}
|
||||
const render = (visible = true, resolve?: () => any, reject?: () => any) => {
|
||||
ReactDOM.render(
|
||||
<ConfigProvider locale={zhCN}>
|
||||
<Drawer {...drawer} className={'nb-drawer'} visible={visible}>
|
||||
{createElement(content, {
|
||||
resolve,
|
||||
reject,
|
||||
})}
|
||||
</Drawer>
|
||||
</ConfigProvider>,
|
||||
env.root
|
||||
)
|
||||
}
|
||||
document.body.appendChild(env.root)
|
||||
|
||||
const formDrawer = {
|
||||
open: (props: any) => {
|
||||
render(
|
||||
false,
|
||||
() => {
|
||||
formDrawer.closeWithConfirm = false;
|
||||
formDrawer.close()
|
||||
},
|
||||
() => {
|
||||
@ -117,6 +105,7 @@ export function FormDrawer(title: any, content: any): IFormDrawer {
|
||||
render(
|
||||
true,
|
||||
() => {
|
||||
formDrawer.closeWithConfirm = false;
|
||||
formDrawer.close()
|
||||
},
|
||||
() => {
|
||||
@ -127,14 +116,53 @@ export function FormDrawer(title: any, content: any): IFormDrawer {
|
||||
},
|
||||
close: () => {
|
||||
if (!env.root) return
|
||||
const els = document.querySelectorAll('.env-root-push');
|
||||
if (els.length) {
|
||||
const last = els[els.length-1];
|
||||
last.className = 'env-root';
|
||||
if (formDrawer.closeWithConfirm) {
|
||||
Modal.confirm({
|
||||
title: '表单内容发生变化,确定不保存吗?',
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
formDrawer.closeWithConfirm = false;
|
||||
const els = document.querySelectorAll('.env-root-push');
|
||||
if (els.length) {
|
||||
const last = els[els.length-1];
|
||||
last.className = 'env-root';
|
||||
}
|
||||
render(false)
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const els = document.querySelectorAll('.env-root-push');
|
||||
if (els.length) {
|
||||
const last = els[els.length-1];
|
||||
last.className = 'env-root';
|
||||
}
|
||||
render(false)
|
||||
}
|
||||
render(false)
|
||||
},
|
||||
closeWithConfirm: false,
|
||||
}
|
||||
|
||||
const closeWithConfirm = (bool) => {
|
||||
formDrawer.closeWithConfirm = bool;
|
||||
}
|
||||
|
||||
const render = (visible = true, resolve?: () => any, reject?: () => any) => {
|
||||
ReactDOM.render(
|
||||
<ConfigProvider locale={zhCN}>
|
||||
<Drawer {...drawer} className={'nb-drawer'} visible={visible}>
|
||||
{createElement(content, {
|
||||
resolve,
|
||||
reject,
|
||||
closeWithConfirm,
|
||||
})}
|
||||
</Drawer>
|
||||
</ConfigProvider>,
|
||||
env.root
|
||||
)
|
||||
}
|
||||
document.body.appendChild(env.root)
|
||||
|
||||
return formDrawer
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,8 @@ import cloneDeep from 'lodash/cloneDeep'
|
||||
import { Spin } from '@nocobase/client';
|
||||
import { markdown } from '@/components/views/Field';
|
||||
|
||||
export function fields2properties(fields = []) {
|
||||
export function fields2properties(fields = [], options: any = {}) {
|
||||
const { mode } = options;
|
||||
const properties = {};
|
||||
fields.forEach(field => {
|
||||
const data = {
|
||||
@ -31,6 +32,9 @@ export function fields2properties(fields = []) {
|
||||
title: field.title,
|
||||
required: field.required,
|
||||
};
|
||||
if (field.createOnly && mode !== 'create') {
|
||||
set(data, 'x-component-props.disabled', true);
|
||||
}
|
||||
const linkages = field.linkages;
|
||||
delete field.linkages;
|
||||
set(data, 'x-component-props.schema', cloneDeep(field));
|
||||
@ -80,13 +84,13 @@ export function fields2properties(fields = []) {
|
||||
data.description = <div className={'markdown-content'} dangerouslySetInnerHTML={{__html: markdown(field.tooltip)}}></div>;
|
||||
}
|
||||
});
|
||||
console.log({properties});
|
||||
console.log({properties, options});
|
||||
return properties;
|
||||
}
|
||||
const actions = createFormActions();
|
||||
|
||||
export function Form(props: any) {
|
||||
const { onReset, __parent, noRequest = false, onFinish, onDraft, resolve, data: record = {}, associatedKey, schema = {} } = props;
|
||||
const { onValueChange, onReset, __parent, noRequest = false, onFinish, onDraft, resolve, data: record = {}, associatedKey, schema = {} } = props;
|
||||
console.log({ noRequest, record, associatedKey, __parent });
|
||||
const { statusable, resourceName, rowKey = 'id', fields = [], appends = [], associationField = {} } = schema;
|
||||
|
||||
@ -125,11 +129,15 @@ export function Form(props: any) {
|
||||
// actions={actions}
|
||||
schema={{
|
||||
type: 'object',
|
||||
properties: fields2properties(fields),
|
||||
properties: fields2properties(fields, { mode: !!Object.keys(data).length ? null : 'create' }),
|
||||
}}
|
||||
onReset={async () => {
|
||||
onReset && await onReset();
|
||||
}}
|
||||
onChange={(values) => {
|
||||
console.log('onValueChange')
|
||||
onValueChange && onValueChange(values)
|
||||
}}
|
||||
onSubmit={async (values) => {
|
||||
console.log({status});
|
||||
if (!noRequest) {
|
||||
|
@ -5,7 +5,7 @@ import { Spin } from '@nocobase/client';
|
||||
import { useRequest, useLocation } from 'umi';
|
||||
import api from '@/api-client';
|
||||
import { Actions } from '../Actions';
|
||||
import { Table as AntdTable, Card, Pagination, Button, Tabs, Descriptions, Tooltip } from 'antd';
|
||||
import { Modal, Table as AntdTable, Card, Pagination, Button, Tabs, Descriptions, Tooltip } from 'antd';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { components, fields2columns } from '@/components/views/SortableTable';
|
||||
import ReactDragListView from 'react-drag-listview';
|
||||
@ -19,7 +19,7 @@ import { Form } from './Form';
|
||||
import { View } from './';
|
||||
|
||||
export function Details(props) {
|
||||
const { onReset, __parent, noRequest, associatedKey, resourceName, onFinish, onDataChange, data, items = [], resolve } = props;
|
||||
const { onValueChange, onReset, __parent, noRequest, associatedKey, resourceName, onFinish, onDataChange, data, items = [], resolve } = props;
|
||||
if (!items || items.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@ -46,6 +46,7 @@ export function Details(props) {
|
||||
}
|
||||
return (
|
||||
<View
|
||||
onValueChange={onValueChange}
|
||||
onReset={onReset}
|
||||
__parent={__parent}
|
||||
noRequest={noRequest}
|
||||
@ -127,7 +128,6 @@ export function SubTable(props: any) {
|
||||
}
|
||||
|
||||
const { type } = associationField;
|
||||
|
||||
const { data = [], loading, mutate, refresh, run, params } = useRequest((params = {}, ...args) => {
|
||||
return !associatedKey || type === 'virtual' || type === 'json' ? Promise.resolve({
|
||||
data: (props.data||[]).map(item => {
|
||||
@ -231,7 +231,7 @@ export function SubTable(props: any) {
|
||||
rowKey={rowKey}
|
||||
dataSource={dataSource}
|
||||
size={size}
|
||||
columns={fields2columns(cloneFields)}
|
||||
columns={fields2columns(cloneFields, { mutate, dataSource, onChange })}
|
||||
pagination={false}
|
||||
onChange={(pagination, filters, sorter, extra) => {
|
||||
|
||||
@ -253,7 +253,7 @@ export function SubTable(props: any) {
|
||||
bodyStyle: {
|
||||
// padding: 0,
|
||||
},
|
||||
content: ({resolve}) => (
|
||||
content: ({resolve, closeWithConfirm}) => (
|
||||
<div>
|
||||
<Details
|
||||
// __parent={__parent}
|
||||
@ -272,6 +272,9 @@ export function SubTable(props: any) {
|
||||
onReset={resolve}
|
||||
onDataChange={() => {
|
||||
|
||||
}}
|
||||
onValueChange={() => {
|
||||
closeWithConfirm && closeWithConfirm(true);
|
||||
}}
|
||||
noRequest={true}
|
||||
data={data}
|
||||
|
@ -5,7 +5,7 @@ import { Spin } from '@nocobase/client';
|
||||
import { useRequest, useHistory } from 'umi';
|
||||
import api from '@/api-client';
|
||||
import { Actions } from '../Actions';
|
||||
import { PageHeader, Table as AntdTable, Card, Pagination, Button, Tabs, Descriptions, Tooltip } from 'antd';
|
||||
import { Modal, PageHeader, Table as AntdTable, Card, Pagination, Button, Tabs, Descriptions, Tooltip } from 'antd';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { components, fields2columns } from '@/components/views/SortableTable';
|
||||
import ReactDragListView from 'react-drag-listview';
|
||||
@ -21,7 +21,7 @@ import pathToRegexp from 'path-to-regexp'
|
||||
export const icon = <LoadingOutlined style={{ fontSize: 36 }} spin />;
|
||||
|
||||
export function Details(props) {
|
||||
const { __parent, associatedKey, resourceName, onFinish, onReset, onDataChange, data, items = [], resolve } = props;
|
||||
const { __parent, associatedKey, resourceName, onFinish, onReset, onDataChange, data, items = [], resolve, onValueChange } = props;
|
||||
if (!items || items.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@ -47,7 +47,10 @@ export function Details(props) {
|
||||
viewName = `${resourceName}.${view.name}`;
|
||||
}
|
||||
return (
|
||||
<View __parent={__parent} associatedKey={associatedKey} onReset={onReset} onFinish={onFinish} onDataChange={onDataChange} data={data} viewName={viewName}/>
|
||||
<View
|
||||
onValueChange={onValueChange}
|
||||
__parent={__parent}
|
||||
associatedKey={associatedKey} onReset={onReset} onFinish={onFinish} onDataChange={onDataChange} data={data} viewName={viewName}/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
@ -403,7 +406,7 @@ export function Table(props: any) {
|
||||
bodyStyle: {
|
||||
// padding: 0,
|
||||
},
|
||||
content: ({resolve}) => (
|
||||
content: ({resolve, closeWithConfirm}) => (
|
||||
<div>
|
||||
<Details
|
||||
__parent={__parent}
|
||||
@ -414,6 +417,9 @@ export function Table(props: any) {
|
||||
resolve();
|
||||
await reloadMenu();
|
||||
}}
|
||||
onValueChange={() => {
|
||||
closeWithConfirm && closeWithConfirm(true);
|
||||
}}
|
||||
onDraft={async () => {
|
||||
await refresh();
|
||||
resolve();
|
||||
|
@ -12,6 +12,7 @@ import './style.less';
|
||||
import { getImageByUrl, testUrl } from '@/components/form.fields';
|
||||
import { CheckOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import marked from 'marked';
|
||||
import set from 'lodash/set';
|
||||
import Lightbox from 'react-image-lightbox';
|
||||
import 'react-image-lightbox/style.css';
|
||||
import api from '@/api-client';
|
||||
@ -231,22 +232,22 @@ export function SubTableField(props: any) {
|
||||
}
|
||||
|
||||
export function LinkToField(props: any) {
|
||||
const { data, schema, value } = props;
|
||||
const { ctx, data, schema, value } = props;
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
console.log({props});
|
||||
// console.log({props});
|
||||
const values = Array.isArray(value) ? value : [value];
|
||||
const isArr = Array.isArray(value);
|
||||
return (
|
||||
<div className={'link-to-field'}>
|
||||
{values.map(item => <LinkToFieldLink parent={data} data={item} schema={schema}/>)}
|
||||
{values.map((item, itemIndex) => <LinkToFieldLink isArr={isArr} itemIndex={itemIndex} ctx={ctx} parent={data} data={item} schema={schema}/>)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function LinkToFieldLink(props) {
|
||||
const { parent, schema, schema: { title, labelField, viewName, name, target, collection_name } } = props;
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { isArr, itemIndex, ctx, parent, schema, schema: { title, labelField, viewName, name, target, collection_name } } = props;
|
||||
const [data, setData] = useState(props.data||{});
|
||||
return (
|
||||
<span className={'link-to-field-tag'}>
|
||||
@ -255,14 +256,25 @@ export function LinkToFieldLink(props) {
|
||||
// setVisible(true);
|
||||
Drawer.open({
|
||||
title: data[labelField],
|
||||
content: ({resolve}) => {
|
||||
console.log({parent, data, props, schema});
|
||||
content: ({resolve, closeWithConfirm}) => {
|
||||
// console.log({ctx, parent, data, props, schema});
|
||||
const { index, mutate, dataSource, onChange } = ctx;
|
||||
return (
|
||||
<div>
|
||||
<View onFinish={(values) => {
|
||||
<View
|
||||
onValueChange={() => {
|
||||
closeWithConfirm && closeWithConfirm(true);
|
||||
}}
|
||||
noRequest={!!onChange} onFinish={(values) => {
|
||||
let items = [...dataSource];
|
||||
const parentData = {...parent};
|
||||
set(parentData, isArr ? [name, itemIndex] : [name], values);
|
||||
items[index] = parentData;
|
||||
setData(values);
|
||||
mutate(items);
|
||||
onChange(items);
|
||||
resolve();
|
||||
console.log({data, values});
|
||||
// console.log({values, parentData, data, items});
|
||||
}} associatedKey={parent.id} data={data} viewName={viewName || `${collection_name}.${name}.descriptions`}/>
|
||||
</div>
|
||||
);
|
||||
|
@ -66,7 +66,7 @@ export function fields2columns(fields = [], ctx: any = {}) {
|
||||
if (!field.dataIndex) {
|
||||
field.dataIndex = field.name.split('.');
|
||||
}
|
||||
field.render = (value, record) => field.interface === 'sort' ? <DragHandle/> : <Field data={record} viewType={'table'} schema={field} value={value}/>;
|
||||
field.render = (value, record, index) => field.interface === 'sort' ? <DragHandle/> : <Field ctx={{...ctx, index}} data={record} viewType={'table'} schema={field} value={value}/>;
|
||||
field.className = `${field.className||''} noco-field-${field.interface}`;
|
||||
if (field.editable && field.interface === 'boolean') {
|
||||
field.title = (
|
||||
|
Loading…
Reference in New Issue
Block a user