tachybase_todo/packages/app/src/components/pages/AdminLoader/Actions/index.tsx
2021-03-24 16:55:08 +08:00

291 lines
8.7 KiB
TypeScript

import React, { useState } from 'react';
import { Space, Button, Popconfirm, Popover } from 'antd';
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';
import set from 'lodash/set';
export function Create(props) {
const { size, onFinish, schema = {}, associatedKey, ...restProps } = props;
const { title, viewName, transform } = schema;
return (
<>
<Button
size={size}
onClick={() => {
Drawer.open({
title: title,
content: ({resolve, closeWithConfirm}) => (
<div>
<View
{...restProps}
onValueChange={() => {
closeWithConfirm && closeWithConfirm(true);
}}
associatedKey={associatedKey}
viewName={viewName}
onReset={resolve}
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 (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);
}}
/>
</div>
),
});
}}
icon={<PlusOutlined />}
type={'primary'}
>{ title }</Button>
</>
)
}
export function Update(props) {
const { onFinish, data, schema = {}, associatedKey, ...restProps } = props;
const { title, viewName } = schema;
return (
<>
<Button
onClick={() => {
Drawer.open({
title: title,
content: ({resolve, closeWithConfirm}) => (
<div>
<View
{...restProps}
associatedKey={associatedKey}
data={data}
viewName={viewName}
onReset={resolve}
onDraft={async (values) => {
await resolve();
onFinish && await onFinish(values);
}}
onValueChange={() => {
closeWithConfirm && closeWithConfirm(true);
}}
onFinish={async (values) => {
await resolve();
onFinish && await onFinish(values);
}}
/>
</div>
),
});
}}
icon={<PlusOutlined />}
type={'primary'}
>{ title }</Button>
</>
)
}
export function Add(props) {
const { size, onFinish, schema = {}, associatedKey, ...restProps } = props;
console.log({associatedKey}, 'add');
const { filter, title, viewName, transform, componentProps = {} } = schema;
return (
<>
<Button
size={size}
onClick={() => {
Drawer.open({
title: title,
content: ({resolve}) => {
const [selectedRows, setSelectedRows] = useState([]);
return (
<div>
<View
{...restProps}
defaultFilter={filter}
viewName={viewName}
associatedKey={associatedKey}
onSelected={(values) => {
console.log(values);
setSelectedRows(values.map( item => {
if (!transform) {
return;
}
const data = {};
for (const [sourceKey, targetKey] of Object.entries<string>(transform)) {
const value = get({ data: item }, sourceKey);
set(data, targetKey, value);
}
return data;
}));
}}
/>
<Drawer.Footer>
<Space>
<Button onClick={resolve}></Button>
<Button type={'primary'} onClick={async () => {
console.log({schema, onFinish});
onFinish && await onFinish(selectedRows);
resolve();
}}></Button>
</Space>
</Drawer.Footer>
</div>
);
},
});
}}
icon={<SelectOutlined />}
{...componentProps}
>{ title }</Button>
</>
)
}
export function Destroy(props) {
const { size, schema = {}, onFinish } = props;
const { title } = schema;
return (
<Popconfirm title="确认删除吗?" onConfirm={async () => {
onFinish && await onFinish();
}}>
<Button
size={size}
danger
type={'ghost'}
icon={<DeleteOutlined />}
>{ title }</Button>
</Popconfirm>
)
}
export function Filter(props) {
const { schema = {}, onFinish } = props;
const { title, fields = [] } = schema;
const [visible, setVisible] = useState(false);
const [data, setData] = useState({});
const [filterCount, setFilterCount] = useState(0);
console.log('Filter', { visible, data });
return (
<>
{visible && (
<div
style={{
height: '100vh',
width: '100vw',
zIndex: 1000,
position: 'fixed',
background: 'rgba(0, 0, 0, 0)',
top: 0,
left: 0,
}}
onClick={() => setVisible(false)}
></div>
)}
<Popover
// title="设置筛选"
trigger="click"
visible={visible}
defaultVisible={visible}
placement={'bottomLeft'}
destroyTooltipOnHide
onVisibleChange={(visible) => {
setVisible(visible);
}}
className={'filters-popover'}
style={{
}}
overlayStyle={{
minWidth: 500
}}
content={(
<>
<View data={data} onFinish={async (values) => {
if (values) {
const items = values.filter.and || values.filter.or;
setFilterCount(Object.keys(items).length);
setData(values);
onFinish && await onFinish(values);
}
setVisible(false);
}} schema={{
"type": "filterForm",
"fields": [{
"dataIndex": ["filter"],
"name": "filter",
"interface": "json",
"type": "json",
"component": {
"type": "filter",
'x-component-props': {
fields,
}
},
}],
}}/>
</>
)}
>
<Button icon={<FilterOutlined />} >{filterCount ? `${filterCount}${title}` : title}</Button>
</Popover>
</>
)
}
export function Actions(props) {
const { onTrigger = {}, actions = [], style, ...restProps } = props;
return actions.length > 0 && (
<div className={'action-buttons'} style={style}>
{actions.map(action => (
<div className={`${action.type}-action-button action-button`}>
<Action
{...restProps}
onFinish={onTrigger[action.type]}
schema={action}
/>
</div>
))}
</div>
);
}
export default Actions;
const ACTIONS = new Map<string, any>();
export function registerAction(type: string, Action: any) {
ACTIONS.set(type, Action);
}
export function getAction(type: string) {
return ACTIONS.get(type);
}
export function Action(props) {
const { schema = {} } = props;
// cnsole.log(schema);
const { type } = schema;
const Component = getAction(type);
return Component && <Component {...props}/>;
}
registerAction('add', Add);
registerAction('update', Update);
registerAction('create', Create);
registerAction('destroy', Destroy);
registerAction('filter', Filter);