fix: add ellipsis property to record picker (#527)

* fix: the association fields of table text is overflow

* fix: add m2o ellipsis

* fix: add Kanban ellipsis

* fix: change KanbanV2 to Kanban

Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
SemmyWong 2022-06-23 22:23:45 +08:00 committed by GitHub
parent e65ed6dfa1
commit 33a08288c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 102 additions and 59 deletions

View File

@ -23,7 +23,7 @@ const InternalField: React.FC = (props) => {
} }
}; };
const ctx = useFormBlockContext(); const ctx = useFormBlockContext();
useEffect(() => { useEffect(() => {
if (ctx?.field) { if (ctx?.field) {
ctx.field.added = ctx.field.added || new Set(); ctx.field.added = ctx.field.added || new Set();
@ -46,7 +46,7 @@ const InternalField: React.FC = (props) => {
field.disabled = true; field.disabled = true;
} }
if (fieldSchema['x-read-pretty'] === true) { if (fieldSchema['x-read-pretty'] === true) {
field.readPretty = true; field.readPretty = true;
} }
setRequired(); setRequired();
// @ts-ignore // @ts-ignore

View File

@ -23,7 +23,7 @@ export const attachment: IField = {
}, },
}, },
schemaInitialize(schema: ISchema, { block }) { schemaInitialize(schema: ISchema, { block }) {
if (['Table', 'KanbanV2'].includes(block)) { if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {}; schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['size'] = 'small'; schema['x-component-props']['size'] = 'small';
} }

View File

@ -45,7 +45,7 @@ export const m2m: IField = {
}, },
}, },
}, },
schemaInitialize(schema: ISchema, { readPretty }) { schemaInitialize(schema: ISchema, { readPretty, block }) {
if (readPretty) { if (readPretty) {
schema['properties'] = { schema['properties'] = {
viewer: cloneDeep(recordPickerViewer), viewer: cloneDeep(recordPickerViewer),
@ -55,6 +55,10 @@ export const m2m: IField = {
selector: cloneDeep(recordPickerSelector), selector: cloneDeep(recordPickerSelector),
}; };
} }
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
}, },
initialize: (values: any) => { initialize: (values: any) => {
if (values.type === 'belongsToMany') { if (values.type === 'belongsToMany') {
@ -161,7 +165,7 @@ export const m2m: IField = {
required: true, required: true,
default: '{{ useNewId("f_") }}', default: '{{ useNewId("f_") }}',
description: description:
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
'x-component': 'Input', 'x-component': 'Input',
'x-disabled': '{{ !createOnly }}', 'x-disabled': '{{ !createOnly }}',
@ -171,9 +175,7 @@ export const m2m: IField = {
col23: { col23: {
type: 'void', type: 'void',
'x-component': 'Grid.Col', 'x-component': 'Grid.Col',
properties: { properties: {},
},
}, },
}, },
}, },
@ -196,7 +198,7 @@ export const m2m: IField = {
required: true, required: true,
default: '{{ useNewId("f_") }}', default: '{{ useNewId("f_") }}',
description: description:
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
'x-component': 'Input', 'x-component': 'Input',
'x-disabled': '{{ !createOnly }}', 'x-disabled': '{{ !createOnly }}',

View File

@ -44,7 +44,7 @@ export const m2o: IField = {
}, },
}, },
}, },
schemaInitialize(schema: ISchema, { readPretty }) { schemaInitialize(schema: ISchema, { readPretty, block }) {
if (readPretty) { if (readPretty) {
schema['properties'] = { schema['properties'] = {
viewer: cloneDeep(recordPickerViewer), viewer: cloneDeep(recordPickerViewer),
@ -54,6 +54,10 @@ export const m2o: IField = {
selector: cloneDeep(recordPickerSelector), selector: cloneDeep(recordPickerSelector),
}; };
} }
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
}, },
properties: { properties: {
'uiSchema.title': { 'uiSchema.title': {
@ -126,7 +130,7 @@ export const m2o: IField = {
required: true, required: true,
default: '{{ useNewId("f_") }}', default: '{{ useNewId("f_") }}',
description: description:
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
'x-component': 'Input', 'x-component': 'Input',
'x-disabled': '{{ !createOnly }}', 'x-disabled': '{{ !createOnly }}',

View File

@ -43,7 +43,7 @@ export const o2m: IField = {
}, },
}, },
}, },
schemaInitialize(schema: ISchema, { field, readPretty }) { schemaInitialize(schema: ISchema, { field, readPretty, block }) {
const association = `${field.collectionName}.${field.name}`; const association = `${field.collectionName}.${field.name}`;
schema['type'] = 'void'; schema['type'] = 'void';
schema['x-component'] = 'TableField'; schema['x-component'] = 'TableField';
@ -93,6 +93,10 @@ export const o2m: IField = {
// selector: cloneDeep(recordPickerSelector), // selector: cloneDeep(recordPickerSelector),
// }; // };
// } // }
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
}, },
properties: { properties: {
'uiSchema.title': { 'uiSchema.title': {
@ -178,7 +182,7 @@ export const o2m: IField = {
required: true, required: true,
default: '{{ useNewId("f_") }}', default: '{{ useNewId("f_") }}',
description: description:
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
'x-component': 'Input', 'x-component': 'Input',
'x-disabled': '{{ !createOnly }}', 'x-disabled': '{{ !createOnly }}',
@ -194,8 +198,7 @@ export const o2m: IField = {
col21: { col21: {
type: 'void', type: 'void',
'x-component': 'Grid.Col', 'x-component': 'Grid.Col',
properties: { properties: {},
},
}, },
col22: { col22: {
type: 'void', type: 'void',

View File

@ -45,7 +45,7 @@ export const o2o: IField = {
}, },
}, },
}, },
schemaInitialize(schema: ISchema, { readPretty }) { schemaInitialize(schema: ISchema, { readPretty, block }) {
if (readPretty) { if (readPretty) {
schema['properties'] = { schema['properties'] = {
viewer: cloneDeep(recordPickerViewer), viewer: cloneDeep(recordPickerViewer),
@ -55,6 +55,10 @@ export const o2o: IField = {
selector: cloneDeep(recordPickerSelector), selector: cloneDeep(recordPickerSelector),
}; };
} }
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
}, },
properties: { properties: {
'uiSchema.title': { 'uiSchema.title': {
@ -139,7 +143,7 @@ export const o2o: IField = {
required: true, required: true,
default: '{{ useNewId("f_") }}', default: '{{ useNewId("f_") }}',
description: description:
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
'x-component': 'Input', 'x-component': 'Input',
'x-disabled': '{{ !createOnly }}', 'x-disabled': '{{ !createOnly }}',
@ -213,7 +217,7 @@ export const oho: IField = {
}, },
}, },
}, },
schemaInitialize(schema: ISchema, { readPretty }) { schemaInitialize(schema: ISchema, { readPretty, block }) {
if (readPretty) { if (readPretty) {
schema['properties'] = { schema['properties'] = {
viewer: cloneDeep(recordPickerViewer), viewer: cloneDeep(recordPickerViewer),
@ -223,6 +227,10 @@ export const oho: IField = {
selector: cloneDeep(recordPickerSelector), selector: cloneDeep(recordPickerSelector),
}; };
} }
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
}, },
properties: { properties: {
'uiSchema.title': { 'uiSchema.title': {
@ -307,7 +315,7 @@ export const oho: IField = {
required: true, required: true,
default: '{{ useNewId("f_") }}', default: '{{ useNewId("f_") }}',
description: description:
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
'x-component': 'Input', 'x-component': 'Input',
'x-disabled': '{{ !createOnly }}', 'x-disabled': '{{ !createOnly }}',
@ -380,7 +388,7 @@ export const obo: IField = {
}, },
}, },
}, },
schemaInitialize(schema: ISchema, { readPretty }) { schemaInitialize(schema: ISchema, { readPretty, block }) {
if (readPretty) { if (readPretty) {
schema['properties'] = { schema['properties'] = {
viewer: cloneDeep(recordPickerViewer), viewer: cloneDeep(recordPickerViewer),
@ -390,6 +398,10 @@ export const obo: IField = {
selector: cloneDeep(recordPickerSelector), selector: cloneDeep(recordPickerSelector),
}; };
} }
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
}, },
properties: { properties: {
'uiSchema.title': { 'uiSchema.title': {
@ -462,7 +474,7 @@ export const obo: IField = {
required: true, required: true,
default: '{{ useNewId("f_") }}', default: '{{ useNewId("f_") }}',
description: description:
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',
'x-component': 'Input', 'x-component': 'Input',
'x-disabled': '{{ !createOnly }}', 'x-disabled': '{{ !createOnly }}',

View File

@ -1,5 +1,5 @@
import { Popover } from 'antd'; import { Popover } from 'antd';
import React, { CSSProperties, useState } from 'react'; import React, { CSSProperties, forwardRef, useImperativeHandle, useState } from 'react';
const ellipsisDefaultStyle: CSSProperties = { const ellipsisDefaultStyle: CSSProperties = {
overflow: 'hidden', overflow: 'hidden',
@ -9,9 +9,19 @@ const ellipsisDefaultStyle: CSSProperties = {
wordBreak: 'break-all', wordBreak: 'break-all',
}; };
export const EllipsisWithTooltip = (props) => { interface IEllipsisWithTooltipProps {
ellipsis: boolean;
popoverContent: unknown;
children: any;
}
export const EllipsisWithTooltip = forwardRef((props: Partial<IEllipsisWithTooltipProps>, ref: any) => {
const [ellipsis, setEllipsis] = useState(false); const [ellipsis, setEllipsis] = useState(false);
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
useImperativeHandle(ref, () => {
return {
setPopoverVisible: setVisible,
};
});
if (!props.ellipsis) { if (!props.ellipsis) {
return <>{props.children}</>; return <>{props.children}</>;
} }
@ -44,4 +54,4 @@ export const EllipsisWithTooltip = (props) => {
</div> </div>
</Popover> </Popover>
); );
}; });

View File

@ -58,7 +58,7 @@ export const KanbanCardDesigner = (props: any) => {
const { refresh } = useDesignable(); const { refresh } = useDesignable();
const field = useField(); const field = useField();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const fields = useFormItemInitializerFields({ readPretty: true, block: 'KanbanV2' }); const fields = useFormItemInitializerFields({ readPretty: true, block: 'Kanban' });
if (!designable) { if (!designable) {
return null; return null;
} }

View File

@ -31,14 +31,14 @@ const schema: ISchema = {
properties: { properties: {
kanban: { kanban: {
type: 'array', type: 'array',
'x-component': 'KanbanV2', 'x-component': 'Kanban',
'x-component-props': { 'x-component-props': {
useProps: '{{ useKanbanBlockProps }}', useProps: '{{ useKanbanBlockProps }}',
}, },
properties: { properties: {
card: { card: {
type: 'void', type: 'void',
'x-component': 'KanbanV2.Card', 'x-component': 'Kanban.Card',
properties: { properties: {
f_g8j5jvalqh0: { f_g8j5jvalqh0: {
'x-decorator': 'FormItem', 'x-decorator': 'FormItem',

View File

@ -5,7 +5,7 @@ group:
path: /schema-components path: /schema-components
--- ---
# KanbanV2 # Kanban
## 示例 ## 示例

View File

@ -1,47 +1,59 @@
import { Field } from '@formily/core'; import { Field } from '@formily/core';
import { observer, RecursionField, useField, useFieldSchema } from '@formily/react'; import { observer, RecursionField, useField, useFieldSchema } from '@formily/react';
import { toArr } from '@formily/shared'; import { toArr } from '@formily/shared';
import { Space } from 'antd'; import React, { useRef, useState } from 'react';
import React, { useState } from 'react';
import { BlockAssociationContext, WithoutTableFieldResource } from '../../../block-provider'; import { BlockAssociationContext, WithoutTableFieldResource } from '../../../block-provider';
import { CollectionProvider, useCollection } from '../../../collection-manager'; import { CollectionProvider, useCollection } from '../../../collection-manager';
import { RecordProvider } from '../../../record-provider'; import { RecordProvider } from '../../../record-provider';
import { FormProvider } from '../../core'; import { FormProvider } from '../../core';
import { useCompile } from '../../hooks'; import { useCompile } from '../../hooks';
import { ActionContext } from '../action'; import { ActionContext } from '../action';
import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip';
import { useFieldNames } from './useFieldNames'; import { useFieldNames } from './useFieldNames';
interface IEllipsisWithTooltipRef {
setPopoverVisible: (boolean) => void;
}
export const ReadPrettyRecordPicker: React.FC = observer((props: any) => { export const ReadPrettyRecordPicker: React.FC = observer((props: any) => {
const { ellipsis } = props;
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const field = useField<Field>(); const field = useField<Field>();
const fieldNames = useFieldNames(props); const fieldNames = useFieldNames(props);
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [popoverVisible, setPopoverVisible] = useState<boolean>();
const { getField } = useCollection(); const { getField } = useCollection();
const collectionField = getField(fieldSchema.name); const collectionField = getField(fieldSchema.name);
const [record, setRecord] = useState({}); const [record, setRecord] = useState({});
const compile = useCompile(); const compile = useCompile();
const ellipsisWithTooltipRef = useRef<IEllipsisWithTooltipRef>();
const renderRecords = () =>
toArr(field.value).map((record, index, arr) => {
return (
<>
<span>
<a
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
setVisible(true);
setRecord(record);
ellipsisWithTooltipRef?.current?.setPopoverVisible(false);
}}
>
{compile(record?.[fieldNames?.label || 'label'])}
</a>
</span>
{index < arr.length - 1 ? <span style={{ marginRight: 4, color: '#aaa' }}>, </span> : null}
</>
);
});
return collectionField ? ( return collectionField ? (
<div> <div>
<BlockAssociationContext.Provider value={`${collectionField.collectionName}.${collectionField.name}`}> <BlockAssociationContext.Provider value={`${collectionField.collectionName}.${collectionField.name}`}>
<CollectionProvider name={collectionField.target}> <CollectionProvider name={collectionField.target}>
<Space size={0} split={<span style={{ marginRight: 4, color: '#aaa' }}>, </span>}> <EllipsisWithTooltip ellipsis={ellipsis} ref={ellipsisWithTooltipRef}>
{toArr(field.value).map((record, index) => { {renderRecords()}
return ( </EllipsisWithTooltip>
<span>
<a
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
setVisible(true);
setRecord(record);
}}
>
{compile(record?.[fieldNames?.label || 'label'])}
</a>
</span>
);
})}
</Space>
<ActionContext.Provider value={{ visible, setVisible, openMode: 'drawer' }}> <ActionContext.Provider value={{ visible, setVisible, openMode: 'drawer' }}>
<RecordProvider record={record}> <RecordProvider record={record}>
<WithoutTableFieldResource.Provider value={true}> <WithoutTableFieldResource.Provider value={true}>

View File

@ -74,12 +74,12 @@ export const TableColumnDesigner = (props) => {
}; };
columnSchema['x-component-props'] = { columnSchema['x-component-props'] = {
...columnSchema['x-component-props'], ...columnSchema['x-component-props'],
sorter: v sorter: v,
} };
schema['x-component-props'] = columnSchema['x-component-props']; schema['x-component-props'] = columnSchema['x-component-props'];
field.componentProps.sorter = v; field.componentProps.sorter = v;
dn.emit('patch', { dn.emit('patch', {
schema schema,
}); });
dn.refresh(); dn.refresh();
}} }}
@ -102,7 +102,7 @@ export const TableColumnDesigner = (props) => {
schema: { schema: {
'x-uid': fieldSchema['x-uid'], 'x-uid': fieldSchema['x-uid'],
'x-component-props': { 'x-component-props': {
fieldNames, ...fieldSchema['x-component-props'],
}, },
}, },
}); });
@ -117,7 +117,7 @@ export const TableColumnDesigner = (props) => {
'x-component': 'Grid', 'x-component': 'Grid',
}} }}
confirm={{ confirm={{
title: t('Delete table column') title: t('Delete table column'),
}} }}
/> />
</GeneralSchemaDesigner> </GeneralSchemaDesigner>

View File

@ -1,7 +1,7 @@
import { ISchema, Schema, useFieldSchema, useForm } from '@formily/react'; import { ISchema, Schema, useFieldSchema, useForm } from '@formily/react';
import { uid } from '@formily/shared'; import { uid } from '@formily/shared';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { SchemaInitializerItemOptions, useTableBlockContext } from '../'; import { SchemaInitializerItemOptions } from '../';
import { useCollection, useCollectionManager } from '../collection-manager'; import { useCollection, useCollectionManager } from '../collection-manager';
import { useDesignable } from '../schema-component'; import { useDesignable } from '../schema-component';
import { useSchemaTemplateManager } from '../schema-templates'; import { useSchemaTemplateManager } from '../schema-templates';
@ -757,7 +757,7 @@ export const createKanbanBlockSchema = (options) => {
}, },
...others, ...others,
}, },
'x-designer': 'KanbanV2.Designer', 'x-designer': 'Kanban.Designer',
'x-component': 'CardItem', 'x-component': 'CardItem',
properties: { properties: {
actions: { actions: {
@ -773,7 +773,7 @@ export const createKanbanBlockSchema = (options) => {
}, },
[uid()]: { [uid()]: {
type: 'array', type: 'array',
'x-component': 'KanbanV2', 'x-component': 'Kanban',
'x-component-props': { 'x-component-props': {
useProps: '{{ useKanbanBlockProps }}', useProps: '{{ useKanbanBlockProps }}',
}, },
@ -782,8 +782,8 @@ export const createKanbanBlockSchema = (options) => {
type: 'void', type: 'void',
'x-read-pretty': true, 'x-read-pretty': true,
'x-decorator': 'BlockItem', 'x-decorator': 'BlockItem',
'x-component': 'KanbanV2.Card', 'x-component': 'Kanban.Card',
'x-designer': 'KanbanV2.Card.Designer', 'x-designer': 'Kanban.Card.Designer',
properties: { properties: {
grid: { grid: {
type: 'void', type: 'void',
@ -796,7 +796,7 @@ export const createKanbanBlockSchema = (options) => {
type: 'void', type: 'void',
title: '{{ t("View") }}', title: '{{ t("View") }}',
'x-designer': 'Action.Designer', 'x-designer': 'Action.Designer',
'x-component': 'KanbanV2.CardViewer', 'x-component': 'Kanban.CardViewer',
'x-component-props': { 'x-component-props': {
openMode: 'drawer', openMode: 'drawer',
}, },