Merge pull request #567 from ylei-tsubame/correct-webui-deps

Web UI: correct UI's NPM dependencies after upgrading `nextjs`
main
Yanhao Lei 11 months ago committed by GitHub
commit 00ccddba9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      striker-ui/components/Files/AddFileForm.tsx
  2. 9
      striker-ui/components/Files/ManageFilePanel.tsx
  3. 11
      striker-ui/components/GateForm.tsx
  4. 12
      striker-ui/components/IconWithIndicator.tsx
  5. 3
      striker-ui/components/JobSummary.tsx
  6. 11
      striker-ui/components/ManageFence/ManageFencePanel.tsx
  7. 23
      striker-ui/components/ManageManifest/ManageManifestPanel.tsx
  8. 8
      striker-ui/components/ManageUps/ManageUpsPanel.tsx
  9. 7
      striker-ui/components/Network/Network.tsx
  10. 13
      striker-ui/components/PrepareHostForm.tsx
  11. 19
      striker-ui/components/PrepareNetworkForm.tsx
  12. 3
      striker-ui/components/StrikerConfig/AddPeerDialog.tsx
  13. 20
      striker-ui/components/StrikerConfig/ConfigPeersForm.tsx
  14. 17
      striker-ui/components/StrikerConfig/ManageChangedSSHKeysForm.tsx
  15. 7
      striker-ui/components/StrikerConfig/ManageUsersForm.tsx
  16. 11
      striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx
  17. 5
      striker-ui/components/StrikerInitForm.tsx
  18. 5
      striker-ui/hooks/useActiveFetch.ts
  19. 3
      striker-ui/hooks/useFormUtils.ts
  20. 30
      striker-ui/hooks/useProtect.ts
  21. 34
      striker-ui/hooks/useProtectedState.ts
  22. 2054
      striker-ui/package-lock.json
  23. 16
      striker-ui/package.json
  24. 11
      striker-ui/pages/config/index.tsx
  25. 8
      striker-ui/pages/manage-element/index.tsx

