Загрузка данных


import { OTHER_VALUES } from '@/domains/controller/components/CreateController/model/formNames';
import { useControllerRepository } from '@/domains/equipment/repositories/controller.repository';
import { useNetInterfaceRepository } from '@/domains/equipment/repositories/netInterface.repository';
import { ConfirmIpChangeModal } from '@/entities/Modals';
import { useGetEquipmentWindowQuery } from '@/shared/api/auth/equipment/client';
import { Helpers } from '@/shared/lib';
import { yupResolver } from '@hookform/resolvers/yup';
import { QueryStatus, skipToken } from '@reduxjs/toolkit/query';
import {
  DeviceModel,
  useAddControllerModelMutation,
  useGetApiV1SecondaryInterfaceValueOwnerByOwnerIdQuery,
  useGetControllerByIdQuery,
  useGetControllerModelByIdQuery,
} from '@shared/api/controller/client';
import {
  Button,
  Drawer,
  DrawerActions,
  DrawerProps,
  Loader,
} 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 { useControllerActions } from '@shared/store/сontrollers/controllers.actions';
import {
  useSelectActiveControllerId,
  useSelectControllerLocationId,
} 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 { UpdateControllerForm } from './UpdateControllerForm';
import { OTHER_NAMES } from './model/formNames';
import { UpdateControllerFormData } from './model/types';
import { updateControllerFormSchema } from './validation/validator';

const FIVE_SECONDS = 5000;

