Загрузка данных
import { useDeviceRepository } from '@/domains/equipment/repositories/device.repository';
import { useNetInterfaceRepository } from '@/domains/equipment/repositories/netInterface.repository';
import { Helpers } from '@/shared/lib';
import { useDeviceActions } from '@/shared/store/сontrollers/device.actions';
import { yupResolver } from '@hookform/resolvers/yup';
import { QueryStatus } from '@reduxjs/toolkit/dist/query';
import { DrawerProps } from '@sber-friend/flamingo-core';
import {
DeviceModel,
Ieee8021X,
InterfaceType,
useGetApiV1SecondaryInterfaceValueOwnerByOwnerIdQuery,
useGetDeviceByIdQuery,
} from '@shared/api/controller/client';
import { Button, Drawer } from '@shared/components';
import { useCloseDrawer } from '@shared/hooks/drawer/useCloseDrawer';
import { useSelectDrawerType } from '@shared/hooks/drawer/useSelectDrawerType';
import {
EventActionTypes,
useSendClickStreamEvent,
} from '@shared/hooks/useSendClickStreamEvent';
import { DrawerTypes } from '@shared/model/drawer/drawer.types';
import { useSelectActiveDeviceId } from '@shared/store/сontrollers/сontrollers.selectors';
import { useSyncControlPage } from '@widgets/Monitoring/hooks';
import { memo, useEffect, useState } from 'react';
import {
FormProvider,
Resolver,
SubmitHandler,
useForm,
} from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { UpdateDeviceForm } from './UpdateDeviceForm/UpdateDeviceForm';
import { OTHER_VALUES } from './model/formNames';
import { UpdateDeviceFormData } from './model/types';
import { updateDeviceSchema } from './validation/validator';
export const UpdateDeviceDrawer = memo(() => {
const { t } = useTranslation('common');
const { sendEvent } = useSendClickStreamEvent(EventActionTypes.updateDevice);
const closeDrawer = useCloseDrawer();
const { setActiveDeviceId } = useDeviceActions();
const drawerType = useSelectDrawerType();
const open = drawerType[DrawerTypes.updateDevice];
const activeDeviceId = useSelectActiveDeviceId();
const { updateDevice, updateDeviceStatus, isUpdateDeviceLoading } =
useDeviceRepository();
const { isSuccess: isDeviceSuccess, currentData: device } =
useGetDeviceByIdQuery(
{ deviceId: activeDeviceId! },
{
skip: !activeDeviceId,
refetchOnMountOrArgChange: true,
refetchOnReconnect: true,
},
);
const id = device?.id;
const {
data: secondaryInterfaceData,
isSuccess: isSecondaryInterfaceSuccess,
} = useGetApiV1SecondaryInterfaceValueOwnerByOwnerIdQuery(
{ ownerId: id! },
{ skip: !id },
);
const defaultValues: UpdateDeviceFormData = {
name: device?.name,
description: device?.description,
ip: device?.ip || '',
controlPage: device?.controlPage ?? '',
hardwareId: device?.hardwareId,
type:
(device?.interface?.type?.toLowerCase().trim() as InterfaceType) ?? '',
bidirectional: Boolean(device?.bidirectional),
mac: device?.mac ?? '',
manufacturerName: device?.model?.manufacturer?.name,
typeName: device?.model?.type?.name,
sipUri: device?.sipUri ?? '',
hasSipUri: device?.model?.type?.hasSipUri ?? null,
modelId: device?.model?.id,
firmware: device?.firmware,
serialNumber: device?.serialNumber,
inventoryNumber: device?.inventoryNumber,
protocolIp: device?.interface?.protocolIp,
ipAvLan: device?.interface?.ipAvLan ?? '',
port: device?.interface?.port,
// TODO Саша будет присылать null либо не будет присылать поле вовсе
ieee8021x:
device?.interface?.ieee8021x === ('' as Ieee8021X)
? undefined
: device?.interface?.ieee8021x,
netInterface: !!secondaryInterfaceData?.length,
netInterfaceInfo: secondaryInterfaceData?.map((secondaryInterface) => {
return {
gateway: secondaryInterface.gateway,
mac: secondaryInterface.mac,
ip: secondaryInterface.ip,
subnetMask: secondaryInterface.subnetMask,
nameId: secondaryInterface.name?.id,
id: secondaryInterface.id,
};
}),
disableMonitoring: device?.disableMonitoring ?? false,
};
useEffect(() => {
if (isSecondaryInterfaceSuccess && secondaryInterfaceData) {
methods.setValue(
OTHER_VALUES.netInterface,
!!secondaryInterfaceData?.length,
);
methods.setValue(
OTHER_VALUES.netInterfaceInfo,
secondaryInterfaceData?.map((secondaryInterface) => {
return {
gateway: secondaryInterface.gateway,
mac: secondaryInterface.mac,
ip: secondaryInterface.ip,
subnetMask: secondaryInterface.subnetMask,
nameId: secondaryInterface.name?.id,
id: secondaryInterface.id,
};
}),
);
}
}, [isSecondaryInterfaceSuccess, secondaryInterfaceData]);
const methods = useForm<UpdateDeviceFormData>({
mode: 'onBlur',
reValidateMode: 'onChange',
defaultValues,
resolver: yupResolver(updateDeviceSchema) as Resolver<UpdateDeviceFormData>,
});
const netInterfaceInfo = methods.watch(OTHER_VALUES.netInterfaceInfo);
const netInterface = methods.watch(OTHER_VALUES.netInterface);
const { deleteNetInterfaces } = useNetInterfaceRepository();
const [model, setModel] = useState<DeviceModel | null>(null);
useEffect(() => {
if (device?.model) {
setModel(device.model);
}
}, [device]);
const handleClearModel = () => {
methods.setValue('modelId', '');
methods.setValue('manufacturerName', '');
methods.setValue('typeName', '');
methods.setValue('sipUri', '');
methods.setValue('hasSipUri', null);
};
useEffect(() => {
if (model) {
methods.setValue('manufacturerName', model?.manufacturer?.name);
methods.setValue('typeName', model?.type?.name);
methods.setValue('hasSipUri', model.type?.hasSipUri);
}
}, [model]);
useEffect(() => {
(async () => {
if (
!netInterface &&
isSecondaryInterfaceSuccess &&
netInterfaceInfo &&
!!netInterfaceInfo.length
) {
await deleteNetInterfaces(
netInterfaceInfo?.map((netInterface) => netInterface.id),
);
methods.setValue(OTHER_VALUES.netInterfaceInfo, []);
}
})();
}, [netInterface, netInterfaceInfo, isSecondaryInterfaceSuccess]);
useSyncControlPage(device?.ip, methods);
useEffect(() => {
if (updateDeviceStatus === QueryStatus.fulfilled) {
closeDrawer(DrawerTypes.updateDevice);
sendEvent();
}
}, [updateDeviceStatus]);
const submitHandler: SubmitHandler<UpdateDeviceFormData> = async (values) => {
if (device?.id) {
await updateDevice(values, device.id);
}
};
useEffect(() => {
if (isDeviceSuccess && device && open && id) {
methods.reset(defaultValues);
}
}, [device, open, isDeviceSuccess, id]);
const { isValid, dirtyFields } = methods.formState;
const isDirtyFields = !Helpers.isEmpty(dirtyFields);
const isSaveButtonDisabled = !isDirtyFields || !isValid;
const actions = {
actionPrimary: (
<Button
onClick={methods.handleSubmit(submitHandler)}
loading={isUpdateDeviceLoading}
disabled={isSaveButtonDisabled}
>
{t('buttons.save')}
</Button>
),
};
const handleClose: DrawerProps['onClose'] = () => {
methods.reset(defaultValues);
setModel(null);
};
if (!device) {
return null;
}
return (
<FormProvider {...methods}>
<Drawer
type={DrawerTypes.updateDevice}
actions={actions}
title={t('drawerTitle.updateDevice')}
onClose={handleClose}
>
<UpdateDeviceForm
initialModel={device?.model}
setModel={setModel}
handleClearModel={handleClearModel}
/>
</Drawer>
</FormProvider>
);
});