mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-10-29 01:12:19 +00:00
Merge pull request #216 from stephb9959/main
[WIFI-13515] Supporting deviceTypes in lowercase
This commit is contained in:
4
package-lock.json
generated
4
package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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,35 +64,62 @@ const FastMultiSelectInput = ({
|
|||||||
{label}
|
{label}
|
||||||
<ConfigurationFieldExplanation definitionKey={definitionKey} />
|
<ConfigurationFieldExplanation definitionKey={definitionKey} />
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Select
|
{isCreatable ? (
|
||||||
chakraStyles={{
|
<CreatableSelect
|
||||||
control: (provided, { isDisabled: isControlDisabled }) => ({
|
chakraStyles={{
|
||||||
...provided,
|
control: (provided, { isDisabled: isControlDisabled }) => ({
|
||||||
borderRadius: '15px',
|
...provided,
|
||||||
opacity: isControlDisabled ? '0.8 !important' : '1',
|
borderRadius: '15px',
|
||||||
border: '2px solid',
|
opacity: isControlDisabled ? '0.8 !important' : '1',
|
||||||
}),
|
border: '2px solid',
|
||||||
dropdownIndicator: (provided) => ({
|
}),
|
||||||
...provided,
|
dropdownIndicator: (provided) => ({
|
||||||
backgroundColor: 'unset',
|
...provided,
|
||||||
border: 'unset',
|
backgroundColor: 'unset',
|
||||||
}),
|
border: 'unset',
|
||||||
}}
|
}),
|
||||||
classNamePrefix={isPortal ? 'chakra-react-select' : ''}
|
}}
|
||||||
menuPortalTarget={isPortal ? document.body : undefined}
|
classNamePrefix={isPortal ? 'chakra-react-select' : ''}
|
||||||
isMulti
|
menuPortalTarget={isPortal ? document.body : undefined}
|
||||||
closeMenuOnSelect={false}
|
isMulti
|
||||||
options={canSelectAll ? [{ value: '*', label: t('common.all') }, ...options] : options}
|
closeMenuOnSelect={false}
|
||||||
value={
|
options={options}
|
||||||
value?.map((val) => {
|
value={value}
|
||||||
if (val === '*') return { value: val, label: t('common.all') };
|
onChange={onChange}
|
||||||
return options.find((opt) => opt.value === val);
|
onBlur={onBlur}
|
||||||
}) ?? []
|
isDisabled={isDisabled}
|
||||||
}
|
/>
|
||||||
onChange={onChange}
|
) : (
|
||||||
onBlur={onBlur}
|
<Select
|
||||||
isDisabled={isDisabled}
|
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={canSelectAll ? [{ value: '*', label: t('common.all') }, ...options] : options}
|
||||||
|
value={
|
||||||
|
value?.map((val) => {
|
||||||
|
if (val === '*') return { value: val, label: t('common.all') };
|
||||||
|
return options.find((opt) => opt.value === val);
|
||||||
|
}) ?? []
|
||||||
|
}
|
||||||
|
onChange={onChange}
|
||||||
|
onBlur={onBlur}
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<FormErrorMessage>{error}</FormErrorMessage>
|
<FormErrorMessage>{error}</FormErrorMessage>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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,25 +45,39 @@ 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(
|
||||||
const allIndex = option.findIndex((opt) => opt.value === '*');
|
(option) => {
|
||||||
if (option.length === 0 && emptyIsUndefined) {
|
if (isCreatable) {
|
||||||
setValue(undefined);
|
if (typeof option === 'string') {
|
||||||
} else if (allIndex === 0 && option.length > 1) {
|
setValue([...value, option]);
|
||||||
const newValues = option.slice(1);
|
} else {
|
||||||
setValue(newValues.map((val) => val.value));
|
setValue(option);
|
||||||
} else if (allIndex >= 0) {
|
}
|
||||||
if (!hasVirtualAll) setValue(['*']);
|
|
||||||
else setValue(options.map(({ value: v }) => v));
|
// setValue([...value, option]);
|
||||||
} else if (option.length > 0) setValue(option.map((val) => val.value));
|
} else {
|
||||||
else setValue([]);
|
const allIndex = option.findIndex((opt) => opt.value === '*');
|
||||||
setTouched(true);
|
if (option.length === 0 && emptyIsUndefined) {
|
||||||
}, []);
|
setValue(undefined);
|
||||||
|
} else if (allIndex === 0 && option.length > 1) {
|
||||||
|
const newValues = option.slice(1);
|
||||||
|
setValue(newValues.map((val) => val.value));
|
||||||
|
} else if (allIndex >= 0) {
|
||||||
|
if (!hasVirtualAll) setValue(['*']);
|
||||||
|
else setValue(options.map(({ value: v }) => v));
|
||||||
|
} else if (option.length > 0) setValue(option.map((val) => val.value));
|
||||||
|
else setValue([]);
|
||||||
|
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}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,35 +69,38 @@ 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(
|
||||||
onSuccess: () => {
|
{ ...data, modelIds: data.modelIds.map((v) => v.value) },
|
||||||
toast({
|
{
|
||||||
id: `config-create-success`,
|
onSuccess: () => {
|
||||||
title: t('common.success'),
|
toast({
|
||||||
description: t('controller.configurations.create_success'),
|
id: `config-create-success`,
|
||||||
status: 'success',
|
title: t('common.success'),
|
||||||
duration: 5000,
|
description: t('controller.configurations.create_success'),
|
||||||
isClosable: true,
|
status: 'success',
|
||||||
position: 'top-right',
|
duration: 5000,
|
||||||
});
|
isClosable: true,
|
||||||
setSubmitting(false);
|
position: 'top-right',
|
||||||
resetForm();
|
});
|
||||||
modalProps.onClose();
|
setSubmitting(false);
|
||||||
|
resetForm();
|
||||||
|
modalProps.onClose();
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
const e = error as AxiosError;
|
||||||
|
toast({
|
||||||
|
id: `config-create-error`,
|
||||||
|
title: t('common.error'),
|
||||||
|
description: e?.response?.data?.ErrorDescription,
|
||||||
|
status: 'error',
|
||||||
|
duration: 5000,
|
||||||
|
isClosable: true,
|
||||||
|
position: 'top-right',
|
||||||
|
});
|
||||||
|
setSubmitting(false);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
);
|
||||||
const e = error as AxiosError;
|
|
||||||
toast({
|
|
||||||
id: `config-create-error`,
|
|
||||||
title: t('common.error'),
|
|
||||||
description: e?.response?.data?.ErrorDescription,
|
|
||||||
status: 'error',
|
|
||||||
duration: 5000,
|
|
||||||
isClosable: true,
|
|
||||||
position: 'top-right',
|
|
||||||
});
|
|
||||||
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} />
|
||||||
|
|||||||
@@ -70,40 +70,44 @@ 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(
|
||||||
onSuccess: () => {
|
{ ...data, modelIds: data.modelIds.map((v) => v.value) },
|
||||||
toast({
|
{
|
||||||
id: `config-edit-success`,
|
onSuccess: () => {
|
||||||
title: t('common.success'),
|
toast({
|
||||||
description: t('controller.configurations.update_success'),
|
id: `config-edit-success`,
|
||||||
status: 'success',
|
title: t('common.success'),
|
||||||
duration: 5000,
|
description: t('controller.configurations.update_success'),
|
||||||
isClosable: true,
|
status: 'success',
|
||||||
position: 'top-right',
|
duration: 5000,
|
||||||
});
|
isClosable: true,
|
||||||
setSubmitting(false);
|
position: 'top-right',
|
||||||
resetForm();
|
});
|
||||||
modalProps.onClose();
|
setSubmitting(false);
|
||||||
|
resetForm();
|
||||||
|
modalProps.onClose();
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
const e = error as AxiosError;
|
||||||
|
toast({
|
||||||
|
id: `config-edit-error`,
|
||||||
|
title: t('common.error'),
|
||||||
|
description: e?.response?.data?.ErrorDescription,
|
||||||
|
status: 'error',
|
||||||
|
duration: 5000,
|
||||||
|
isClosable: true,
|
||||||
|
position: 'top-right',
|
||||||
|
});
|
||||||
|
setSubmitting(false);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
);
|
||||||
const e = error as AxiosError;
|
|
||||||
toast({
|
|
||||||
id: `config-edit-error`,
|
|
||||||
title: t('common.error'),
|
|
||||||
description: e?.response?.data?.ErrorDescription,
|
|
||||||
status: 'error',
|
|
||||||
duration: 5000,
|
|
||||||
isClosable: true,
|
|
||||||
position: 'top-right',
|
|
||||||
});
|
|
||||||
setSubmitting(false);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box>
|
<Box>
|
||||||
@@ -139,6 +143,7 @@ const EditDefaultConfiguration = ({ modalProps, config }: Props) => {
|
|||||||
value: devType,
|
value: devType,
|
||||||
})) ?? []
|
})) ?? []
|
||||||
}
|
}
|
||||||
|
isCreatable
|
||||||
isRequired
|
isRequired
|
||||||
/>
|
/>
|
||||||
<StringField
|
<StringField
|
||||||
|
|||||||
@@ -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'))
|
||||||
|
|||||||
Reference in New Issue
Block a user