feat(web): ui update
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-04-02 15:15:36
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-04-07 14:48:00
|
||||
* @Last Modified time: 2026-04-16 11:34:41
|
||||
*/
|
||||
import { type FC, useEffect, useMemo } from 'react';
|
||||
import { LexicalComposer } from '@lexical/react/LexicalComposer';
|
||||
@@ -81,7 +81,7 @@ export interface Jinja2EditorProps {
|
||||
value?: string;
|
||||
onChange?: (value: string) => void;
|
||||
options?: Suggestion[];
|
||||
variant?: 'outlined' | 'borderless';
|
||||
variant?: 'outlined' | 'borderless' | 'filled';
|
||||
height?: number;
|
||||
size?: 'default' | 'small';
|
||||
className?: string;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2025-12-23 16:22:51
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-04-07 16:29:36
|
||||
* @Last Modified time: 2026-04-16 12:04:37
|
||||
*/
|
||||
import { type FC, useState, useMemo } from 'react';
|
||||
import { LexicalComposer } from '@lexical/react/LexicalComposer';
|
||||
@@ -25,7 +25,7 @@ export interface LexicalEditorProps {
|
||||
value?: string;
|
||||
onChange?: (value: string) => void;
|
||||
options?: Suggestion[];
|
||||
variant?: 'outlined' | 'borderless';
|
||||
variant?: 'outlined' | 'borderless' | 'filled';
|
||||
height?: number;
|
||||
fontSize?: number;
|
||||
lineHeight?: number;
|
||||
@@ -60,6 +60,7 @@ const Editor: FC<LexicalEditorProps> =({
|
||||
}) => {
|
||||
console.log('Editor value', value)
|
||||
const [_count, setCount] = useState(0);
|
||||
const [focused, setFocused] = useState(false);
|
||||
|
||||
if (language === 'jinja2') {
|
||||
return (
|
||||
@@ -90,7 +91,7 @@ const Editor: FC<LexicalEditorProps> =({
|
||||
// Calculate minimum height based on type and size
|
||||
const minheight = useMemo(() => {
|
||||
if (type === 'input') {
|
||||
return `${height ? height : size === 'small' && variant === 'borderless' ? 18 : size === 'small' ? 26 : 30}px`
|
||||
return `${height ? height : size === 'small' && ['borderless', 'filled'].includes(variant) ? 18 : size === 'small' ? 26 : 30}px`
|
||||
}
|
||||
return `${height ? height : size === 'small' ? 60 : 120}px`
|
||||
}, [type, size, height, variant])
|
||||
@@ -102,7 +103,7 @@ const Editor: FC<LexicalEditorProps> =({
|
||||
|
||||
// Calculate line height based on size prop
|
||||
const lineHeight = useMemo(() => {
|
||||
return `${height ? height - 10 : size === 'small' && variant === 'borderless' ? 18 : size === 'small' ? 16 : 20}px`
|
||||
return `${height ? height - 10 : size === 'small' && ['borderless', 'filled'].includes(variant) ? 18 : size === 'small' ? 16 : 20}px`
|
||||
}, [size])
|
||||
|
||||
// Calculate placeholder minimum height
|
||||
@@ -112,20 +113,24 @@ const Editor: FC<LexicalEditorProps> =({
|
||||
|
||||
return (
|
||||
<LexicalComposer initialConfig={initialConfig}>
|
||||
<div style={{ position: 'relative' }} className={className}>
|
||||
<div style={{ position: 'relative', borderRadius: '8px', background: variant === 'filled' ? '#F6F6F6': 'transparent' }} className={className}>
|
||||
<RichTextPlugin
|
||||
contentEditable={
|
||||
<ContentEditable
|
||||
style={{
|
||||
minHeight: minheight,
|
||||
padding: height ? '4px 6px' : variant === 'borderless' ? '0' : '6px 8px',
|
||||
border: variant === 'borderless' ? 'none' : '1px solid #EBEBEB',
|
||||
padding: height ? '4px 6px' : variant === 'outlined' ? '6px 8px': '0',
|
||||
border: type === 'input' && focused
|
||||
? '1px solid #171719'
|
||||
: variant === 'outlined' ? '1px solid #EBEBEB' : 'none',
|
||||
borderRadius: '8px',
|
||||
outline: 'none',
|
||||
resize: 'none',
|
||||
fontSize: fontSize,
|
||||
lineHeight: lineHeight,
|
||||
}}
|
||||
onFocus={() => type === 'input' && setFocused(true)}
|
||||
onBlur={() => type === 'input' && setFocused(false)}
|
||||
/>
|
||||
}
|
||||
placeholder={
|
||||
@@ -133,12 +138,13 @@ const Editor: FC<LexicalEditorProps> =({
|
||||
style={{
|
||||
minHeight: placeHolderMinheight,
|
||||
position: 'absolute',
|
||||
top: variant === 'borderless' ? '2px' : '6px',
|
||||
left: variant === 'borderless' ? '0' : '11px',
|
||||
color: '#A8A9AA',
|
||||
top: variant === 'outlined' ? '6px' : type === 'input' ? '6px' : '2px',
|
||||
left: variant === 'outlined' ? '11px' : type === 'input' ? '8px' : '0',
|
||||
color: 'rgba(23,23,25,0.25)',
|
||||
fontSize: fontSize,
|
||||
lineHeight: placeHolderMinheight,
|
||||
pointerEvents: 'none',
|
||||
borderRadius: '8px',
|
||||
}}
|
||||
>
|
||||
{placeholder}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-09 18:24:53
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 15:23:45
|
||||
* @Last Modified time: 2026-04-16 12:06:16
|
||||
*/
|
||||
import { useMemo, type FC } from 'react'
|
||||
import clsx from 'clsx'
|
||||
@@ -343,7 +343,7 @@ const CaseList: FC<CaseListProps> = ({
|
||||
return (
|
||||
<Flex key={conditionField.key} gap={4} align="start" className="rb:mb-2!">
|
||||
<div className="rb:flex-1 rb:bg-[#F6F6F6] rb:rounded-lg">
|
||||
<Row className={clsx("rb:p-1!", {
|
||||
<Row className={clsx("rb:px-1!", {
|
||||
'rb-border-b': !hideRightField
|
||||
})}>
|
||||
<Col flex="144px">
|
||||
@@ -377,7 +377,7 @@ const CaseList: FC<CaseListProps> = ({
|
||||
</Row>
|
||||
|
||||
{!hideRightField && (
|
||||
<div className="rb:py-1 rb:px-1.5">
|
||||
<div className={['boolean', 'array[boolean]'].includes(leftFieldType as string) ? "rb:py-1 rb:px-1.5" : ''}>
|
||||
{leftFieldType === 'array[file]'
|
||||
? <>TODO</>
|
||||
: leftFieldType === 'number'
|
||||
@@ -415,7 +415,7 @@ const CaseList: FC<CaseListProps> = ({
|
||||
<Form.Item name={[conditionField.name, 'right']} noStyle>
|
||||
{['boolean', 'array[boolean]'].includes(leftFieldType as string)
|
||||
? <RadioGroupBtn options={[{ value: true, label: 'True' }, { value: false, label: 'False' }]} type="inner" />
|
||||
: <Editor options={options} size="small" type="input" />
|
||||
: <Editor options={options} size="small" type="input" variant='borderless' height={28} />
|
||||
}
|
||||
</Form.Item>
|
||||
)
|
||||
|
||||
@@ -94,7 +94,7 @@ const CodeExecution: FC<CodeExecutionProps> = ({ options }) => {
|
||||
{ label: 'JAVASCRIPT', value: 'javascript' }
|
||||
]}
|
||||
popupMatchSelectWidth={false}
|
||||
className={`rb:font-medium! rb:w-25! rb:h-4! rb:p-0! ${styles.editor}`}
|
||||
className={`rb:font-medium! rb:w-25! rb:h-4! rb:py-0! rb:px-2! ${styles.editor}`}
|
||||
onChange={handleChangeLanguage}
|
||||
variant="borderless"
|
||||
/>
|
||||
|
||||
@@ -178,7 +178,7 @@ const ConditionList: FC<CaseListProps> = ({
|
||||
className="rb:mb-2!"
|
||||
>
|
||||
<div className="rb:flex-1 rb:bg-[#F6F6F6] rb:rounded-lg">
|
||||
<Row className={clsx("rb:p-1!", {
|
||||
<Row className={clsx("rb:px-1!", {
|
||||
'rb-border-b': !hideRightField
|
||||
})}>
|
||||
<Col flex="1">
|
||||
@@ -218,7 +218,7 @@ const ConditionList: FC<CaseListProps> = ({
|
||||
</Row>
|
||||
|
||||
{!hideRightField && (
|
||||
<div className="rb:py-1 rb:px-1.5">
|
||||
<div className={leftFieldType === 'boolean' ? "rb:py-1 rb:px-1.5" : ''}>
|
||||
{leftFieldType === 'number'
|
||||
? (
|
||||
<Flex align="center">
|
||||
|
||||
@@ -155,7 +155,7 @@ const CycleVarsList: FC<CycleVarsListProps> = ({
|
||||
? <CodeMirrorEditor
|
||||
language="json"
|
||||
placeholder={object_placeholder}
|
||||
variant="outlined"
|
||||
variant="filled"
|
||||
size="small"
|
||||
/>
|
||||
: (
|
||||
|
||||
@@ -101,24 +101,20 @@ const FilterConditions: FC<FilterConditionsProps> = ({
|
||||
align="start"
|
||||
className="rb:mb-2!"
|
||||
>
|
||||
<div className="rb:flex-1 rb:bg-[#F6F6F6] rb:rounded-lg">
|
||||
<div className="rb:flex-1">
|
||||
{variableType === 'array[file]' &&
|
||||
<Row className="rb:p-1! rb-border-b">
|
||||
<Col span={24}>
|
||||
<Form.Item name={[field.name, 'key']} noStyle>
|
||||
<Select
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
options={fileSubVariable}
|
||||
fieldNames={{ value: 'filed', label: 'label' }}
|
||||
onChange={(value) => handleKeyFieldChange(index, value)}
|
||||
variant="borderless"
|
||||
className="rb:w-full! rb:h-7!"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Form.Item name={[field.name, 'key']} noStyle>
|
||||
<Select
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
options={fileSubVariable}
|
||||
fieldNames={{ value: 'filed', label: 'label' }}
|
||||
onChange={(value) => handleKeyFieldChange(index, value)}
|
||||
className="rb:w-full! select rb:mb-1!"
|
||||
variant="borderless"
|
||||
/>
|
||||
</Form.Item>
|
||||
}
|
||||
<Row>
|
||||
<Row gutter={8}>
|
||||
<Col flex={hideValueField ? '1' : "96px"}>
|
||||
<Form.Item name={[field.name, 'comparison_operator']} noStyle>
|
||||
<Select
|
||||
@@ -129,28 +125,27 @@ const FilterConditions: FC<FilterConditionsProps> = ({
|
||||
size="small"
|
||||
popupMatchSelectWidth={false}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
className="rb:w-full! select"
|
||||
variant="borderless"
|
||||
className="rb:w-full! rb:h-7!"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
{!hideValueField && (
|
||||
<Col flex="1">
|
||||
<Form.Item name={[field.name, 'value']} className="rb:pt-0.5! rb:mb-0! rb:pl-2!">
|
||||
<Form.Item name={[field.name, 'value']} noStyle>
|
||||
{innerType === 'boolean'
|
||||
? <RadioGroupBtn options={[{ value: true, label: 'True' }, { value: false, label: 'False' }]} type="inner" />
|
||||
: keyFieldValue === 'type'
|
||||
? <Select
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
options={typeOptions.map(vo => ({ value: vo, label: t(`application.${vo}`) } ))}
|
||||
variant="borderless"
|
||||
className="rb:w-full!"
|
||||
variant="filled"
|
||||
/>
|
||||
: <Editor
|
||||
variant="borderless"
|
||||
variant="filled"
|
||||
type="input"
|
||||
size="small"
|
||||
height={24}
|
||||
height={28}
|
||||
options={keyFieldType ? options.flatMap(vo => {
|
||||
if (vo.dataType === keyFieldType) return [vo];
|
||||
const filteredChildren = vo.children?.filter(sub => sub.dataType === keyFieldType);
|
||||
@@ -167,7 +162,7 @@ const FilterConditions: FC<FilterConditionsProps> = ({
|
||||
</Row>
|
||||
</div>
|
||||
<div
|
||||
className="rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/workflow/deleteBg.svg')] rb:hover:bg-[url('@/assets/images/workflow/deleteBg_hover.svg')]"
|
||||
className="rb:size-4 rb:mt-1.5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/workflow/deleteBg.svg')] rb:hover:bg-[url('@/assets/images/workflow/deleteBg_hover.svg')]"
|
||||
onClick={() => remove(field.name)}
|
||||
></div>
|
||||
</Flex>
|
||||
|
||||
@@ -58,7 +58,7 @@ const MappingList: FC<MappingListProps> = ({ label, name, options, extra, valueK
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
options={options}
|
||||
size="small"
|
||||
className="rb:w-51!"
|
||||
className="rb:flex-1!"
|
||||
/>
|
||||
</Form.Item>
|
||||
<div
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
}
|
||||
.properties :global(.select.ant-select-single.ant-select-sm.ant-select-borderless) {
|
||||
height: 28px;
|
||||
border: 1px solid #F6F6F6;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.properties :global(.select.ant-select-single.ant-select-sm.ant-select-borderless.ant-select-focused) {
|
||||
border: 1px solid #171719;
|
||||
}
|
||||
.properties :global(.ant-table-wrapper .ant-table-thead>tr>th),
|
||||
.properties :global(.ant-table-wrapper .ant-table-thead>tr>td),
|
||||
|
||||
Reference in New Issue
Block a user