fix(variable-input): fix style (#1761)

* fix(variable-input): fix style

* refactor: avoid lint error

* feat: add invariable

* fix: fix the default value variable of the expression is empty
This commit is contained in:
被雨水过滤的空气-Rairn 2023-04-26 09:56:25 +08:00 committed by GitHub
parent 9101bbbb1b
commit 95e4e7e7b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 126 additions and 92 deletions

View File

@ -175,4 +175,5 @@ export const linkTo: IField = {
// },
],
},
invariable: true,
};

View File

@ -282,4 +282,5 @@ export const m2m: IField = {
// },
],
},
invariable: true,
};

View File

@ -214,4 +214,5 @@ export const m2o: IField = {
// },
],
},
invariable: true,
};

View File

@ -273,4 +273,5 @@ export const o2m: IField = {
// },
],
},
invariable: true,
};

View File

@ -252,6 +252,7 @@ export const o2o: IField = {
// },
],
},
invariable: true,
};
export const oho: IField = {
@ -422,6 +423,7 @@ export const oho: IField = {
// },
],
},
invariable: true,
};
export const obo: IField = {
@ -605,4 +607,5 @@ export const obo: IField = {
// },
],
},
invariable: true,
};

View File

@ -10,5 +10,7 @@ export interface IField extends ISchema {
default?: IDefault;
operators?: any[];
filterable?: any;
/** 不支持使用变量的值进行设置 */
invariable?: boolean;
[key: string]: any;
}

View File

