diff --git a/src/api/index.ts b/src/api/index.ts index 98170fd..96d9183 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -62,18 +62,15 @@ export async function handleRequestError( dispatch: AppDispatch, onErrorAction: ActionCreatorWithPayload ): Promise { - if (!(response instanceof Error)) { - const { status } = response; - if (status === 403) { - dispatch( - updateAuth({ - username: '', - password: '', - isAuthenticated: false, - error: 'Your token is no longer valid.', - }) - ); - } + if (!(response instanceof Error) && response.status === 403) { + dispatch( + updateAuth({ + username: '', + password: '', + isAuthenticated: false, + error: 'Your token is no longer valid.', + }) + ); } else { dispatch(onErrorAction(await getRequestFailMessage(response))); } diff --git a/src/components/routes/MainRoute/WebRoute/WebSections.tsx b/src/components/routes/MainRoute/WebRoute/WebSections.tsx index 119db0c..063f56f 100644 --- a/src/components/routes/MainRoute/WebRoute/WebSections.tsx +++ b/src/components/routes/MainRoute/WebRoute/WebSections.tsx @@ -1,6 +1,4 @@ -import { PivotItem, PivotLinkSize, ScreenWidthMinLarge } from '@fluentui/react'; import React, { useState } from 'react'; -import { useMediaQuery } from 'react-responsive'; import { Route, Switch, useRouteMatch } from 'react-router-dom'; import { PivotRoutes } from '../../../ui/PivotRoutes/PivotRoutes'; import { WebDomainsList } from '../../../ui/WebDomainsList/WebDomainsList'; @@ -9,21 +7,19 @@ import { WebInstructions } from '../../../ui/WebInstructions/WebInstructions'; export const WebSections: React.FunctionComponent = () => { const { path, url } = useRouteMatch(); const openedGroupsState = useState([]); - const isMinLargeScreen = useMediaQuery({ - minWidth: ScreenWidthMinLarge, - }); - const pivotProps = { - linkSize: isMinLargeScreen ? PivotLinkSize.large : PivotLinkSize.normal, - }; + const pivotItems = [ + { + itemKey: url, + headerText: 'Domains', + }, + { + itemKey: `${url}/instructions`, + headerText: 'Uploading Instructions', + }, + ]; return ( <> - - - - + diff --git a/src/components/routes/MainRoute/mail/MailUsersRoute/MailUsersSections.tsx b/src/components/routes/MainRoute/mail/MailUsersRoute/MailUsersSections.tsx index 29c35b1..168f497 100644 --- a/src/components/routes/MainRoute/mail/MailUsersRoute/MailUsersSections.tsx +++ b/src/components/routes/MainRoute/mail/MailUsersRoute/MailUsersSections.tsx @@ -1,13 +1,6 @@ -import { - MessageBar, - MessageBarType, - PivotItem, - PivotLinkSize, - ScreenWidthMinLarge, -} from '@fluentui/react'; +import { MessageBar, MessageBarType } from '@fluentui/react'; import React, { useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useMediaQuery } from 'react-responsive'; import { Route, Switch, useRouteMatch } from 'react-router-dom'; import { getUsers } from '../../../../../features/usersSlice'; import { RootState } from '../../../../../store'; @@ -26,13 +19,16 @@ export const MailUsersSections: React.FunctionComponent = () => { const dispatch = useDispatch(); - const isMinLargeScreen = useMediaQuery({ - minWidth: ScreenWidthMinLarge, - }); - - const pivotProps = { - linkSize: isMinLargeScreen ? PivotLinkSize.large : PivotLinkSize.normal, - }; + const pivotItems = [ + { + itemKey: url, + headerText: 'Mail Users', + }, + { + itemKey: `${url}/add`, + headerText: 'Add a Mail User', + }, + ]; useEffect(() => { if (!users.length) { @@ -41,10 +37,7 @@ export const MailUsersSections: React.FunctionComponent = () => { }, [dispatch, users.length]); return ( <> - - - - + diff --git a/src/components/routes/MainRoute/system/BackupsRoute/BackupsRoute.tsx b/src/components/routes/MainRoute/system/BackupsRoute/BackupsRoute.tsx index c5251e6..5dd894d 100644 --- a/src/components/routes/MainRoute/system/BackupsRoute/BackupsRoute.tsx +++ b/src/components/routes/MainRoute/system/BackupsRoute/BackupsRoute.tsx @@ -4,13 +4,13 @@ import { DialogFooter, DialogType, MessageBarType, - PivotItem, PrimaryButton, ProgressIndicator, Stack, Text, } from '@fluentui/react'; -import React, { useCallback, useEffect, useState } from 'react'; +import { useConstCallback } from '@uifabric/react-hooks'; +import React, { useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Route, Switch, useRouteMatch } from 'react-router-dom'; import { @@ -32,13 +32,23 @@ const BackupSections: React.FunctionComponent = () => { const [isDialogHidden, setIsDialogHidden] = useState(true); const { backups, unmatchedFileSize, error } = status; - const onDialogClose = useCallback( + const onDialogClose = useConstCallback( (_event: React.MouseEvent): void => { setIsDialogHidden(true); - }, - [] + } ); + const pivotItems = [ + { + itemKey: url, + headerText: 'Backup Status', + }, + { + itemKey: `${url}/config`, + headerText: 'Backup Configuration', + }, + ]; + useEffect(() => { if (error) { setIsDialogHidden(false); @@ -68,13 +78,7 @@ const BackupSections: React.FunctionComponent = () => { - - - - + {backups && backups.length > 0 && ( @@ -142,22 +146,24 @@ export const BackupsRoute: React.FunctionComponent & { ]} /> - - - The box makes an incremental backup each night. By default the backup - is stored on the machine itself, but you can also have it stored on - Amazon S3. - - - - {error && ( - - {error} - - )} - {isLoading && } - {!isLoading && !error && } - + + + + The box makes an incremental backup each night. By default the + backup is stored on the machine itself, but you can also have it + stored on Amazon S3. + + + + {error && ( + + {error} + + )} + {isLoading && } + {!isLoading && !error && } + + ); }; diff --git a/src/components/routes/MainRoute/system/CertificatesRoute/CertificatesRoute.tsx b/src/components/routes/MainRoute/system/CertificatesRoute/CertificatesRoute.tsx index 1fcba88..e29904f 100644 --- a/src/components/routes/MainRoute/system/CertificatesRoute/CertificatesRoute.tsx +++ b/src/components/routes/MainRoute/system/CertificatesRoute/CertificatesRoute.tsx @@ -1,16 +1,12 @@ import { MessageBar, MessageBarType, - PivotItem, - PivotLinkSize, ProgressIndicator, - ScreenWidthMinLarge, Stack, Text, } from '@fluentui/react'; import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useMediaQuery } from 'react-responsive'; import { Route, Switch, @@ -45,12 +41,16 @@ const CertificateSections: React.FunctionComponent = () => { const history = useHistory(); const { path, url } = useRouteMatch(); - const isMinLargeScreen = useMediaQuery({ - minWidth: ScreenWidthMinLarge, - }); - const pivotProps = { - linkSize: isMinLargeScreen ? PivotLinkSize.large : PivotLinkSize.normal, - }; + const pivotRoutes = [ + { + itemKey: url, + headerText: 'Certificate Status', + }, + { + itemKey: `${url}${SectionKeys.install}`, + headerText: 'Install Custom Certificate', + }, + ]; useEffect(() => { if (sslAction?.type === SSLActionType.install) { @@ -66,13 +66,7 @@ const CertificateSections: React.FunctionComponent = () => { return ( <> - - - - + diff --git a/src/components/routes/MainRoute/system/CustomDnsRoute/CustomDnsRoute.tsx b/src/components/routes/MainRoute/system/CustomDnsRoute/CustomDnsRoute.tsx index 2b074c0..cad68ca 100644 --- a/src/components/routes/MainRoute/system/CustomDnsRoute/CustomDnsRoute.tsx +++ b/src/components/routes/MainRoute/system/CustomDnsRoute/CustomDnsRoute.tsx @@ -1,7 +1,6 @@ import { MessageBar, MessageBarType, - PivotItem, ProgressIndicator, Stack, Text, @@ -40,6 +39,21 @@ const CustomDnsSections: React.FunctionComponent = () => { const { path, url } = useRouteMatch(); const openedGroupsState = useState([]); + const pivotItems = [ + { + itemKey: url, + headerText: 'DNS Records', + }, + { + itemKey: `${url}/add`, + headerText: 'Add Custom Record', + }, + { + itemKey: `${url}/nameserver`, + headerText: 'Secondary Nameserver', + }, + ]; + useEffect(() => { if (!zones.length) { dispatch(getZones()); @@ -57,14 +71,7 @@ const CustomDnsSections: React.FunctionComponent = () => { }, [dispatch]); return ( <> - - - - - + @@ -131,17 +138,19 @@ export const CustomDnsRoute: React.FunctionComponent & { ]} /> - - This is an advanced configuration page. - - - - It is possible to set custom DNS records on domains hosted here. - - - - - + + + This is an advanced configuration page. + + + + It is possible to set custom DNS records on domains hosted here. + + + + + + ); }; diff --git a/src/components/routes/MainRoute/system/ExternalDnsRoute/ExternalDnsRoute.tsx b/src/components/routes/MainRoute/system/ExternalDnsRoute/ExternalDnsRoute.tsx index d5694d4..59077cd 100644 --- a/src/components/routes/MainRoute/system/ExternalDnsRoute/ExternalDnsRoute.tsx +++ b/src/components/routes/MainRoute/system/ExternalDnsRoute/ExternalDnsRoute.tsx @@ -2,13 +2,14 @@ import { Link, MessageBar, MessageBarType, - PivotItem, ProgressIndicator, + ScreenWidthMinLarge, Stack, Text, } from '@fluentui/react'; import React, { useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { useMediaQuery } from 'react-responsive'; import { Route, Switch, useRouteMatch } from 'react-router-dom'; import { getDump } from '../../../../../features/dnsSlice'; import { RootState } from '../../../../../store'; @@ -22,15 +23,19 @@ import { PivotRoutes } from '../../../../ui/PivotRoutes/PivotRoutes'; const ExternalDnsSections: React.FunctionComponent = () => { const { path, url } = useRouteMatch(); const openedGroupsState = useState([]); + const pivotItems = [ + { + itemKey: url, + headerText: 'DNS Records', + }, + { + itemKey: `${url}/zone-file`, + headerText: 'Zone File Generator', + }, + ]; return ( <> - - - - + @@ -50,6 +55,9 @@ export const ExternalDnsRoute: React.FunctionComponent & { (state: RootState) => state.dns ); const dispatch = useDispatch(); + const isMinLargeScreen = useMediaQuery({ + minWidth: ScreenWidthMinLarge, + }); useEffect(() => { if (!dump.length) { @@ -74,48 +82,54 @@ export const ExternalDnsRoute: React.FunctionComponent & { ]} /> - - This is an advanced configuration page. - - - - Although your box is configured to serve its own DNS, it is possible - to host your DNS elsewhere — such as in the DNS control panel provided - by your domain name registrar or virtual cloud provider — by copying - the DNS zone information shown in the table below into your external - DNS server’s control panel. - - - If you do so, you are responsible for keeping your DNS entries up to - date! If you previously enabled DNSSEC on your domain name by setting - a DS record at your registrar, you will likely have to turn it off - before changing nameservers. - - - You may encounter zone file errors when attempting to create a TXT - record with a long string. - - RFC 4408 - {' '} - states a TXT record is allowed to contain multiple strings, and this - technique can be used to construct records that would exceed the - 255-byte maximum length. You may need to adopt this technique when - adding DomainKeys. Use a tool like - - named-checkzone - {' '} - to validate your zone file. + + + This is an advanced configuration page. - - - {getDumpError && ( - - {getDumpError} + + + Although your box is configured to serve its own DNS, it is possible + to host your DNS elsewhere — such as in the DNS control panel + provided by your domain name registrar or virtual cloud provider — + by copying the DNS zone information shown in the table below into + your external DNS server’s control panel. + + + If you do so, you are responsible for keeping your DNS entries up to + date! If you previously enabled DNSSEC on your domain name by + setting a DS record at your registrar, you will likely have to turn + it off before changing nameservers. + + + You may encounter zone file errors when attempting to create a TXT + record with a long string. + + RFC 4408 + {' '} + states a TXT record is allowed to contain multiple strings, and this + technique can be used to construct records that would exceed the + 255-byte maximum length. You may need to adopt this technique when + adding DomainKeys. Use a tool like + + named-checkzone + {' '} + to validate your zone file. - )} - {isGettingDump && } - {!isGettingDump && !getDumpError && } - + + + {getDumpError && ( + + {getDumpError} + + )} + {isGettingDump && } + {!isGettingDump && !getDumpError && } + + ); }; diff --git a/src/components/ui/ActionConfirmDialog/ActionConfirmDialog.tsx b/src/components/ui/ActionConfirmDialog/ActionConfirmDialog.tsx index 4ae788c..3a5aea0 100644 --- a/src/components/ui/ActionConfirmDialog/ActionConfirmDialog.tsx +++ b/src/components/ui/ActionConfirmDialog/ActionConfirmDialog.tsx @@ -6,7 +6,7 @@ import { PrimaryButton, Stack, } from '@fluentui/react'; -import React, { useCallback } from 'react'; +import React from 'react'; import { DialogFooter } from '../DialogFooter/DialogFooter'; import { MessageBar } from '../MessageBar/MessageBar'; import { Pre } from '../Pre/Pre'; @@ -33,18 +33,18 @@ export const ActionConfirmDialog: React.FunctionComponent< actionResponse, ...rest }) => { - const onConfirmButtonClick = useCallback(() => { + const onConfirmButtonClick = (): void => { if (!actionResponse) { onConfirm(); } else if (rest.onDismiss) { rest.onDismiss(); } - }, [actionResponse, onConfirm, rest]); - const onCancelButtonClick = useCallback(() => { + }; + const onCancelButtonClick = (): void => { if (rest.onDismiss) { rest.onDismiss(); } - }, [rest]); + }; return (