This is an automated email from the ASF dual-hosted git repository. shuai pushed a commit to branch feat/schema-form in repository https://gitbox.apache.org/repos/asf/answer.git
commit 9b7c2bd85ab91b18d0044b51955a3878168b2117 Author: shuai <lishuail...@sifou.com> AuthorDate: Fri Aug 8 10:20:46 2025 +0800 feat: schemeForm support tagSelector component --- .../SchemaForm/components/TagSelector.tsx | 66 ++++++++++++++++++++++ ui/src/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(-) 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<Props> = ({ + 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 ( + <TagSelector + value={fieldObject?.value || []} + onChange={handleChange} + maxTagLength={maxTagLength || 0} + isInvalid={fieldObject?.isInvalid} + formText={description} + errMsg={fieldObject?.errorMsg} + /> + ); +}; + +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<FormRef, FormProps> = ( 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<FormRef, FormProps> = ( /> </InputGroup> ) : null} + {widget === 'tag_selector' ? ( + <TagSelector + maxTagLength={max_length} + fieldName={key} + onChange={onChange} + formData={formData} + description={description} + /> + ) : null} {/* Unified handling of `Feedback` and `Text` */} <Form.Control.Feedback type="invalid"> {fieldState?.errorMsg} </Form.Control.Feedback> - {description ? ( + {description && widget !== 'tag_selector' ? ( <Form.Text dangerouslySetInnerHTML={{ __html: description }} /> ) : null} </Form.Group> 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<string | boolean | number>; 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;