@ -18,9 +18,16 @@ import { SchemaComponent } from '../../core';
import { useCompile, useDesignable, useFieldComponentOptions } from '../../hooks';
import { BlockItem } from '../block-item';
import { HTMLEncode } from '../input/shared';
import { isInvariable } from '../variable';
import { FilterFormDesigner } from './FormItem.FilterFormDesigner';
import { useEnsureOperatorsValid } from './SchemaSettingOptions';
const defaultInputStyle = css`
& > .nb-form-item {
flex: 1;
}
`;
const divWrap = (schema: ISchema) => {
return {
type: 'void',
@ -420,8 +427,7 @@ FormItem.Designer = function Designer() {
type: 'object',
title: t('Set default value'),
properties: {
// 关系字段不支持设置变量
default: collectionField?.target
default: isInvariable(interfaceConfig)
? {
...(fieldSchema || {}),
'x-decorator': 'FormItem',
@ -434,6 +440,12 @@ FormItem.Designer = function Designer() {
service: {
resource: collectionField?.target,
},
// for DynamicExpression
sourceCollection: form?.values.sourceCollection,
style: {
width: '100%',
verticalAlign: 'top',
},
},
name: 'default',
title: t('Default value'),
@ -447,6 +459,7 @@ FormItem.Designer = function Designer() {
...(fieldSchema?.['x-component-props'] || {}),
collectionName: collectionField?.collectionName,
schema: collectionField?.uiSchema,
className: defaultInputStyle,
renderSchemaComponent: function Com(props) {
const s = _.cloneDeep(fieldSchema) || ({} as Schema);
s.title = '';
@ -464,6 +477,7 @@ FormItem.Designer = function Designer() {
defaultValue: getFieldDefaultValue(s, collectionField),
style: {
width: '100%',
verticalAlign: 'top',
},
},
}}

View File

@ -6,6 +6,7 @@ import moment from 'moment';
import React from 'react';
import { useTranslation } from 'react-i18next';
import classNames from 'classnames';
import { useCompile } from '../..';
import { XButton } from './XButton';
@ -51,7 +52,7 @@ const ConstantTypes = {
boolean: {
label: `{{t("Boolean")}}`,
value: 'boolean',
component({ onChange, value }) {
component: function Com({ onChange, value }) {
const { t } = useTranslation();
return (
<Select
@ -88,7 +89,7 @@ const ConstantTypes = {
null: {
label: `{{t("Null")}}`,
value: 'null',
component() {
component: function Com() {
const { t } = useTranslation();
return <AntInput readOnly placeholder={t('Null')} className="null-value" />;
},
@ -115,12 +116,12 @@ export function Input(props) {
const compile = useCompile();
const form = useForm();
const { value = '', scope, onChange, children, button, useTypedConstant, style } = props;
const { value = '', scope, onChange, children, button, useTypedConstant, style, className } = props;
const parsed = parseValue(value);
const isConstant = typeof parsed === 'string';
const type = isConstant ? parsed : '';
const variable = isConstant ? null : parsed;
const varialbeOptions = typeof scope === 'function' ? scope() : scope ?? [];
const variableOptions = typeof scope === 'function' ? scope() : scope ?? [];
const { component: ConstantComponent, ...constantOption }: VariableOptions & { component?: React.FC<any> } = children
? {
@ -134,7 +135,7 @@ export function Input(props) {
label: '{{t("Null")}}',
component: ConstantTypes.null.component,
};
const options: VariableOptions[] = compile([constantOption, ...varialbeOptions]);
const options: VariableOptions[] = compile([constantOption, ...variableOptions]);
function onSwitch(next) {
if (next[0] === '') {
@ -166,7 +167,9 @@ export function Input(props) {
<AntInput.Group
compact
style={style}
className={css`
className={classNames(
className,
css`
width: auto;
display: flex !important;
.ant-input-disabled {
@ -179,9 +182,9 @@ export function Input(props) {
width: 4em;
min-width: 4em;
}
`}
`,
)}
>
<div style={{ flex: 1 }}>
{variable ? (
<div
className={css`
@ -234,6 +237,7 @@ export function Input(props) {
user-select: 'none';
`,
)}
// eslint-disable-next-line react/no-unknown-property
unselectable="on"
aria-hidden
onClick={() => onChange(null)}
@ -245,7 +249,6 @@ export function Input(props) {
) : (
children ?? <ConstantComponent value={value} onChange={onChange} />
)}
</div>
{options.length > 1 ? (
<Cascader
options={options}

View File

@ -1,8 +1,9 @@
import { connect, mapReadPretty } from '@formily/react';
import { IField } from '../../../collection-manager';
import { Input } from './Input';
import { TextArea } from './TextArea';
import { JSONInput } from './JSONInput';
import { TextArea } from './TextArea';
export function Variable() {
return null;
@ -15,3 +16,7 @@ Variable.TextArea = connect(TextArea, mapReadPretty(TextArea.ReadPretty));
Variable.JSON = connect(JSONInput);
export default Variable;
export function isInvariable(value: IField) {
return !!value?.invariable;
}

View File

@ -7,14 +7,15 @@ type Props = {
onChange: (value: any) => void;
collectionName: string;
renderSchemaComponent?: (props: any) => any;
style: React.CSSProperties;
schema: any;
operator: any;
children: any;
children?: any;
className?: string;
style?: React.CSSProperties;
};
export const VariableInput = (props: Props) => {
const { value, onChange, renderSchemaComponent: RenderSchemaComponent, style, schema } = props;
const { value, onChange, renderSchemaComponent: RenderSchemaComponent, style, schema, className } = props;
const compile = useCompile();
const userVariable = useUserVariable({ schema, level: 1 });
const scope = useMemo(() => {
@ -37,7 +38,7 @@ export const VariableInput = (props: Props) => {
}, []);
return (
<Variable.Input value={value} onChange={onChange} scope={scope} style={style}>
<Variable.Input className={className} value={value} onChange={onChange} scope={scope} style={style}>
<RenderSchemaComponent value={value} onChange={onChange} />
</Variable.Input>
);

View File

@ -1,7 +1,7 @@
import React, { useState, useMemo } from 'react';
import { onFieldInputValueChange, onFormInitialValuesChange } from '@formily/core';
import { useForm, observer, connect, mapReadPretty, useFormEffects } from '@formily/react';
import { connect, mapReadPretty, observer, useForm, useFormEffects } from '@formily/react';
import { Tag } from 'antd';
import React, { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useRecord, Variable } from '@nocobase/client';
@ -10,7 +10,7 @@ import { NAMESPACE } from '../locale';
import { useCollectionFieldOptions } from '../variable';
const InternalExpression = observer((props: any) => {
const { onChange } = props;
const { onChange, sourceCollection } = props;
const { values } = useForm();
const [collection, setCollection] = useState(values?.sourceCollection);
@ -24,17 +24,18 @@ const InternalExpression = observer((props: any) => {
});
});
const options = useCollectionFieldOptions({ collection });
const options = useCollectionFieldOptions({ collection: sourceCollection || collection });
return <Variable.TextArea {...props} scope={options} />;
});
function Result(props) {
const { sourceCollection } = props;
const { t } = useTranslation();
const values = useRecord();
const options = useMemo(
() => useCollectionFieldOptions({ collection: values.sourceCollection }),
[values.sourceCollection, values.sourceCollection],
() => useCollectionFieldOptions({ collection: sourceCollection || values.sourceCollection }),
[values.sourceCollection, values.sourceCollection, sourceCollection],
);
return props.value ? (
<Variable.TextArea {...props} scope={options} />

View File

@ -21,4 +21,5 @@ export default {
properties: {
...defaultProps,
},
invariable: true,
} as IField;