diff --git a/application/constants/templates.py b/application/constants/templates.py index 6b5b8adb..9dad891a 100644 --- a/application/constants/templates.py +++ b/application/constants/templates.py @@ -10,6 +10,7 @@ class InputTypes(StrEnum): """ checkbox = 'checkbox' number = 'number' + password = 'password' radio_select = 'radio_select' select = 'select' slider = 'slider' diff --git a/application/schemas/templates/inputs.py b/application/schemas/templates/inputs.py index d91d92c8..b4bd5d92 100644 --- a/application/schemas/templates/inputs.py +++ b/application/schemas/templates/inputs.py @@ -132,7 +132,7 @@ def ensure_default_in_range(cls, values: dict) -> dict: class TextualInput(BaseInput): """ - User inputs where user can choose one or more option from predefined set. + User inputs with one of the text kind widget. """ type: Literal[InputTypes.text] | Literal[InputTypes.textarea] = Field( description='Type of form input.', example=Literal[InputTypes.text] @@ -190,18 +190,25 @@ class SliderInput(NumericInput): class TextInput(TextualInput): """ - User inputs where user can choose one or more option from predefined set. + User inputs with simple one line textfield. """ type: Literal[InputTypes.text] = Field(description='Type of form input.', example=InputTypes.text) class TextareaInput(TextualInput): """ - User inputs where user can choose one or more option from predefined set. + User inputs with multiline textbox. """ type: Literal[InputTypes.textarea] = Field(description='Type of form input.', example=InputTypes.textarea) +class PasswordInput(TextualInput): + """ + User inputs with password textfield which hides entered text. + """ + type: Literal[InputTypes.password] = Field(description='Type of form input.', example=InputTypes.password) + + Input = Annotated[CheckboxInput | NumberInputs | RadioSelectInput | @@ -209,5 +216,6 @@ class TextareaInput(TextualInput): SliderInput | SwitchInput | TextareaInput | - TextInput, + TextInput | + PasswordInput, Field(discriminator='type')] diff --git a/frontend/src/app/main/applications/TemplateInputs/TemplateInputs.js b/frontend/src/app/main/applications/TemplateInputs/TemplateInputs.js index 62b9a3f2..a47aaeba 100644 --- a/frontend/src/app/main/applications/TemplateInputs/TemplateInputs.js +++ b/frontend/src/app/main/applications/TemplateInputs/TemplateInputs.js @@ -7,6 +7,7 @@ import { selectTemplates } from 'app/store/templatesSlice'; import TypeCheckbox from './TypeCheckbox'; import TypeNumber from './TypeNumber'; +import TypePassword from './TypePassword'; import TypeRadio from './TypeRadio'; import TypeSelect from './TypeSelect'; import TypeSlider from './TypeSlider'; @@ -67,6 +68,9 @@ const TemplateInputs = ({ setTemplateFormData, clearMessages, templateFromCatalo case 'text': newItem = { ...item, default: e.target.value }; break; + case 'password': + newItem = { ...item, default: e.target.value }; + break; case 'textarea': newItem = { ...item, default: e.target.value }; break; @@ -127,6 +131,8 @@ const TemplateInputs = ({ setTemplateFormData, clearMessages, templateFromCatalo switch (item.type) { case 'text': return ; + case 'password': + return ; case 'textarea': return ; case 'select': diff --git a/frontend/src/app/main/applications/TemplateInputs/TypePassword.js b/frontend/src/app/main/applications/TemplateInputs/TypePassword.js new file mode 100644 index 00000000..b835d6b2 --- /dev/null +++ b/frontend/src/app/main/applications/TemplateInputs/TypePassword.js @@ -0,0 +1,42 @@ +import { Visibility, VisibilityOff } from '@mui/icons-material'; +import { FormHelperText } from '@mui/material'; +import FormControl from '@mui/material/FormControl'; +import IconButton from '@mui/material/IconButton'; +import InputAdornment from '@mui/material/InputAdornment'; +import TextField from '@mui/material/TextField'; +import { useState } from 'react'; + +const TypePassword = ({ item, onChangeInputs }) => { + const [showPassword, setShowPassword] = useState(false); + const handleClickShowPassword = () => setShowPassword(!showPassword); + const handleMouseDownPassword = () => setShowPassword(!showPassword); + + return ( + + onChangeInputs(e, item)} + InputProps={{ + endAdornment: ( + + + {showPassword ? : } + + + ), + }} + /> + {item?.description} + + ); +}; + +export default TypePassword; diff --git a/frontend/src/app/main/templates/TemplateModal/TemplateBuilder/InputsBuilder/InputFields/InputTypes.js b/frontend/src/app/main/templates/TemplateModal/TemplateBuilder/InputsBuilder/InputFields/InputTypes.js index b69de6a8..f5831103 100644 --- a/frontend/src/app/main/templates/TemplateModal/TemplateBuilder/InputsBuilder/InputFields/InputTypes.js +++ b/frontend/src/app/main/templates/TemplateModal/TemplateBuilder/InputsBuilder/InputFields/InputTypes.js @@ -1,7 +1,17 @@ import { FormControl, InputLabel, MenuItem, Select } from '@mui/material'; import { useEffect, useState } from 'react'; -const TYPE_VALUES = ['text', 'textarea', 'select', 'radio_select', 'switch', 'checkbox', 'slider', 'number']; +const TYPE_VALUES = [ + 'text', + 'password', + 'textarea', + 'select', + 'radio_select', + 'switch', + 'checkbox', + 'slider', + 'number', +]; const InputTypes = ({ typeValue, index, handleOnChangeInput, infoIsYamlValid }) => { const [type, setType] = useState(''); diff --git a/frontend/src/app/main/templates/TemplateModal/TemplateBuilder/InputsBuilder/InputItem.js b/frontend/src/app/main/templates/TemplateModal/TemplateBuilder/InputsBuilder/InputItem.js index a5b0b2dd..7f2930a1 100644 --- a/frontend/src/app/main/templates/TemplateModal/TemplateBuilder/InputsBuilder/InputItem.js +++ b/frontend/src/app/main/templates/TemplateModal/TemplateBuilder/InputsBuilder/InputItem.js @@ -59,7 +59,14 @@ const InputItem = ({ input, index, infoIsYamlValid }) => { infoIsYamlValid={infoIsYamlValid} /> )} - + {input.type === 'password' && ( + + )} {input.type === 'textarea' && (