mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-10-29 17:32:20 +00:00
Merge pull request #175 from stephb9959/main
[WIFI-12441] Added export button to device table
This commit is contained in:
10105
package-lock.json
generated
10105
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
91
package.json
91
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ucentral-client",
|
||||
"version": "2.10.0(15)",
|
||||
"version": "2.10.0(19)",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"main": "index.tsx",
|
||||
@@ -15,83 +15,82 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@chakra-ui/icons": "^2.0.11",
|
||||
"@chakra-ui/icons": "^2.0.18",
|
||||
"@chakra-ui/react": "^2.3.6",
|
||||
"@chakra-ui/theme-tools": "^2.0.12",
|
||||
"@chakra-ui/utils": "^2.0.11",
|
||||
"@emotion/react": "^11.10.4",
|
||||
"@emotion/styled": "^11.10.4",
|
||||
"@fontsource/inter": "^4.5.14",
|
||||
"@chakra-ui/utils": "^2.0.14",
|
||||
"@emotion/react": "^11.10.6",
|
||||
"@emotion/styled": "^11.10.6",
|
||||
"@fontsource/inter": "^4.5.15",
|
||||
"@googlemaps/react-wrapper": "^1.1.35",
|
||||
"@googlemaps/typescript-guards": "^2.0.3",
|
||||
"@react-spring/web": "^9.5.5",
|
||||
"axios": "^1.1.3",
|
||||
"@phosphor-icons/react": "^2.0.8",
|
||||
"@react-spring/web": "^9.7.2",
|
||||
"@tanstack/react-query": "^4.29.3",
|
||||
"@tanstack/react-table": "^8.8.5",
|
||||
"@textea/json-viewer": "^2.16.2",
|
||||
"axios": "^1.3.5",
|
||||
"buffer": "^6.0.3",
|
||||
"chakra-react-select": "^4.6.0",
|
||||
"chart.js": "^3.9.1",
|
||||
"dagre": "^0.8.5",
|
||||
"fast-equals": "^5.0.1",
|
||||
"formik": "^2.2.9",
|
||||
"fast-equals": "^4.0.3",
|
||||
"framer-motion": "^7.6.1",
|
||||
"i18next": "^22.0.0",
|
||||
"i18next-browser-languagedetector": "^6.1.8",
|
||||
"i18next-http-backend": "^1.4.4",
|
||||
"libphonenumber-js": "^1.10.14",
|
||||
"phosphor-react": "^1.4.1",
|
||||
"framer-motion": "^10.12.2",
|
||||
"i18next": "^22.4.14",
|
||||
"i18next-browser-languagedetector": "^7.0.1",
|
||||
"i18next-http-backend": "^2.2.0",
|
||||
"libphonenumber-js": "^1.10.26",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-app-polyfill": "^3.0.0",
|
||||
"react-chartjs-2": "^4.3.1",
|
||||
"chart.js": "^3.9.1",
|
||||
"react-country-flag": "^3.0.2",
|
||||
"react-country-flag": "^3.1.0",
|
||||
"react-csv": "^2.2.2",
|
||||
"react-datepicker": "^4.8.0",
|
||||
"react-datepicker": "^4.11.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"@textea/json-viewer": "^2.10.0",
|
||||
"react-fast-compare": "^3.2.0",
|
||||
"react-i18next": "^11.18.6",
|
||||
"react-fast-compare": "^3.2.1",
|
||||
"react-i18next": "^12.2.0",
|
||||
"react-masonry-css": "^1.0.16",
|
||||
"@tanstack/react-query": "^4.12.0",
|
||||
"@tanstack/react-table": "^8.7.9",
|
||||
"react-router-dom": "^6.4.2",
|
||||
"react-router-dom": "^6.10.0",
|
||||
"react-table": "^7.8.0",
|
||||
"react-virtualized-auto-sizer": "^1.0.7",
|
||||
"react-window": "^1.8.8",
|
||||
"react-virtualized-auto-sizer": "^1.0.15",
|
||||
"react-window": "^1.8.9",
|
||||
"source-map-explorer": "^2.5.3",
|
||||
"vite": "^3.1.8",
|
||||
"typescript": "^4.8.4",
|
||||
"uuid": "^9.0.0",
|
||||
"vite": "^4.2.1",
|
||||
"yup": "^0.32.11",
|
||||
"zustand": "^4.1.2"
|
||||
"zustand": "^4.3.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/google.maps": "^3.51.0",
|
||||
"@types/node": "^18.11.2",
|
||||
"@types/react": "^18.0.21",
|
||||
"@types/google.maps": "^3.52.5",
|
||||
"@types/node": "^18.15.11",
|
||||
"@types/react": "^18.0.37",
|
||||
"@types/react-csv": "^1.1.3",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@types/react-table": "^7.7.12",
|
||||
"@types/react-datepicker": "4.8.0",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@types/react-datepicker": "4.10.0",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/react-table": "^7.7.14",
|
||||
"@types/react-virtualized-auto-sizer": "^1.0.1",
|
||||
"@types/react-window": "^1.8.5",
|
||||
"eslint": "8.25.0",
|
||||
"vite-tsconfig-paths": "^3.5.1",
|
||||
"lint-staged": "^13.0.3",
|
||||
"@vitejs/plugin-react": "^2.1.0",
|
||||
"vite-plugin-pwa": "^0.13.1",
|
||||
"prettier": "^2.7.1",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@vitejs/plugin-react": "^3.1.0",
|
||||
"eslint": "8.38.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||
"eslint-config-airbnb-typescript-prettier": "^5.0.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-babel": "^5.3.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.6.1",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-no-inline-styles": "^1.0.5",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.31.10",
|
||||
"eslint-plugin-react-hooks": "^4.6.0"
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"lint-staged": "^13.2.1",
|
||||
"prettier": "^2.8.7",
|
||||
"vite-tsconfig-paths": "^4.2.0"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Button, IconButton, Tooltip, useBreakpoint } from '@chakra-ui/react';
|
||||
import { Warning } from 'phosphor-react';
|
||||
import { Warning } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ThemeProps } from 'models/Theme';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { IconButton, SpaceProps } from '@chakra-ui/react';
|
||||
import { X } from 'phosphor-react';
|
||||
import { X } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface CloseButtonProps extends SpaceProps {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Button, IconButton, Tooltip, useBreakpoint, SpaceProps } from '@chakra-ui/react';
|
||||
import { Plus } from 'phosphor-react';
|
||||
import { Plus } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface CreateButtonProps extends SpaceProps {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Button, IconButton, Tooltip, useBreakpoint } from '@chakra-ui/react';
|
||||
import { Trash } from 'phosphor-react';
|
||||
import { Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface DeleteButtonProps {
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import axios from 'axios';
|
||||
import { Barcode, Power, TerminalWindow, WifiHigh, Wrench } from 'phosphor-react';
|
||||
import { Barcode, Power, TerminalWindow, WifiHigh, Wrench } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useControllerStore } from 'contexts/ControllerSocketProvider/useStore';
|
||||
import { useBlinkDevice, useGetDeviceRtty } from 'hooks/Network/Devices';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { IconButton, Button, Tooltip, useBreakpoint } from '@chakra-ui/react';
|
||||
import { Pen } from 'phosphor-react';
|
||||
import { Pen } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface EditButtonProps {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Button, IconButton, ThemeTypings, Tooltip, useBreakpoint } from '@chakra-ui/react';
|
||||
import { ArrowsClockwise } from 'phosphor-react';
|
||||
import { ArrowsClockwise } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface RefreshButtonProps {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Button, IconButton, Tooltip, useBreakpoint } from '@chakra-ui/react';
|
||||
import { FloppyDisk } from 'phosphor-react';
|
||||
import { FloppyDisk } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface SaveButtonProps
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { Button, IconButton, Tooltip, useBreakpoint } from '@chakra-ui/react';
|
||||
import { ArrowRight, FloppyDisk } from 'phosphor-react';
|
||||
import { ArrowRight, FloppyDisk } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface StepButtonProps {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Button, IconButton, Tooltip, useBreakpoint, useDisclosure } from '@chakra-ui/react';
|
||||
import { Pencil, X } from 'phosphor-react';
|
||||
import { Pencil, X } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ConfirmCloseAlertModal } from '../../Modals/ConfirmCloseAlert';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Button, IconButton, Tooltip, useBreakpoint } from '@chakra-ui/react';
|
||||
import { Warning } from 'phosphor-react';
|
||||
import { Warning } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ThemeProps } from 'models/Theme';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Heading, IconButton, Spacer, Tooltip, useDisclosure } from '@chakra-ui/react';
|
||||
import { ArrowsOut, Info } from 'phosphor-react';
|
||||
import { ArrowsOut, Info } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Card } from '../Card';
|
||||
import { CardBody } from '../Card/CardBody';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { As, Flex, Heading, Icon, Spacer, Text, Tooltip, useColorModeValue } from '@chakra-ui/react';
|
||||
import { Info } from 'phosphor-react';
|
||||
import { Info } from '@phosphor-icons/react';
|
||||
import { Card } from '../Card';
|
||||
|
||||
type Props = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { Button, Checkbox, IconButton, Menu, MenuButton, MenuItem, MenuList, useBreakpoint } from '@chakra-ui/react';
|
||||
import { FunnelSimple } from 'phosphor-react';
|
||||
import { FunnelSimple } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useAuth } from 'contexts/AuthProvider';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Box, Checkbox, IconButton, Menu, MenuButton, MenuItem, MenuList, Tooltip } from '@chakra-ui/react';
|
||||
import { VisibilityState } from '@tanstack/react-table';
|
||||
import { FunnelSimple } from 'phosphor-react';
|
||||
import { FunnelSimple } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { DataGridColumn } from './useDataGrid';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '@chakra-ui/react';
|
||||
import { SortDirection } from '@tanstack/react-table';
|
||||
import { ArrowDown, ArrowUp, Circle } from 'phosphor-react';
|
||||
import { ArrowDown, ArrowUp, Circle } from '@phosphor-icons/react';
|
||||
|
||||
export type DataGridSortIconProps = {
|
||||
sortInfo: false | SortDirection;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '@chakra-ui/react';
|
||||
import { ArrowDown, ArrowUp, Circle } from 'phosphor-react';
|
||||
import { ArrowDown, ArrowUp, Circle } from '@phosphor-icons/react';
|
||||
|
||||
interface Props {
|
||||
isSorted: boolean;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '@chakra-ui/react';
|
||||
import { ArrowDown, ArrowUp, Circle } from 'phosphor-react';
|
||||
import { ArrowDown, ArrowUp, Circle } from '@phosphor-icons/react';
|
||||
|
||||
interface Props {
|
||||
isSorted: boolean;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { AddIcon } from '@chakra-ui/icons';
|
||||
import { IconButton, Input, InputGroup, InputRightElement, Tooltip } from '@chakra-ui/react';
|
||||
import { Trash } from 'phosphor-react';
|
||||
import { Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { DataTable } from '../../../DataTables/DataTable';
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
PopoverHeader,
|
||||
PopoverTrigger,
|
||||
} from '@chakra-ui/react';
|
||||
import { Question } from 'phosphor-react';
|
||||
import { Question } from '@phosphor-icons/react';
|
||||
|
||||
export type InfoPopoverProps = {
|
||||
title: string;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { InfoIcon } from '@chakra-ui/icons';
|
||||
import { Heading, IconButton, LayoutProps, LightMode, SpaceProps, Spacer, Tooltip } from '@chakra-ui/react';
|
||||
import { MagnifyingGlass } from 'phosphor-react';
|
||||
import { MagnifyingGlass } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
Textarea,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import { ClipboardText } from 'phosphor-react';
|
||||
import { ClipboardText } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SaveButton } from '../../Buttons/SaveButton';
|
||||
import { Modal } from '../Modal';
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
Textarea,
|
||||
useBoolean,
|
||||
} from '@chakra-ui/react';
|
||||
import { UploadSimple } from 'phosphor-react';
|
||||
import { UploadSimple } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useFastField } from 'hooks/useFastField';
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import axios from 'axios';
|
||||
import { FormikProps } from 'formik';
|
||||
import { ArrowLeft } from 'phosphor-react';
|
||||
import { ArrowLeft } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import ConfirmIgnoreCommand from '../ConfirmIgnoreCommand';
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
Spinner,
|
||||
Switch,
|
||||
} from '@chakra-ui/react';
|
||||
import { ArrowLeft } from 'phosphor-react';
|
||||
import { ArrowLeft } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Modal } from '../Modal';
|
||||
import { useDownloadTrace, useTrace } from 'hooks/Network/Trace';
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
useColorMode,
|
||||
} from '@chakra-ui/react';
|
||||
import { JsonViewer } from '@textea/json-viewer';
|
||||
import { ArrowLeft } from 'phosphor-react';
|
||||
import { ArrowLeft } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { Modal, ModalOverlay, ModalContent, ModalBody, Center, Spinner } from '@chakra-ui/react';
|
||||
import { ArrowLeft, Download, Gauge } from 'phosphor-react';
|
||||
import { ArrowLeft, Download, Gauge } from '@phosphor-icons/react';
|
||||
import { CSVLink } from 'react-csv';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ConfirmIgnoreCommand from '../ConfirmIgnoreCommand';
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
Tooltip,
|
||||
} from '@chakra-ui/react';
|
||||
import { TOptions } from 'i18next';
|
||||
import { X } from 'phosphor-react';
|
||||
import { X } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { ProvisioningVenueNotificationMessage } from '../../utils';
|
||||
|
||||
@@ -122,9 +122,9 @@ export const getHoursAgo = (hoursAgo = 1, date = new Date()) => {
|
||||
export const dateForFilename = (dateString: number) => {
|
||||
const convertedTimestamp = unixToDateString(dateString);
|
||||
const date = new Date(convertedTimestamp);
|
||||
return `${date.getFullYear()}_${twoDigitNumber(date.getMonth() + 1)}_${twoDigitNumber(
|
||||
return `${date.getFullYear()}.${twoDigitNumber(date.getMonth() + 1)}.${twoDigitNumber(
|
||||
date.getDate(),
|
||||
)}_${twoDigitNumber(date.getHours())}h${twoDigitNumber(date.getMinutes())}m${twoDigitNumber(date.getSeconds())}s`;
|
||||
)}-${twoDigitNumber(date.getHours())}.${twoDigitNumber(date.getMinutes())}.${twoDigitNumber(date.getSeconds())}`;
|
||||
};
|
||||
|
||||
export const formatDaysAgoCompact = (d1: number, d2: number = new Date().getTime()) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
Tooltip,
|
||||
VStack,
|
||||
} from '@chakra-ui/react';
|
||||
import { ArrowSquareDown, ArrowSquareUp, Clock } from 'phosphor-react';
|
||||
import { ArrowSquareDown, ArrowSquareUp, Clock } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
import { compactSecondsToDetailed, minimalSecondsToDetailed } from 'helpers/dateFormatting';
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
useBreakpoint,
|
||||
Portal,
|
||||
} from '@chakra-ui/react';
|
||||
import { ArrowCircleLeft } from 'phosphor-react';
|
||||
import { ArrowCircleLeft } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAuth } from 'contexts/AuthProvider';
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import { MagnifyingGlass, Trash } from 'phosphor-react';
|
||||
import { MagnifyingGlass, Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { DefaultConfigurationResponse, useDeleteDefaultConfig } from 'hooks/Network/DefaultConfigurations';
|
||||
import { AxiosError } from 'models/Axios';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Button, Grid, GridItem, Heading, Link, Spacer, useClipboard, useDisclosure } from '@chakra-ui/react';
|
||||
import { Eye, EyeSlash } from 'phosphor-react';
|
||||
import { Eye, EyeSlash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ViewCapabilitiesModal from './ViewCapabilitiesModal';
|
||||
import ViewConfigurationModal from './ViewConfigurationModal';
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { Wrapper } from '@googlemaps/react-wrapper';
|
||||
import { Globe } from 'phosphor-react';
|
||||
import { Globe } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { GoogleMap } from 'components/Maps/GoogleMap';
|
||||
import { GoogleMapMarker } from 'components/Maps/GoogleMap/Marker';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Download } from 'phosphor-react';
|
||||
import { Download } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ResponsiveButton } from 'components/Buttons/ResponsiveButton';
|
||||
import { DeviceCommandHistory, useDownloadScriptResult } from 'hooks/Network/Commands';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Download } from 'phosphor-react';
|
||||
import { Download } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ResponsiveButton } from 'components/Buttons/ResponsiveButton';
|
||||
import { DeviceCommandHistory } from 'hooks/Network/Commands';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Download } from 'phosphor-react';
|
||||
import { Download } from '@phosphor-icons/react';
|
||||
import { CSVLink } from 'react-csv';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ResponsiveButton } from 'components/Buttons/ResponsiveButton';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Badge, Box, HStack, IconButton, Tooltip, useDisclosure, useToast } from '@chakra-ui/react';
|
||||
import { MagnifyingGlass, Trash } from 'phosphor-react';
|
||||
import { MagnifyingGlass, Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import FormattedDate from 'components/InformationDisplays/FormattedDate';
|
||||
import { uppercaseFirstLetter } from 'helpers/stringHelper';
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
Tooltip,
|
||||
useBreakpoint,
|
||||
} from '@chakra-ui/react';
|
||||
import { Clock, Prohibit } from 'phosphor-react';
|
||||
import { Clock, Prohibit } from '@phosphor-icons/react';
|
||||
import ReactDatePicker from 'react-datepicker';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CloseButton } from 'components/Buttons/CloseButton';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Box, IconButton, Text, useDisclosure } from '@chakra-ui/react';
|
||||
import { MagnifyingGlass } from 'phosphor-react';
|
||||
import { MagnifyingGlass } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import DetailedLogViewModal from './DetailedLogViewModal';
|
||||
import FormattedDate from 'components/InformationDisplays/FormattedDate';
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
useToast,
|
||||
useBreakpoint,
|
||||
} from '@chakra-ui/react';
|
||||
import { Plus } from 'phosphor-react';
|
||||
import { Plus } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
import { CardBody } from 'components/Containers/Card/CardBody';
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
Tooltip,
|
||||
UnorderedList,
|
||||
} from '@chakra-ui/react';
|
||||
import { LockSimple, LockSimpleOpen } from 'phosphor-react';
|
||||
import { LockSimple, LockSimpleOpen } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
import { CardBody } from 'components/Containers/Card/CardBody';
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
Tooltip,
|
||||
useBreakpoint,
|
||||
} from '@chakra-ui/react';
|
||||
import { Clock, Prohibit } from 'phosphor-react';
|
||||
import { Clock, Prohibit } from '@phosphor-icons/react';
|
||||
import ReactDatePicker from 'react-datepicker';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CloseButton } from 'components/Buttons/CloseButton';
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { JsonViewer } from '@textea/json-viewer';
|
||||
import { ClockCounterClockwise } from 'phosphor-react';
|
||||
import { ClockCounterClockwise } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RefreshButton } from 'components/Buttons/RefreshButton';
|
||||
import { LoadingOverlay } from 'components/LoadingOverlay';
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { JsonViewer } from '@textea/json-viewer';
|
||||
import { ListDashes } from 'phosphor-react';
|
||||
import { ListDashes } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RefreshButton } from 'components/Buttons/RefreshButton';
|
||||
import FormattedDate from 'components/InformationDisplays/FormattedDate';
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { JsonViewer } from '@textea/json-viewer';
|
||||
import { Barcode } from 'phosphor-react';
|
||||
import { Barcode } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Modal } from 'components/Modals/Modal';
|
||||
import { DeviceConfiguration } from 'models/Device';
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import axios from 'axios';
|
||||
import { Heart, HeartBreak, LockSimple, LockSimpleOpen, WifiHigh, WifiSlash } from 'phosphor-react';
|
||||
import { Heart, HeartBreak, LockSimple, LockSimpleOpen, WifiHigh, WifiSlash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Masonry from 'react-masonry-css';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import { MagnifyingGlass, Pen, Trash } from 'phosphor-react';
|
||||
import { MagnifyingGlass, Pen, Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { BlacklistDevice, useDeleteBlacklistDevice } from 'hooks/Network/Blacklist';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Heart, Warning } from 'phosphor-react';
|
||||
import { Heart, Warning } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SimpleIconStatDisplay from 'components/Containers/SimpleIconStatDisplay';
|
||||
import { ControllerDashboardHealth } from 'hooks/Network/Controller';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Alert, AlertDescription, AlertIcon, AlertTitle, Box, Center, Spacer, Spinner } from '@chakra-ui/react';
|
||||
import { Clock, WifiHigh } from 'phosphor-react';
|
||||
import { Clock, WifiHigh } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Masonry from 'react-masonry-css';
|
||||
import AssociationsPieChart from './AssociationsPieChart';
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
Tooltip,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { MagnifyingGlass, Trash } from 'phosphor-react';
|
||||
import { MagnifyingGlass, Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import DeviceActionDropdown from 'components/Buttons/DeviceActionDropdown';
|
||||
import { DeviceWithStatus, useDeleteDevice } from 'hooks/Network/Devices';
|
||||
|
||||
146
src/pages/Devices/ListCard/ExportButton/index.tsx
Normal file
146
src/pages/Devices/ListCard/ExportButton/index.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Button, Center, HStack, Heading, IconButton, Progress, Tooltip, useDisclosure } from '@chakra-ui/react';
|
||||
import { Download, Export } from '@phosphor-icons/react';
|
||||
import { CSVLink } from 'react-csv';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ExportedDeviceInfo, getAllExportedDevicesInfo, getSelectExportedDevicesInfo } from './utils';
|
||||
import { ResponsiveButton } from 'components/Buttons/ResponsiveButton';
|
||||
import { Modal } from 'components/Modals/Modal';
|
||||
import { dateForFilename } from 'helpers/dateFormatting';
|
||||
|
||||
const HEADER_MAPPING: { key: keyof ExportedDeviceInfo; label: string }[] = [
|
||||
{ key: 'serialNumber', label: 'Serial Number' },
|
||||
{ key: 'connected', label: 'Connected' },
|
||||
{ key: 'firmware', label: 'Firmware' },
|
||||
{ key: 'memory', label: 'Memory (%)' },
|
||||
{ key: 'load', label: 'Load (%)' },
|
||||
{ key: 'temperature', label: 'Temperature (°C)' },
|
||||
{ key: 'sanity', label: 'Sanity (%)' },
|
||||
{ key: 'revision', label: 'Revision' },
|
||||
{ key: 'ip', label: 'IP Address' },
|
||||
{ key: 'provisioning', label: 'Provisioning' },
|
||||
{ key: 'radiusSessions', label: 'Radius Sessions' },
|
||||
{ key: 'uptime', label: 'Uptime (s)' },
|
||||
{ key: 'lastContact', label: 'Last Contact (UTC)' },
|
||||
{ key: 'lastUpgrade', label: 'Last Upgrade (UTC)' },
|
||||
{ key: 'rx', label: 'RX (MB)' },
|
||||
{ key: 'tx', label: 'TX (MB)' },
|
||||
{ key: 'twoG', label: '2G Associations' },
|
||||
{ key: 'fiveG', label: '5G Associations' },
|
||||
{ key: 'sixG', label: '6G Associations' },
|
||||
{ key: 'certificateExpiry', label: 'Certificate Expiry (UTC)' },
|
||||
];
|
||||
type Status = {
|
||||
progress: number;
|
||||
status: 'loading-all' | 'loading-select' | 'success' | 'error' | 'idle';
|
||||
error?: string;
|
||||
lastResults?: ExportedDeviceInfo[];
|
||||
};
|
||||
|
||||
type Props = {
|
||||
currentPageSerialNumbers: string[];
|
||||
};
|
||||
|
||||
const ExportDevicesTableButton = ({ currentPageSerialNumbers }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const modalProps = useDisclosure();
|
||||
const [status, setStatus] = React.useState<Status>({
|
||||
progress: 0,
|
||||
status: 'idle',
|
||||
});
|
||||
|
||||
const setProgress = (progress: number) => {
|
||||
setStatus((prev) => ({ ...prev, progress }));
|
||||
};
|
||||
|
||||
const handleAllClick = async () => {
|
||||
setStatus((prev) => ({ ...prev, error: undefined, lastResults: undefined, status: 'loading-all', progress: 0 }));
|
||||
getAllExportedDevicesInfo(setProgress)
|
||||
.then((result) => {
|
||||
setStatus((prev) => ({ ...prev, status: 'success', lastResults: result }));
|
||||
})
|
||||
.catch((error) => {
|
||||
setStatus((prev) => ({ ...prev, status: 'error', error }));
|
||||
});
|
||||
};
|
||||
const handleCurrentPageClick = async () => {
|
||||
setStatus((prev) => ({ ...prev, error: undefined, lastResults: undefined, status: 'loading-select', progress: 0 }));
|
||||
getSelectExportedDevicesInfo(currentPageSerialNumbers, setProgress)
|
||||
.then((result) => {
|
||||
setStatus((prev) => ({ ...prev, status: 'success', lastResults: result }));
|
||||
})
|
||||
.catch((error) => {
|
||||
setStatus((prev) => ({ ...prev, status: 'error', error }));
|
||||
});
|
||||
};
|
||||
|
||||
const onOpen = () => {
|
||||
setStatus({ progress: 0, status: 'idle' });
|
||||
modalProps.onOpen();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip label={t('common.export')}>
|
||||
<IconButton aria-label={t('common.export')} icon={<Export size={20} />} colorScheme="blue" onClick={onOpen} />
|
||||
</Tooltip>
|
||||
<Modal {...modalProps} title={t('common.export')}>
|
||||
<Box>
|
||||
<Center mb={8}>
|
||||
<HStack>
|
||||
<Button
|
||||
onClick={handleAllClick}
|
||||
colorScheme="gray"
|
||||
isDisabled={status.status.includes('loading')}
|
||||
isLoading={status.status === 'loading-all'}
|
||||
>
|
||||
{t('devices.all')} {t('devices.title')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleCurrentPageClick}
|
||||
colorScheme="gray"
|
||||
isDisabled={currentPageSerialNumbers.length === 0 || status.status.includes('loading')}
|
||||
isLoading={status.status === 'loading-select'}
|
||||
>
|
||||
{t('table.export_current_page')} ({currentPageSerialNumbers.length})
|
||||
</Button>
|
||||
</HStack>
|
||||
</Center>
|
||||
{status.status.includes('loading') || status.status === 'success' ? (
|
||||
<Box>
|
||||
<Center>
|
||||
<Heading size="sm">{Math.round(status.progress)}%</Heading>
|
||||
</Center>
|
||||
<Box px={8}>
|
||||
<Progress
|
||||
isIndeterminate={status.progress === 0}
|
||||
value={status.progress}
|
||||
colorScheme={status.progress !== 100 ? 'blue' : 'green'}
|
||||
hasStripe={status.progress !== 100}
|
||||
isAnimated={status.progress !== 100}
|
||||
/>
|
||||
</Box>
|
||||
<Center my={8} hidden={!status.lastResults}>
|
||||
<CSVLink
|
||||
filename={`devices_export_${dateForFilename(new Date().getTime() / 1000)}.csv`}
|
||||
data={status.lastResults ?? []}
|
||||
headers={HEADER_MAPPING}
|
||||
>
|
||||
<ResponsiveButton
|
||||
color="blue"
|
||||
icon={<Download size={20} />}
|
||||
isCompact={false}
|
||||
label={t('common.download')}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</CSVLink>
|
||||
</Center>
|
||||
</Box>
|
||||
) : null}
|
||||
</Box>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExportDevicesTableButton;
|
||||
209
src/pages/Devices/ListCard/ExportButton/utils.ts
Normal file
209
src/pages/Devices/ListCard/ExportButton/utils.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
import { axiosGw, axiosProv } from 'constants/axiosInstances';
|
||||
import { DeviceWithStatus } from 'hooks/Network/Devices';
|
||||
import { InventoryTag } from 'hooks/Network/Inventory';
|
||||
|
||||
export type ExportedDeviceInfo = {
|
||||
serialNumber: string;
|
||||
connected: 'true' | 'false';
|
||||
firmware: string;
|
||||
memory: number;
|
||||
load: number;
|
||||
temperature: number;
|
||||
sanity: number;
|
||||
revision: string;
|
||||
ip: string;
|
||||
/** Venue, Entity or subscriber name */
|
||||
provisioning: string;
|
||||
radiusSessions: number;
|
||||
/** Uptime in seconds */
|
||||
uptime: number;
|
||||
/** Last Contact as date */
|
||||
lastContact: string;
|
||||
/** Last Upgrade as date */
|
||||
lastUpgrade: string;
|
||||
/** Rx MBs */
|
||||
rx: number;
|
||||
/** Tx MBs */
|
||||
tx: number;
|
||||
twoG: number;
|
||||
fiveG: number;
|
||||
sixG: number;
|
||||
/** Expiry as date */
|
||||
certificateExpiry: string;
|
||||
};
|
||||
|
||||
const getDevicesProvisioningStatus = async (serialNumbers: string[]) =>
|
||||
serialNumbers.length === 0
|
||||
? []
|
||||
: axiosProv
|
||||
.get(`inventory?withExtendedInfo=true&select=${serialNumbers}`)
|
||||
.then(({ data }: { data: { taglist: InventoryTag[] } }) =>
|
||||
serialNumbers.map((serialNumber) => {
|
||||
const found = data.taglist.find((tag) => tag.serialNumber === serialNumber);
|
||||
|
||||
let provisioning = 'Not Found';
|
||||
|
||||
if (found) {
|
||||
if (found.entity.length > 0) provisioning = found.extendedInfo?.entity?.name ?? found.entity;
|
||||
else if (found.venue.length > 0) provisioning = found.extendedInfo?.venue?.name ?? found.venue;
|
||||
else if (found.subscriber.length > 0)
|
||||
provisioning = found.extendedInfo?.subscriber?.name ?? found.subscriber;
|
||||
}
|
||||
|
||||
return {
|
||||
serialNumber,
|
||||
provisioning,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
const getDeviceGatewayInfo = (limit: number, offset: number) =>
|
||||
axiosGw
|
||||
.get(`devices?deviceWithStatus=true&limit=${limit}&offset=${offset}`)
|
||||
.then((response) => response.data) as Promise<{ devicesWithStatus: DeviceWithStatus[] }>;
|
||||
|
||||
const getAllGatewayDeviceInfo = async (
|
||||
count: number,
|
||||
initialProgress: number,
|
||||
setProgress: (progress: number) => void,
|
||||
) => {
|
||||
const progressStep = (90 - initialProgress) / Math.ceil(count / 100);
|
||||
let newProgress = initialProgress;
|
||||
let offset = 0;
|
||||
let devices: DeviceWithStatus[] = [];
|
||||
let devicesResponse: { devicesWithStatus: DeviceWithStatus[] };
|
||||
do {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
devicesResponse = await getDeviceGatewayInfo(100, offset);
|
||||
devices = devices.concat(devicesResponse.devicesWithStatus);
|
||||
setProgress((newProgress += progressStep));
|
||||
offset += 100;
|
||||
} while (devicesResponse.devicesWithStatus.length === 100);
|
||||
|
||||
return devices;
|
||||
};
|
||||
|
||||
export const getAllExportedDevicesInfo = async (setProgress: (progress: number) => void) => {
|
||||
// Base Setup
|
||||
setProgress(0);
|
||||
const devicesCount = await axiosGw.get('devices?countOnly=true').then((response) => response.data.count as number);
|
||||
setProgress(10);
|
||||
|
||||
if (devicesCount === 0) {
|
||||
setProgress(100);
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get Devices Info
|
||||
const devices = await getAllGatewayDeviceInfo(devicesCount, 10, setProgress);
|
||||
|
||||
const serialNumbers = devices
|
||||
.filter((device) => device.entity.length > 0 || device.venue.length > 0 || device.subscriber.length > 0)
|
||||
.map((device) => device.serialNumber);
|
||||
const provisioningStatus = await getDevicesProvisioningStatus(serialNumbers);
|
||||
|
||||
setProgress(95);
|
||||
|
||||
const unixToStr = (unixValue: number) => {
|
||||
try {
|
||||
return new Date(unixValue * 1000).toISOString();
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
const exportedDevicesInfo: ExportedDeviceInfo[] = devices.map((device) => {
|
||||
const provisioning = provisioningStatus.find((status) => status.serialNumber === device.serialNumber)?.provisioning;
|
||||
return {
|
||||
serialNumber: device.serialNumber,
|
||||
connected: device.connected ? 'true' : 'false',
|
||||
firmware: device.firmware,
|
||||
memory: device.memoryUsed,
|
||||
load: device.load,
|
||||
temperature: device.temperature,
|
||||
sanity: device.sanity,
|
||||
revision: device.compatible,
|
||||
ip: device.ipAddress.length > 0 ? device.ipAddress : '',
|
||||
provisioning: provisioning ?? '',
|
||||
radiusSessions: typeof device.hasRADIUSSessions === 'number' ? device.hasRADIUSSessions : 0,
|
||||
uptime: !device.connected || device.started === 0 ? 0 : Math.floor(Date.now() / 1000 - device.started),
|
||||
lastContact: typeof device.lastContact === 'string' ? '' : unixToStr(device.lastContact),
|
||||
lastUpgrade: typeof device.lastFWUpdate === 'string' ? '' : unixToStr(device.lastFWUpdate),
|
||||
rx: device.rxBytes / 1024 / 1024,
|
||||
tx: device.txBytes / 1024 / 1024,
|
||||
twoG: device.associations_2G,
|
||||
fiveG: device.associations_5G,
|
||||
sixG: device.associations_6G,
|
||||
certificateExpiry: device.certificateExpiryDate ? unixToStr(device.certificateExpiryDate) : '',
|
||||
};
|
||||
});
|
||||
|
||||
setProgress(100);
|
||||
return exportedDevicesInfo;
|
||||
};
|
||||
|
||||
const getSelectDevicesGatewayInfo = (serialNumbers: string[]) =>
|
||||
axiosGw
|
||||
.get(`devices?deviceWithStatus=true&select=${serialNumbers.join(',')}`)
|
||||
.then((response) => response.data) as Promise<{ devicesWithStatus: DeviceWithStatus[] }>;
|
||||
|
||||
export const getSelectExportedDevicesInfo = async (
|
||||
serialNumbers: string[],
|
||||
setProgress: (progress: number) => void,
|
||||
) => {
|
||||
// Base Setup
|
||||
setProgress(0);
|
||||
const devicesCount = serialNumbers.length;
|
||||
setProgress(10);
|
||||
|
||||
if (devicesCount === 0) {
|
||||
setProgress(100);
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get Devices Info
|
||||
const devices = (await getSelectDevicesGatewayInfo(serialNumbers)).devicesWithStatus;
|
||||
setProgress(90);
|
||||
|
||||
const provSerialNumbers = devices
|
||||
.filter((device) => device.entity.length > 0 || device.venue.length > 0 || device.subscriber.length > 0)
|
||||
.map((device) => device.serialNumber);
|
||||
const provisioningStatus = await getDevicesProvisioningStatus(provSerialNumbers);
|
||||
|
||||
setProgress(95);
|
||||
|
||||
const unixToStr = (unixValue: number) => {
|
||||
try {
|
||||
return new Date(unixValue * 1000).toISOString();
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
const exportedDevicesInfo: ExportedDeviceInfo[] = devices.map((device) => {
|
||||
const provisioning = provisioningStatus.find((status) => status.serialNumber === device.serialNumber)?.provisioning;
|
||||
return {
|
||||
serialNumber: device.serialNumber,
|
||||
connected: device.connected ? 'true' : 'false',
|
||||
firmware: device.firmware,
|
||||
memory: device.memoryUsed,
|
||||
load: device.load,
|
||||
temperature: device.temperature,
|
||||
sanity: device.sanity,
|
||||
revision: device.compatible,
|
||||
ip: device.ipAddress.length > 0 ? device.ipAddress : '',
|
||||
provisioning: provisioning ?? '',
|
||||
radiusSessions: typeof device.hasRADIUSSessions === 'number' ? device.hasRADIUSSessions : 0,
|
||||
uptime: !device.connected || device.started === 0 ? 0 : Math.floor(Date.now() / 1000 - device.started),
|
||||
lastContact: typeof device.lastContact === 'string' ? '' : unixToStr(device.lastContact),
|
||||
lastUpgrade: typeof device.lastFWUpdate === 'string' ? '' : unixToStr(device.lastFWUpdate),
|
||||
rx: device.rxBytes / 1024,
|
||||
tx: device.txBytes / 1024,
|
||||
twoG: device.associations_2G,
|
||||
fiveG: device.associations_5G,
|
||||
sixG: device.associations_6G,
|
||||
certificateExpiry: device.certificateExpiryDate ? unixToStr(device.certificateExpiryDate) : '',
|
||||
};
|
||||
});
|
||||
|
||||
setProgress(100);
|
||||
return exportedDevicesInfo;
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Button, Tooltip } from '@chakra-ui/react';
|
||||
import { CheckCircle, Question, WarningCircle } from 'phosphor-react';
|
||||
import { CheckCircle, Question, WarningCircle } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getRevision } from 'helpers/stringHelper';
|
||||
import { DeviceWithStatus } from 'hooks/Network/Devices';
|
||||
|
||||
@@ -8,11 +8,12 @@ import {
|
||||
ThermometerCold,
|
||||
ThermometerHot,
|
||||
WarningCircle,
|
||||
} from 'phosphor-react';
|
||||
} from '@phosphor-icons/react';
|
||||
import ReactCountryFlag from 'react-country-flag';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Actions from './Actions';
|
||||
import ExportDevicesTableButton from './ExportButton';
|
||||
import DeviceListFirmwareButton from './FirmwareButton';
|
||||
import DeviceTableGpsCell from './GpsCell';
|
||||
import AP from './icons/AP.png';
|
||||
@@ -646,6 +647,9 @@ const DeviceListCard = () => {
|
||||
title: `${getCount.data?.count} ${t('devices.title')}`,
|
||||
objectListed: t('devices.title'),
|
||||
leftContent: <GlobalSearchBar />,
|
||||
otherButtons: (
|
||||
<ExportDevicesTableButton currentPageSerialNumbers={data.map((device) => device.serialNumber)} />
|
||||
),
|
||||
}}
|
||||
columns={columns}
|
||||
data={data}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Cake } from 'phosphor-react';
|
||||
import { Cake } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SimpleIconStatDisplay from 'components/Containers/SimpleIconStatDisplay';
|
||||
import { FirmwareDashboardResponse } from 'hooks/Network/Firmware';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Heading, Table, Tbody, Td, Th, Thead, Tooltip, Tr } from '@chakra-ui/react';
|
||||
import { Info } from 'phosphor-react';
|
||||
import { Info } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { FloppyDisk } from 'phosphor-react';
|
||||
import { FloppyDisk } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SimpleIconStatDisplay from 'components/Containers/SimpleIconStatDisplay';
|
||||
import { FirmwareDashboardResponse } from 'hooks/Network/Firmware';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Alert, AlertDescription, AlertIcon, AlertTitle, Box, Center, Spacer, Spinner } from '@chakra-ui/react';
|
||||
import { Clock, WifiHigh } from 'phosphor-react';
|
||||
import { Clock, WifiHigh } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Masonry from 'react-masonry-css';
|
||||
import AverageFirmwareAge from './AverageFirmwareAge';
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
useClipboard,
|
||||
UseDisclosureReturn,
|
||||
} from '@chakra-ui/react';
|
||||
import { Pen, Plus, X } from 'phosphor-react';
|
||||
import { Pen, Plus, X } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SaveButton } from 'components/Buttons/SaveButton';
|
||||
import { DataTable } from 'components/DataTables/DataTable';
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import axios from 'axios';
|
||||
import { Database } from 'phosphor-react';
|
||||
import { Database } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import FormattedDate from 'components/InformationDisplays/FormattedDate';
|
||||
import { Modal } from 'components/Modals/Modal';
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
useBoolean,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { MagnifyingGlass } from 'phosphor-react';
|
||||
import { MagnifyingGlass } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import FirmwareDetailsModal from './Modal';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Flex, HStack, IconButton, Select, Spacer, Table, Text, Th, Thead, Tooltip, Tr } from '@chakra-ui/react';
|
||||
import { Download } from 'phosphor-react';
|
||||
import { Download } from '@phosphor-icons/react';
|
||||
import { CSVLink } from 'react-csv';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ReactVirtualizedAutoSizer from 'react-virtualized-auto-sizer';
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
Tooltip,
|
||||
Tr,
|
||||
} from '@chakra-ui/react';
|
||||
import { Download } from 'phosphor-react';
|
||||
import { Download } from '@phosphor-icons/react';
|
||||
import { CSVLink } from 'react-csv';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ReactVirtualizedAutoSizer from 'react-virtualized-auto-sizer';
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
Tooltip,
|
||||
Tr,
|
||||
} from '@chakra-ui/react';
|
||||
import { Download } from 'phosphor-react';
|
||||
import { Download } from '@phosphor-icons/react';
|
||||
import { CSVLink } from 'react-csv';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ReactVirtualizedAutoSizer from 'react-virtualized-auto-sizer';
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
Tooltip,
|
||||
Tr,
|
||||
} from '@chakra-ui/react';
|
||||
import { Download } from 'phosphor-react';
|
||||
import { Download } from '@phosphor-icons/react';
|
||||
import { CSVLink } from 'react-csv';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ReactVirtualizedAutoSizer from 'react-virtualized-auto-sizer';
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
Text,
|
||||
useClipboard,
|
||||
} from '@chakra-ui/react';
|
||||
import { Eye, Trash } from 'phosphor-react';
|
||||
import { Eye, Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ApiKey, useDeleteApiKey } from 'hooks/Network/ApiKeys';
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import axios from 'axios';
|
||||
import { Pen } from 'phosphor-react';
|
||||
import { Pen } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ApiKey, useUpdateApiKey } from 'hooks/Network/ApiKeys';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Button, IconButton, Text, Tooltip, useDisclosure } from '@chakra-ui/react';
|
||||
import { Pen } from 'phosphor-react';
|
||||
import { Pen } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import AddPhoneNumberModal from './AddPhoneNumberModal';
|
||||
import { useAuth } from 'contexts/AuthProvider';
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
useToast,
|
||||
useBreakpoint,
|
||||
} from '@chakra-ui/react';
|
||||
import { Plus } from 'phosphor-react';
|
||||
import { Plus } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { DataTable } from '../../components/DataTables/DataTable';
|
||||
import FormattedDate from '../../components/InformationDisplays/FormattedDate';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { Avatar, AvatarBadge, Box, Center, Heading, Text, useDisclosure } from '@chakra-ui/react';
|
||||
import { Pen } from 'phosphor-react';
|
||||
import { Pen } from '@phosphor-icons/react';
|
||||
import AvatarModal from './AvatarModal';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
import { CardBody } from 'components/Containers/Card/CardBody';
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
Tooltip,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { MagnifyingGlass, Trash } from 'phosphor-react';
|
||||
import { MagnifyingGlass, Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Script, useDeleteScript } from 'hooks/Network/Scripts';
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
useBoolean,
|
||||
useClipboard,
|
||||
} from '@chakra-ui/react';
|
||||
import { UploadSimple } from 'phosphor-react';
|
||||
import { UploadSimple } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useFastField } from 'hooks/useFastField';
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
Text,
|
||||
useClipboard,
|
||||
} from '@chakra-ui/react';
|
||||
import { Eye, Trash } from 'phosphor-react';
|
||||
import { Eye, Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import EditSecretButton from './EditButton';
|
||||
import { Secret, useDeleteSystemSecret } from 'hooks/Network/Secrets';
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
useDisclosure,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import { Pencil } from 'phosphor-react';
|
||||
import { Pencil } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Secret, useUpdateSystemSecret } from 'hooks/Network/Secrets';
|
||||
import { AxiosError } from 'models/Axios';
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import axios from 'axios';
|
||||
import { FloppyDisk } from 'phosphor-react';
|
||||
import { FloppyDisk } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { Modal } from '../../../../components/Modals/Modal';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { IconButton, Tooltip, useDisclosure } from '@chakra-ui/react';
|
||||
import { Article } from 'phosphor-react';
|
||||
import { Article } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SystemLoggingModal from './Modal';
|
||||
import { EndpointApiResponse } from 'hooks/Network/Endpoints';
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
VStack,
|
||||
} from '@chakra-ui/react';
|
||||
import { MultiValue, Select } from 'chakra-react-select';
|
||||
import { ArrowsClockwise } from 'phosphor-react';
|
||||
import { ArrowsClockwise } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import FormattedDate from '../../../components/InformationDisplays/FormattedDate';
|
||||
import SystemLoggingButton from './LoggingButton';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { IconButton, Menu, MenuButton, MenuItem, MenuList, Tooltip, useToast } from '@chakra-ui/react';
|
||||
import { Wrench } from 'phosphor-react';
|
||||
import { Wrench } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useResetMfa, useResetPassword, useSendUserEmailValidation, useSuspendUser } from 'hooks/Network/Users';
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import axios from 'axios';
|
||||
import { MagnifyingGlass, Trash } from 'phosphor-react';
|
||||
import { MagnifyingGlass, Trash } from '@phosphor-icons/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import ActionsDropdown from './ActionsDropdown';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '@chakra-ui/react';
|
||||
import { Barcode, FloppyDisk, Info, ListBullets, TerminalWindow, UsersThree, WifiHigh } from 'phosphor-react';
|
||||
import { Barcode, FloppyDisk, Info, ListBullets, TerminalWindow, UsersThree, WifiHigh } from '@phosphor-icons/react';
|
||||
import { Route } from 'models/Routes';
|
||||
|
||||
const DefaultConfigurationsPage = React.lazy(() => import('pages/DefaultConfigurations'));
|
||||
|
||||
Reference in New Issue
Block a user