export const UpdateControllerDrawer = memo(() => {
  const { t } = useTranslation();

  const { sendEvent } = useSendClickStreamEvent(
    EventActionTypes.createController,
  );

  const { cleanControllerLocationId } = useControllerActions();

  const closeDrawer = useCloseDrawer();
  const drawerType = useSelectDrawerType();
  const open = drawerType[DrawerTypes.updateController];

  const controllerId = useSelectActiveControllerId();
  const locationId = useSelectControllerLocationId();

  const {
    updateController,
    isUpdateControllerLoading,
    controllerUpdateStatus,
    resetUpdateController,
  } = useControllerRepository();

  const { data: controller } = useGetControllerByIdQuery(
    { controllerId: controllerId ?? '' },
    {
      skip: !controllerId,
      refetchOnMountOrArgChange: true,
    },
  );

  const id = controller?.id;
  const currentIp = controller?.ip?.trim() ?? '';

  const { data: equipmentWindowData } = useGetEquipmentWindowQuery(
    { ip: currentIp },
    {
      skip: !currentIp || !open,
      pollingInterval: FIVE_SECONDS,
    },
  );

  const hasActiveWindows =
    !!equipmentWindowData?.status && equipmentWindowData.status !== 'absent';

  const {
    data: secondaryInterfaceData,
    isSuccess: isSecondaryInterfaceSuccess,
  } = useGetApiV1SecondaryInterfaceValueOwnerByOwnerIdQuery(
    { ownerId: id! },
    { skip: !id },
  );

  const [model, setModel] = useState<DeviceModel | null>(null);
  const [pendingValues, setPendingValues] =
    useState<UpdateControllerFormData | null>(null);

  const [createdModelId, setCreatedModelId] = useState<string | null>(null);

  const [, createDeviceModelResult] = useAddControllerModelMutation({
    fixedCacheKey: 'create-controller-model',
  });

  useEffect(() => {
    const id = createDeviceModelResult.data?.id;

    if (id) {
      setCreatedModelId(id);
    }
  }, [createDeviceModelResult.data?.id]);

  const { data: createdModel } = useGetControllerModelByIdQuery(
    createdModelId ? { modelId: createdModelId } : skipToken,
    {
      refetchOnMountOrArgChange: true,
    },
  );

  useEffect(() => {
    if (createdModel) {
      setModel(createdModel);
    }
  }, [createdModel]);

  const defaultValues: UpdateControllerFormData = {
    name: controller?.name,
    description: controller?.description,
    locationId: controller?.locationId,
    firmware: controller?.firmware,
    controlPage: controller?.controlPage,
    subnetMask: controller?.subnetMask,
    gateway: controller?.gateway,
    telnetPort: controller?.telnetPort,
    port: controller?.interface?.port,
    timeZone: controller?.timeZone,
    sendNotifications: controller?.sendNotifications,
    ip: controller?.ip,
    mac: controller?.mac,
    typeName: controller?.model?.type?.name,
    manufacturerName: controller?.model?.manufacturer?.name,
    modelId: controller?.model?.id,
    segment: controller?.segment,
    serialNumber: controller?.serialNumber,
    inventoryNumber: controller?.inventoryNumber,
    protocolIp: controller?.interface?.protocolIp,
    localAddress: controller?.interface?.localAddress,
    ieee8021x: controller?.interface?.ieee8021x,
    isMain: controller?.isMain,
    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: controller?.disableMonitoring ?? false,
    qrCodeType: controller?.qrCodeType,
  };

  const methods = useForm<UpdateControllerFormData>({
    mode: 'onBlur',
    reValidateMode: 'onChange',
    defaultValues,
    resolver: yupResolver(
      updateControllerFormSchema,
    ) as Resolver<UpdateControllerFormData>,
  });

  const handleClearModel = () => {
    methods.setValue('modelId', '');
    methods.setValue('manufacturerName', '');
    methods.setValue('typeName', '');
  };

  useEffect(() => {
    if (controller?.model) {
      setModel(controller.model);
    }
  }, [controller]);

  useEffect(() => {
    if (model) {
      const isModelChanged = model.id !== controller?.model?.id;

      methods.setValue('modelId', model?.id || '', {
        shouldDirty: isModelChanged,
        shouldValidate: true,
      });
      methods.setValue('manufacturerName', model?.manufacturer?.name);
      methods.setValue('typeName', model?.type?.name);
    }
  }, [model]);

  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 netInterfaceInfo = methods.watch(OTHER_NAMES.netInterfaceInfo);
  const netInterface = methods.watch(OTHER_NAMES.netInterface);

  const { deleteNetInterfaces } = useNetInterfaceRepository();

  useEffect(() => {
    (async () => {
      if (
        !netInterface &&
        isSecondaryInterfaceSuccess &&
        netInterfaceInfo &&
        !!netInterfaceInfo.length
      ) {
        await deleteNetInterfaces(
          netInterfaceInfo?.map((netInterface) => netInterface.id),
        );

        methods.setValue(OTHER_VALUES.netInterfaceInfo, []);
      }
    })();
  }, [netInterface, netInterfaceInfo, isSecondaryInterfaceSuccess]);

  useSyncControlPage(controller?.ip, methods);

  useEffect(() => {
    if (!Helpers.isEmpty(locationId)) {
      methods.setValue(OTHER_NAMES.locationId, locationId);
      methods.reset(methods.getValues());
    }
  }, [locationId]);

  useEffect(() => {
    if (controllerUpdateStatus === QueryStatus.fulfilled && controller?.id) {
      closeDrawer(DrawerTypes.updateController);
      resetUpdateController();
      sendEvent();
    }
  }, [controller?.id, controllerUpdateStatus]);

  const updateNetworkDevice = async (values: UpdateControllerFormData) => {
    if (!id) {
      return;
    }

    await updateController(values, id);
    cleanControllerLocationId();
  };

  const submitHandler: SubmitHandler<UpdateControllerFormData> = async (
    values,
  ) => {
    const oldIp = controller?.ip?.trim() ?? '';
    const newIp = values.ip?.trim() ?? '';

    if (oldIp !== newIp && hasActiveWindows) {
      setPendingValues(values);
      return;
    }

    await updateNetworkDevice(values);
  };

  const handleConfirmIpChange = async () => {
    if (!pendingValues) {
      return;
    }

    const values = pendingValues;

    setPendingValues(null);
    await updateNetworkDevice(values);
  };

  const handleCancelIpChange = () => {
    setPendingValues(null);
  };

  useEffect(() => {
    methods.reset(defaultValues);
  }, [controller, open]);

  const { isValid, dirtyFields } = methods.formState;

  const isDirtyLocationId =
    methods.getValues().locationId !== defaultValues.locationId;

  const isDirtyFields = !Helpers.isEmpty(dirtyFields) || isDirtyLocationId;
  const isSaveButtonDisabled = !isDirtyFields || !isValid;

  const actions: DrawerActions = {
    actionPrimary: (
      <Button
        onClick={methods.handleSubmit(submitHandler)}
        disabled={isSaveButtonDisabled}
        loading={isUpdateControllerLoading}
      >
        {controllerUpdateStatus === QueryStatus.pending ? (
          <Loader />
        ) : (
          t('common:buttons.save')
        )}
      </Button>
    ),
  };

  const handleClose: DrawerProps['onClose'] = () => {
    cleanControllerLocationId();
    methods.reset(defaultValues);
    setModel(null);
    setPendingValues(null);
  };

  if (!controller) {
    return null;
  }

  const initialModel = model ? model : controller.model;

  return (
    <>
      <FormProvider {...methods}>
        <Drawer
          type={DrawerTypes.updateController}
          actions={actions}
          title={t('common:drawerTitle.updateController')}
          onClose={handleClose}
        >
          <UpdateControllerForm
            initialModel={initialModel}
            setModel={setModel}
            handleClearModel={handleClearModel}
          />
        </Drawer>
      </FormProvider>

      <ConfirmIpChangeModal
        open={!!pendingValues}
        oldIp={controller?.ip ?? ''}
        newIp={pendingValues?.ip ?? ''}
        onConfirm={handleConfirmIpChange}
        onClose={handleCancelIpChange}
      />
    </>
  );
});


