[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", "name": "wlan-cloud-owprov-ui",
"version": "2.9.0(16)", "version": "2.9.0(18)",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "wlan-cloud-owprov-ui", "name": "wlan-cloud-owprov-ui",
"version": "2.9.0(16)", "version": "2.9.0(18)",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@chakra-ui/icons": "^2.0.11", "@chakra-ui/icons": "^2.0.11",

View File

@@ -1,6 +1,6 @@
{ {
"name": "wlan-cloud-owprov-ui", "name": "wlan-cloud-owprov-ui",
"version": "2.9.0(16)", "version": "2.9.0(18)",
"description": "", "description": "",
"main": "index.tsx", "main": "index.tsx",
"scripts": { "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 = { const defaultProps = {
isDisabled: false, isDisabled: false,
isLoading: false, isLoading: false,
isCompact: false, isCompact: true,
label: undefined, label: undefined,
}; };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -149,12 +149,6 @@ const EditTagModal = ({
title={t('crud.edit_obj', { obj: tag?.name ?? tag?.serialNumber })} title={t('crud.edit_obj', { obj: tag?.name ?? tag?.serialNumber })}
right={ 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}> <Popover isOpen={isDeleteOpen} onOpen={onDeleteOpen} onClose={onDeleteClose}>
<Tooltip hasArrow label={t('crud.delete')} placement="top" isDisabled={isDeleteOpen}> <Tooltip hasArrow label={t('crud.delete')} placement="top" isDisabled={isDeleteOpen}>
<Box> <Box>
@@ -208,6 +202,13 @@ const EditTagModal = ({
onClick={handlePushConfig} onClick={handlePushConfig}
/> />
</Tooltip> </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 /> <EditButton ml={2} isDisabled={editing} onClick={setEditing.toggle} isCompact />
<CloseButton ml={2} onClick={closeModal} /> <CloseButton ml={2} onClick={closeModal} />
</> </>

View File

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

View File

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

View File

@@ -1,14 +1,13 @@
import React from 'react'; import React from 'react';
import { AddIcon } from '@chakra-ui/icons'; import { Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { Button, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import CreateSubscriberForm from './Form'; import CreateSubscriberForm from './Form';
import CloseButton from 'components/Buttons/CloseButton'; import CloseButton from 'components/Buttons/CloseButton';
import CreateButton from 'components/Buttons/CreateButton';
import SaveButton from 'components/Buttons/SaveButton'; import SaveButton from 'components/Buttons/SaveButton';
import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert'; import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert';
import ModalHeader from 'components/Modals/ModalHeader'; import ModalHeader from 'components/Modals/ModalHeader';
import { useAuth } from 'contexts/AuthProvider';
import useFormModal from 'hooks/useFormModal'; import useFormModal from 'hooks/useFormModal';
import useFormRef from 'hooks/useFormRef'; import useFormRef from 'hooks/useFormRef';
@@ -18,7 +17,6 @@ const propTypes = {
}; };
const CreateSubscriberModal = ({ refresh, operatorId }) => { const CreateSubscriberModal = ({ refresh, operatorId }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { user } = useAuth();
const { form, formRef } = useFormRef(); const { form, formRef } = useFormRef();
const { isOpen, isConfirmOpen, onOpen, closeConfirm, closeModal, closeCancelAndForm } = useFormModal({ const { isOpen, isConfirmOpen, onOpen, closeConfirm, closeModal, closeCancelAndForm } = useFormModal({
isDirty: form?.dirty, isDirty: form?.dirty,
@@ -26,16 +24,7 @@ const CreateSubscriberModal = ({ refresh, operatorId }) => {
return ( return (
<> <>
<Button <CreateButton onClick={onOpen} ml={2} />
hidden={user?.userRole === 'CSR'}
alignItems="center"
colorScheme="blue"
rightIcon={<AddIcon />}
onClick={onOpen}
ml={2}
>
{t('crud.create')}
</Button>
<Modal onClose={closeModal} isOpen={isOpen} size="xl"> <Modal onClose={closeModal} isOpen={isOpen} size="xl">
<ModalOverlay /> <ModalOverlay />
<ModalContent maxWidth={{ sm: '600px', md: '700px', lg: '800px', xl: '50%' }}> <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" definitionKey="interface.ipv4.dhcp-lease.macaddr"
isRequired isRequired
w="220px" 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} mr={4}
/> />
<StaticLeaseOffsetField subnet={ipv4?.subnet} /> <StaticLeaseOffsetField subnet={ipv4?.subnet} />
@@ -122,7 +134,7 @@ const DhcpIpV4 = ({ namePrefix, isDisabled }: Props) => {
isRequired isRequired
options={{ options={{
modalTitle: 'Reserved Addresses', modalTitle: 'Reserved Addresses',
buttonLabel: 'Reserved Addresses', buttonLabel: 'Manage Reserved Addresses',
onFormSubmit: (v: { onFormSubmit: (v: {
__temp_ip?: string; __temp_ip?: string;
secondMacAddress: string; secondMacAddress: string;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,19 @@
import * as React from 'react'; 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 { Download } from 'phosphor-react';
import { CSVLink } from 'react-csv'; import { CSVLink } from 'react-csv';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -131,9 +145,9 @@ const FmsLogsCard = () => {
filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`} filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`}
data={downloadableLogs as object[]} data={downloadableLogs as object[]}
> >
<Button onClick={() => {}} colorScheme="blue" leftIcon={<Download />}> <Tooltip label={t('logs.export')} hasArrow>
{t('logs.export')} <IconButton aria-label={t('logs.export')} icon={<Download />} colorScheme="blue" />
</Button> </Tooltip>
</CSVLink> </CSVLink>
</HStack> </HStack>
</CardHeader> </CardHeader>

View File

@@ -1,5 +1,19 @@
import * as React from 'react'; 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 { Download } from 'phosphor-react';
import { CSVLink } from 'react-csv'; import { CSVLink } from 'react-csv';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -134,9 +148,9 @@ const GeneralLogsCard = () => {
filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`} filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`}
data={downloadableLogs as object[]} data={downloadableLogs as object[]}
> >
<Button onClick={() => {}} colorScheme="blue" leftIcon={<Download />}> <Tooltip label={t('logs.export')} hasArrow>
{t('logs.export')} <IconButton aria-label={t('logs.export')} icon={<Download />} colorScheme="blue" />
</Button> </Tooltip>
</CSVLink> </CSVLink>
</HStack> </HStack>
</CardHeader> </CardHeader>

View File

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

View File

@@ -1,5 +1,19 @@
import * as React from 'react'; 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 { Download } from 'phosphor-react';
import { CSVLink } from 'react-csv'; import { CSVLink } from 'react-csv';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -131,9 +145,9 @@ const SecLogsCard = () => {
filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`} filename={`logs_${dateForFilename(new Date().getTime() / 1000)}.csv`}
data={downloadableLogs as object[]} data={downloadableLogs as object[]}
> >
<Button onClick={() => {}} colorScheme="blue" leftIcon={<Download />}> <Tooltip label={t('logs.export')} hasArrow>
{t('logs.export')} <IconButton aria-label={t('logs.export')} icon={<Download />} colorScheme="blue" />
</Button> </Tooltip>
</CSVLink> </CSVLink>
</HStack> </HStack>
</CardHeader> </CardHeader>

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
import * as React from 'react'; 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 { useTranslation } from 'react-i18next';
import SystemLoggingModal from './Modal'; import SystemLoggingModal from './Modal';
import { EndpointApiResponse } from 'hooks/Network/Endpoints'; import { EndpointApiResponse } from 'hooks/Network/Endpoints';
@@ -15,9 +16,17 @@ const SystemLoggingButton = ({ endpoint, token }: Props) => {
return ( return (
<> <>
<Button colorScheme="teal" onClick={modalProps.onOpen} mr={2} my="auto"> <Tooltip label={t('system.logging')} hasArrow>
{t('system.logging')} <IconButton
</Button> 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} /> <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 { useTranslation } from 'react-i18next';
import SystemLoggingButton from './LoggingButton'; import SystemLoggingButton from './LoggingButton';
import SystemCertificatesTable from './SystemCertificatesTable'; import SystemCertificatesTable from './SystemCertificatesTable';
import RefreshButton from 'components/Buttons/RefreshButton';
import Card from 'components/Card'; import Card from 'components/Card';
import CardBody from 'components/Card/CardBody'; import CardBody from 'components/Card/CardBody';
import FormattedDate from 'components/FormattedDate'; import FormattedDate from 'components/FormattedDate';
@@ -70,16 +71,7 @@ const SystemTile = ({ endpoint, token }: Props) => {
<Heading pt={0}>{endpoint.type}</Heading> <Heading pt={0}>{endpoint.type}</Heading>
<Spacer /> <Spacer />
<SystemLoggingButton endpoint={endpoint} token={token} /> <SystemLoggingButton endpoint={endpoint} token={token} />
<Button <RefreshButton onClick={refresh} isFetching={isFetchingSystem || isFetchingSubsystems} />
mt={1}
minWidth="112px"
colorScheme="blue"
rightIcon={<ArrowsClockwise />}
onClick={refresh}
isLoading={isFetchingSystem || isFetchingSubsystems}
>
{t('common.refresh')}
</Button>
</Box> </Box>
<CardBody> <CardBody>
<VStack w="100%"> <VStack w="100%">

View File

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

View File

@@ -1,11 +1,11 @@
import React from 'react'; import React from 'react';
import { AddIcon } from '@chakra-ui/icons'; import { useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { Button, useDisclosure, Modal, ModalOverlay, ModalContent, ModalBody } from '@chakra-ui/react';
import { useMutation } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import CreateUserForm from './Form'; import CreateUserForm from './Form';
import CloseButton from 'components/Buttons/CloseButton'; import CloseButton from 'components/Buttons/CloseButton';
import CreateButton from 'components/Buttons/CreateButton';
import SaveButton from 'components/Buttons/SaveButton'; import SaveButton from 'components/Buttons/SaveButton';
import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert'; import ConfirmCloseAlert from 'components/Modals/Actions/ConfirmCloseAlert';
import ModalHeader from 'components/Modals/ModalHeader'; import ModalHeader from 'components/Modals/ModalHeader';
@@ -47,16 +47,7 @@ const CreateUserModal = ({ requirements, refreshUsers }) => {
return ( return (
<> <>
<Button {user?.userRole === 'CSR' ? null : <CreateButton onClick={onOpen} ml={2} />}
hidden={user?.userRole === 'CSR'}
alignItems="center"
colorScheme="blue"
rightIcon={<AddIcon />}
onClick={onOpen}
ml={2}
>
{t('crud.create')}
</Button>
<Modal onClose={closeModal} isOpen={isOpen} size="xl" scrollBehavior="inside"> <Modal onClose={closeModal} isOpen={isOpen} size="xl" scrollBehavior="inside">
<ModalOverlay /> <ModalOverlay />
<ModalContent maxWidth={{ sm: '600px', md: '700px', lg: '800px', xl: '50%' }}> <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 CreateUserModal from './CreateUserModal';
import EditUserModal from './EditUserModal'; import EditUserModal from './EditUserModal';
import UserActions from './UserActions'; import UserActions from './UserActions';
import RefreshButton from 'components/Buttons/RefreshButton';
import Card from 'components/Card'; import Card from 'components/Card';
import CardBody from 'components/Card/CardBody'; import CardBody from 'components/Card/CardBody';
import CardHeader from 'components/Card/CardHeader'; import CardHeader from 'components/Card/CardHeader';
@@ -145,15 +146,7 @@ const UserTable = ({ title }) => {
preference="provisioning.userTable.hiddenColumns" preference="provisioning.userTable.hiddenColumns"
/> />
<CreateUserModal requirements={requirements} refreshUsers={refreshUsers} /> <CreateUserModal requirements={requirements} refreshUsers={refreshUsers} />
<Button <RefreshButton onClick={refreshUsers} isFetching={isFetching} ml={2} />
colorScheme="gray"
onClick={refreshUsers}
rightIcon={<ArrowsClockwise />}
ml={2}
isLoading={isFetching}
>
{t('common.refresh')}
</Button>
</Box> </Box>
</Flex> </Flex>
</CardHeader> </CardHeader>

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { Button, Modal, ModalOverlay, ModalContent, ModalBody, useDisclosure } from '@chakra-ui/react'; import { Modal, ModalOverlay, ModalContent, ModalBody, useDisclosure, Tooltip, IconButton } from '@chakra-ui/react';
import { Plus } from 'phosphor-react'; import { Copy } from 'phosphor-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import Actions from './Actions'; import Actions from './Actions';
@@ -38,9 +38,14 @@ const UseExistingContactModal = ({ onAssignContact, venue }: Props) => {
return ( return (
<> <>
<Button type="button" colorScheme="blue" rightIcon={<Plus size={20} />} onClick={onOpen} ml={2}> <Tooltip label={t('venues.use_existing')}>
{t('venues.use_existing')} <IconButton
</Button> aria-label={t('venues.use_existing')}
icon={<Copy size={20} />}
onClick={onOpen}
colorScheme="teal"
/>
</Tooltip>
<Modal initialFocusRef={undefined} onClose={onClose} isOpen={isOpen} size="xl"> <Modal initialFocusRef={undefined} onClose={onClose} isOpen={isOpen} size="xl">
<ModalOverlay /> <ModalOverlay />
<ModalContent maxWidth={{ sm: '90%', md: '900px', lg: '1000px', xl: '80%' }}> <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 CardComponent from './additions/card/Card';
import CardBodyComponent from './additions/card/CardBody'; import CardBodyComponent from './additions/card/CardBody';
import CardHeaderComponent from './additions/card/CardHeader'; import CardHeaderComponent from './additions/card/CardHeader';
@@ -13,19 +13,30 @@ import breakpoints from './foundations/breakpoints';
import font from './foundations/fonts'; import font from './foundations/fonts';
import globalStyles from './styles'; import globalStyles from './styles';
// import { mode } from "@chakra-ui/theme-tools"; const config: ThemeConfig = {
export default extendTheme( initialColorMode: 'light',
{ breakpoints }, // Breakpoints useSystemColorMode: false,
globalStyles, };
font, // Global styles
buttonStyles, // Button styles const theme = extendTheme({
badgeStyles, // Badge styles config,
drawerStyles, // Sidebar variant for Chakra's drawer font,
alertStyles, breakpoints,
CardComponent, // Card component colors: globalStyles.colors,
CardBodyComponent, // Card Body component styles: globalStyles.styles,
CardHeaderComponent, // Card Header component components: {
MainPanelComponent, // Main Panel component Alert: alertStyles.components.Alert,
PanelContentComponent, // Panel Content component Badge: badgeStyles.components.Badge,
PanelContainerComponent, // Panel Container component 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 { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths'; import tsconfigPaths from 'vite-tsconfig-paths';
import { VitePWA } from 'vite-plugin-pwa';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [tsconfigPaths(), react()],
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',
},
],
},
}),
],
build: { build: {
outDir: './build', outDir: './build',
chunkSizeWarningLimit: 1000, chunkSizeWarningLimit: 1000,