@ -6,6 +6,7 @@ import {
useCallback, useCallback,
useMemo, useMemo,
useRef, useRef,
useState,
} from 'react'; } from 'react';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
@ -20,7 +21,6 @@ import MessageBox from '../MessageBox';
import MessageGroup from '../MessageGroup'; import MessageGroup from '../MessageGroup';
import fileListSchema from './schema'; import fileListSchema from './schema';
import UploadFileProgress from './UploadFileProgress'; import UploadFileProgress from './UploadFileProgress';
import useProtectedState from '../../hooks/useProtectedState';
const REQUEST_INCOMPLETE_UPLOAD_LIMIT = 99; const REQUEST_INCOMPLETE_UPLOAD_LIMIT = 99;
@ -41,9 +41,7 @@ const AddFileForm: FC<AddFileFormProps> = (props) => {
const filePickerRef = useRef<HTMLInputElement>(null); const filePickerRef = useRef<HTMLInputElement>(null);
const [uploads, setUploads] = useProtectedState<UploadFiles | undefined>( const [uploads, setUploads] = useState<UploadFiles | undefined>();
undefined,
);
const formik = useFormik<FileFormikValues>({ const formik = useFormik<FileFormikValues>({
initialValues: {}, initialValues: {},

@ -22,7 +22,6 @@ import useActiveFetch from '../../hooks/useActiveFetch';
import useChecklist from '../../hooks/useChecklist'; import useChecklist from '../../hooks/useChecklist';
import useConfirmDialogProps from '../../hooks/useConfirmDialogProps'; import useConfirmDialogProps from '../../hooks/useConfirmDialogProps';
import useFetch from '../../hooks/useFetch'; import useFetch from '../../hooks/useFetch';
import useProtectedState from '../../hooks/useProtectedState';
const toFileOverviewList = (rows: string[][]) => const toFileOverviewList = (rows: string[][]) =>
rows.reduce<APIFileOverviewList>((previous, row) => { rows.reduce<APIFileOverviewList>((previous, row) => {
@ -115,12 +114,8 @@ const ManageFilePanel: FC = () => {
const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps(); const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps();
const [edit, setEdit] = useState<boolean>(false); const [edit, setEdit] = useState<boolean>(false);
const [file, setFile] = useProtectedState<APIFileDetail | undefined>( const [file, setFile] = useState<APIFileDetail | undefined>();
undefined, const [files, setFiles] = useState<APIFileOverviewList | undefined>();
);
const [files, setFiles] = useProtectedState<APIFileOverviewList | undefined>(
undefined,
);
const { isLoading: loadingFilesPeriodic } = periodicFetch<string[][]>( const { isLoading: loadingFilesPeriodic } = periodicFetch<string[][]>(
`${API_BASE_URL}/file`, `${API_BASE_URL}/file`,

@ -1,5 +1,11 @@
import { Box, BoxProps, SxProps, Theme } from '@mui/material'; import { Box, BoxProps, SxProps, Theme } from '@mui/material';
import { forwardRef, useImperativeHandle, useMemo, useRef } from 'react'; import {
forwardRef,
useImperativeHandle,
useMemo,
useRef,
useState,
} from 'react';
import INPUT_TYPES from '../lib/consts/INPUT_TYPES'; import INPUT_TYPES from '../lib/consts/INPUT_TYPES';
@ -12,7 +18,6 @@ import OutlinedInputWithLabel from './OutlinedInputWithLabel';
import Spinner from './Spinner'; import Spinner from './Spinner';
import { buildPeacefulStringTestBatch } from '../lib/test_input'; import { buildPeacefulStringTestBatch } from '../lib/test_input';
import useFormUtils from '../hooks/useFormUtils'; import useFormUtils from '../hooks/useFormUtils';
import useProtectedState from '../hooks/useProtectedState';
const INPUT_ROOT_SX: SxProps<Theme> = { width: '100%' }; const INPUT_ROOT_SX: SxProps<Theme> = { width: '100%' };
@ -67,7 +72,7 @@ const GateForm = forwardRef<GateFormForwardedRefContent, GateFormProps>(
const inputPassphraseRef = useRef<InputForwardedRefContent<'string'>>({}); const inputPassphraseRef = useRef<InputForwardedRefContent<'string'>>({});
const messageGroupRef = useRef<MessageGroupForwardedRefContent>({}); const messageGroupRef = useRef<MessageGroupForwardedRefContent>({});
const [isSubmitting, setIsSubmitting] = useProtectedState<boolean>(false); const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
const formUtils = useFormUtils( const formUtils = useFormUtils(
[INPUT_ID_GATE_ID, INPUT_ID_GATE_PASSPHRASE], [INPUT_ID_GATE_ID, INPUT_ID_GATE_PASSPHRASE],

@ -11,14 +11,13 @@ import {
useCallback, useCallback,
useImperativeHandle, useImperativeHandle,
useMemo, useMemo,
useState,
} from 'react'; } from 'react';
import { BLACK, BLUE } from '../lib/consts/DEFAULT_THEME'; import { BLACK, BLUE } from '../lib/consts/DEFAULT_THEME';
import FlexBox, { FlexBoxProps } from './FlexBox'; import FlexBox, { FlexBoxProps } from './FlexBox';
import { BodyText, BodyTextProps } from './Text'; import { BodyText, BodyTextProps } from './Text';
import useProtect from '../hooks/useProtect';
import useProtectedState from '../hooks/useProtectedState';
type IndicatorValue = boolean | number; type IndicatorValue = boolean | number;
@ -79,10 +78,9 @@ const IconWithIndicator = forwardRef<
}, },
ref, ref,
) => { ) => {
const { protect } = useProtect(); const [indicatorValue, setIndicatorValue] = useState<boolean | number>(
const [indicatorValue, setIndicatorValue] = useProtectedState< initialIndicatorValue,
boolean | number );
>(initialIndicatorValue, protect);
const buildIndicator = useCallback( const buildIndicator = useCallback(
( (
@ -127,7 +125,7 @@ const IconWithIndicator = forwardRef<
...indicatorTextSx, ...indicatorTextSx,
}} }}
> >
{value > INDICATOR_MAX ? `${INDICATOR_MAX}+` : value} {Number(value) > INDICATOR_MAX ? `${INDICATOR_MAX}+` : value}
</BodyText> </BodyText>
), ),
[indicatorTextSx, restIndicatorTextProps], [indicatorTextSx, restIndicatorTextProps],

@ -8,7 +8,6 @@ import FlexBox from './FlexBox';
import List from './List'; import List from './List';
import periodicFetch from '../lib/fetchers/periodicFetch'; import periodicFetch from '../lib/fetchers/periodicFetch';
import { BodyText } from './Text'; import { BodyText } from './Text';
import useProtectedState from '../hooks/useProtectedState';
type AnvilJobs = { type AnvilJobs = {
[jobUUID: string]: { [jobUUID: string]: {
@ -58,7 +57,7 @@ const JobSummary = forwardRef<JobSummaryForwardedRefContent, JobSummaryProps>(
}, },
ref, ref,
) => { ) => {
const [anvilJobs, setAnvilJobs] = useProtectedState<AnvilJobs>({}); const [anvilJobs, setAnvilJobs] = useState<AnvilJobs>({});
const [isOpenJobSummary, setIsOpenJobSummary] = const [isOpenJobSummary, setIsOpenJobSummary] =
useState<boolean>(openInitially); useState<boolean>(openInitially);
const [menuAnchorElement, setMenuAnchorElement] = useState< const [menuAnchorElement, setMenuAnchorElement] = useState<

@ -29,7 +29,6 @@ import useChecklist from '../../hooks/useChecklist';
import useConfirmDialogProps from '../../hooks/useConfirmDialogProps'; import useConfirmDialogProps from '../../hooks/useConfirmDialogProps';
import useFormUtils from '../../hooks/useFormUtils'; import useFormUtils from '../../hooks/useFormUtils';
import useIsFirstRender from '../../hooks/useIsFirstRender'; import useIsFirstRender from '../../hooks/useIsFirstRender';
import useProtectedState from '../../hooks/useProtectedState';
type FenceFormData = { type FenceFormData = {
agent: string; agent: string;
@ -130,15 +129,15 @@ const ManageFencePanel: FC = () => {
const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps(); const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps();
const [formDialogProps, setFormDialogProps] = useConfirmDialogProps(); const [formDialogProps, setFormDialogProps] = useConfirmDialogProps();
const [fenceOverviews, setFenceOverviews] = useProtectedState< const [fenceOverviews, setFenceOverviews] = useState<
APIFenceOverview | undefined APIFenceOverview | undefined
>(undefined); >();
const [fenceTemplate, setFenceTemplate] = useProtectedState< const [fenceTemplate, setFenceTemplate] = useState<
APIFenceTemplate | undefined APIFenceTemplate | undefined
>(undefined); >();
const [isEditFences, setIsEditFences] = useState<boolean>(false); const [isEditFences, setIsEditFences] = useState<boolean>(false);
const [isLoadingFenceTemplate, setIsLoadingFenceTemplate] = const [isLoadingFenceTemplate, setIsLoadingFenceTemplate] =
useProtectedState<boolean>(true); useState<boolean>(true);
const { isLoading: isFenceOverviewsLoading } = const { isLoading: isFenceOverviewsLoading } =
periodicFetch<APIFenceOverview>(`${API_BASE_URL}/fence`, { periodicFetch<APIFenceOverview>(`${API_BASE_URL}/fence`, {

@ -45,7 +45,6 @@ import useChecklist from '../../hooks/useChecklist';
import useConfirmDialogProps from '../../hooks/useConfirmDialogProps'; import useConfirmDialogProps from '../../hooks/useConfirmDialogProps';
import useFormUtils from '../../hooks/useFormUtils'; import useFormUtils from '../../hooks/useFormUtils';
import useIsFirstRender from '../../hooks/useIsFirstRender'; import useIsFirstRender from '../../hooks/useIsFirstRender';
import useProtectedState from '../../hooks/useProtectedState';
const REQ_BODY_MAX_DEPTH = 6; const REQ_BODY_MAX_DEPTH = 6;
@ -155,25 +154,25 @@ const ManageManifestPanel: FC = () => {
const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps(); const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps();
const [hostOverviews, setHostOverviews] = useProtectedState< const [hostOverviews, setHostOverviews] = useState<
APIHostOverviewList | undefined APIHostOverviewList | undefined
>(undefined); >();
const [isEditManifests, setIsEditManifests] = useState<boolean>(false); const [isEditManifests, setIsEditManifests] = useState<boolean>(false);
const [isLoadingHostOverviews, setIsLoadingHostOverviews] = const [isLoadingHostOverviews, setIsLoadingHostOverviews] =
useProtectedState<boolean>(true); useState<boolean>(true);
const [isLoadingManifestDetail, setIsLoadingManifestDetail] = const [isLoadingManifestDetail, setIsLoadingManifestDetail] =
useProtectedState<boolean>(true); useState<boolean>(true);
const [isLoadingManifestTemplate, setIsLoadingManifestTemplate] = const [isLoadingManifestTemplate, setIsLoadingManifestTemplate] =
useProtectedState<boolean>(true); useState<boolean>(true);
const [manifestOverviews, setManifestOverviews] = useProtectedState< const [manifestOverviews, setManifestOverviews] = useState<
APIManifestOverviewList | undefined APIManifestOverviewList | undefined
>(undefined); >();
const [manifestDetail, setManifestDetail] = useProtectedState< const [manifestDetail, setManifestDetail] = useState<
APIManifestDetail | undefined APIManifestDetail | undefined
>(undefined); >();
const [manifestTemplate, setManifestTemplate] = useProtectedState< const [manifestTemplate, setManifestTemplate] = useState<
APIManifestTemplate | undefined APIManifestTemplate | undefined
>(undefined); >();
const { isLoading: isLoadingManifestOverviews } = const { isLoading: isLoadingManifestOverviews } =
periodicFetch<APIManifestOverviewList>(`${API_BASE_URL}/manifest`, { periodicFetch<APIManifestOverviewList>(`${API_BASE_URL}/manifest`, {

@ -27,7 +27,6 @@ import useChecklist from '../../hooks/useChecklist';
import useConfirmDialogProps from '../../hooks/useConfirmDialogProps'; import useConfirmDialogProps from '../../hooks/useConfirmDialogProps';
import useFormUtils from '../../hooks/useFormUtils'; import useFormUtils from '../../hooks/useFormUtils';
import useIsFirstRender from '../../hooks/useIsFirstRender'; import useIsFirstRender from '../../hooks/useIsFirstRender';
import useProtectedState from '../../hooks/useProtectedState';
type UpsFormData = { type UpsFormData = {
agent: string; agent: string;
@ -115,12 +114,11 @@ const ManageUpsPanel: FC = () => {
const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps(); const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps();
const [formDialogProps, setFormDialogProps] = useConfirmDialogProps(); const [formDialogProps, setFormDialogProps] = useConfirmDialogProps();
const [isEditUpses, setIsEditUpses] = useState<boolean>(false); const [isEditUpses, setIsEditUpses] = useState<boolean>(false);
const [isLoadingUpsTemplate, setIsLoadingUpsTemplate] = const [isLoadingUpsTemplate, setIsLoadingUpsTemplate] =
useProtectedState<boolean>(true); useState<boolean>(true);
const [upsTemplate, setUpsTemplate] = useProtectedState< const [upsTemplate, setUpsTemplate] = useState<APIUpsTemplate | undefined>();
APIUpsTemplate | undefined
>(undefined);
const { data: upsOverviews, isLoading: isUpsOverviewLoading } = const { data: upsOverviews, isLoading: isUpsOverviewLoading } =
periodicFetch<APIUpsOverview>(`${API_BASE_URL}/ups`, { periodicFetch<APIUpsOverview>(`${API_BASE_URL}/ups`, {

@ -1,5 +1,5 @@
import { Box, Divider, styled } from '@mui/material'; import { Box, Divider, styled } from '@mui/material';
import { useContext } from 'react'; import { useContext, useState } from 'react';
import API_BASE_URL from '../../lib/consts/API_BASE_URL'; import API_BASE_URL from '../../lib/consts/API_BASE_URL';
import { import {
@ -14,7 +14,6 @@ import periodicFetch from '../../lib/fetchers/periodicFetch';
import processNetworkData from './processNetwork'; import processNetworkData from './processNetwork';
import Spinner from '../Spinner'; import Spinner from '../Spinner';
import { HeaderText, BodyText } from '../Text'; import { HeaderText, BodyText } from '../Text';
import useProtectedState from '../../hooks/useProtectedState';
const PREFIX = 'Network'; const PREFIX = 'Network';
@ -72,9 +71,7 @@ const selectDecorator = (state: string): Colours => {
const Network = (): JSX.Element => { const Network = (): JSX.Element => {
const { uuid } = useContext(AnvilContext); const { uuid } = useContext(AnvilContext);
const [processed, setProcessed] = useProtectedState< const [processed, setProcessed] = useState<ProcessedNetwork | undefined>();
ProcessedNetwork | undefined
>(undefined);
const { isLoading } = periodicFetch<AnvilNetwork>( const { isLoading } = periodicFetch<AnvilNetwork>(
`${API_BASE_URL}/anvil/${uuid}/network`, `${API_BASE_URL}/anvil/${uuid}/network`,

@ -31,8 +31,6 @@ import { Panel, PanelHeader } from './Panels';
import RadioGroupWithLabel from './RadioGroupWithLabel'; import RadioGroupWithLabel from './RadioGroupWithLabel';
import Spinner from './Spinner'; import Spinner from './Spinner';
import { BodyText, HeaderText, MonoText } from './Text'; import { BodyText, HeaderText, MonoText } from './Text';
import useProtect from '../hooks/useProtect';
import useProtectedState from '../hooks/useProtectedState';
const ENTERPRISE_KEY_LABEL = 'Alteeve enterprise key'; const ENTERPRISE_KEY_LABEL = 'Alteeve enterprise key';
const HOST_IP_LABEL = 'Host IP address'; const HOST_IP_LABEL = 'Host IP address';
@ -55,8 +53,6 @@ const GRID_COLUMNS: Exclude<GridProps['columns'], undefined> = {
const GRID_SPACING: Exclude<GridProps['spacing'], undefined> = '1em'; const GRID_SPACING: Exclude<GridProps['spacing'], undefined> = '1em';
const PrepareHostForm: FC = () => { const PrepareHostForm: FC = () => {
const { protect } = useProtect();
const confirmDialogRef = useRef<ConfirmDialogForwardedRefContent>({}); const confirmDialogRef = useRef<ConfirmDialogForwardedRefContent>({});
const inputEnterpriseKeyRef = useRef<InputForwardedRefContent<'string'>>({}); const inputEnterpriseKeyRef = useRef<InputForwardedRefContent<'string'>>({});
const inputHostNameRef = useRef<InputForwardedRefContent<'string'>>({}); const inputHostNameRef = useRef<InputForwardedRefContent<'string'>>({});
@ -77,13 +73,10 @@ const PrepareHostForm: FC = () => {
const [connectedHostIPAddress, setConnectedHostIPAddress] = useState< const [connectedHostIPAddress, setConnectedHostIPAddress] = useState<
string | undefined string | undefined
>(); >();
const [connectedHostPassword, setConnectedHostPassword] = useProtectedState< const [connectedHostPassword, setConnectedHostPassword] = useState<
string | undefined string | undefined
>(undefined, protect); >();
const [connectedHostUUID, setConnectedHostUUID] = useProtectedState<string>( const [connectedHostUUID, setConnectedHostUUID] = useState<string>('');
'',
protect,
);
const [inputHostType, setInputHostType] = useState<string>(''); const [inputHostType, setInputHostType] = useState<string>('');
const [isInputEnterpriseKeyValid, setIsInputEnterpriseKeyValid] = const [isInputEnterpriseKeyValid, setIsInputEnterpriseKeyValid] =
useState<boolean>(true); useState<boolean>(true);

@ -1,5 +1,5 @@
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { FC, useCallback, useEffect, useMemo, useRef } from 'react'; import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import api from '../lib/api'; import api from '../lib/api';
import ConfirmDialog from './ConfirmDialog'; import ConfirmDialog from './ConfirmDialog';
@ -22,7 +22,6 @@ import { buildPeacefulStringTestBatch } from '../lib/test_input';
import { HeaderText } from './Text'; import { HeaderText } from './Text';
import useConfirmDialogProps from '../hooks/useConfirmDialogProps'; import useConfirmDialogProps from '../hooks/useConfirmDialogProps';
import useFormUtils from '../hooks/useFormUtils'; import useFormUtils from '../hooks/useFormUtils';
import useProtectedState from '../hooks/useProtectedState';
const INPUT_ID_PREP_NET_HOST_NAME = 'prepare-network-host-name-input'; const INPUT_ID_PREP_NET_HOST_NAME = 'prepare-network-host-name-input';
@ -107,16 +106,14 @@ const PrepareNetworkForm: FC<PrepareNetworkFormProps> = ({
const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps(); const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps();
const [hostDetail, setHostDetail] = useProtectedState< const [hostDetail, setHostDetail] = useState<APIHostDetail | undefined>();
APIHostDetail | undefined const [fatalErrorMessage, setFatalErrorMessage] = useState<
>(undefined);
const [fatalErrorMessage, setFatalErrorMessage] = useProtectedState<
Message | undefined Message | undefined
>(undefined); >();
const [isLoadingHostDetail, setIsLoadingHostDetail] = const [isLoadingHostDetail, setIsLoadingHostDetail] = useState<boolean>(true);
useProtectedState<boolean>(true); const [previousHostUUID, setPreviousHostUUID] = useState<
const [previousHostUUID, setPreviousHostUUID] = string | undefined
useProtectedState<PrepareNetworkFormProps['hostUUID']>(undefined); >();
const { const {
buildFinishInputTestBatchFunction, buildFinishInputTestBatchFunction,

@ -27,7 +27,6 @@ import {
buildPeacefulStringTestBatch, buildPeacefulStringTestBatch,
} from '../../lib/test_input'; } from '../../lib/test_input';
import { HeaderText } from '../Text'; import { HeaderText } from '../Text';
import useProtectedState from '../../hooks/useProtectedState';
const IT_IDS = { const IT_IDS = {
dbPort: 'dbPort', dbPort: 'dbPort',
@ -61,7 +60,7 @@ const AddPeerDialog = forwardRef<
}>({}); }>({});
const [isEnablePingTest, setIsEnablePingTest] = useState<boolean>(false); const [isEnablePingTest, setIsEnablePingTest] = useState<boolean>(false);
const [isSubmittingAddPeer, setIsSubmittingAddPeer] = const [isSubmittingAddPeer, setIsSubmittingAddPeer] =
useProtectedState<boolean>(false); useState<boolean>(false);
const buildInputFirstRenderFunction = useCallback( const buildInputFirstRenderFunction = useCallback(
(key: string) => (key: string) =>

@ -15,21 +15,14 @@ import { ExpandablePanel } from '../Panels';
import periodicFetch from '../../lib/fetchers/periodicFetch'; import periodicFetch from '../../lib/fetchers/periodicFetch';
import State from '../State'; import State from '../State';
import { BodyText, MonoText, SmallText } from '../Text'; import { BodyText, MonoText, SmallText } from '../Text';
import useProtect from '../../hooks/useProtect';
import useProtectedState from '../../hooks/useProtectedState';
const ConfigPeersForm: FC<ConfigPeerFormProps> = ({ const ConfigPeersForm: FC<ConfigPeerFormProps> = ({
refreshInterval = 60000, refreshInterval = 60000,
}) => { }) => {
const { protect } = useProtect();
const addPeerDialogRef = useRef<ConfirmDialogForwardedRefContent>({}); const addPeerDialogRef = useRef<ConfirmDialogForwardedRefContent>({});
const confirmDialogRef = useRef<ConfirmDialogForwardedRefContent>({}); const confirmDialogRef = useRef<ConfirmDialogForwardedRefContent>({});
const [apiMessage, setAPIMessage] = useProtectedState<Message | undefined>( const [apiMessage, setApiMessage] = useState<Message | undefined>(undefined);
undefined,
protect,
);
const [confirmDialogProps, setConfirmDialogProps] = const [confirmDialogProps, setConfirmDialogProps] =
useState<ConfirmDialogProps>({ useState<ConfirmDialogProps>({
actionProceedText: '', actionProceedText: '',
@ -37,11 +30,12 @@ const ConfigPeersForm: FC<ConfigPeerFormProps> = ({
titleText: '', titleText: '',
}); });
const [inboundConnections, setInboundConnections] = const [inboundConnections, setInboundConnections] =
useProtectedState<InboundConnectionList>({}, protect); useState<InboundConnectionList>({});
const [isEditPeerConnections, setIsEditPeerConnections] = const [isEditPeerConnections, setIsEditPeerConnections] =
useState<boolean>(false); useState<boolean>(false);
const [peerConnections, setPeerConnections] = const [peerConnections, setPeerConnections] = useState<PeerConnectionList>(
useProtectedState<PeerConnectionList>({}, protect); {},
);
const apiMessageElement = useMemo( const apiMessageElement = useMemo(
() => () =>
@ -58,7 +52,7 @@ const ConfigPeersForm: FC<ConfigPeerFormProps> = ({
{ {
refreshInterval, refreshInterval,
onError: (error) => { onError: (error) => {
setAPIMessage({ setApiMessage({
children: `Failed to get connection data. Error: ${error}`, children: `Failed to get connection data. Error: ${error}`,
type: 'error', type: 'error',
}); });
@ -190,7 +184,7 @@ const ConfigPeersForm: FC<ConfigPeerFormProps> = ({
emsg.children = `Failed to delete peer connection(s). ${emsg.children}`; emsg.children = `Failed to delete peer connection(s). ${emsg.children}`;
setAPIMessage(emsg); setApiMessage(emsg);
}); });
}, },
proceedColour: 'red', proceedColour: 'red',

@ -1,4 +1,4 @@
import { FC, useMemo, useRef } from 'react'; import { FC, useMemo, useRef, useState } from 'react';
import API_BASE_URL from '../../lib/consts/API_BASE_URL'; import API_BASE_URL from '../../lib/consts/API_BASE_URL';
@ -14,7 +14,6 @@ import { ExpandablePanel } from '../Panels';
import periodicFetch from '../../lib/fetchers/periodicFetch'; import periodicFetch from '../../lib/fetchers/periodicFetch';
import { BodyText } from '../Text'; import { BodyText } from '../Text';
import useChecklist from '../../hooks/useChecklist'; import useChecklist from '../../hooks/useChecklist';
import useProtectedState from '../../hooks/useProtectedState';
const ManageChangedSSHKeysForm: FC<ManageChangedSSHKeysFormProps> = ({ const ManageChangedSSHKeysForm: FC<ManageChangedSSHKeysFormProps> = ({
mitmExternalHref = 'https://en.wikipedia.org/wiki/Man-in-the-middle_attack', mitmExternalHref = 'https://en.wikipedia.org/wiki/Man-in-the-middle_attack',
@ -22,14 +21,10 @@ const ManageChangedSSHKeysForm: FC<ManageChangedSSHKeysFormProps> = ({
}) => { }) => {
const confirmDialogRef = useRef<ConfirmDialogForwardedRefContent>({}); const confirmDialogRef = useRef<ConfirmDialogForwardedRefContent>({});
const [apiMessage, setAPIMessage] = useProtectedState<Message | undefined>( const [apiMessage, setApiMessage] = useState<Message | undefined>();
undefined, const [changedSSHKeys, setChangedSSHKeys] = useState<ChangedSSHKeys>({});
);
const [changedSSHKeys, setChangedSSHKeys] = useProtectedState<ChangedSSHKeys>(
{},
);
const [confirmDialogProps, setConfirmDialogProps] = const [confirmDialogProps, setConfirmDialogProps] =
useProtectedState<ConfirmDialogProps>({ useState<ConfirmDialogProps>({
actionProceedText: '', actionProceedText: '',
content: '', content: '',
titleText: '', titleText: '',
@ -51,7 +46,7 @@ const ManageChangedSSHKeysForm: FC<ManageChangedSSHKeysFormProps> = ({
`${API_BASE_URL}/ssh-key/conflict`, `${API_BASE_URL}/ssh-key/conflict`,
{ {
onError: (error) => { onError: (error) => {
setAPIMessage({ setApiMessage({
children: `Failed to fetch SSH key conflicts. Error: ${error}`, children: `Failed to fetch SSH key conflicts. Error: ${error}`,
type: 'error', type: 'error',
}); });
@ -177,7 +172,7 @@ const ManageChangedSSHKeysForm: FC<ManageChangedSSHKeysFormProps> = ({
emsg.children = `Failed to delete selected SSH key conflicts. ${emsg.children}`; emsg.children = `Failed to delete selected SSH key conflicts. ${emsg.children}`;
setAPIMessage(emsg); setApiMessage(emsg);
}); });
}, },
proceedColour: 'red', proceedColour: 'red',

@ -20,7 +20,6 @@ import { BodyText } from '../Text';
import useChecklist from '../../hooks/useChecklist'; import useChecklist from '../../hooks/useChecklist';
import useConfirmDialogProps from '../../hooks/useConfirmDialogProps'; import useConfirmDialogProps from '../../hooks/useConfirmDialogProps';
import useFormUtils from '../../hooks/useFormUtils'; import useFormUtils from '../../hooks/useFormUtils';
import useProtectedState from '../../hooks/useProtectedState';
const getFormEntries = ( const getFormEntries = (
...[{ target }]: DivFormEventHandlerParameters ...[{ target }]: DivFormEventHandlerParameters
@ -51,12 +50,12 @@ const ManageUsersForm: FC = () => {
const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps(); const [confirmDialogProps, setConfirmDialogProps] = useConfirmDialogProps();
const [editUsers, setEditUsers] = useState<boolean>(false); const [editUsers, setEditUsers] = useState<boolean>(false);
const [listMessage, setListMessage] = useProtectedState<Message>({ const [listMessage, setListMessage] = useState<Message>({
children: `No users found.`, children: `No users found.`,
}); });
const [userDetail, setUserDetail] = useProtectedState< const [userDetail, setUserDetail] = useState<
UserOverviewMetadata | undefined UserOverviewMetadata | undefined
>(undefined); >();
const { data: users, isLoading: loadingUsers } = const { data: users, isLoading: loadingUsers } =
periodicFetch<UserOverviewMetadataList>(`${API_BASE_URL}/user`, { periodicFetch<UserOverviewMetadataList>(`${API_BASE_URL}/user`, {

@ -1,5 +1,5 @@
import { Grid, Switch } from '@mui/material'; import { Grid, Switch } from '@mui/material';
import { FC, useMemo } from 'react'; import { FC, useMemo, useState } from 'react';
import api from '../../lib/api'; import api from '../../lib/api';
import ContainedButton from '../ContainedButton'; import ContainedButton from '../ContainedButton';
@ -9,8 +9,6 @@ import MessageBox, { Message } from '../MessageBox';
import { Panel, PanelHeader } from '../Panels'; import { Panel, PanelHeader } from '../Panels';
import Spinner from '../Spinner'; import Spinner from '../Spinner';
import { BodyText, HeaderText } from '../Text'; import { BodyText, HeaderText } from '../Text';
import useProtect from '../../hooks/useProtect';
import useProtectedState from '../../hooks/useProtectedState';
const StretchedButton: FC<ContainedButtonProps> = (props) => ( const StretchedButton: FC<ContainedButtonProps> = (props) => (
<ContainedButton {...props} sx={{ width: '100%' }} /> <ContainedButton {...props} sx={{ width: '100%' }} />
@ -21,12 +19,7 @@ const SimpleOperationsPanel: FC<SimpleOperationsPanelProps> = ({
onSubmit, onSubmit,
title, title,
}) => { }) => {
const { protect } = useProtect(); const [message, setMessage] = useState<Message | undefined>();
const [message, setMessage] = useProtectedState<Message | undefined>(
undefined,
protect,
);
const headerElement = useMemo( const headerElement = useMemo(
() => () =>

@ -30,7 +30,6 @@ import { Panel, PanelHeader } from './Panels';
import setMapNetwork from '../lib/setMapNetwork'; import setMapNetwork from '../lib/setMapNetwork';
import Spinner from './Spinner'; import Spinner from './Spinner';
import { BodyText, HeaderText, InlineMonoText, MonoText } from './Text'; import { BodyText, HeaderText, InlineMonoText, MonoText } from './Text';
import useProtectedState from '../hooks/useProtectedState';
const StrikerInitForm: FC = () => { const StrikerInitForm: FC = () => {
const { const {
@ -51,9 +50,7 @@ const StrikerInitForm: FC = () => {
const [isSubmittingForm, setIsSubmittingForm] = useState<boolean>(false); const [isSubmittingForm, setIsSubmittingForm] = useState<boolean>(false);
const [hostNumber, setHostNumber] = useState<string | undefined>(); const [hostNumber, setHostNumber] = useState<string | undefined>();
const [hostDetail, setHostDetail] = useProtectedState< const [hostDetail, setHostDetail] = useState<APIHostDetail | undefined>();
APIHostDetail | undefined
>(undefined);
const allowGetHostDetail = useRef<boolean>(true); const allowGetHostDetail = useRef<boolean>(true);

@ -1,8 +1,7 @@
import { useCallback } from 'react'; import { useCallback, useState } from 'react';
import api from '../lib/api'; import api from '../lib/api';
import handleAPIError from '../lib/handleAPIError'; import handleAPIError from '../lib/handleAPIError';
import useProtectedState from './useProtectedState';
type ActiveFetchSetter<T> = (data: T) => void; type ActiveFetchSetter<T> = (data: T) => void;
@ -22,7 +21,7 @@ const useActiveFetch = <Data>(
): ActiveFetchHookResponse => { ): ActiveFetchHookResponse => {
const { onError, onData, url: urlPrefix = '' } = options; const { onError, onData, url: urlPrefix = '' } = options;
const [loading, setLoading] = useProtectedState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const fetch = useCallback<ActiveFetcher>( const fetch = useCallback<ActiveFetcher>(
(urlPostfix = '') => { (urlPostfix = '') => {

@ -7,7 +7,6 @@ import buildObjectStateSetterCallback, {
import handleAPIError from '../lib/handleAPIError'; import handleAPIError from '../lib/handleAPIError';
import { Message } from '../components/MessageBox'; import { Message } from '../components/MessageBox';
import { MessageGroupForwardedRefContent } from '../components/MessageGroup'; import { MessageGroupForwardedRefContent } from '../components/MessageGroup';
import useProtectedState from './useProtectedState';
const useFormUtils = < const useFormUtils = <
U extends string, U extends string,
@ -17,7 +16,7 @@ const useFormUtils = <
ids: I, ids: I,
messageGroupRef: MutableRefObject<MessageGroupForwardedRefContent>, messageGroupRef: MutableRefObject<MessageGroupForwardedRefContent>,
): FormUtils<M> => { ): FormUtils<M> => {
const [formSubmitting, setFormSubmitting] = useProtectedState<boolean>(false); const [formSubmitting, setFormSubmitting] = useState<boolean>(false);
const [formValidity, setFormValidity] = useState<FormValidity<M>>({}); const [formValidity, setFormValidity] = useState<FormValidity<M>>({});
const setApiMessage = useCallback( const setApiMessage = useCallback(

@ -1,30 +0,0 @@
import { useEffect, useRef } from 'react';
// Allow any function as callback in the protect function.
// Could be used to wrap async callbacks to prevent them from running after
// component unmount.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyFunction = (...args: any[]) => any;
type ProtectFunction = <F extends AnyFunction>(
fn: F,
...args: Parameters<F>
) => ReturnType<F>;
const useProtect = (): { protect: ProtectFunction } => {
const isComponentMountedRef = useRef<boolean>(true);
useEffect(
() => () => {
isComponentMountedRef.current = false;
},
[],
);
return {
protect: (fn, ...args) =>
isComponentMountedRef.current ? fn(...args) : undefined,
};
};
export default useProtect;

@ -1,34 +0,0 @@
import { Dispatch, SetStateAction, useMemo, useState } from 'react';
import useProtect from './useProtect';
type SetStateFunction<S> = Dispatch<SetStateAction<S>>;
type SetStateParameters<S> = Parameters<SetStateFunction<S>>;
type SetStateReturnType<S> = ReturnType<SetStateFunction<S>>;
const useProtectedState = <S>(
initialState: S | (() => S),
protect?: (
fn: SetStateFunction<S>,
...args: SetStateParameters<S>
) => SetStateReturnType<S>,
): [S, SetStateFunction<S>] => {
const { protect: defaultProtect } = useProtect();
const [state, setState] = useState<S>(initialState);
const pfn = useMemo(
() => protect ?? defaultProtect,
[defaultProtect, protect],
);
return [
state,
(...args: SetStateParameters<S>): SetStateReturnType<S> =>
pfn(setState, ...args),
];
};
export default useProtectedState;

File diff suppressed because it is too large Load Diff

@ -20,9 +20,8 @@
"@emotion/styled": "^11.6.0", "@emotion/styled": "^11.6.0",
"@fontsource/roboto-condensed": "^4.5.0", "@fontsource/roboto-condensed": "^4.5.0",
"@fontsource/source-code-pro": "^4.5.1", "@fontsource/source-code-pro": "^4.5.1",
"@mui/icons-material": "^5.2.4", "@mui/icons-material": "^5.6.0",
"@mui/material": "^5.2.4", "@mui/material": "^5.6.0",
"@mui/styles": "^5.2.3",
"@mui/x-data-grid": "^5.12.3", "@mui/x-data-grid": "^5.12.3",
"@novnc/novnc": "^1.2.0", "@novnc/novnc": "^1.2.0",
"axios": "^0.24.0", "axios": "^0.24.0",
@ -32,8 +31,7 @@
"netmask": "^2.0.2", "netmask": "^2.0.2",
"next": "^13.5.4", "next": "^13.5.4",
"pretty-bytes": "^5.6.0", "pretty-bytes": "^5.6.0",
"react": "17.0.2", "react": "^18.0.0",
"react-dom": "17.0.2",
"swr": "^1.2.2", "swr": "^1.2.2",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"yup": "^1.2.0" "yup": "^1.2.0"
@ -47,8 +45,8 @@
"@types/novnc-core": "^0.1.3", "@types/novnc-core": "^0.1.3",
"@types/react": "^17.0.11", "@types/react": "^17.0.11",
"@types/uuid": "^8.3.4", "@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^4.27.0", "@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^4.27.0", "@typescript-eslint/parser": "^6.17.0",
"eslint": "^7.28.0", "eslint": "^7.28.0",
"eslint-config-airbnb": "^18.2.1", "eslint-config-airbnb": "^18.2.1",
"eslint-config-next": "^11.1.0", "eslint-config-next": "^11.1.0",
@ -59,7 +57,7 @@
"eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-hooks": "^4.2.0",
"husky": "^6.0.0", "husky": "^6.0.0",
"lint-staged": "^11.0.0", "lint-staged": "^11.0.0",
"prettier": "^2.2.1", "prettier": "^2.8.8",
"typescript": "^4.1.5" "typescript": "^4.9.5"
} }
} }

@ -11,16 +11,12 @@ import {
ComplexOperationsPanel, ComplexOperationsPanel,
SimpleOperationsPanel, SimpleOperationsPanel,
} from '../../components/StrikerConfig'; } from '../../components/StrikerConfig';
import useProtect from '../../hooks/useProtect';
import useProtectedState from '../../hooks/useProtectedState';
// This page can't be reused, and default is set within the render function. // This page can't be reused, and default is set within the render function.
// eslint-disable-next-line react/require-default-props // eslint-disable-next-line react/require-default-props
const Config: FC<{ refreshInterval?: number }> = ({ const Config: FC<{ refreshInterval?: number }> = ({
refreshInterval = 60000, refreshInterval = 60000,
}) => { }) => {
const { protect } = useProtect();
const [isOpenConfirmDialog, setIsOpenConfirmDialog] = const [isOpenConfirmDialog, setIsOpenConfirmDialog] =
useState<boolean>(false); useState<boolean>(false);
const [confirmDialogProps, setConfirmDialogProps] = const [confirmDialogProps, setConfirmDialogProps] =
@ -37,11 +33,10 @@ const Config: FC<{ refreshInterval?: number }> = ({
}, },
titleText: '', titleText: '',
}); });
const [simpleOpsInstallTarget, setSimpleOpsInstallTarget] = useProtectedState< const [simpleOpsInstallTarget, setSimpleOpsInstallTarget] = useState<
APIHostInstallTarget | undefined APIHostInstallTarget | undefined
>(undefined, protect); >();
const [simpleOpsPanelHeader, setSimpleOpsPanelHeader] = const [simpleOpsPanelHeader, setSimpleOpsPanelHeader] = useState<string>('');
useProtectedState<string>('', protect);
const { data: hostDetail, isLoading: loadingHostDetail } = const { data: hostDetail, isLoading: loadingHostDetail } =
periodicFetch<APIHostDetail>(`${API_BASE_URL}/host/local`, { periodicFetch<APIHostDetail>(`${API_BASE_URL}/host/local`, {

@ -18,8 +18,6 @@ import Tab from '../../components/Tab';
import TabContent from '../../components/TabContent'; import TabContent from '../../components/TabContent';
import Tabs from '../../components/Tabs'; import Tabs from '../../components/Tabs';
import useIsFirstRender from '../../hooks/useIsFirstRender'; import useIsFirstRender from '../../hooks/useIsFirstRender';
import useProtect from '../../hooks/useProtect';
import useProtectedState from '../../hooks/useProtectedState';
const TAB_ID_PREPARE_HOST = 'prepare-host'; const TAB_ID_PREPARE_HOST = 'prepare-host';
const TAB_ID_PREPARE_NETWORK = 'prepare-network'; const TAB_ID_PREPARE_NETWORK = 'prepare-network';
@ -54,11 +52,9 @@ const PrepareHostTabContent: FC = () => (
const PrepareNetworkTabContent: FC = () => { const PrepareNetworkTabContent: FC = () => {
const isFirstRender = useIsFirstRender(); const isFirstRender = useIsFirstRender();
const { protect } = useProtect(); const [hostOverviewList, setHostOverviewList] = useState<
const [hostOverviewList, setHostOverviewList] = useProtectedState<
APIHostOverviewList | undefined APIHostOverviewList | undefined
>(undefined, protect); >();
const [hostSubTabId, setHostSubTabId] = useState<string | false>(false); const [hostSubTabId, setHostSubTabId] = useState<string | false>(false);
const hostSubTabs = useMemo(() => { const hostSubTabs = useMemo(() => {

Loading…
Cancel
Save