import { Box, Button, Modal, Typography } from '@/shared/components';
import { useTranslation } from 'react-i18next';

interface ConfirmIpChangeModalProps {
  open: boolean;
  oldIp: string;
  newIp: string;
  onConfirm: () => void | Promise<void>;
  onClose: () => void;
}

export const ConfirmIpChangeModal = ({
  open,
  oldIp,
  newIp,
  onConfirm,
  onClose,
}: ConfirmIpChangeModalProps) => {
  const { t } = useTranslation('common');

  return (
    <Modal
      open={open}
      title={t('modalTitle.confirmIpChange')}
      onClose={onClose}
      actionPrimary={<Button onClick={onConfirm}>{t('yes')}</Button>}
      actionSecondary={<Button onClick={onClose}>{t('no')}</Button>}
    >
      <Box p='0px 16px' textAlign='center'>
        <Typography variant='caption2'>
          {t('common:messages.confirmIpChange', {
            oldIp,
            newIp,
          })}
        </Typography>
      </Box>
    </Modal>
  );
};


{
  "monitoring": "Мониторинг",
  "user": "Пользователь",
  "controller": "Контроллер",
  "device": "Дочернее устройство",
  "location": "Локация",
  "service-status": "Сервисный статус",
  "ticket": "Заявка",
  "name": "Наименование",
  "type": "Тип",
  "source": "Источник",
  "authentication": "Аутентификация",
  "untitled": "Без названия",
  "favorite": "Избранное",
  "description": "Описание",
  "information": "Информация",
  "info": "Инфо",
  "address": "Адрес",
  "number": "Номер",
  "archived": "В архиве",
  "archive": "В архив",
  "ipAvLan": "AV LAN",
  "contractor": "Подрядчик",
  "contractors": "Подрядчики",
  "comment": "Комментарий",
  "serviceStatus": "Сервисный статус",
  "equipment": "Оборудование",
  "padlet": "Панель SmartRoom",
  "extron": "Extron",
  "network-device": "Самостоятельное сетевое устройство",
  "offline-device": "Самостоятельное несетевое устройство",
  "secondaryInterfaceName": "Наименование",
  "show": "Показывать",
  "hide": "Не показывать",
  "tokens": "Токены",
  "showDeleted": "Показывать с удаленными",

  "serviceUnavailable": "Недоступные сервисы:",
  "checkingAvailable": "Проверка доступности...",

  "loginPage": {
    "subtitle": "Система мониторинга и управления мультимедийным оборудованием в офисном пространстве",
    "signIn": "Войти в мониторинг"
  },

  "deadline": "Срок",

  "controllers": "Контроллеры",
  "devices": "Устройства",

  "actions": "Действия",

  "all": "Все",
  "yes": "Да",
  "no": "Нет",
  "acknowledge": "Подтвердить",

  "ipSettings": "IP настройки",

  "createdAt": "Дата создания",
  "updatedAt": "Дата обновления",
  "deletedAt": "Дата удаления",
  "status": "Статус",
  "reason": "Причина",
  "time": "Время",
  "error": "Ошибка",

  "date": "Дата",

  "timeFrom": "Время от",
  "timeTo": "Время до",

  "loading": "Загрузка...",

  "sort": "Сортировать",
  "downloadExcel": "Скачать Excel",
  "sortBy": {
    "asc": "По возрастанию",
    "desc": "По убыванию",
    "status": "По статусу"
  },

  "showBy": "Показать по",
  "labels": {
    "filters": "Фильтры",
    "domain": "Домен"
  },

  "openInMonitoring": "Открыть в мониторинге",
  "buttons": {
    "close": "Закрыть",
    "details": "Детали",
    "copy": "Копировать",
    "copied": "Скопировано",
    "copiedError": "Не удалось скопировать",
    "edit": "Редактировать",
    "rename": "Переименовать",
    "save": "Сохранить",
    "apply": "Применить",
    "add": "Добавить",
    "addMore": "Добавить еще",
    "delete": "Удалить",
    "clearAll": "Очистить всё",
    "reset": "Сбросить",
    "update": "Обновить",
    "cancel": "Отмена",
    "updateStatuses": "Обновить статусы",
    "settings": "Настройки",
    "recountLocationStatus": "Пересчитать статус комнаты",
    "recountEquipmentStatus": "Пересчитать общий статус оборудования"
  },

  "placeholders": {
    "findByName": "Найти по названию",
    "findByFullName": "Найти по ФИО",
    "leaveComment": "Оставьте комментарий",
    "editing": "Редактирование",
    "selectValue": "Выберите значение",
    "search": "Поиск",
    "found": "Найдено"
  },

  "messages": {
    "sendNotifications": "Отправлять уведомления",
    "nothingFound": "Ничего не найдено",
    "noActiveTickets": "Нет активных заявок",
    "noComments": "Комментарии отсутствуют",
    "addModel": "Добавьте модель",
    "noDescription": "Описание отсутствует",
    "notSelected": "Не выбрано",
    "deleteConfirmation": "Вы уверены, что хотите удалить",
    "unknown": "Неизвестно",
    "requiredMessage": "Обязательное поле",
    "wrongFormatMessage": "Неправильный формат",
    "interfaceTypeMessage": "Выберите тип интерфейса",
    "segmentMessage": "Выберите домен",
    "maxMessage": "Максимальное количество символов",
    "minMessage": "Минимальное количество символов",
    "maxNumberMessage": "Максимальное число",
    "protocolIpMessage": "Выберите протокол",
    "ieee8021XMessage": "Выберите 802.1X",
    "interfacePortMessage": "Номер порта должен быть числом от 1 до 65535",
    "invalidUUIDMessage": "Некорректный SmartRoomID",
    "invalidLocationIDMessage": "Некорректный ID локации",
    "sipUriFormatMessage": "Некорректный формат SIP URI",
    "sipUriDomainMessage": "SIP URI должен содержать корректный домен",
    "confirmIpChange": "Предупреждение! При изменении IP-адреса контроллера с {{oldIp}} на {{newIp}} сбросятся все окна аутентификации. Продолжить?"
  },

  "pageTitle": {
    "dashboards": "Дашборды",
    "monitoring": "Мониторинг",
    "locations": "Локации",
    "equipment": "Оборудование",
    "users": "Пользователи",
    "audit": "Аудит",
    "settings": "Настройки",
    "tasksHistory": "История задач"
  },

  "tabs": {
    "equipments": "Оборудование",
    "information": "Информация",
    "controller": "Контроллер",
    "location": "Локация",
    "devices": "Оборудование",
    "comments": "Комментарии",
    "ping": "Пинг",
    "messages": "Сообщения",
    "tracing": "Трассировка",
    "tasks": "Задачи",
    "networkAccess": "Сетевой доступ",
    "tickets": "Заявки",
    "errors": "Ошибки",
    "common": "Общие",
    "serviceStatuses": "Статусы",
    "padlet": "Панель SmartRoom",
    "owners": "Владельцы",
    "equipmentToken": "Токены",
    "authSessionWindows": "Аутентификация",
    "equipment": "Оборудование",
    "users": "Пользователи"
  },

  "drawerTitle": {
    "createController": "Создание контроллера",
    "updateDevice": "Редактирование дочернего устройства",
    "createDevice": "Создание устройства",
    "updateLocation": "Редактирование локации",
    "updateController": "Редактирование контроллера",
    "updateEquipmentLocation": "Редактирование локации оборудования",
    "aboutLocation": "О локации",
    "createRoom": "Создание помещения",
    "structureManagement": "Управление структурой",
    "createUser": "Создание пользователя",
    "createOwner": "Создание владельца",
    "updateUser": "Редактирование пользователя",
    "tasksInfo": "Информация о задачах",
    "createControllerModel": "Создание модели контроллера",
    "updateControllerModel": "Редактирование модели контроллера",
    "createControllerType": "Создание типа контроллера",
    "updateControllerType": "Редактирование типа контроллера",
    "createDeviceType": "Создание типа устройства",
    "updateDeviceType": "Редактирование типа устройства",
    "createDeviceModel": "Создание модели устройства",
    "updateDeviceModel": "Редактирование модели устройства",
    "createManufacturer": "Создание производителя",
    "updateManufacturer": "Редактирование производителя",
    "createTicket": "Создание заявки",
    "updateTicket": "Редактирование заявки",
    "ticketInfo": "Информация о заявке",
    "auditMessageDetails": "Детали сообщения",
    "tableSettings": "Настройки таблицы",
    "createContractor": "Создание подрядчика",
    "updateContractor": "Редактирование подрядчика",
    "dashboardPageSettings": "Настройки дашбордов",
    "createSecondaryInterface": "Создание дополнительного интерфейса",
    "updateSecondaryInterface": "Редактирование дополнительного интерфейса",
    "PadletCreate": "Создание панели управления с приложением SmartRoom",
    "PadletUpdate": "Редактирование панели управления с приложением SmartRoom",
    "PadletInfo": "Панель управления с приложением SmartRoom",
    "NetworkEquipmentCreate": "Создание самостоятельного сетевого устройства",
    "NetworkEquipmentUpdate": "Редактирование самостоятельного сетевого устройства",
    "NetworkEquipmentInfo": "Самостоятельное сетевое устройство",
    "offlineEquipmentCreate": "Создание самостоятельного несетевого устройства",
    "offlineEquipmentUpdate": "Редактирование самостоятельного несетевого устройства",
    "offlineEquipmentInfo": "Самостоятельное несетевое устройство",
    "equipmentFilters": "Дополнительные фильтры",
    "createPadletType": "Создание типа Панели SmartRoom",
    "updatePadletType": "Редактирование типа Панели SmartRoom",
    "createPadletModel": "Создание модели Панели SmartRoom",
    "updatePadletModel": "Обновление модели Панели SmartRoom",
    "createEquipmentToken": "Генерация токена",
    "updateEquipmentToken": "Обновление информации токена"
  },

  "modalTitle": {
    "deleteController": "Удаление контроллера",
    "deleteLocation": "Удаление локации",
    "deleteDevice": "Удаление дочернего устройства",
    "deletePadlet": "Удаление панели SmartRoom",
    "deleteNetworkDevice": "Удаление самостоятельного сетевого устройства",
    "deleteOfflineEquipment": "Удаление самостоятельного несетевого устройства",
    "deleteUser": "Удаление пользователя",
    "deleteControllerModal": "Удаление модели контроллера",
    "deleteDeviceModal": "Удаление модели устройства",
    "deleteControllerType": "Удаление типа контроллера",
    "deleteDeviceType": "Удаление типа устройства",
    "deleteManufacturer": "Удаление производителя",
    "deleteContractor": "Удаление подрядчика",
    "deleteSecondaryInterface": "Удаление дополнительного интерфейса",
    "deletePadletType": "Удаление типа Панели SmartRoom",
    "deletePadletModel": "Удаление модели Панели SmartRoom",
    "deleteEquipmentToken": "Удаление токена оборудования",
    "confirmIpChange": "Изменение IP-адреса"
  },

  "withProblem": "С проблемой",

  "VIP": "VIP",
  "notVIP": "Не VIP",
  "openTickets": "Открытые заявки",
  "closedTickets": "Закрытые заявки",
  "notClosedTickets": "Нет закрытых заявок",
  "notOpenTickets": "Нет открытых заявок",
  "favourite": "Избранные",
  "notFavourite": "Не избранные",
  "SmartRoomID": "SmartRoom ID",

  "errors": {
    "serviceUnavailable": "Сервис недоступен",
    "authorization": "Необходимо авторизоваться",
    "noAccess": "Нет доступа",
    "previousTaskNotCompleted": "Дождитесь выполнения предыдущей задачи",
    "somethingWentWrong": "Что-то пошло не так",
    "name not unique": "Имя не уникально"
  },
  "nothingToPick": "Нечего выбрать"
}



