Merge pull request #216 from stephb9959/main

[WIFI-13515] Supporting deviceTypes in lowercase
This commit is contained in:
Charles Bourque
2024-03-15 17:53:25 +01:00
committed by GitHub
7 changed files with 160 additions and 104 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "ucentral-client", "name": "ucentral-client",
"version": "3.0.2(8)", "version": "3.0.2(9)",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ucentral-client", "name": "ucentral-client",
"version": "3.0.2(8)", "version": "3.0.2(9)",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@chakra-ui/anatomy": "^2.1.1", "@chakra-ui/anatomy": "^2.1.1",

View File

@@ -1,6 +1,6 @@
{ {
"name": "ucentral-client", "name": "ucentral-client",
"version": "3.0.2(8)", "version": "3.0.2(9)",
"description": "", "description": "",
"private": true, "private": true,
"main": "index.tsx", "main": "index.tsx",

View File

@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { FormControl, FormErrorMessage, FormLabel } from '@chakra-ui/react'; import { FormControl, FormErrorMessage, FormLabel } from '@chakra-ui/react';
import { Select } from 'chakra-react-select'; import { CreatableSelect, Select } from 'chakra-react-select';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import isEqual from 'react-fast-compare'; import isEqual from 'react-fast-compare';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -25,6 +25,7 @@ const propTypes = {
isHidden: PropTypes.bool, isHidden: PropTypes.bool,
isPortal: PropTypes.bool.isRequired, isPortal: PropTypes.bool.isRequired,
definitionKey: PropTypes.string, definitionKey: PropTypes.string,
isCreatable: PropTypes.bool,
}; };
const defaultProps = { const defaultProps = {
@@ -36,6 +37,7 @@ const defaultProps = {
isDisabled: false, isDisabled: false,
isHidden: false, isHidden: false,
definitionKey: null, definitionKey: null,
isCreatable: false,
}; };
const FastMultiSelectInput = ({ const FastMultiSelectInput = ({
@@ -50,6 +52,7 @@ const FastMultiSelectInput = ({
isRequired, isRequired,
isDisabled, isDisabled,
isHidden, isHidden,
isCreatable,
isPortal, isPortal,
definitionKey, definitionKey,
}) => { }) => {
@@ -61,6 +64,32 @@ const FastMultiSelectInput = ({
{label} {label}
<ConfigurationFieldExplanation definitionKey={definitionKey} /> <ConfigurationFieldExplanation definitionKey={definitionKey} />
</FormLabel> </FormLabel>
{isCreatable ? (
<CreatableSelect
chakraStyles={{
control: (provided, { isDisabled: isControlDisabled }) => ({
...provided,
borderRadius: '15px',
opacity: isControlDisabled ? '0.8 !important' : '1',
border: '2px solid',
}),
dropdownIndicator: (provided) => ({
...provided,
backgroundColor: 'unset',
border: 'unset',
}),
}}
classNamePrefix={isPortal ? 'chakra-react-select' : ''}
menuPortalTarget={isPortal ? document.body : undefined}
isMulti
closeMenuOnSelect={false}
options={options}
value={value}
onChange={onChange}
onBlur={onBlur}
isDisabled={isDisabled}
/>
) : (
<Select <Select
chakraStyles={{ chakraStyles={{
control: (provided, { isDisabled: isControlDisabled }) => ({ control: (provided, { isDisabled: isControlDisabled }) => ({
@@ -90,6 +119,7 @@ const FastMultiSelectInput = ({
onBlur={onBlur} onBlur={onBlur}
isDisabled={isDisabled} isDisabled={isDisabled}
/> />
)}
<FormErrorMessage>{error}</FormErrorMessage> <FormErrorMessage>{error}</FormErrorMessage>
</FormControl> </FormControl>
); );

View File

@@ -20,6 +20,7 @@ const propTypes = {
canSelectAll: PropTypes.bool, canSelectAll: PropTypes.bool,
isPortal: PropTypes.bool, isPortal: PropTypes.bool,
definitionKey: PropTypes.string, definitionKey: PropTypes.string,
isCreatable: PropTypes.bool,
}; };
const defaultProps = { const defaultProps = {
@@ -31,6 +32,7 @@ const defaultProps = {
canSelectAll: false, canSelectAll: false,
isPortal: false, isPortal: false,
definitionKey: null, definitionKey: null,
isCreatable: false,
}; };
const MultiSelectField = ({ const MultiSelectField = ({
@@ -43,12 +45,23 @@ const MultiSelectField = ({
emptyIsUndefined, emptyIsUndefined,
canSelectAll, canSelectAll,
hasVirtualAll, hasVirtualAll,
isCreatable,
isPortal, isPortal,
definitionKey, definitionKey,
}) => { }) => {
const [{ value }, { touched, error }, { setValue, setTouched }] = useField(name); const [{ value }, { touched, error }, { setValue, setTouched }] = useField(name);
const onChange = useCallback((option) => { const onChange = useCallback(
(option) => {
if (isCreatable) {
if (typeof option === 'string') {
setValue([...value, option]);
} else {
setValue(option);
}
// setValue([...value, option]);
} else {
const allIndex = option.findIndex((opt) => opt.value === '*'); const allIndex = option.findIndex((opt) => opt.value === '*');
if (option.length === 0 && emptyIsUndefined) { if (option.length === 0 && emptyIsUndefined) {
setValue(undefined); setValue(undefined);
@@ -61,7 +74,10 @@ const MultiSelectField = ({
} else if (option.length > 0) setValue(option.map((val) => val.value)); } else if (option.length > 0) setValue(option.map((val) => val.value));
else setValue([]); else setValue([]);
setTouched(true); setTouched(true);
}, []); }
},
[value],
);
const onFieldBlur = useCallback(() => { const onFieldBlur = useCallback(() => {
setTouched(true); setTouched(true);
@@ -82,6 +98,7 @@ const MultiSelectField = ({
isHidden={isHidden} isHidden={isHidden}
isPortal={isPortal} isPortal={isPortal}
definitionKey={definitionKey} definitionKey={definitionKey}
isCreatable={isCreatable}
/> />
); );
}; };

View File

@@ -69,7 +69,9 @@ const CreateDefaultConfigurationModal = () => {
key={formKey} key={formKey}
validationSchema={DefaultConfigurationSchema(t)} validationSchema={DefaultConfigurationSchema(t)}
onSubmit={(data, { setSubmitting, resetForm }) => { onSubmit={(data, { setSubmitting, resetForm }) => {
createConfig.mutateAsync(data, { createConfig.mutateAsync(
{ ...data, modelIds: data.modelIds.map((v) => v.value) },
{
onSuccess: () => { onSuccess: () => {
toast({ toast({
id: `config-create-success`, id: `config-create-success`,
@@ -97,7 +99,8 @@ const CreateDefaultConfigurationModal = () => {
}); });
setSubmitting(false); setSubmitting(false);
}, },
}); },
);
}} }}
> >
<Box> <Box>
@@ -133,6 +136,7 @@ const CreateDefaultConfigurationModal = () => {
value: devType, value: devType,
})) ?? [] })) ?? []
} }
isCreatable
isRequired isRequired
/> />
<StringField name="configuration" label={t('configurations.one')} isArea isDisabled={isDisabled} mt={4} /> <StringField name="configuration" label={t('configurations.one')} isArea isDisabled={isDisabled} mt={4} />

View File

@@ -70,12 +70,15 @@ const EditDefaultConfiguration = ({ modalProps, config }: Props) => {
innerRef={formRef as React.Ref<FormikProps<DefaultConfigurationResponse>>} innerRef={formRef as React.Ref<FormikProps<DefaultConfigurationResponse>>}
initialValues={{ initialValues={{
...config, ...config,
modelIds: config.modelIds.map((v) => ({ label: v, value: v })),
configuration: JSON.stringify(config.configuration, null, 2), configuration: JSON.stringify(config.configuration, null, 2),
}} }}
key={formKey} key={formKey}
validationSchema={DefaultConfigurationSchema(t)} validationSchema={DefaultConfigurationSchema(t)}
onSubmit={(data, { setSubmitting, resetForm }) => { onSubmit={(data, { setSubmitting, resetForm }) => {
updateConfig.mutateAsync(data, { updateConfig.mutateAsync(
{ ...data, modelIds: data.modelIds.map((v) => v.value) },
{
onSuccess: () => { onSuccess: () => {
toast({ toast({
id: `config-edit-success`, id: `config-edit-success`,
@@ -103,7 +106,8 @@ const EditDefaultConfiguration = ({ modalProps, config }: Props) => {
}); });
setSubmitting(false); setSubmitting(false);
}, },
}); },
);
}} }}
> >
<Box> <Box>
@@ -139,6 +143,7 @@ const EditDefaultConfiguration = ({ modalProps, config }: Props) => {
value: devType, value: devType,
})) ?? [] })) ?? []
} }
isCreatable
isRequired isRequired
/> />
<StringField <StringField

View File

@@ -6,7 +6,7 @@ export const DefaultConfigurationSchema = (t: (str: string) => string) =>
.shape({ .shape({
name: Yup.string().required(t('form.required')), name: Yup.string().required(t('form.required')),
description: Yup.string(), description: Yup.string(),
modelIds: Yup.array().of(Yup.string()).required(t('form.required')).min(1, t('form.required')), modelIds: Yup.array().of(Yup.object()).required(t('form.required')).min(1, t('form.required')),
platform: Yup.string().oneOf(['ap', 'switch']).required(t('form.required')), platform: Yup.string().oneOf(['ap', 'switch']).required(t('form.required')),
configuration: Yup.string() configuration: Yup.string()
.required(t('form.required')) .required(t('form.required'))