mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 11:56:29 +00:00
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:
parent
9101bbbb1b
commit
95e4e7e7b0
@ -175,4 +175,5 @@ export const linkTo: IField = {
|
|||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
invariable: true,
|
||||||
};
|
};
|
||||||
|
@ -282,4 +282,5 @@ export const m2m: IField = {
|
|||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
invariable: true,
|
||||||
};
|
};
|
||||||
|
@ -214,4 +214,5 @@ export const m2o: IField = {
|
|||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
invariable: true,
|
||||||
};
|
};
|
||||||
|
@ -273,4 +273,5 @@ export const o2m: IField = {
|
|||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
invariable: true,
|
||||||
};
|
};
|
||||||
|
@ -252,6 +252,7 @@ export const o2o: IField = {
|
|||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
invariable: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const oho: IField = {
|
export const oho: IField = {
|
||||||
@ -422,6 +423,7 @@ export const oho: IField = {
|
|||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
invariable: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const obo: IField = {
|
export const obo: IField = {
|
||||||
@ -605,4 +607,5 @@ export const obo: IField = {
|
|||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
invariable: true,
|
||||||
};
|
};
|
||||||
|
@ -10,5 +10,7 @@ export interface IField extends ISchema {
|
|||||||
default?: IDefault;
|
default?: IDefault;
|
||||||
operators?: any[];
|
operators?: any[];
|
||||||
filterable?: any;
|
filterable?: any;
|
||||||
|
/** 不支持使用变量的值进行设置 */
|
||||||
|
invariable?: boolean;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,16 @@ import { SchemaComponent } from '../../core';
|
|||||||
import { useCompile, useDesignable, useFieldComponentOptions } from '../../hooks';
|
import { useCompile, useDesignable, useFieldComponentOptions } from '../../hooks';
|
||||||
import { BlockItem } from '../block-item';
|
import { BlockItem } from '../block-item';
|
||||||
import { HTMLEncode } from '../input/shared';
|
import { HTMLEncode } from '../input/shared';
|
||||||
|
import { isInvariable } from '../variable';
|
||||||
import { FilterFormDesigner } from './FormItem.FilterFormDesigner';
|
import { FilterFormDesigner } from './FormItem.FilterFormDesigner';
|
||||||
import { useEnsureOperatorsValid } from './SchemaSettingOptions';
|
import { useEnsureOperatorsValid } from './SchemaSettingOptions';
|
||||||
|
|
||||||
|
const defaultInputStyle = css`
|
||||||
|
& > .nb-form-item {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const divWrap = (schema: ISchema) => {
|
const divWrap = (schema: ISchema) => {
|
||||||
return {
|
return {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
@ -420,8 +427,7 @@ FormItem.Designer = function Designer() {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
title: t('Set default value'),
|
title: t('Set default value'),
|
||||||
properties: {
|
properties: {
|
||||||
// 关系字段不支持设置变量
|
default: isInvariable(interfaceConfig)
|
||||||
default: collectionField?.target
|
|
||||||
? {
|
? {
|
||||||
...(fieldSchema || {}),
|
...(fieldSchema || {}),
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
@ -434,6 +440,12 @@ FormItem.Designer = function Designer() {
|
|||||||
service: {
|
service: {
|
||||||
resource: collectionField?.target,
|
resource: collectionField?.target,
|
||||||
},
|
},
|
||||||
|
// for DynamicExpression
|
||||||
|
sourceCollection: form?.values.sourceCollection,
|
||||||
|
style: {
|
||||||
|
width: '100%',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
name: 'default',
|
name: 'default',
|
||||||
title: t('Default value'),
|
title: t('Default value'),
|
||||||
@ -447,6 +459,7 @@ FormItem.Designer = function Designer() {
|
|||||||
...(fieldSchema?.['x-component-props'] || {}),
|
...(fieldSchema?.['x-component-props'] || {}),
|
||||||
collectionName: collectionField?.collectionName,
|
collectionName: collectionField?.collectionName,
|
||||||
schema: collectionField?.uiSchema,
|
schema: collectionField?.uiSchema,
|
||||||
|
className: defaultInputStyle,
|
||||||
renderSchemaComponent: function Com(props) {
|
renderSchemaComponent: function Com(props) {
|
||||||
const s = _.cloneDeep(fieldSchema) || ({} as Schema);
|
const s = _.cloneDeep(fieldSchema) || ({} as Schema);
|
||||||
s.title = '';
|
s.title = '';
|
||||||
@ -464,6 +477,7 @@ FormItem.Designer = function Designer() {
|
|||||||
defaultValue: getFieldDefaultValue(s, collectionField),
|
defaultValue: getFieldDefaultValue(s, collectionField),
|
||||||
style: {
|
style: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
verticalAlign: 'top',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
@ -6,6 +6,7 @@ import moment from 'moment';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
import { useCompile } from '../..';
|
import { useCompile } from '../..';
|
||||||
import { XButton } from './XButton';
|
import { XButton } from './XButton';
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ const ConstantTypes = {
|
|||||||
boolean: {
|
boolean: {
|
||||||
label: `{{t("Boolean")}}`,
|
label: `{{t("Boolean")}}`,
|
||||||
value: 'boolean',
|
value: 'boolean',
|
||||||
component({ onChange, value }) {
|
component: function Com({ onChange, value }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
@ -88,7 +89,7 @@ const ConstantTypes = {
|
|||||||
null: {
|
null: {
|
||||||
label: `{{t("Null")}}`,
|
label: `{{t("Null")}}`,
|
||||||
value: 'null',
|
value: 'null',
|
||||||
component() {
|
component: function Com() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return <AntInput readOnly placeholder={t('Null')} className="null-value" />;
|
return <AntInput readOnly placeholder={t('Null')} className="null-value" />;
|
||||||
},
|
},
|
||||||
@ -115,12 +116,12 @@ export function Input(props) {
|
|||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
const form = useForm();
|
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 parsed = parseValue(value);
|
||||||
const isConstant = typeof parsed === 'string';
|
const isConstant = typeof parsed === 'string';
|
||||||
const type = isConstant ? parsed : '';
|
const type = isConstant ? parsed : '';
|
||||||
const variable = isConstant ? null : 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
|
const { component: ConstantComponent, ...constantOption }: VariableOptions & { component?: React.FC<any> } = children
|
||||||
? {
|
? {
|
||||||
@ -134,7 +135,7 @@ export function Input(props) {
|
|||||||
label: '{{t("Null")}}',
|
label: '{{t("Null")}}',
|
||||||
component: ConstantTypes.null.component,
|
component: ConstantTypes.null.component,
|
||||||
};
|
};
|
||||||
const options: VariableOptions[] = compile([constantOption, ...varialbeOptions]);
|
const options: VariableOptions[] = compile([constantOption, ...variableOptions]);
|
||||||
|
|
||||||
function onSwitch(next) {
|
function onSwitch(next) {
|
||||||
if (next[0] === '') {
|
if (next[0] === '') {
|
||||||
@ -166,86 +167,88 @@ export function Input(props) {
|
|||||||
<AntInput.Group
|
<AntInput.Group
|
||||||
compact
|
compact
|
||||||
style={style}
|
style={style}
|
||||||
className={css`
|
className={classNames(
|
||||||
width: auto;
|
className,
|
||||||
display: flex !important;
|
css`
|
||||||
.ant-input-disabled {
|
width: auto;
|
||||||
.ant-tag {
|
display: flex !important;
|
||||||
color: #bfbfbf;
|
.ant-input-disabled {
|
||||||
border-color: #d9d9d9;
|
.ant-tag {
|
||||||
|
color: #bfbfbf;
|
||||||
|
border-color: #d9d9d9;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.ant-input.null-value {
|
||||||
.ant-input.null-value {
|
width: 4em;
|
||||||
width: 4em;
|
min-width: 4em;
|
||||||
min-width: 4em;
|
}
|
||||||
}
|
`,
|
||||||
`}
|
)}
|
||||||
>
|
>
|
||||||
<div style={{ flex: 1 }}>
|
{variable ? (
|
||||||
{variable ? (
|
<div
|
||||||
|
className={css`
|
||||||
|
position: relative;
|
||||||
|
line-height: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.ant-select-clear {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-input {
|
||||||
|
overflow: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
${disabled ? '' : 'padding-right: 28px;'}
|
||||||
|
|
||||||
|
.ant-tag {
|
||||||
|
display: inline;
|
||||||
|
line-height: 19px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px 7px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className={css`
|
onInput={(e) => e.preventDefault()}
|
||||||
position: relative;
|
onKeyDown={(e) => {
|
||||||
line-height: 0;
|
if (e.key !== 'Backspace') {
|
||||||
|
e.preventDefault();
|
||||||
&:hover {
|
return;
|
||||||
.ant-select-clear {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
onChange(null);
|
||||||
.ant-input {
|
}}
|
||||||
overflow: auto;
|
className={cx('ant-input', { 'ant-input-disabled': disabled })}
|
||||||
white-space: nowrap;
|
contentEditable={!disabled}
|
||||||
${disabled ? '' : 'padding-right: 28px;'}
|
suppressContentEditableWarning
|
||||||
|
|
||||||
.ant-tag {
|
|
||||||
display: inline;
|
|
||||||
line-height: 19px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 2px 7px;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
>
|
>
|
||||||
<div
|
<Tag contentEditable={false} color="blue">
|
||||||
onInput={(e) => e.preventDefault()}
|
{variableText}
|
||||||
onKeyDown={(e) => {
|
</Tag>
|
||||||
if (e.key !== 'Backspace') {
|
|
||||||
e.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onChange(null);
|
|
||||||
}}
|
|
||||||
className={cx('ant-input', { 'ant-input-disabled': disabled })}
|
|
||||||
contentEditable={!disabled}
|
|
||||||
suppressContentEditableWarning
|
|
||||||
>
|
|
||||||
<Tag contentEditable={false} color="blue">
|
|
||||||
{variableText}
|
|
||||||
</Tag>
|
|
||||||
</div>
|
|
||||||
{!disabled ? (
|
|
||||||
<span
|
|
||||||
className={cx(
|
|
||||||
'ant-select-clear',
|
|
||||||
css`
|
|
||||||
user-select: 'none';
|
|
||||||
`,
|
|
||||||
)}
|
|
||||||
unselectable="on"
|
|
||||||
aria-hidden
|
|
||||||
onClick={() => onChange(null)}
|
|
||||||
>
|
|
||||||
<CloseCircleFilled />
|
|
||||||
</span>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
{!disabled ? (
|
||||||
children ?? <ConstantComponent value={value} onChange={onChange} />
|
<span
|
||||||
)}
|
className={cx(
|
||||||
</div>
|
'ant-select-clear',
|
||||||
|
css`
|
||||||
|
user-select: 'none';
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
// eslint-disable-next-line react/no-unknown-property
|
||||||
|
unselectable="on"
|
||||||
|
aria-hidden
|
||||||
|
onClick={() => onChange(null)}
|
||||||
|
>
|
||||||
|
<CloseCircleFilled />
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
children ?? <ConstantComponent value={value} onChange={onChange} />
|
||||||
|
)}
|
||||||
{options.length > 1 ? (
|
{options.length > 1 ? (
|
||||||
<Cascader
|
<Cascader
|
||||||
options={options}
|
options={options}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { connect, mapReadPretty } from '@formily/react';
|
import { connect, mapReadPretty } from '@formily/react';
|
||||||
|
|
||||||
|
import { IField } from '../../../collection-manager';
|
||||||
import { Input } from './Input';
|
import { Input } from './Input';
|
||||||
import { TextArea } from './TextArea';
|
|
||||||
import { JSONInput } from './JSONInput';
|
import { JSONInput } from './JSONInput';
|
||||||
|
import { TextArea } from './TextArea';
|
||||||
|
|
||||||
export function Variable() {
|
export function Variable() {
|
||||||
return null;
|
return null;
|
||||||
@ -15,3 +16,7 @@ Variable.TextArea = connect(TextArea, mapReadPretty(TextArea.ReadPretty));
|
|||||||
Variable.JSON = connect(JSONInput);
|
Variable.JSON = connect(JSONInput);
|
||||||
|
|
||||||
export default Variable;
|
export default Variable;
|
||||||
|
|
||||||
|
export function isInvariable(value: IField) {
|
||||||
|
return !!value?.invariable;
|
||||||
|
}
|
||||||
|
@ -7,14 +7,15 @@ type Props = {
|
|||||||
onChange: (value: any) => void;
|
onChange: (value: any) => void;
|
||||||
collectionName: string;
|
collectionName: string;
|
||||||
renderSchemaComponent?: (props: any) => any;
|
renderSchemaComponent?: (props: any) => any;
|
||||||
style: React.CSSProperties;
|
|
||||||
schema: any;
|
schema: any;
|
||||||
operator: any;
|
operator: any;
|
||||||
children: any;
|
children?: any;
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VariableInput = (props: Props) => {
|
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 compile = useCompile();
|
||||||
const userVariable = useUserVariable({ schema, level: 1 });
|
const userVariable = useUserVariable({ schema, level: 1 });
|
||||||
const scope = useMemo(() => {
|
const scope = useMemo(() => {
|
||||||
@ -37,7 +38,7 @@ export const VariableInput = (props: Props) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
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} />
|
<RenderSchemaComponent value={value} onChange={onChange} />
|
||||||
</Variable.Input>
|
</Variable.Input>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useMemo } from 'react';
|
|
||||||
import { onFieldInputValueChange, onFormInitialValuesChange } from '@formily/core';
|
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 { Tag } from 'antd';
|
||||||
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { useRecord, Variable } from '@nocobase/client';
|
import { useRecord, Variable } from '@nocobase/client';
|
||||||
@ -10,7 +10,7 @@ import { NAMESPACE } from '../locale';
|
|||||||
import { useCollectionFieldOptions } from '../variable';
|
import { useCollectionFieldOptions } from '../variable';
|
||||||
|
|
||||||
const InternalExpression = observer((props: any) => {
|
const InternalExpression = observer((props: any) => {
|
||||||
const { onChange } = props;
|
const { onChange, sourceCollection } = props;
|
||||||
const { values } = useForm();
|
const { values } = useForm();
|
||||||
const [collection, setCollection] = useState(values?.sourceCollection);
|
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} />;
|
return <Variable.TextArea {...props} scope={options} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
function Result(props) {
|
function Result(props) {
|
||||||
|
const { sourceCollection } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const values = useRecord();
|
const values = useRecord();
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => useCollectionFieldOptions({ collection: values.sourceCollection }),
|
() => useCollectionFieldOptions({ collection: sourceCollection || values.sourceCollection }),
|
||||||
[values.sourceCollection, values.sourceCollection],
|
[values.sourceCollection, values.sourceCollection, sourceCollection],
|
||||||
);
|
);
|
||||||
return props.value ? (
|
return props.value ? (
|
||||||
<Variable.TextArea {...props} scope={options} />
|
<Variable.TextArea {...props} scope={options} />
|
||||||
|
@ -21,4 +21,5 @@ export default {
|
|||||||
properties: {
|
properties: {
|
||||||
...defaultProps,
|
...defaultProps,
|
||||||
},
|
},
|
||||||
|
invariable: true,
|
||||||
} as IField;
|
} as IField;
|
||||||
|
Loading…
Reference in New Issue
Block a user