{
  "monitoring": "Monitoring",
  "user": "User",
  "controller": "Controller",
  "device": "Subordinate device",
  "location": "Location",
  "service-status": "Service status",
  "ticket": "Ticket",
  "name": "Name",
  "type": "Type",
  "source": "Source",
  "authentication": "Authentication",
  "untitled": "Untitled",
  "favorite": "Favorite",
  "description": "Description",
  "information": "Information",
  "info": "Info",
  "address": "Address",
  "number": "Number",
  "archived": "Archived",
  "archive": "To archive",
  "ipAvLan": "AV LAN",
  "contractor": "Contractor",
  "contractors": "Contractors",
  "comment": "Comment",
  "serviceStatus": "Service status",
  "equipment": "Equipment",
  "padlet": "SmartRoom Panel",
  "extron": "Extron",
  "network-device": "Independent network equipment",
  "offline-device": "Independent offline equipment",
  "secondaryInterfaceName": "Name",
  "show": "Show",
  "hide": "Hide",
  "tokens": "Tokens",
  "showDeleted": "Show with deleted",

  "serviceUnavailable": "Unavailable services:",
  "checkingAvailable": "Checking availability...",

  "loginPage": {
    "subtitle": "Monitoring and control system for multimedia equipment in an office space",
    "signIn": "Sign in"
  },
  "deadline": "Deadline",

  "controllers": "Controllers",
  "devices": "Devices",

  "actions": "Actions",

  "all": "All",
  "yes": "Yes",
  "no": "No",
  "acknowledge": "Acknowledge",

  "ipSettings": "IP settings",

  "createdAt": "Created at",
  "updatedAt": "Updated at",
  "deletedAt": "Deleted at",
  "status": "Status",
  "time": "Time",
  "reason": "Reason",
  "error": "Error",

  "date": "Date",

  "timeFrom": "Date from",
  "timeTo": "Date to",

  "loading": "Loading...",

  "sort": "Sort",
  "downloadExcel": "Download Excel",
  "sortBy": {
    "asc": "Ascending",
    "desc": "Descending",
    "status": "By status"
  },

  "showBy": "Show by",
  "labels": {
    "filters": "Filters",
    "domain": "Domain"
  },

  "openInMonitoring": "Open in monitoring",
  "buttons": {
    "close": "Close",
    "details": "Details",
    "copy": "Copy",
    "copied": "Copied",
    "copiedError": "Failed to copy",
    "edit": "Edit",
    "save": "Save",
    "apply": "Apply",
    "add": "Add",
    "addMore": "Add more",
    "delete": "Delete",
    "rename": "Rename",
    "clearAll": "Clear all",
    "reset": "Reset",
    "update": "Update",
    "cancel": "Cancel",
    "signIn": "Sign in",
    "updateStatuses": "Update statuses",
    "settings": "Settings",
    "recountStatuses": "Recount location status",
    "recountEquipmentStatus": "Recount common equipment status"
  },

  "placeholders": {
    "findByName": "Find by name",
    "findByFullName": "Find by full name",
    "leaveComment": "Leave a comment",
    "editing": "Editing",
    "selectValue": "Select value",
    "search": "Search",
    "found": "Found"
  },

  "messages": {
    "sendNotifications": "Send notifications",
    "nothingFound": "Nothing was found",
    "noActiveTickets": "No active tickets",
    "noComments": "No comments",
    "addModel": "Add model",
    "noDescription": "No description",
    "notSelected": "Not selected",
    "deleteConfirmation": "Are you sure you want to delete",
    "unknown": "Unknown",
    "requiredMessage": "Required field",
    "wrongFormatMessage": "Incorrect format",
    "interfaceTypeMessage": "Select interface type",
    "segmentMessage": "Select domain",
    "maxMessage": "Maximum number of characters",
    "minMessage": "Minimal number of characters",
    "maxNumberMessage": "Maximum number",
    "protocolIpMessage": "Select protocol",
    "ieee8021XMessage": "Select 802.1X",
    "interfacePortMessage": "The port number must be a number between 1 and 65535",
    "invalidUUIDMessage": "Incorrect SmartRoomID",
    "invalidLocationIDMessage": "Incorrect Location ID",
    "sipUriFormatMessage": "Incorrect format",
    "sipUriDomainMessage": "SIP URI must contain the correct domain",
    "confirmIpChange": "Warning! Changing the controller IP from {{oldIp}} to {{newIp}} will reset all authentication windows. Continue?"
  },

  "pageTitle": {
    "dashboards": "Dashboards",
    "monitoring": "Monitoring",
    "locations": "Locations",
    "equipment": "Equipment",
    "users": "Users",
    "audit": "Audit",
    "settings": "Settings",
    "tasksHistory": "Tasks history"
  },

  "tabs": {
    "equipments": "Equipments",
    "information": "Information",
    "controller": "Controller",
    "devices": "Devices",
    "location": "Location",
    "comments": "Comments",
    "ping": "Ping",
    "messages": "Messages",
    "tracing": "Tracing",
    "tasks": "Tasks",
    "networkAccess": "Network access",
    "tickets": "Tickets",
    "errors": "Errors",
    "common": "Common",
    "serviceStatuses": "Statuses",
    "padlet": "Panel SmartRoom",
    "owners": "Owners",
    "equipmentToken": "Tokens",
    "authSessionWindows": "Authentication",
    "equipment": "Equipment",
    "users": "Users"
  },

  "drawerTitle": {
    "createController": "Create controller",
    "updateDevice": "Edit device",
    "createDevice": "Create device",
    "updateLocation": "Edit location",
    "updateController": "Edit controller",
    "updateEquipmentLocation": "Edit equipment location",
    "aboutLocation": "About location",
    "createRoom": "Create room",
    "structureManagement": "Structure management",
    "createUser": "Create user",
    "createOwner": "Create owner",
    "updateUser": "Edit user",
    "tasksInfo": "Tasks info",
    "createControllerModel": "Create controller model",
    "updateControllerModel": "Edit controller model",
    "createControllerType": "Create controller type",
    "updateControllerType": "Edit controller type",
    "createDeviceType": "Create device type",
    "updateDeviceType": "Edit device type",
    "createDeviceModel": "Create device model",
    "updateDeviceModel": "Edit device model",
    "createManufacturer": "Create manufacturer",
    "updateManufacturer": "Edit manufacturer",
    "createTicket": "Create ticket",
    "updateTicket": "Edit ticket",
    "ticketInfo": "Ticket info",
    "auditMessageDetails": "Message details",
    "tableSettings": "Table Settings",
    "createContractor": "Create contractor",
    "updateContractor": "Edit contractor",
    "dashboardPageSettings": "Dashboard settings",
    "createSecondaryInterface": "Create secondary interface",
    "updateSecondaryInterface": "Update secondary interface",
    "PadletCreate": "Create control panel with SmartRoom application",
    "PadletUpdate": "Edit control panel with SmartRoom application",
    "PadletInfo": "Control panel with SmartRoom application",
    "NetworkEquipmentCreate": "Create independent network equipment",
    "NetworkEquipmentUpdate": "Edit independent network equipment",
    "NetworkEquipmentInfo": "Independent network equipment",
    "offlineEquipmentCreate": "Create independent offline equipment",
    "offlineEquipmentUpdate": "Edit independent offline equipment",
    "offlineEquipmentInfo": "Independent offline equipment",
    "equipmentFilters": "Additional filters",
    "createPadletType": "Create Panel SmartRoom type",
    "updatePadletType": "Update Panel SmartRoom type",
    "createPadletModel": "Create Panel SmartRoom model",
    "updatePadletModel": "Update Panel SmartRoom model",
    "createEquipmentToken": "Token generation",
    "updateEquipmentToken": "Edit equipment token",
    "deleteEquipmentToken": "Delete equipment token"
  },

  "modalTitle": {
    "deleteController": "Delete controller",
    "deleteLocation": "Delete location",
    "deleteDevice": "Delete device",
    "deletePadlet": "Delete SmartRoom padlet",
    "deleteNetworkDevice": "Delete network device",
    "deleteOfflineEquipment": "Delete offline equipment",
    "deleteUser": "Delete user",
    "deleteControllerModal": "Delete controller modal",
    "deleteDeviceModal": "Delete device modal",
    "deleteControllerType": "Delete controller type",
    "deleteDeviceType": "Delete device type",
    "deleteManufacturer": "Delete manufacturer",
    "deleteContractor": "Delete contractor",
    "deleteSecondaryInterface": "Delete secondary interface",
    "deletePadletType": "Delete Panel SmartRoom type",
    "deletePadletModel": "Delete Panel SmartRoom model",
    "deleteEquipmentToken": "Delete equipment token",
    "confirmIpChange": "Change IP address"
  },

  "withProblem": "With problem",

  "VIP": "VIP",
  "notVIP": "Not VIP",
  "openTickets": "Open Tickets",
  "closedTickets": "Closed Tickets",
  "notClosedTickets": "Not Closed Tickets",
  "notOpenTickets": "Not Open Tickets",
  "favourite": "Favorite",
  "notFavourite": "Not Favorite",
  "SmartRoomID": "SmartRoom ID",

  "errors": {
    "serviceUnavailable": "Service unavailable",
    "authorization": "You need to login",
    "noAccess": "No access",
    "previousTaskNotCompleted": "Wait for the previous task to complete",
    "somethingWentWrong": "Something went wrong",
    "name not unique": "Name not unique"
  },
  "nothingToPick": "Nothing to pick"
}