add slider field type

This commit is contained in:
Michael Schramm 2021-05-15 10:25:45 +02:00
parent 94f1de3e25
commit de1180d547
6 changed files with 185 additions and 14 deletions

View File

@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- add default page background
- add environment list in [doc](doc/environment.md)
- show error message on homepage in case there is a problem with api connection
- new slider field type
### Changed

View File

@ -7,6 +7,7 @@ import { LinkType } from './link.type'
import { NumberType } from './number.type'
import { RadioType } from './radio.type'
import { RatingType } from './rating.type'
import { SliderType } from './slider.type'
import { TextType } from './text.type'
import { TextareaType } from './textarea.type'
import { AdminFieldTypeProps } from './type.props'
@ -15,15 +16,16 @@ import { YesNoType } from './yes_no.type'
export const adminTypes: {
[key: string]: React.FC<AdminFieldTypeProps>
} = {
textfield: TextType,
date: DateType,
email: EmailType,
textarea: TextareaType,
link: LinkType,
dropdown: DropdownType,
rating: RatingType,
radio: RadioType,
email: EmailType,
hidden: HiddenType,
yes_no: YesNoType,
link: LinkType,
number: NumberType,
radio: RadioType,
rating: RatingType,
slider: SliderType,
textarea: TextareaType,
textfield: TextType,
yes_no: YesNoType,
}

View File

@ -0,0 +1,90 @@
import { Form, InputNumber, Slider } from 'antd'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { AdminFieldTypeProps } from './type.props'
export const SliderType: React.FC<AdminFieldTypeProps> = (props) => {
const { t } = useTranslation()
return (
<div>
<Form.Item shouldUpdate noStyle>
{(form) => {
const getValue = (name, defaultValue: number): number => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const current = form.getFieldValue([
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
...form['prefixName'],
props.field.name as string,
'optionKeys',
name,
])
if (!current) {
return defaultValue
}
return parseFloat(current)
}
const max = getValue('max', 100)
const min = getValue('min', 0)
const step = getValue('step', 1)
return (
<Form.Item
label={t('type:slider.default')}
name={[props.field.name as string, 'value']}
labelCol={{ span: 6 }}
getValueFromEvent={(value: number) =>
typeof value === 'number' ? value.toFixed(2) : value
}
getValueProps={(value: string) => ({ value: value ? parseFloat(value) : undefined })}
>
<Slider min={min} max={max} step={step} dots={(max - min) / step <= 10} />
</Form.Item>
)
}}
</Form.Item>
<Form.Item
label={t('type:slider.min')}
name={[props.field.name as string, 'optionKeys', 'min']}
labelCol={{ span: 6 }}
initialValue={0}
getValueFromEvent={(value: number) =>
typeof value === 'number' ? value.toFixed(2) : value
}
getValueProps={(e: string) => ({ value: e ? parseFloat(e) : undefined })}
>
<InputNumber />
</Form.Item>
<Form.Item
label={t('type:slider.max')}
name={[props.field.name as string, 'optionKeys', 'max']}
labelCol={{ span: 6 }}
initialValue={100}
getValueFromEvent={(value: number) =>
typeof value === 'number' ? value.toFixed(2) : value
}
getValueProps={(e: string) => ({ value: e ? parseFloat(e) : undefined })}
>
<InputNumber />
</Form.Item>
<Form.Item
label={t('type:slider.step')}
name={[props.field.name as string, 'optionKeys', 'step']}
labelCol={{ span: 6 }}
initialValue={1}
getValueFromEvent={(value: number) =>
typeof value === 'number' ? value.toFixed(2) : value
}
getValueProps={(e: string) => ({ value: e ? parseFloat(e) : undefined })}
>
<InputNumber />
</Form.Item>
</div>
)
}

View File

@ -6,6 +6,7 @@ import { LinkType } from './link.type'
import { NumberType } from './number.type'
import { RadioType } from './radio.type'
import { RatingType } from './rating.type'
import { SliderType } from './slider.type'
import { TextType } from './text.type'
import { TextareaType } from './textarea.type'
import { FieldTypeProps } from './type.props'
@ -14,14 +15,15 @@ import { YesNoType } from './yes_no.type'
export const fieldTypes: {
[key: string]: React.FC<FieldTypeProps>
} = {
textfield: TextType,
date: DateType,
email: EmailType,
textarea: TextareaType,
link: LinkType,
dropdown: DropdownType,
rating: RatingType,
radio: RadioType,
yes_no: YesNoType,
email: EmailType,
link: LinkType,
number: NumberType,
radio: RadioType,
rating: RatingType,
slider: SliderType,
textarea: TextareaType,
textfield: TextType,
yes_no: YesNoType,
}

View File

@ -0,0 +1,69 @@
import { Form, Slider, Spin } from 'antd'
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { FieldTypeProps } from './type.props'
export const SliderType: React.FC<FieldTypeProps> = ({ field, urlValue }) => {
const [min, setMin] = useState<number>()
const [max, setMax] = useState<number>()
const [step, setStep] = useState<number>()
const [loading, setLoading] = useState(true)
const { t } = useTranslation()
useEffect(() => {
field.options.forEach((option) => {
if (option.key === 'min') {
setMin(parseFloat(option.value))
}
if (option.key === 'max') {
setMax(parseFloat(option.value))
}
if (option.key === 'step') {
setStep(parseFloat(option.value))
}
})
setLoading(false)
}, [field])
let initialValue: number = undefined
if (field.value) {
initialValue = parseFloat(field.value)
}
if (urlValue) {
initialValue = parseFloat(urlValue)
}
if (loading) {
return (
<div>
<Spin />
</div>
)
}
return (
<div>
<Form.Item
name={[field.id, 'value']}
rules={[{ required: field.required, message: t('validation:valueRequired') }]}
initialValue={initialValue}
getValueFromEvent={(value: number) =>
typeof value === 'number' ? value.toFixed(2) : value
}
getValueProps={(value: string) => ({ value: value ? parseFloat(value) : undefined })}
>
<Slider
min={min}
max={max}
step={step}
tooltipVisible={true}
dots={(max - min) / step <= 10}
/>
</Form.Item>
</div>
)
}

View File

@ -19,6 +19,13 @@
"titlePlaceholder": "Title",
"valuePlaceholder": "Value"
},
"slider": {
"default": "Default Value",
"name": "Slider",
"min": "Min Value",
"max": "Max Value",
"step": "Step Size"
},
"email": {
"default": "Default Email",
"name": "Email"