From 19aed9f9c8221e5ae3f67f160954898a072f976b Mon Sep 17 00:00:00 2001 From: shuai Date: Fri, 8 Aug 2025 10:20:46 +0800 Subject: [PATCH] feat: schemeForm support tagSelector component --- .../SchemaForm/components/TagSelector.tsx | 66 +++++++++++++++++++ .../components/SchemaForm/components/index.ts | 2 + ui/src/components/SchemaForm/index.tsx | 13 +++- ui/src/components/SchemaForm/types.ts | 6 +- 4 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 ui/src/components/SchemaForm/components/TagSelector.tsx diff --git a/ui/src/components/SchemaForm/components/TagSelector.tsx b/ui/src/components/SchemaForm/components/TagSelector.tsx new file mode 100644 index 00000000..f23b14f6 --- /dev/null +++ b/ui/src/components/SchemaForm/components/TagSelector.tsx @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { FC } from 'react'; + +import { TagSelector } from '@/components'; +import type * as Type from '@/common/interface'; + +interface Props { + maxTagLength?: number; + description?: string; + fieldName: string; + onChange?: (fd: Type.FormDataType) => void; + formData: Type.FormDataType; +} +const Index: FC = ({ + description, + maxTagLength, + fieldName, + onChange, + formData, +}) => { + const fieldObject = formData[fieldName]; + const handleChange = (data: Type.Tag[]) => { + const state = { + ...formData, + [fieldName]: { + ...formData[fieldName], + value: data, + isInvalid: false, + }, + }; + if (typeof onChange === 'function') { + onChange(state); + } + }; + + return ( + + ); +}; + +export default Index; diff --git a/ui/src/components/SchemaForm/components/index.ts b/ui/src/components/SchemaForm/components/index.ts index df28f4ac..2a75307d 100644 --- a/ui/src/components/SchemaForm/components/index.ts +++ b/ui/src/components/SchemaForm/components/index.ts @@ -27,6 +27,7 @@ import Textarea from './Textarea'; import Input from './Input'; import Button from './Button'; import InputGroup from './InputGroup'; +import TagSelector from './TagSelector'; export { Legend, @@ -39,4 +40,5 @@ export { Input, Button, InputGroup, + TagSelector, }; diff --git a/ui/src/components/SchemaForm/index.tsx b/ui/src/components/SchemaForm/index.tsx index 6b7cbbf0..421e0b1e 100644 --- a/ui/src/components/SchemaForm/index.tsx +++ b/ui/src/components/SchemaForm/index.tsx @@ -51,6 +51,7 @@ import { Input, Button as SfButton, InputGroup, + TagSelector, } from './components'; export * from './types'; @@ -258,6 +259,7 @@ const SchemaForm: ForwardRefRenderFunction = ( description, enum: enumValues = [], enumNames = [], + max_length = 0, } = properties[key]; const { 'ui:widget': widget = 'input', 'ui:options': uiOpt } = uiSchema?.[key] || {}; @@ -413,11 +415,20 @@ const SchemaForm: ForwardRefRenderFunction = ( /> ) : null} + {widget === 'tag_selector' ? ( + + ) : null} {/* Unified handling of `Feedback` and `Text` */} {fieldState?.errorMsg} - {description ? ( + {description && widget !== 'tag_selector' ? ( ) : null} diff --git a/ui/src/components/SchemaForm/types.ts b/ui/src/components/SchemaForm/types.ts index 8347b98f..db1aa8a5 100644 --- a/ui/src/components/SchemaForm/types.ts +++ b/ui/src/components/SchemaForm/types.ts @@ -44,12 +44,13 @@ export interface JSONSchema { required?: string[]; properties: { [key: string]: { - type: 'string' | 'boolean' | 'number'; + type?: 'string' | 'boolean' | 'number'; title: string; description?: string; enum?: Array; enumNames?: string[]; default?: string | boolean | number | any[]; + max_length?: number; }; }; } @@ -152,7 +153,8 @@ export type UIWidget = | 'switch' | 'legend' | 'button' - | 'input_group'; + | 'input_group' + | 'tag_selector'; export interface UISchema { [key: string]: { 'ui:widget'?: UIWidget;