mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 06:46:38 +00:00
fix(client): fix variable component read pretty mode (#1673)
This commit is contained in:
parent
13b74bde3f
commit
93348c9ce6
@ -13,7 +13,7 @@ function useOptions({ filter }: CollectionSelectProps) {
|
||||
const compile = useCompile();
|
||||
const { collections = [] } = useCollectionManager();
|
||||
const filtered = typeof filter === 'function' ? collections.filter(filter) : collections;
|
||||
return filtered.map(item => ({
|
||||
return filtered.filter(item => !item.hidden).map(item => ({
|
||||
label: compile(item.title),
|
||||
value: item.name,
|
||||
color: item.category?.color,
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { useState, useEffect, useRef, useMemo } from 'react';
|
||||
import { Input, Cascader, Button } from 'antd';
|
||||
import { Input, Cascader, Button, Tag } from 'antd';
|
||||
import { useForm } from '@formily/react';
|
||||
import { cx, css } from '@emotion/css';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import * as sanitizeHTML from 'sanitize-html';
|
||||
|
||||
import { useCompile } from '../..';
|
||||
import { EllipsisWithTooltip, useCompile } from '../..';
|
||||
import { useRecord } from '../../../record-provider';
|
||||
|
||||
type RangeIndexes = [number, number, number, number];
|
||||
|
||||
@ -380,61 +381,97 @@ export function TextArea(props) {
|
||||
contentEditable={!disabled}
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
/>
|
||||
<Button className={cx('x-button', css`
|
||||
position: relative;
|
||||
`)}>
|
||||
<span
|
||||
className={css`
|
||||
font-style: italic;
|
||||
font-family: "New York", "Times New Roman", Times, serif;
|
||||
`}
|
||||
>x</span>
|
||||
<Cascader
|
||||
placeholder={t('Select a variable')}
|
||||
value={[]}
|
||||
options={options}
|
||||
onChange={(keyPaths = [], selectedOptions = []) => {
|
||||
setSelectedVar(keyPaths as string[]);
|
||||
if (!keyPaths.length) {
|
||||
return;
|
||||
}
|
||||
const option = selectedOptions[selectedOptions.length - 1];
|
||||
if (!option?.children?.length) {
|
||||
onInsert(keyPaths);
|
||||
}
|
||||
}}
|
||||
changeOnSelect
|
||||
onClick={(e: any) => {
|
||||
if (e.detail !== 2) {
|
||||
return;
|
||||
}
|
||||
for (let n = e.target; n && n !== e.currentTarget; n = n.parentNode) {
|
||||
if (Array.from(n.classList ?? []).includes('ant-cascader-menu-item')) {
|
||||
onInsert(selectedVar);
|
||||
}
|
||||
}
|
||||
}}
|
||||
dropdownClassName={css`
|
||||
.ant-cascader-menu{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`}
|
||||
dropdownRender={(menu) => (
|
||||
<>
|
||||
{menu}
|
||||
<div
|
||||
className={css`
|
||||
padding: .5em;
|
||||
border-top: 1px solid rgba(0, 0, 0, .06);
|
||||
color: rgba(0, 0, 0, .45);
|
||||
`}
|
||||
>
|
||||
{t('Double click to choose entire object')}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
{!disabled
|
||||
? (
|
||||
<Button className={cx('x-button', css`
|
||||
position: relative;
|
||||
`)}>
|
||||
<span
|
||||
className={css`
|
||||
font-style: italic;
|
||||
font-family: "New York", "Times New Roman", Times, serif;
|
||||
`}
|
||||
>x</span>
|
||||
<Cascader
|
||||
placeholder={t('Select a variable')}
|
||||
value={[]}
|
||||
options={options}
|
||||
onChange={(keyPaths = [], selectedOptions = []) => {
|
||||
setSelectedVar(keyPaths as string[]);
|
||||
if (!keyPaths.length) {
|
||||
return;
|
||||
}
|
||||
const option = selectedOptions[selectedOptions.length - 1];
|
||||
if (!option?.children?.length) {
|
||||
onInsert(keyPaths);
|
||||
}
|
||||
}}
|
||||
changeOnSelect
|
||||
onClick={(e: any) => {
|
||||
if (e.detail !== 2) {
|
||||
return;
|
||||
}
|
||||
for (let n = e.target; n && n !== e.currentTarget; n = n.parentNode) {
|
||||
if (Array.from(n.classList ?? []).includes('ant-cascader-menu-item')) {
|
||||
onInsert(selectedVar);
|
||||
}
|
||||
}
|
||||
}}
|
||||
dropdownClassName={css`
|
||||
.ant-cascader-menu{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`}
|
||||
dropdownRender={(menu) => (
|
||||
<>
|
||||
{menu}
|
||||
<div
|
||||
className={css`
|
||||
padding: .5em;
|
||||
border-top: 1px solid rgba(0, 0, 0, .06);
|
||||
color: rgba(0, 0, 0, .45);
|
||||
`}
|
||||
>
|
||||
{t('Double click to choose entire object')}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
)
|
||||
: null
|
||||
}
|
||||
</Input.Group>
|
||||
);
|
||||
}
|
||||
|
||||
TextArea.ReadPretty = (props) => {
|
||||
const { value, multiline = true, scope } = props;
|
||||
const compile = useCompile();
|
||||
const options = compile((typeof scope === 'function' ? scope() : scope) ?? []);
|
||||
const keyLabelMap = useMemo(() => createOptionsValueLabelMap(options), [scope]);
|
||||
const html = renderHTML(value ?? '', keyLabelMap);
|
||||
|
||||
const content = (
|
||||
<span
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
className={css`
|
||||
overflow: auto;
|
||||
|
||||
.ant-tag {
|
||||
display: inline;
|
||||
line-height: 19px;
|
||||
margin: 0 .25em;
|
||||
padding: 2px 7px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
`}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<EllipsisWithTooltip ellipsis popoverContent={content}>
|
||||
{content}
|
||||
</EllipsisWithTooltip>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { connect } from '@formily/react';
|
||||
import { connect, mapReadPretty } from '@formily/react';
|
||||
|
||||
import { Input } from "./Input";
|
||||
import { TextArea } from "./TextArea";
|
||||
@ -12,7 +12,7 @@ export function Variable() {
|
||||
|
||||
Variable.Input = connect(Input);
|
||||
|
||||
Variable.TextArea = connect(TextArea);
|
||||
Variable.TextArea = connect(TextArea, mapReadPretty(TextArea.ReadPretty));
|
||||
|
||||
Variable.JSON = connect(JSONInput);
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React, { useState } from "react";
|
||||
import { onFieldInputValueChange } from '@formily/core';
|
||||
import { observer, connect, mapReadPretty, useFormEffects } from '@formily/react';
|
||||
import React, { useState, useMemo } from "react";
|
||||
import { onFieldInputValueChange, onFormInitialValuesChange } from '@formily/core';
|
||||
import { useForm, observer, connect, mapReadPretty, useFormEffects } from '@formily/react';
|
||||
import { Tag } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Variable } from "@nocobase/client";
|
||||
import { useRecord, Variable } from "@nocobase/client";
|
||||
|
||||
import { NAMESPACE } from "../locale";
|
||||
import { useCollectionFieldOptions } from "../variable";
|
||||
@ -12,10 +12,14 @@ import { useCollectionFieldOptions } from "../variable";
|
||||
|
||||
|
||||
const InternalExpression = observer((props: any) => {
|
||||
const { value, onChange } = props;
|
||||
const [collection, setCollection] = useState(null);
|
||||
const { onChange } = props;
|
||||
const { values } = useForm();
|
||||
const [collection, setCollection] = useState(values?.sourceCollection);
|
||||
|
||||
useFormEffects(() => {
|
||||
onFormInitialValuesChange(form => {
|
||||
setCollection(form.values.sourceCollection);
|
||||
});
|
||||
onFieldInputValueChange('sourceCollection', (f) => {
|
||||
setCollection(f.value);
|
||||
onChange(null);
|
||||
@ -26,17 +30,18 @@ const InternalExpression = observer((props: any) => {
|
||||
|
||||
return (
|
||||
<Variable.TextArea
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
{...props}
|
||||
scope={options}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
function Result({ value }) {
|
||||
function Result(props) {
|
||||
const { t } = useTranslation();
|
||||
return value
|
||||
? <Tag color="purple">{t('Expression')}</Tag>
|
||||
const values = useRecord();
|
||||
const options = useMemo(() => useCollectionFieldOptions({ collection: values.sourceCollection }), [values.sourceCollection, values.sourceCollection]);
|
||||
return props.value
|
||||
? <Variable.TextArea {...props} scope={options} />
|
||||
: <Tag>{t('Unconfigured', { ns: NAMESPACE })}</Tag>;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user