[WIFI-12412] Fixing SSID.services configuration options

Signed-off-by: Charles <charles.bourque96@gmail.com>
This commit is contained in:
Charles
2023-03-17 09:21:40 +01:00
parent 8a262eb36b
commit e196d4b9ef
52 changed files with 5942 additions and 6027 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "wlan-cloud-owprov-ui",
"version": "2.9.0(16)",
"version": "2.9.0(18)",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "wlan-cloud-owprov-ui",
"version": "2.9.0(16)",
"version": "2.9.0(18)",
"license": "ISC",
"dependencies": {
"@chakra-ui/icons": "^2.0.11",

View File

@@ -1,6 +1,6 @@
{
"name": "wlan-cloud-owprov-ui",
"version": "2.9.0(16)",
"version": "2.9.0(18)",
"description": "",
"main": "index.tsx",
"scripts": {

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

View File

@@ -15,7 +15,7 @@ interface Props extends ThemeProps {
const defaultProps = {
isDisabled: false,
isLoading: false,
isCompact: false,
isCompact: true,
label: undefined,
};

View File

@@ -15,7 +15,7 @@ const defaultProps = {
onClick: () => {},
isDisabled: false,
isLoading: false,
isCompact: false,
isCompact: true,
label: undefined,
};

View File

@@ -15,7 +15,7 @@ interface Props {
const defaultProps = {
isDisabled: false,
isLoading: false,
isCompact: false,
isCompact: true,
label: undefined,
ml: undefined,
};

View File

@@ -15,7 +15,7 @@ const defaultProps = {
label: 'Edit',
isDisabled: false,
isLoading: false,
isCompact: false,
isCompact: true,
ml: undefined,
};

View File

@@ -14,7 +14,7 @@ interface Props {
const defaultProps = {
isDisabled: false,
isFetching: false,
isCompact: false,
isCompact: true,
ml: undefined,
};

View File

@@ -15,7 +15,7 @@ const ResponsiveButton = ({
onClick,
isDisabled,
isLoading,
isCompact,
isCompact = true,
color,
label,
icon,

View File

@@ -18,7 +18,7 @@ const defaultProps = {
onSave: undefined,
isDisabled: false,
isLoading: false,
isCompact: false,
isCompact: true,
ml: undefined,
};

View File

@@ -17,7 +17,7 @@ interface Props {
const defaultProps = {
isDisabled: false,
isLoading: false,
isCompact: false,
isCompact: true,
isDirty: false,
ml: undefined,
};

View File

@@ -15,7 +15,7 @@ interface Props extends ThemeProps {
const defaultProps = {
isDisabled: false,
isLoading: false,
isCompact: false,
isCompact: true,
label: undefined,
};

View File

@@ -33,7 +33,7 @@ const ColumnPicker = ({
setHiddenColumns,
defaultHiddenColumns = [],
size,
isCompact,
isCompact = true,
}: ColumnPickerProps) => {
const { t } = useTranslation();
const { getPref, setPref } = useAuth();

View File

@@ -5,27 +5,29 @@ import useFastField from 'hooks/useFastField';
import { FieldProps } from 'models/Form';
interface Props extends FieldProps, LayoutProps {
formatValue?: (value: string) => string;
hideButton?: boolean;
}
const StringField = ({
const StringField: React.FC<Props> = ({
name,
isDisabled = false,
label,
hideButton = false,
isRequired = false,
element,
formatValue,
isArea = false,
emptyIsUndefined = false,
definitionKey,
...props
}: Props) => {
}) => {
const { value, error, isError, onChange, onBlur } = useFastField<string | undefined>({ name });
const onFieldChange = useCallback(
(e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
if (emptyIsUndefined && e.target.value.length === 0) onChange(undefined);
else onChange(e.target.value);
else onChange(formatValue ? formatValue(e.target.value) : e.target.value);
},
[onChange],
);

View File

@@ -1,5 +1,14 @@
import React, { useState } from 'react';
import { Button, Modal, ModalOverlay, ModalContent, ModalBody, useDisclosure, Flex } from '@chakra-ui/react';
import {
Modal,
ModalOverlay,
ModalContent,
ModalBody,
useDisclosure,
Flex,
Tooltip,
IconButton,
} from '@chakra-ui/react';
import { MagnifyingGlass } from 'phosphor-react';
import { useTranslation } from 'react-i18next';
import SubscriberSearchDisplayTable from './Table';
@@ -19,9 +28,9 @@ const SubscriberSearchModal = ({ operatorId }: Props) => {
return (
<>
<Button alignItems="center" colorScheme="blue" rightIcon={<MagnifyingGlass />} onClick={onOpen} ml={2}>
{t('common.search')}
</Button>
<Tooltip label={t('common.search')} hasArrow>
<IconButton aria-label={t('common.search')} icon={<MagnifyingGlass />} onClick={onOpen} colorScheme="teal" />
</Tooltip>
<Modal onClose={onClose} isOpen={isOpen} size="xl">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '90%', md: '900px', lg: '1000px', xl: '80%' }}>

View File

@@ -1,12 +1,12 @@
import React, { useEffect, useMemo, useState } from 'react';
import { AddIcon } from '@chakra-ui/icons';
import { Button, Modal, ModalOverlay, ModalContent, ModalBody, Center, Spinner } from '@chakra-ui/react';
import { Modal, ModalOverlay, ModalContent, ModalBody, Center, Spinner } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import CreateSubscriberDeviceStep0 from './MultiStepForm/Step0';
import CreateSubscriberDeviceStep1 from './MultiStepForm/Step1';
import CreateSubscriberDeviceStep2 from './MultiStepForm/Step2';
import CreateSubscriberDeviceStep3 from './MultiStepForm/Step3';
import CloseButton from 'components/Buttons/CloseButton';
import CreateButton from 'components/Buttons/CreateButton';
import StepButton from 'components/Buttons/StepButton';
import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert';
import ModalHeader from 'components/Modals/ModalHeader';
@@ -141,16 +141,7 @@ const CreateSubscriberDeviceModal = ({ refresh, operatorId, subscriberId, device
return (
<>
<Button
hidden={user?.userRole === 'CSR'}
alignItems="center"
colorScheme="blue"
rightIcon={<AddIcon />}
onClick={onOpen}
ml={2}
>
{t('crud.create')}
</Button>
{user?.userRole === 'CSR' ? null : <CreateButton onClick={onOpen} ml={2} />}
<Modal onClose={closeModal} isOpen={isOpen} size="xl">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '90%', md: '900px', lg: '1000px', xl: '80%' }}>

View File

@@ -66,7 +66,7 @@ const DeviceActionDropdown = ({
return (
<Menu>
<Tooltip label={t('commands.other')}>
<Tooltip label={t('common.actions')}>
<MenuButton
as={IconButton}
aria-label="Commands"

View File

@@ -1,11 +1,11 @@
import React, { useCallback, useState } from 'react';
import { AddIcon } from '@chakra-ui/icons';
import { Button, useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { useMutation } from '@tanstack/react-query';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import CreateConfigurationForm from './Form';
import CloseButton from 'components/Buttons/CloseButton';
import CreateButton from 'components/Buttons/CreateButton';
import SaveButton from 'components/Buttons/SaveButton';
import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert';
import ModalHeader from 'components/Modals/ModalHeader';
@@ -51,9 +51,7 @@ const CreateConfigurationModal = ({ refresh, entityId }) => {
return (
<>
<Button alignItems="center" colorScheme="blue" rightIcon={<AddIcon />} onClick={openModal} ml={2}>
{t('crud.create')}
</Button>
<CreateButton onClick={openModal} ml={2} />
<Modal onClose={closeModal} isOpen={isOpen} size="xl" scrollBehavior="inside">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '90%', md: '900px', lg: '1000px', xl: '80%' }}>

View File

@@ -1,10 +1,10 @@
import React from 'react';
import { AddIcon } from '@chakra-ui/icons';
import { Button, useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import CreateContactForm from './Form';
import CloseButton from 'components/Buttons/CloseButton';
import CreateButton from 'components/Buttons/CreateButton';
import SaveButton from 'components/Buttons/SaveButton';
import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert';
import ModalHeader from 'components/Modals/ModalHeader';
@@ -47,16 +47,7 @@ const CreateContactModal = ({ refresh, entityId, isVenue, onCreate }) => {
return (
<>
<Button
hidden={user?.userRole === 'CSR'}
alignItems="center"
colorScheme="blue"
rightIcon={<AddIcon />}
onClick={onOpen}
ml={2}
>
{t('crud.create')}
</Button>
{user?.userRole === 'CSR' ? null : <CreateButton onClick={onOpen} ml={2} />}
<Modal onClose={closeModal} isOpen={isOpen} size="xl" initialFocusRef={initialRef}>
<ModalOverlay />
<ModalContent maxWidth={{ sm: '600px', md: '700px', lg: '800px', xl: '50%' }}>

View File

@@ -66,7 +66,7 @@ const DeviceActionDropdown = ({
return (
<Menu>
<Tooltip label={t('commands.other')}>
<Tooltip label={t('common.actions')}>
<MenuButton
as={IconButton}
aria-label="Commands"

View File

@@ -149,12 +149,6 @@ const EditTagModal = ({
title={t('crud.edit_obj', { obj: tag?.name ?? tag?.serialNumber })}
right={
<>
<SaveButton
onClick={form.submitForm}
isLoading={form.isSubmitting}
isDisabled={!editing || !form.isValid || (configuration !== null && !configuration.__form.isValid)}
mr={2}
/>
<Popover isOpen={isDeleteOpen} onOpen={onDeleteOpen} onClose={onDeleteClose}>
<Tooltip hasArrow label={t('crud.delete')} placement="top" isDisabled={isDeleteOpen}>
<Box>
@@ -208,6 +202,13 @@ const EditTagModal = ({
onClick={handlePushConfig}
/>
</Tooltip>
<SaveButton
onClick={form.submitForm}
isLoading={form.isSubmitting}
isDisabled={!editing || !form.isValid || (configuration !== null && !configuration.__form.isValid)}
hidden={!editing}
ml={2}
/>
<EditButton ml={2} isDisabled={editing} onClick={setEditing.toggle} isCompact />
<CloseButton ml={2} onClick={closeModal} />
</>

View File

@@ -1,15 +1,5 @@
import React, { useState } from 'react';
import {
useDisclosure,
Modal,
ModalOverlay,
ModalContent,
ModalBody,
useBreakpoint,
Button,
Tooltip,
IconButton,
} from '@chakra-ui/react';
import { useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody, Tooltip, IconButton } from '@chakra-ui/react';
import { UploadSimple } from 'phosphor-react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
@@ -36,7 +26,6 @@ const defaultProps = {
const ImportDeviceCsvModal = ({ refresh, deviceClass, parent }) => {
const { t } = useTranslation();
const breakpoint = useBreakpoint();
const [refreshId, setRefreshId] = useState(uuid());
// 0: explanation, file import and file analysis
// 1: testing the serial number list with the API
@@ -91,22 +80,6 @@ const ImportDeviceCsvModal = ({ refresh, deviceClass, parent }) => {
onOpen();
};
const getButton = () => {
if (breakpoint !== 'base' && breakpoint !== 'sm') {
return (
<Button ml={2} colorScheme="blue" onClick={openModal} rightIcon={<UploadSimple size={20} />}>
{t('devices.import_batch_tags')}
</Button>
);
}
return (
<Tooltip label={t('devices.import_batch_tags')}>
<IconButton ml={2} colorScheme="blue" onClick={openModal} icon={<UploadSimple size={20} />} />
</Tooltip>
);
};
const closeModal = () => (isCloseable ? onClose() : openConfirm());
const closeCancelAndForm = () => {
@@ -116,7 +89,9 @@ const ImportDeviceCsvModal = ({ refresh, deviceClass, parent }) => {
return (
<>
{getButton()}
<Tooltip label={t('devices.import_batch_tags')}>
<IconButton ml={2} colorScheme="teal" onClick={openModal} icon={<UploadSimple size={20} />} />
</Tooltip>
<Modal onClose={closeModal} isOpen={isOpen} size="xl">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '600px', md: '700px', lg: '800px', xl: '50%' }}>

View File

@@ -1,14 +1,13 @@
import React from 'react';
import { AddIcon } from '@chakra-ui/icons';
import { Button, useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import CreateLocationForm from './Form';
import CloseButton from 'components/Buttons/CloseButton';
import CreateButton from 'components/Buttons/CreateButton';
import SaveButton from 'components/Buttons/SaveButton';
import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert';
import ModalHeader from 'components/Modals/ModalHeader';
import { useAuth } from 'contexts/AuthProvider';
import useFormRef from 'hooks/useFormRef';
const propTypes = {
@@ -22,7 +21,6 @@ const defaultProps = {
const CreateLocationModal = ({ refresh, entityId }) => {
const { t } = useTranslation();
const { user } = useAuth();
const { isOpen, onOpen, onClose } = useDisclosure();
const { isOpen: showConfirm, onOpen: openConfirm, onClose: closeConfirm } = useDisclosure();
const { form, formRef } = useFormRef();
@@ -36,16 +34,7 @@ const CreateLocationModal = ({ refresh, entityId }) => {
return (
<>
<Button
hidden={user?.userRole === 'CSR'}
alignItems="center"
colorScheme="blue"
rightIcon={<AddIcon />}
onClick={onOpen}
ml={2}
>
{t('crud.create')}
</Button>
<CreateButton onClick={onOpen} ml={2} />
<Modal onClose={closeModal} isOpen={isOpen} size="xl">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '600px', md: '700px', lg: '800px', xl: '50%' }}>

View File

@@ -1,14 +1,13 @@
import React from 'react';
import { AddIcon } from '@chakra-ui/icons';
import { Button, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import CreateSubscriberForm from './Form';
import CloseButton from 'components/Buttons/CloseButton';
import CreateButton from 'components/Buttons/CreateButton';
import SaveButton from 'components/Buttons/SaveButton';
import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert';
import ModalHeader from 'components/Modals/ModalHeader';
import { useAuth } from 'contexts/AuthProvider';
import useFormModal from 'hooks/useFormModal';
import useFormRef from 'hooks/useFormRef';
@@ -18,7 +17,6 @@ const propTypes = {
};
const CreateSubscriberModal = ({ refresh, operatorId }) => {
const { t } = useTranslation();
const { user } = useAuth();
const { form, formRef } = useFormRef();
const { isOpen, isConfirmOpen, onOpen, closeConfirm, closeModal, closeCancelAndForm } = useFormModal({
isDirty: form?.dirty,
@@ -26,16 +24,7 @@ const CreateSubscriberModal = ({ refresh, operatorId }) => {
return (
<>
<Button
hidden={user?.userRole === 'CSR'}
alignItems="center"
colorScheme="blue"
rightIcon={<AddIcon />}
onClick={onOpen}
ml={2}
>
{t('crud.create')}
</Button>
<CreateButton onClick={onOpen} ml={2} />
<Modal onClose={closeModal} isOpen={isOpen} size="xl">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '600px', md: '700px', lg: '800px', xl: '50%' }}>

View File

@@ -42,6 +42,18 @@ const DhcpIpV4 = ({ namePrefix, isDisabled }: Props) => {
definitionKey="interface.ipv4.dhcp-lease.macaddr"
isRequired
w="220px"
formatValue={(v) => {
const r = /([a-f0-9]{2})([a-f0-9]{2})/i;
let str = v.replace(/[^a-f0-9]/gi, '');
while (r.test(str)) {
str = str.replace(r, `$1:$2`);
}
str = str.slice(0, 17);
return str;
}}
mr={4}
/>
<StaticLeaseOffsetField subnet={ipv4?.subnet} />
@@ -122,7 +134,7 @@ const DhcpIpV4 = ({ namePrefix, isDisabled }: Props) => {
isRequired
options={{
modalTitle: 'Reserved Addresses',
buttonLabel: 'Reserved Addresses',
buttonLabel: 'Manage Reserved Addresses',
onFormSubmit: (v: {
__temp_ip?: string;
secondMacAddress: string;

View File

@@ -74,7 +74,6 @@ const AdvancedSettings: React.FC<{ editing: boolean; namePrefix: string }> = ({
definitionKey="interface.ssid.services"
isDisabled={!editing}
options={[
{ value: 'captive', label: 'captive' },
{ value: 'radius-gw-proxy', label: 'radius-gw-proxy' },
{ value: 'wifi-steering', label: 'wifi-steering' },
]}

View File

@@ -1,15 +1,5 @@
import React from 'react';
import {
Button,
IconButton,
Tooltip,
useBreakpoint,
useDisclosure,
Modal,
ModalBody,
ModalContent,
ModalOverlay,
} from '@chakra-ui/react';
import { IconButton, Tooltip, useDisclosure, Modal, ModalBody, ModalContent, ModalOverlay } from '@chakra-ui/react';
import { CheckCircle, WarningOctagon } from 'phosphor-react';
import PropTypes from 'prop-types';
import isEqual from 'react-fast-compare';
@@ -30,7 +20,6 @@ const defaultProps = {
const ViewConfigErrorsModal = ({ errors, activeConfigurations, isDisabled }) => {
const { t } = useTranslation();
const { isOpen, onOpen, onClose } = useDisclosure();
const breakpoint = useBreakpoint();
const errorAmount =
errors.globals.length +
errors.unit.length +
@@ -42,28 +31,20 @@ const ViewConfigErrorsModal = ({ errors, activeConfigurations, isDisabled }) =>
return (
<>
{breakpoint !== 'base' && breakpoint !== 'sm' ? (
<Button
<Tooltip
label={`${errorAmount} ${errorAmount === 1 ? t('common.error') : t('common.errors')}`}
hasArrow
shouldWrapChildren
>
<IconButton
colorScheme={errorAmount === 0 ? 'green' : 'red'}
type="button"
onClick={onOpen}
ml={2}
rightIcon={errorAmount === 0 ? <CheckCircle size={20} /> : <WarningOctagon size={20} />}
icon={errorAmount === 0 ? <CheckCircle size={20} /> : <WarningOctagon size={20} />}
isDisabled={isDisabled || errorAmount === 0}
>
{errorAmount} {errorAmount === 1 ? t('common.error') : t('common.errors')}
</Button>
) : (
<Tooltip label={`${errorAmount} ${errorAmount === 1 ? t('common.error') : t('common.errors')}`}>
<IconButton
colorScheme={errorAmount === 0 ? 'green' : 'red'}
type="button"
onClick={onOpen}
icon={errorAmount === 0 ? <CheckCircle size={20} /> : <WarningOctagon size={20} />}
isDisabled={isDisabled || errorAmount === 0}
/>
</Tooltip>
)}
/>
</Tooltip>
<Modal onClose={onClose} isOpen={isOpen} size="xl" scrollBehavior="inside">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '600px', md: '700px', lg: '800px', xl: '50%' }}>

View File

@@ -1,15 +1,5 @@
import React from 'react';
import {
Button,
IconButton,
Tooltip,
useBreakpoint,
useDisclosure,
Modal,
ModalBody,
ModalContent,
ModalOverlay,
} from '@chakra-ui/react';
import { IconButton, Tooltip, useDisclosure, Modal, ModalBody, ModalContent, ModalOverlay } from '@chakra-ui/react';
import { CheckCircle, WarningOctagon } from 'phosphor-react';
import PropTypes from 'prop-types';
import isEqual from 'react-fast-compare';
@@ -30,7 +20,6 @@ const defaultProps = {
const ViewConfigWarningsModal = ({ warnings, activeConfigurations, isDisabled }) => {
const { t } = useTranslation();
const { isOpen, onOpen, onClose } = useDisclosure();
const breakpoint = useBreakpoint();
const warningsAmount =
warnings.globals.length +
warnings.unit.length +
@@ -42,27 +31,19 @@ const ViewConfigWarningsModal = ({ warnings, activeConfigurations, isDisabled })
return (
<>
{breakpoint !== 'base' && breakpoint !== 'sm' ? (
<Button
<Tooltip
label={`${warningsAmount} ${warningsAmount === 1 ? t('common.warning') : t('common.warnings')}`}
hasArrow
shouldWrapChildren
>
<IconButton
colorScheme={warningsAmount === 0 ? 'green' : 'yellow'}
type="button"
onClick={onOpen}
rightIcon={warningsAmount === 0 ? <CheckCircle size={20} /> : <WarningOctagon size={20} />}
icon={warningsAmount === 0 ? <CheckCircle size={20} /> : <WarningOctagon size={20} />}
isDisabled={isDisabled || warningsAmount === 0}
>
{warningsAmount} {warningsAmount === 1 ? t('common.warning') : t('common.warnings')}
</Button>
) : (
<Tooltip label={`${warningsAmount} ${warningsAmount === 1 ? t('common.warning') : t('common.warnings')}`}>
<IconButton
colorScheme={warningsAmount === 0 ? 'green' : 'yellow'}
type="button"
onClick={onOpen}
icon={warningsAmount === 0 ? <CheckCircle size={20} /> : <WarningOctagon size={20} />}
isDisabled={isDisabled || warningsAmount === 0}
/>
</Tooltip>
)}
/>
</Tooltip>
<Modal onClose={onClose} isOpen={isOpen} size="xl" scrollBehavior="inside">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '600px', md: '700px', lg: '800px', xl: '50%' }}>

View File

@@ -149,7 +149,6 @@ const ConfigurationCard = ({ id }) => {
<SaveButton
onClick={handleSubmitClick}
isLoading={updateEntity.isLoading}
isCompact={false}
isDisabled={
!editing || !form.isValid || sections.invalidValues.length > 0 || (!form.dirty && !sections.isDirty)
}

View File

@@ -33,7 +33,6 @@ const EntityCard = ({ id }) => {
<SaveButton
onClick={form.submitForm}
isLoading={form.isSubmitting}
isCompact={false}
isDisabled={!editing || !form.isValid || !form.dirty}
ml={2}
/>

View File

@@ -1,5 +1,19 @@
import * as React from 'react';
import { Badge, Box, Button, Flex, HStack, Select, Spacer, Table, Text, Th, Thead, Tr } from '@chakra-ui/react';
import {
Badge,
Box,
Flex,
HStack,
IconButton,
Select,
Spacer,
Table,
Text,
Th,
Thead,
Tooltip,
Tr,
} from '@chakra-ui/react';
import { Download } from 'phosphor-react';
import { CSVLink } from 'react-csv';
import { useTranslation } from 'react-i18next';
@@ -131,9 +145,9 @@ const FmsLogsCard = () => {
filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`}
data={downloadableLogs as object[]}
>
<Button onClick={() => {}} colorScheme="blue" leftIcon={<Download />}>
{t('logs.export')}
</Button>
<Tooltip label={t('logs.export')} hasArrow>
<IconButton aria-label={t('logs.export')} icon={<Download />} colorScheme="blue" />
</Tooltip>
</CSVLink>
</HStack>
</CardHeader>

View File

@@ -1,5 +1,19 @@
import * as React from 'react';
import { Badge, Box, Button, Flex, HStack, Select, Spacer, Table, Text, Th, Thead, Tr } from '@chakra-ui/react';
import {
Badge,
Box,
Flex,
HStack,
IconButton,
Select,
Spacer,
Table,
Text,
Th,
Thead,
Tooltip,
Tr,
} from '@chakra-ui/react';
import { Download } from 'phosphor-react';
import { CSVLink } from 'react-csv';
import { useTranslation } from 'react-i18next';
@@ -134,9 +148,9 @@ const GeneralLogsCard = () => {
filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`}
data={downloadableLogs as object[]}
>
<Button onClick={() => {}} colorScheme="blue" leftIcon={<Download />}>
{t('logs.export')}
</Button>
<Tooltip label={t('logs.export')} hasArrow>
<IconButton aria-label={t('logs.export')} icon={<Download />} colorScheme="blue" />
</Tooltip>
</CSVLink>
</HStack>
</CardHeader>

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import { Box, Button, Flex, HStack, Spacer, Table, Text, Th, Thead, Tr } from '@chakra-ui/react';
import { Box, Flex, HStack, IconButton, Spacer, Table, Text, Th, Thead, Tooltip, Tr } from '@chakra-ui/react';
import { Download } from 'phosphor-react';
import { CSVLink } from 'react-csv';
import { useTranslation } from 'react-i18next';
@@ -124,9 +124,9 @@ const NotificationsCard = () => {
filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`}
data={downloadableLogs as object[]}
>
<Button onClick={() => {}} colorScheme="blue" leftIcon={<Download />}>
{t('logs.export')}
</Button>
<Tooltip label={t('logs.export')} hasArrow>
<IconButton aria-label={t('logs.export')} icon={<Download />} colorScheme="blue" />
</Tooltip>
</CSVLink>
</HStack>
</CardHeader>

View File

@@ -1,5 +1,19 @@
import * as React from 'react';
import { Badge, Box, Button, Flex, HStack, Select, Spacer, Table, Text, Th, Thead, Tr } from '@chakra-ui/react';
import {
Badge,
Box,
Flex,
HStack,
IconButton,
Select,
Spacer,
Table,
Text,
Th,
Thead,
Tooltip,
Tr,
} from '@chakra-ui/react';
import { Download } from 'phosphor-react';
import { CSVLink } from 'react-csv';
import { useTranslation } from 'react-i18next';
@@ -131,9 +145,9 @@ const SecLogsCard = () => {
filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`}
data={downloadableLogs as object[]}
>
<Button onClick={() => {}} colorScheme="blue" leftIcon={<Download />}>
{t('logs.export')}
</Button>
<Tooltip label={t('logs.export')} hasArrow>
<IconButton aria-label={t('logs.export')} icon={<Download />} colorScheme="blue" />
</Tooltip>
</CSVLink>
</HStack>
</CardHeader>

View File

@@ -29,11 +29,12 @@ const OperatorDetailsCard = ({ id }) => {
<Heading size="md">{operator?.name}</Heading>
</Box>
<Spacer />
<DeleteOperatorButton isDisabled={editing || isFetching} operator={operator} />
<SaveButton
onClick={form.submitForm}
isLoading={form.isSubmitting}
isCompact={false}
isDisabled={!editing || !form.isValid || !form.dirty}
hidden={!editing}
ml={2}
/>
<ToggleEditButton
@@ -43,7 +44,6 @@ const OperatorDetailsCard = ({ id }) => {
isDirty={formRef.dirty}
ml={2}
/>
<DeleteOperatorButton isDisabled={editing || isFetching} operator={operator} />
<RefreshButton onClick={refetch} isFetching={isFetching} isDisabled={editing} ml={2} />
</CardHeader>
<CardBody>

View File

@@ -1,4 +1,5 @@
import * as React from 'react';
import { Box } from '@chakra-ui/react';
import ApiKeyTable from './Table';
import Card from 'components/Card';
import CardBody from 'components/Card/CardBody';
@@ -10,7 +11,9 @@ const ApiKeysCard = () => {
return (
<Card p={4}>
<CardBody>
<ApiKeyTable userId={user?.id ?? ''} />
<Box w="100%">
<ApiKeyTable userId={user?.id ?? ''} />
</Box>
</CardBody>
</Card>
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { ChevronDownIcon } from '@chakra-ui/icons';
import { Button, Menu, MenuButton, MenuItem, MenuList } from '@chakra-ui/react';
import { IconButton, Menu, MenuButton, MenuItem, MenuList, Tooltip } from '@chakra-ui/react';
import { Wrench } from 'phosphor-react';
import { useTranslation } from 'react-i18next';
import { useSendEmailResetSubscriber, useSuspendSubscriber } from 'hooks/Network/Subscribers';
import useMutationResult from 'hooks/useMutationResult';
@@ -12,13 +12,7 @@ interface Props {
isDisabled?: boolean;
}
const SubscriberActions = (
{
subscriber,
refresh,
isDisabled
}: Props
) => {
const SubscriberActions: React.FC<Props> = ({ subscriber, refresh, isDisabled }) => {
const { t } = useTranslation();
const { mutateAsync: suspend } = useSuspendSubscriber({ id: subscriber?.id ?? '' });
const { mutateAsync: resetPassword } = useSendEmailResetSubscriber({ id: subscriber?.id ?? '' });
@@ -41,9 +35,9 @@ const SubscriberActions = (
return (
<Menu>
<MenuButton as={Button} rightIcon={<ChevronDownIcon />} ml={2} isDisabled={isDisabled}>
{t('common.actions')}
</MenuButton>
<Tooltip label={t('common.actions')} aria-label={t('common.actions')} hasArrow>
<MenuButton as={IconButton} icon={<Wrench size={20} />} ml={2} isDisabled={isDisabled} />
</Tooltip>
<MenuList>
<MenuItem onClick={handleSuspendClick}>
{subscriber?.suspended ? t('users.stop_suspension') : t('users.suspend')}

View File

@@ -19,7 +19,7 @@ interface Props {
id: string;
}
const SubscriberCard = ({ id }: Props) => {
const SubscriberCard: React.FC<Props> = ({ id }) => {
const [editing, setEditing] = useBoolean();
const { data: subscriber, refetch, isFetching } = useGetSubscriber({ id });
const { form, formRef } = useFormRef();
@@ -41,11 +41,12 @@ const SubscriberCard = ({ id }: Props) => {
</Flex>
<Spacer />
<Box>
<DeleteVenuePopover isDisabled={editing || isFetching} subscriber={subscriber} />
<SaveButton
onClick={form.submitForm}
isLoading={form.isSubmitting}
isCompact={false}
isDisabled={!editing || !form.isValid || !form.dirty}
hidden={!editing}
ml={2}
/>
<ToggleEditButton
@@ -55,9 +56,8 @@ const SubscriberCard = ({ id }: Props) => {
isDirty={form.dirty}
ml={2}
/>
<DeleteVenuePopover isDisabled={editing || isFetching} subscriber={subscriber} />
<RefreshButton onClick={refetch} isFetching={isFetching} isDisabled={editing} ml={2} />
<Actions subscriber={subscriber} refresh={refetch} isDisabled={editing} />
<RefreshButton onClick={refetch} isFetching={isFetching} isDisabled={editing} ml={2} />
</Box>
</CardHeader>
<CardBody>

View File

@@ -1,5 +1,6 @@
import * as React from 'react';
import { Button, useDisclosure } from '@chakra-ui/react';
import { IconButton, Tooltip, useDisclosure } from '@chakra-ui/react';
import { Article } from 'phosphor-react';
import { useTranslation } from 'react-i18next';
import SystemLoggingModal from './Modal';
import { EndpointApiResponse } from 'hooks/Network/Endpoints';
@@ -15,9 +16,17 @@ const SystemLoggingButton = ({ endpoint, token }: Props) => {
return (
<>
<Button colorScheme="teal" onClick={modalProps.onOpen} mr={2} my="auto">
{t('system.logging')}
</Button>
<Tooltip label={t('system.logging')} hasArrow>
<IconButton
aria-label={t('system.logging')}
colorScheme="teal"
type="button"
my="auto"
onClick={modalProps.onOpen}
icon={<Article size={20} />}
mr={2}
/>
</Tooltip>
<SystemLoggingModal modalProps={modalProps} endpoint={endpoint.uri} token={token} />
</>
);

View File

@@ -21,6 +21,7 @@ import { ArrowsClockwise } from 'phosphor-react';
import { useTranslation } from 'react-i18next';
import SystemLoggingButton from './LoggingButton';
import SystemCertificatesTable from './SystemCertificatesTable';
import RefreshButton from 'components/Buttons/RefreshButton';
import Card from 'components/Card';
import CardBody from 'components/Card/CardBody';
import FormattedDate from 'components/FormattedDate';
@@ -70,16 +71,7 @@ const SystemTile = ({ endpoint, token }: Props) => {
<Heading pt={0}>{endpoint.type}</Heading>
<Spacer />
<SystemLoggingButton endpoint={endpoint} token={token} />
<Button
mt={1}
minWidth="112px"
colorScheme="blue"
rightIcon={<ArrowsClockwise />}
onClick={refresh}
isLoading={isFetchingSystem || isFetchingSubsystems}
>
{t('common.refresh')}
</Button>
<RefreshButton onClick={refresh} isFetching={isFetchingSystem || isFetchingSubsystems} />
</Box>
<CardBody>
<VStack w="100%">

View File

@@ -77,7 +77,7 @@ const UserActions = ({ id, isSuspended, isWaitingForCheck, refresh, size = 'sm',
return (
<Menu>
<Tooltip label={t('commands.other')}>
<Tooltip label={t('common.actions')}>
<MenuButton
as={IconButton}
aria-label="Commands"

View File

@@ -1,11 +1,11 @@
import React from 'react';
import { AddIcon } from '@chakra-ui/icons';
import { Button, useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { useMutation } from '@tanstack/react-query';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import CreateUserForm from './Form';
import CloseButton from 'components/Buttons/CloseButton';
import CreateButton from 'components/Buttons/CreateButton';
import SaveButton from 'components/Buttons/SaveButton';
import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert';
import ModalHeader from 'components/Modals/ModalHeader';
@@ -47,16 +47,7 @@ const CreateUserModal = ({ requirements, refreshUsers }) => {
return (
<>
<Button
hidden={user?.userRole === 'CSR'}
alignItems="center"
colorScheme="blue"
rightIcon={<AddIcon />}
onClick={onOpen}
ml={2}
>
{t('crud.create')}
</Button>
{user?.userRole === 'CSR' ? null : <CreateButton onClick={onOpen} ml={2} />}
<Modal onClose={closeModal} isOpen={isOpen} size="xl" scrollBehavior="inside">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '600px', md: '700px', lg: '800px', xl: '50%' }}>

View File

@@ -7,6 +7,7 @@ import { v4 as uuid } from 'uuid';
import CreateUserModal from './CreateUserModal';
import EditUserModal from './EditUserModal';
import UserActions from './UserActions';
import RefreshButton from 'components/Buttons/RefreshButton';
import Card from 'components/Card';
import CardBody from 'components/Card/CardBody';
import CardHeader from 'components/Card/CardHeader';
@@ -145,15 +146,7 @@ const UserTable = ({ title }) => {
preference="provisioning.userTable.hiddenColumns"
/>
<CreateUserModal requirements={requirements} refreshUsers={refreshUsers} />
<Button
colorScheme="gray"
onClick={refreshUsers}
rightIcon={<ArrowsClockwise />}
ml={2}
isLoading={isFetching}
>
{t('common.refresh')}
</Button>
<RefreshButton onClick={refreshUsers} isFetching={isFetching} ml={2} />
</Box>
</Flex>
</CardHeader>

View File

@@ -79,7 +79,7 @@ const DeleteVenuePopover = ({ venue, isDisabled }) => {
<Popover isOpen={isOpen} onOpen={onOpen} onClose={onClose}>
<PopoverAnchor>
<span>
<DeleteButton onClick={onOpen} isDisabled={isDisabled} ml={2} />
<DeleteButton onClick={onOpen} isDisabled={isDisabled} />
</span>
</PopoverAnchor>
<PopoverContent>

View File

@@ -35,7 +35,6 @@ const VenueCard = ({ id }: { id: string }) => {
<SaveButton
onClick={form.submitForm}
isLoading={form.isSubmitting}
isCompact={false}
isDisabled={!editing || !form.isValid || !form.dirty}
ml={2}
/>

View File

@@ -1,6 +1,6 @@
import React, { useCallback } from 'react';
import { Button, Modal, ModalOverlay, ModalContent, ModalBody, useDisclosure } from '@chakra-ui/react';
import { Plus } from 'phosphor-react';
import { Modal, ModalOverlay, ModalContent, ModalBody, useDisclosure, Tooltip, IconButton } from '@chakra-ui/react';
import { Copy } from 'phosphor-react';
import { useTranslation } from 'react-i18next';
import { v4 as uuid } from 'uuid';
import Actions from './Actions';
@@ -38,9 +38,14 @@ const UseExistingContactModal = ({ onAssignContact, venue }: Props) => {
return (
<>
<Button type="button" colorScheme="blue" rightIcon={<Plus size={20} />} onClick={onOpen} ml={2}>
{t('venues.use_existing')}
</Button>
<Tooltip label={t('venues.use_existing')}>
<IconButton
aria-label={t('venues.use_existing')}
icon={<Copy size={20} />}
onClick={onOpen}
colorScheme="teal"
/>
</Tooltip>
<Modal initialFocusRef={undefined} onClose={onClose} isOpen={isOpen} size="xl">
<ModalOverlay />
<ModalContent maxWidth={{ sm: '90%', md: '900px', lg: '1000px', xl: '80%' }}>

View File

@@ -1,4 +1,4 @@
import { extendTheme } from '@chakra-ui/react';
import { Tooltip, extendTheme } from '@chakra-ui/react';
import CardComponent from './additions/card/Card';
import CardBodyComponent from './additions/card/CardBody';
import CardHeaderComponent from './additions/card/CardHeader';
@@ -13,19 +13,30 @@ import breakpoints from './foundations/breakpoints';
import font from './foundations/fonts';
import globalStyles from './styles';
// import { mode } from "@chakra-ui/theme-tools";
export default extendTheme(
{ breakpoints }, // Breakpoints
globalStyles,
font, // Global styles
buttonStyles, // Button styles
badgeStyles, // Badge styles
drawerStyles, // Sidebar variant for Chakra's drawer
alertStyles,
CardComponent, // Card component
CardBodyComponent, // Card Body component
CardHeaderComponent, // Card Header component
MainPanelComponent, // Main Panel component
PanelContentComponent, // Panel Content component
PanelContainerComponent, // Panel Container component
);
const config: ThemeConfig = {
initialColorMode: 'light',
useSystemColorMode: false,
};
const theme = extendTheme({
config,
font,
breakpoints,
colors: globalStyles.colors,
styles: globalStyles.styles,
components: {
Alert: alertStyles.components.Alert,
Badge: badgeStyles.components.Badge,
Button: buttonStyles.components.Button,
Drawer: drawerStyles.components.Drawer,
Card: CardComponent.components.Card,
CardBody: CardBodyComponent.components.CardBody,
CardHeader: CardHeaderComponent.components.CardHeader,
MainPanel: MainPanelComponent.components.MainPanel,
PanelContent: PanelContentComponent.components.PanelContent,
PanelContainer: PanelContainerComponent.components.PanelContainer,
},
});
Tooltip.defaultProps = { ...Tooltip.defaultProps, hasArrow: true };
export default theme;

View File

@@ -1,49 +1,9 @@
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
import { VitePWA } from 'vite-plugin-pwa';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
tsconfigPaths(),
react(),
VitePWA({
registerType: 'autoUpdate',
devOptions: {
enabled: true,
/* other options */
},
manifest: {
name: 'OpenWiFi Provisioning App',
short_name: 'OpenWiFiProvisioning',
description: 'OpenWiFi Provisioning App',
theme_color: '#000000',
icons: [
{
src: 'android-chrome-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: 'android-chrome-384x384.png',
sizes: '384x384',
type: 'image/png',
},
{
src: 'android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png',
},
{
src: 'android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable',
},
],
},
}),
],
plugins: [tsconfigPaths(), react()],
build: {
outDir: './build',
chunkSizeWarningLimit: 1000,