mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 10:28:10 +08:00
feat: add checkbox list
This commit is contained in:
171
web/app/components/base/checkbox-list/index.tsx
Normal file
171
web/app/components/base/checkbox-list/index.tsx
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
'use client'
|
||||||
|
import Badge from '@/app/components/base/badge'
|
||||||
|
import Checkbox from '@/app/components/base/checkbox'
|
||||||
|
import cn from '@/utils/classnames'
|
||||||
|
import type { FC } from 'react'
|
||||||
|
import { useCallback, useMemo } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
export type CheckboxListOption = {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
disabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CheckboxListProps = {
|
||||||
|
title?: string
|
||||||
|
label?: string
|
||||||
|
description?: string
|
||||||
|
options: CheckboxListOption[]
|
||||||
|
value?: string[]
|
||||||
|
onChange?: (value: string[]) => void
|
||||||
|
disabled?: boolean
|
||||||
|
containerClassName?: string
|
||||||
|
showSelectAll?: boolean
|
||||||
|
showCount?: boolean
|
||||||
|
maxHeight?: string | number
|
||||||
|
}
|
||||||
|
|
||||||
|
const CheckboxList: FC<CheckboxListProps> = ({
|
||||||
|
title = '',
|
||||||
|
label,
|
||||||
|
description,
|
||||||
|
options,
|
||||||
|
value = [],
|
||||||
|
onChange,
|
||||||
|
disabled = false,
|
||||||
|
containerClassName,
|
||||||
|
showSelectAll = true,
|
||||||
|
showCount = true,
|
||||||
|
maxHeight,
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const selectedCount = value.length
|
||||||
|
|
||||||
|
const isAllSelected = useMemo(() => {
|
||||||
|
const selectableOptions = options.filter(option => !option.disabled)
|
||||||
|
return selectableOptions.length > 0 && selectableOptions.every(option => value.includes(option.value))
|
||||||
|
}, [options, value])
|
||||||
|
|
||||||
|
const isIndeterminate = useMemo(() => {
|
||||||
|
const selectableOptions = options.filter(option => !option.disabled)
|
||||||
|
const selectedCount = selectableOptions.filter(option => value.includes(option.value)).length
|
||||||
|
return selectedCount > 0 && selectedCount < selectableOptions.length
|
||||||
|
}, [options, value])
|
||||||
|
|
||||||
|
const handleSelectAll = useCallback(() => {
|
||||||
|
if (disabled)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (isAllSelected) {
|
||||||
|
// Deselect all
|
||||||
|
onChange?.([])
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Select all non-disabled options
|
||||||
|
const allValues = options
|
||||||
|
.filter(option => !option.disabled)
|
||||||
|
.map(option => option.value)
|
||||||
|
onChange?.(allValues)
|
||||||
|
}
|
||||||
|
}, [isAllSelected, options, onChange, disabled])
|
||||||
|
|
||||||
|
const handleToggleOption = useCallback((optionValue: string) => {
|
||||||
|
if (disabled)
|
||||||
|
return
|
||||||
|
|
||||||
|
const newValue = value.includes(optionValue)
|
||||||
|
? value.filter(v => v !== optionValue)
|
||||||
|
: [...value, optionValue]
|
||||||
|
onChange?.(newValue)
|
||||||
|
}, [value, onChange, disabled])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn('flex flex-col gap-1', containerClassName)}>
|
||||||
|
{label && (
|
||||||
|
<div className='system-sm-medium text-text-secondary'>
|
||||||
|
{label}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{description && (
|
||||||
|
<div className='body-xs-regular text-text-tertiary'>
|
||||||
|
{description}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className='rounded-lg border border-components-panel-border bg-components-panel-bg'>
|
||||||
|
{(showSelectAll || title) && (
|
||||||
|
<div className='relative flex items-center gap-2 border-b border-divider-subtle px-3 py-2'>
|
||||||
|
{showSelectAll && (
|
||||||
|
<Checkbox
|
||||||
|
checked={isAllSelected}
|
||||||
|
indeterminate={isIndeterminate}
|
||||||
|
onCheck={handleSelectAll}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className='flex flex-1 items-center gap-1'>
|
||||||
|
{title && (
|
||||||
|
<span className='system-xs-semibold-uppercase leading-5 text-text-secondary'>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{showCount && selectedCount > 0 && (
|
||||||
|
<Badge uppercase>
|
||||||
|
{t('common.operation.selectCount', { count: selectedCount })}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div
|
||||||
|
className='p-1'
|
||||||
|
style={maxHeight ? { maxHeight, overflowY: 'auto' } : {}}
|
||||||
|
>
|
||||||
|
{!options.length ? (
|
||||||
|
<div className='px-3 py-6 text-center text-sm text-text-tertiary'>
|
||||||
|
{t('common.noData')}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
options.map((option) => {
|
||||||
|
const selected = value.includes(option.value)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={option.value}
|
||||||
|
className={cn(
|
||||||
|
'flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 transition-colors hover:bg-state-base-hover',
|
||||||
|
option.disabled && 'cursor-not-allowed opacity-50',
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
if (!option.disabled && !disabled)
|
||||||
|
handleToggleOption(option.value)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
checked={selected}
|
||||||
|
onCheck={() => {
|
||||||
|
if (!option.disabled && !disabled)
|
||||||
|
handleToggleOption(option.value)
|
||||||
|
}}
|
||||||
|
disabled={option.disabled || disabled}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className='system-sm-medium flex-1 truncate text-text-secondary'
|
||||||
|
title={option.label}
|
||||||
|
>
|
||||||
|
{option.label}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CheckboxList
|
||||||
@ -30,7 +30,7 @@ const Checkbox = ({
|
|||||||
<div
|
<div
|
||||||
id={id}
|
id={id}
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex h-4 w-4 cursor-pointer items-center justify-center rounded-[4px] shadow-xs shadow-shadow-shadow-3',
|
'flex h-4 w-4 shrink-0 cursor-pointer items-center justify-center rounded-[4px] shadow-xs shadow-shadow-shadow-3',
|
||||||
checkClassName,
|
checkClassName,
|
||||||
disabled && disabledClassName,
|
disabled && disabledClassName,
|
||||||
className,
|
className,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import CheckboxList from '@/app/components/base/checkbox-list'
|
||||||
import type { FormSchema } from '@/app/components/base/form/types'
|
import type { FormSchema } from '@/app/components/base/form/types'
|
||||||
import { FormTypeEnum } from '@/app/components/base/form/types'
|
import { FormTypeEnum } from '@/app/components/base/form/types'
|
||||||
import Input from '@/app/components/base/input'
|
import Input from '@/app/components/base/input'
|
||||||
@ -5,6 +6,7 @@ import Radio from '@/app/components/base/radio'
|
|||||||
import RadioE from '@/app/components/base/radio/ui'
|
import RadioE from '@/app/components/base/radio/ui'
|
||||||
import { PortalSelect } from '@/app/components/base/select'
|
import { PortalSelect } from '@/app/components/base/select'
|
||||||
import PureSelect from '@/app/components/base/select/pure'
|
import PureSelect from '@/app/components/base/select/pure'
|
||||||
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||||
import { useTriggerPluginDynamicOptions } from '@/service/use-triggers'
|
import { useTriggerPluginDynamicOptions } from '@/service/use-triggers'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
@ -52,6 +54,7 @@ const BaseField = ({
|
|||||||
}: BaseFieldProps) => {
|
}: BaseFieldProps) => {
|
||||||
const renderI18nObject = useRenderI18nObject()
|
const renderI18nObject = useRenderI18nObject()
|
||||||
const {
|
const {
|
||||||
|
name,
|
||||||
label,
|
label,
|
||||||
required,
|
required,
|
||||||
placeholder,
|
placeholder,
|
||||||
@ -60,6 +63,8 @@ const BaseField = ({
|
|||||||
disabled: formSchemaDisabled,
|
disabled: formSchemaDisabled,
|
||||||
type: formItemType,
|
type: formItemType,
|
||||||
dynamicSelectParams,
|
dynamicSelectParams,
|
||||||
|
multiple = false,
|
||||||
|
tooltip,
|
||||||
} = formSchema
|
} = formSchema
|
||||||
const disabled = propsDisabled || formSchemaDisabled
|
const disabled = propsDisabled || formSchemaDisabled
|
||||||
|
|
||||||
@ -150,6 +155,12 @@ const BaseField = ({
|
|||||||
<span className='ml-1 text-text-destructive-secondary'>*</span>
|
<span className='ml-1 text-text-destructive-secondary'>*</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
{tooltip && (
|
||||||
|
<Tooltip
|
||||||
|
popupContent={<div className='w-[200px]'>{typeof tooltip === 'string' ? tooltip : renderI18nObject(tooltip as Record<string, string>)}</div>}
|
||||||
|
triggerClassName='ml-0.5 w-4 h-4'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={cn(inputContainerClassName)}>
|
<div className={cn(inputContainerClassName)}>
|
||||||
{
|
{
|
||||||
@ -170,7 +181,7 @@ const BaseField = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
formItemType === FormTypeEnum.select && (
|
formItemType === FormTypeEnum.select && !multiple && (
|
||||||
<PureSelect
|
<PureSelect
|
||||||
value={value}
|
value={value}
|
||||||
onChange={v => handleChange(v)}
|
onChange={v => handleChange(v)}
|
||||||
@ -184,6 +195,17 @@ const BaseField = ({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
formItemType === FormTypeEnum.select && multiple && (
|
||||||
|
<CheckboxList
|
||||||
|
title={name}
|
||||||
|
value={value}
|
||||||
|
onChange={v => field.handleChange(v)}
|
||||||
|
options={memorizedOptions}
|
||||||
|
maxHeight='200px'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
{
|
{
|
||||||
formItemType === FormTypeEnum.dynamicSelect && (
|
formItemType === FormTypeEnum.dynamicSelect && (
|
||||||
<PortalSelect
|
<PortalSelect
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export const useGetFormValues = (form: AnyFormApi, formSchemas: FormSchema[]) =>
|
|||||||
|
|
||||||
const getFormValues = useCallback((
|
const getFormValues = useCallback((
|
||||||
{
|
{
|
||||||
needCheckValidatedValues,
|
needCheckValidatedValues = true,
|
||||||
needTransformWhenSecretFieldIsPristine,
|
needTransformWhenSecretFieldIsPristine,
|
||||||
}: GetValuesOptions,
|
}: GetValuesOptions,
|
||||||
) => {
|
) => {
|
||||||
@ -20,7 +20,7 @@ export const useGetFormValues = (form: AnyFormApi, formSchemas: FormSchema[]) =>
|
|||||||
if (!needCheckValidatedValues) {
|
if (!needCheckValidatedValues) {
|
||||||
return {
|
return {
|
||||||
values,
|
values,
|
||||||
isCheckValidated: false,
|
isCheckValidated: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,6 +50,7 @@ export type FormSchema = {
|
|||||||
name: string
|
name: string
|
||||||
label: string | ReactNode | TypeWithI18N | Record<Locale, string>
|
label: string | ReactNode | TypeWithI18N | Record<Locale, string>
|
||||||
required: boolean
|
required: boolean
|
||||||
|
multiple?: boolean
|
||||||
default?: any
|
default?: any
|
||||||
tooltip?: string | TypeWithI18N | Record<Locale, string>
|
tooltip?: string | TypeWithI18N | Record<Locale, string>
|
||||||
show_on?: FormShowOnObject[]
|
show_on?: FormShowOnObject[]
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { CopyFeedbackNew } from '@/app/components/base/copy-feedback'
|
// import { CopyFeedbackNew } from '@/app/components/base/copy-feedback'
|
||||||
import { BaseForm } from '@/app/components/base/form/components/base'
|
import { BaseForm } from '@/app/components/base/form/components/base'
|
||||||
import type { FormRefObject } from '@/app/components/base/form/types'
|
import type { FormRefObject } from '@/app/components/base/form/types'
|
||||||
import { FormTypeEnum } from '@/app/components/base/form/types'
|
import { FormTypeEnum } from '@/app/components/base/form/types'
|
||||||
import Input from '@/app/components/base/input'
|
|
||||||
import Modal from '@/app/components/base/modal/modal'
|
import Modal from '@/app/components/base/modal/modal'
|
||||||
import Toast from '@/app/components/base/toast'
|
import Toast from '@/app/components/base/toast'
|
||||||
import { SupportedCreationMethods } from '@/app/components/plugins/types'
|
import { SupportedCreationMethods } from '@/app/components/plugins/types'
|
||||||
@ -66,7 +65,6 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
|
|||||||
|
|
||||||
const [currentStep, setCurrentStep] = useState<ApiKeyStep>(createType === SupportedCreationMethods.APIKEY ? ApiKeyStep.Verify : ApiKeyStep.Configuration)
|
const [currentStep, setCurrentStep] = useState<ApiKeyStep>(createType === SupportedCreationMethods.APIKEY ? ApiKeyStep.Verify : ApiKeyStep.Configuration)
|
||||||
|
|
||||||
const [subscriptionName, setSubscriptionName] = useState('')
|
|
||||||
const [subscriptionBuilder, setSubscriptionBuilder] = useState<TriggerSubscriptionBuilder | undefined>(builder)
|
const [subscriptionBuilder, setSubscriptionBuilder] = useState<TriggerSubscriptionBuilder | undefined>(builder)
|
||||||
const [verificationError, setVerificationError] = useState<string>('')
|
const [verificationError, setVerificationError] = useState<string>('')
|
||||||
|
|
||||||
@ -76,6 +74,7 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
|
|||||||
|
|
||||||
const providerName = `${detail?.plugin_id}/${detail?.declaration.name}`
|
const providerName = `${detail?.plugin_id}/${detail?.declaration.name}`
|
||||||
const propertiesSchema = detail?.declaration.trigger.subscription_schema.properties_schema || [] // manual
|
const propertiesSchema = detail?.declaration.trigger.subscription_schema.properties_schema || [] // manual
|
||||||
|
const subscriptionFormRef = React.useRef<FormRefObject>(null)
|
||||||
const propertiesFormRef = React.useRef<FormRefObject>(null)
|
const propertiesFormRef = React.useRef<FormRefObject>(null)
|
||||||
const parametersSchema = detail?.declaration.trigger?.subscription_schema?.parameters_schema || [] // apikey and oauth
|
const parametersSchema = detail?.declaration.trigger?.subscription_schema?.parameters_schema || [] // apikey and oauth
|
||||||
const parametersFormRef = React.useRef<FormRefObject>(null)
|
const parametersFormRef = React.useRef<FormRefObject>(null)
|
||||||
@ -151,32 +150,23 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleCreate = () => {
|
const handleCreate = () => {
|
||||||
if (!subscriptionName.trim()) {
|
const parameterForm = parametersFormRef.current?.getFormValues({}) || { values: {}, isCheckValidated: false }
|
||||||
Toast.notify({
|
const subscriptionForm = subscriptionFormRef.current?.getFormValues({})
|
||||||
type: 'error',
|
// console.log('parameterForm', parameterForm)
|
||||||
message: t('pluginTrigger.modal.form.subscriptionName.required'),
|
|
||||||
})
|
if (!subscriptionForm?.isCheckValidated || !parameterForm?.isCheckValidated)
|
||||||
return
|
return
|
||||||
}
|
|
||||||
|
|
||||||
if (!subscriptionBuilder)
|
if (!subscriptionBuilder)
|
||||||
return
|
return
|
||||||
|
|
||||||
const parameterForm = parametersFormRef.current?.getFormValues({}) || { values: {}, isCheckValidated: false }
|
const subscriptionNameValue = subscriptionForm.values.subscription_name as string
|
||||||
// console.log('formValues', formValues)
|
|
||||||
// if (!formValues.isCheckValidated) {
|
|
||||||
// Toast.notify({
|
|
||||||
// type: 'error',
|
|
||||||
// message: t('pluginTrigger.modal.form.properties.required'),
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
buildSubscription(
|
buildSubscription(
|
||||||
{
|
{
|
||||||
provider: providerName,
|
provider: providerName,
|
||||||
subscriptionBuilderId: subscriptionBuilder.id,
|
subscriptionBuilderId: subscriptionBuilder.id,
|
||||||
name: subscriptionName,
|
name: subscriptionNameValue,
|
||||||
parameters: { ...parameterForm.values, events: ['*'] },
|
parameters: { ...parameterForm.values, events: ['*'] },
|
||||||
// properties: formValues.values,
|
// properties: formValues.values,
|
||||||
},
|
},
|
||||||
@ -228,6 +218,7 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
|
|||||||
ref={credentialsFormRef}
|
ref={credentialsFormRef}
|
||||||
labelClassName='system-sm-medium mb-2 block text-text-primary'
|
labelClassName='system-sm-medium mb-2 block text-text-primary'
|
||||||
preventDefaultSubmit={true}
|
preventDefaultSubmit={true}
|
||||||
|
formClassName='space-y-4'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -241,34 +232,39 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{currentStep === ApiKeyStep.Configuration && <div className='max-h-[70vh] overflow-y-auto'>
|
{currentStep === ApiKeyStep.Configuration && <div className='max-h-[70vh] overflow-y-auto'>
|
||||||
<div className='mb-6'>
|
<BaseForm
|
||||||
<label className='system-sm-medium mb-2 block text-text-primary'>
|
formSchemas={[
|
||||||
{t('pluginTrigger.modal.form.subscriptionName.label')}
|
{
|
||||||
</label>
|
name: 'subscription_name',
|
||||||
<Input
|
label: t('pluginTrigger.modal.form.subscriptionName.label'),
|
||||||
value={subscriptionName}
|
placeholder: t('pluginTrigger.modal.form.subscriptionName.placeholder'),
|
||||||
onChange={e => setSubscriptionName(e.target.value)}
|
type: FormTypeEnum.textInput,
|
||||||
placeholder={t('pluginTrigger.modal.form.subscriptionName.placeholder')}
|
required: true,
|
||||||
/>
|
},
|
||||||
</div>
|
{
|
||||||
|
name: 'callback_url',
|
||||||
<div className='mb-6'>
|
label: t('pluginTrigger.modal.form.callbackUrl.label'),
|
||||||
<label className='system-sm-medium mb-2 block text-text-primary'>
|
placeholder: t('pluginTrigger.modal.form.callbackUrl.placeholder'),
|
||||||
{t('pluginTrigger.modal.form.callbackUrl.label')}
|
type: FormTypeEnum.textInput,
|
||||||
</label>
|
required: false,
|
||||||
<div className='relative'>
|
default: subscriptionBuilder?.endpoint || '',
|
||||||
<Input
|
disabled: true,
|
||||||
value={subscriptionBuilder?.endpoint}
|
tooltip: t('pluginTrigger.modal.form.callbackUrl.tooltip'),
|
||||||
readOnly
|
// extra: subscriptionBuilder?.endpoint ? (
|
||||||
className='pr-12'
|
// <CopyFeedbackNew
|
||||||
placeholder={t('pluginTrigger.modal.form.callbackUrl.placeholder')}
|
// className='absolute right-1 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary'
|
||||||
/>
|
// content={subscriptionBuilder?.endpoint || ''}
|
||||||
<CopyFeedbackNew className='absolute right-1 top-1/2 h-4 w-4 -translate-y-1/2 text-text-tertiary' content={subscriptionBuilder?.endpoint || ''} />
|
// />
|
||||||
</div>
|
// ) : undefined,
|
||||||
<div className='system-xs-regular mt-1 text-text-tertiary'>
|
},
|
||||||
{t('pluginTrigger.modal.form.callbackUrl.description')}
|
]}
|
||||||
</div>
|
ref={subscriptionFormRef}
|
||||||
</div>
|
labelClassName='system-sm-medium mb-2 flex items-center gap-1 text-text-primary'
|
||||||
|
formClassName='space-y-4 mb-4'
|
||||||
|
/>
|
||||||
|
{/* <div className='system-xs-regular mb-6 mt-[-1rem] text-text-tertiary'>
|
||||||
|
{t('pluginTrigger.modal.form.callbackUrl.description')}
|
||||||
|
</div> */}
|
||||||
{createType !== SupportedCreationMethods.MANUAL && parametersSchema.length > 0 && (
|
{createType !== SupportedCreationMethods.MANUAL && parametersSchema.length > 0 && (
|
||||||
<BaseForm
|
<BaseForm
|
||||||
formSchemas={parametersSchema.map(schema => ({
|
formSchemas={parametersSchema.map(schema => ({
|
||||||
@ -283,6 +279,7 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
|
|||||||
}))}
|
}))}
|
||||||
ref={parametersFormRef}
|
ref={parametersFormRef}
|
||||||
labelClassName='system-sm-medium mb-2 block text-text-primary'
|
labelClassName='system-sm-medium mb-2 block text-text-primary'
|
||||||
|
formClassName='space-y-4'
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{createType === SupportedCreationMethods.MANUAL && <>
|
{createType === SupportedCreationMethods.MANUAL && <>
|
||||||
@ -292,6 +289,7 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
|
|||||||
formSchemas={propertiesSchema}
|
formSchemas={propertiesSchema}
|
||||||
ref={propertiesFormRef}
|
ref={propertiesFormRef}
|
||||||
labelClassName='system-sm-medium mb-2 block text-text-primary'
|
labelClassName='system-sm-medium mb-2 block text-text-primary'
|
||||||
|
formClassName='space-y-4'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -311,11 +309,9 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
|
|||||||
Awaiting request from {detail?.declaration.name}...
|
Awaiting request from {detail?.declaration.name}...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<LogViewer logs={logData?.logs || []} />
|
<LogViewer logs={logData?.logs || []} />
|
||||||
</div>
|
</div>
|
||||||
</>}
|
</>}
|
||||||
|
|
||||||
</div>}
|
</div>}
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -30,19 +30,6 @@ type Props = {
|
|||||||
|
|
||||||
export const DEFAULT_METHOD = 'default'
|
export const DEFAULT_METHOD = 'default'
|
||||||
|
|
||||||
/**
|
|
||||||
* 区分创建订阅的授权方式有几种
|
|
||||||
* 1. 只有一种授权方式
|
|
||||||
* - 按钮直接显示授权方式,点击按钮展示创建订阅弹窗
|
|
||||||
* 2. 有多种授权方式
|
|
||||||
* - 下拉框显示授权方式,点击按钮展示下拉框,点击选项展示创建订阅弹窗
|
|
||||||
* 有订阅与无订阅时,按钮形态不同
|
|
||||||
* oauth 的授权类型:
|
|
||||||
* - 是否配置 client_id 和 client_secret
|
|
||||||
* - 未配置则点击按钮去配置
|
|
||||||
* - 已配置则点击按钮去创建
|
|
||||||
* - 固定展示设置按钮
|
|
||||||
*/
|
|
||||||
export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BUTTON }: Props) => {
|
export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BUTTON }: Props) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [selectedCreateInfo, setSelectedCreateInfo] = useState<{ type: SupportedCreationMethods, builder?: TriggerSubscriptionBuilder } | null>(null)
|
const [selectedCreateInfo, setSelectedCreateInfo] = useState<{ type: SupportedCreationMethods, builder?: TriggerSubscriptionBuilder } | null>(null)
|
||||||
|
|||||||
@ -68,6 +68,7 @@ const translation = {
|
|||||||
more: 'More',
|
more: 'More',
|
||||||
selectAll: 'Select All',
|
selectAll: 'Select All',
|
||||||
deSelectAll: 'Deselect All',
|
deSelectAll: 'Deselect All',
|
||||||
|
selectCount: '{{count}} Selected',
|
||||||
},
|
},
|
||||||
errorMsg: {
|
errorMsg: {
|
||||||
fieldRequired: '{{field}} is required',
|
fieldRequired: '{{field}} is required',
|
||||||
@ -76,7 +77,9 @@ const translation = {
|
|||||||
placeholder: {
|
placeholder: {
|
||||||
input: 'Please enter',
|
input: 'Please enter',
|
||||||
select: 'Please select',
|
select: 'Please select',
|
||||||
|
search: 'Search...',
|
||||||
},
|
},
|
||||||
|
noData: 'No data',
|
||||||
label: {
|
label: {
|
||||||
optional: '(optional)',
|
optional: '(optional)',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -68,6 +68,7 @@ const translation = {
|
|||||||
selectAll: '全选',
|
selectAll: '全选',
|
||||||
deSelectAll: '取消全选',
|
deSelectAll: '取消全选',
|
||||||
now: '现在',
|
now: '现在',
|
||||||
|
selectCount: '已选择 {{count}} 项',
|
||||||
},
|
},
|
||||||
errorMsg: {
|
errorMsg: {
|
||||||
fieldRequired: '{{field}} 为必填项',
|
fieldRequired: '{{field}} 为必填项',
|
||||||
@ -76,7 +77,9 @@ const translation = {
|
|||||||
placeholder: {
|
placeholder: {
|
||||||
input: '请输入',
|
input: '请输入',
|
||||||
select: '请选择',
|
select: '请选择',
|
||||||
|
search: '搜索...',
|
||||||
},
|
},
|
||||||
|
noData: '暂无数据',
|
||||||
label: {
|
label: {
|
||||||
optional: '(可选)',
|
optional: '(可选)',
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user