tachybase_todo/packages/app/src/components/actions/index.tsx
2021-04-06 12:52:59 +08:00

380 lines
11 KiB
TypeScript

import React, { useState } from 'react';
import { Space, Button, Popconfirm, Popover } from 'antd';
import {
FilterOutlined,
PlusOutlined,
SelectOutlined,
DeleteOutlined,
PrinterOutlined,
ExportOutlined,
} from '@ant-design/icons';
import Drawer from '@/components/drawer';
import View from '@/components/views';
import get from 'lodash/get';
import set from 'lodash/set';
import ReactToPrint from 'react-to-print';
import api from '@/api-client';
import './style.less';
const ACTIONS = new Map<string, any>();
export function Create(props) {
const { size, onFinish, schema = {}, associatedKey, ...restProps } = props;
const { title, pageTitle, viewName, transform, componentProps = {} } = schema;
return (
<>
<Button
size={size}
onClick={() => {
Drawer.open({
title: pageTitle || 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'}
{...componentProps}
>
{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, componentProps = {} } = schema;
return (
<Popconfirm
title="确认删除吗?"
onConfirm={async e => {
onFinish && (await onFinish());
}}
>
<Button
size={size}
danger
type={'ghost'}
icon={<DeleteOutlined />}
{...componentProps}
>
{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(Array.isArray(items) ? items.length : 0);
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 Print(props) {
const { schema = {}, contentRef } = props;
const { title, buttonProps = {} } = schema;
return (
<ReactToPrint
trigger={() => (
<Button {...buttonProps} icon={<PrinterOutlined />}>
{title}
</Button>
)}
content={() => contentRef.current}
pageStyle={`
@page {
margin: 1cm;
}
table { page-break-inside:auto }
tr { page-break-inside:avoid; page-break-after:auto }
`}
documentTitle={' '}
/>
);
}
export function Export(props) {
const { schema = {}, onFinish } = props;
const { title, buttonProps = {} } = schema;
return (
<Button
{...buttonProps}
icon={<ExportOutlined />}
onClick={async () => {
onFinish && (await onFinish({ fields: [] }));
}}
>
{title}
</Button>
);
}
export function Actions(props) {
const { onTrigger = {}, actions = [], style, ...restProps } = props;
return (
actions.length > 0 && (
<div className={'action-buttons'} style={style}>
{actions.map(
action =>
ACTIONS.has(action.type) && (
<div key={action.__index} className={`${action.type}-action-button action-button`}>
<Action
{...restProps}
onFinish={onTrigger[action.type]}
schema={action}
/>
</div>
),
)}
</div>
)
);
}
export default Actions;
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);
registerAction('print', Print);
registerAction('export', Export);