feat: improve kanban initializer

This commit is contained in:
chenos 2022-03-11 09:19:53 +08:00
parent 3d5817e0b3
commit a28b69326b
7 changed files with 91 additions and 57 deletions

View File

@ -3,14 +3,14 @@ import React from 'react';
import { useDesignable } from '../..'; import { useDesignable } from '../..';
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings'; import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
export const ActionDesigner = () => { export const ActionDesigner = (props) => {
const initialValue = {}; const initialValue = {};
const field = useField(); const field = useField();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const { dn } = useDesignable(); const { dn } = useDesignable();
const isPopupAction = ['create', 'update', 'view'].includes(fieldSchema['x-action'] || ''); const isPopupAction = ['create', 'update', 'view'].includes(fieldSchema['x-action'] || '');
return ( return (
<GeneralSchemaDesigner> <GeneralSchemaDesigner {...props}>
<SchemaSettings.ModalItem <SchemaSettings.ModalItem
title={'编辑'} title={'编辑'}
schema={ schema={

View File

@ -80,6 +80,7 @@ export const Action: ComposedAction = observer((props: any) => {
const field = useField(); const field = useField();
const { run } = useAction(); const { run } = useAction();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const designerProps = fieldSchema['x-designer-props'];
const renderButton = () => ( const renderButton = () => (
<SortableItem <SortableItem
{...others} {...others}
@ -103,7 +104,7 @@ export const Action: ComposedAction = observer((props: any) => {
component={component || Button} component={component || Button}
className={classnames(className, actionDesignerCss)} className={classnames(className, actionDesignerCss)}
> >
<Designer /> <Designer {...designerProps} />
{field.title} {field.title}
</SortableItem> </SortableItem>
); );

View File

@ -120,7 +120,14 @@ const useColProperties = () => {
}, []); }, []);
}; };
export const Grid: any = observer((props) => { const DndWrapper = (props) => {
if (props.dndContext === false) {
return <>{props.children}</>;
}
return <DndContext {...props.dndContext}>{props.children}</DndContext>;
};
export const Grid: any = observer((props: any) => {
const field = useField(); const field = useField();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const { render } = useSchemaInitializer(fieldSchema['x-initializer']); const { render } = useSchemaInitializer(fieldSchema['x-initializer']);
@ -128,7 +135,7 @@ export const Grid: any = observer((props) => {
const rows = useRowProperties(); const rows = useRowProperties();
return ( return (
<div className={'nb-grid'} style={{ position: 'relative' }}> <div className={'nb-grid'} style={{ position: 'relative' }}>
<DndContext> <DndWrapper dndContext={props.dndContext}>
<RowDivider <RowDivider
id={`${addr}_0`} id={`${addr}_0`}
data={{ wrapSchema: wrapRowSchema, insertAdjacent: 'afterBegin', schema: fieldSchema }} data={{ wrapSchema: wrapRowSchema, insertAdjacent: 'afterBegin', schema: fieldSchema }}
@ -144,7 +151,7 @@ export const Grid: any = observer((props) => {
</React.Fragment> </React.Fragment>
); );
})} })}
</DndContext> </DndWrapper>
<div>{render()}</div> <div>{render()}</div>
</div> </div>
); );

View File

@ -1,10 +1,12 @@
import { MenuOutlined } from '@ant-design/icons'; import { MenuOutlined } from '@ant-design/icons';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { useField, useFieldSchema } from '@formily/react'; import { ISchema, useField, useFieldSchema } from '@formily/react';
import { uid } from '@formily/shared';
import { Space } from 'antd'; import { Space } from 'antd';
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useCompile, useDesignable } from '../../../schema-component'; import { useAPIClient } from '../../../api-client';
import { createDesignable, useDesignable } from '../../../schema-component';
import { SchemaInitializer } from '../../../schema-initializer'; import { SchemaInitializer } from '../../../schema-initializer';
import { useFormItemInitializerFields } from '../../../schema-initializer/Initializers/utils'; import { useFormItemInitializerFields } from '../../../schema-initializer/Initializers/utils';
@ -23,26 +25,39 @@ const titleCss = css`
left: 2px; left: 2px;
`; `;
export const removeGridFormItem = (schema, cb) => { const gridRowColWrap = (schema: ISchema) => {
cb(schema, { schema['x-read-pretty'] = true;
removeParentsIfNoChildren: true, return {
breakRemoveOn: { type: 'void',
'x-component': 'Kanban.Card', 'x-component': 'Grid.Row',
properties: {
[uid()]: {
type: 'void',
'x-component': 'Grid.Col',
properties: {
[schema.name || uid()]: schema,
}, },
}); },
},
};
}; };
// export const removeGridFormItem = (schema, cb) => {
// cb(schema, {
// removeParentsIfNoChildren: true,
// breakRemoveOn: {
// 'x-component': 'Kanban.Card',
// },
// });
// };
export const KanbanCardDesigner = (props: any) => { export const KanbanCardDesigner = (props: any) => {
const { dn, designable } = useDesignable(); const { dn, designable } = useDesignable();
const { t } = useTranslation(); const { t } = useTranslation();
const api = useAPIClient();
const { refresh } = useDesignable();
const field = useField(); const field = useField();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const compile = useCompile();
const schemaSettingsProps = {
dn,
field,
fieldSchema,
};
const fields = useFormItemInitializerFields(); const fields = useFormItemInitializerFields();
if (!designable) { if (!designable) {
return null; return null;
@ -52,21 +67,30 @@ export const KanbanCardDesigner = (props: any) => {
<div className={'general-schema-designer-icons'}> <div className={'general-schema-designer-icons'}>
<Space size={2} align={'center'}> <Space size={2} align={'center'}>
<SchemaInitializer.Button <SchemaInitializer.Button
wrap={(s) => { wrap={gridRowColWrap}
s['type'] = 'string'; insert={(schema) => {
s['x-read-pretty'] = true; const gridSchema = fieldSchema.reduceProperties((buf, schema) => {
return s; if (schema['x-component'] === 'Grid') {
return schema;
}
return buf;
}, null);
if (!gridSchema) {
return;
}
const dn = createDesignable({
api,
refresh,
current: gridSchema,
});
dn.loadAPIClientEvents();
dn.insertBeforeEnd(schema);
}} }}
items={[ items={[
{ {
type: 'itemGroup', type: 'itemGroup',
title: t('Display fields'), title: t('Display fields'),
children: fields.map((field) => { children: fields,
return {
...field,
remove: removeGridFormItem,
};
}),
}, },
]} ]}
component={<MenuOutlined style={{ cursor: 'pointer', fontSize: 12 }} />} component={<MenuOutlined style={{ cursor: 'pointer', fontSize: 12 }} />}

View File

@ -1,4 +1,4 @@
import { css } from '@emotion/css'; import { FormLayout } from '@formily/antd';
import { observer, RecursionField, useFieldSchema } from '@formily/react'; import { observer, RecursionField, useFieldSchema } from '@formily/react';
import { Card } from 'antd'; import { Card } from 'antd';
import React, { useContext, useState } from 'react'; import React, { useContext, useState } from 'react';
@ -23,25 +23,10 @@ export const KanbanCard: any = observer((props: any) => {
onClick={(e) => { onClick={(e) => {
setVisible(true); setVisible(true);
}} }}
className={css`
/* .ant-description-input {
line-height: 1.15;
} */
.ant-formily-item-label {
display: none;
}
.ant-formily-item-feedback-layout-loose {
margin-bottom: 12px;
}
.nb-block-item:last-child {
.ant-formily-item {
margin-bottom: 0;
}
}
`}
bordered={false} bordered={false}
hoverable hoverable
style={{ cursor: 'pointer', overflow: 'hidden' }} style={{ cursor: 'pointer', overflow: 'hidden' }}
bodyStyle={{ paddingBottom: 0 }}
> >
<SchemaComponentOptions components={{}}> <SchemaComponentOptions components={{}}>
<DndContext <DndContext
@ -52,11 +37,13 @@ export const KanbanCard: any = observer((props: any) => {
setDisableCardDrag(false); setDisableCardDrag(false);
}} }}
> >
<FormLayout layout={'vertical'}>
<RecursionField <RecursionField
basePath={cardField.address.concat(`${columnIndex}.cards.${cardIndex}`)} basePath={cardField.address.concat(`${columnIndex}.cards.${cardIndex}`)}
schema={fieldSchema} schema={fieldSchema}
onlyRenderProperties onlyRenderProperties
/> />
</FormLayout>
</DndContext> </DndContext>
</SchemaComponentOptions> </SchemaComponentOptions>
</Card> </Card>

View File

@ -47,12 +47,25 @@ const createSchema = (collectionName, { groupField, sortName }) => {
'x-decorator': 'BlockItem', 'x-decorator': 'BlockItem',
'x-designer': 'Kanban.Card.Designer', 'x-designer': 'Kanban.Card.Designer',
'x-read-pretty': true, 'x-read-pretty': true,
properties: {
grid: {
type: 'void',
'x-component': 'Grid',
'x-read-pretty': true,
'x-component-props': {
dndContext: false,
},
properties: {}, properties: {},
}, },
},
},
cardAdder: { cardAdder: {
type: 'void', type: 'void',
'x-component': 'Kanban.CardAdder', 'x-component': 'Kanban.CardAdder',
'x-designer': 'Action.Designer', 'x-designer': 'Action.Designer',
'x-designer-props': {
draggable: false,
},
'x-component-props': { 'x-component-props': {
type: 'text', type: 'text',
openMode: 'drawer', openMode: 'drawer',

View File

@ -23,7 +23,7 @@ const titleCss = css`
`; `;
export const GeneralSchemaDesigner = (props: any) => { export const GeneralSchemaDesigner = (props: any) => {
const { title } = props; const { title, draggable = true } = props;
const { dn, designable } = useDesignable(); const { dn, designable } = useDesignable();
const field = useField(); const field = useField();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
@ -41,9 +41,11 @@ export const GeneralSchemaDesigner = (props: any) => {
{title && <div className={classNames('general-schema-designer-title', titleCss)}>{compile(title)}</div>} {title && <div className={classNames('general-schema-designer-title', titleCss)}>{compile(title)}</div>}
<div className={'general-schema-designer-icons'}> <div className={'general-schema-designer-icons'}>
<Space size={2} align={'center'}> <Space size={2} align={'center'}>
{draggable && (
<DragHandler> <DragHandler>
<DragOutlined /> <DragOutlined />
</DragHandler> </DragHandler>
)}
<SchemaSettings title={<MenuOutlined style={{ cursor: 'pointer', fontSize: 12 }} />} {...schemaSettingsProps}> <SchemaSettings title={<MenuOutlined style={{ cursor: 'pointer', fontSize: 12 }} />} {...schemaSettingsProps}>
{props.children} {props.children}
</SchemaSettings> </SchemaSettings>