Merge pull request #549 from ylei-tsubame/issues/404-prevent-peer-autocomplete

Web UI: patch 404, 545, 546
main
Digimer 1 year ago committed by GitHub
commit 20ae35758a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      striker-ui-api/out/index.js
  2. 2
      striker-ui-api/src/lib/accessModule.ts
  3. 4
      striker-ui-api/src/lib/disassembleEntityId.ts
  4. 20
      striker-ui-api/src/lib/request_handlers/anvil/buildQueryAnvilDetail.ts
  5. 6
      striker-ui-api/src/lib/request_handlers/host/getHostConnection.ts
  6. 4
      striker-ui-api/src/lib/request_handlers/manifest/getManifestDetail.ts
  7. 2
      striker-ui-api/src/lib/request_handlers/manifest/getManifestTemplate.ts
  8. 2
      striker-ui-api/src/lib/request_handlers/ssh-key/getSSHKeyConflict.ts
  9. 2
      striker-ui-api/src/lib/shell.ts
  10. 4
      striker-ui/components/Files/EditFileForm.tsx
  11. 91
      striker-ui/components/Files/ManageFilePanel.tsx
  12. 73
      striker-ui/components/List.tsx
  13. 6
      striker-ui/components/ManageFence/ManageFencePanel.tsx
  14. 6
      striker-ui/components/ManageManifest/ManageManifestPanel.tsx
  15. 106
      striker-ui/components/StrikerConfig/AddPeerDialog.tsx
  16. 55
      striker-ui/hooks/useActiveFetch.ts
  17. 6
      striker-ui/hooks/useChecklist.tsx
  18. 1
      striker-ui/out/_next/static/BhFewlGkfrUA_bCvxhgLY/_buildManifest.js
  19. 0
      striker-ui/out/_next/static/BhFewlGkfrUA_bCvxhgLY/_middlewareManifest.js
  20. 0
      striker-ui/out/_next/static/BhFewlGkfrUA_bCvxhgLY/_ssgManifest.js
  21. 1
      striker-ui/out/_next/static/aBwJM8_Hf5TQtM8KFF7tW/_buildManifest.js
  22. 1
      striker-ui/out/_next/static/chunks/209-4e2794319babfeec.js
  23. 1
      striker-ui/out/_next/static/chunks/247-0dbdd6350b819672.js
  24. 1
      striker-ui/out/_next/static/chunks/27-7790e406eb2ea28d.js
  25. 2
      striker-ui/out/_next/static/chunks/336-33ece0c8120f3bd4.js
  26. 2
      striker-ui/out/_next/static/chunks/404-b8e9ff2043a0d30c.js
  27. 2
      striker-ui/out/_next/static/chunks/560-a9c9ecda0eca25a9.js
  28. 1
      striker-ui/out/_next/static/chunks/62-09a1812bcc63d819.js
  29. 1
      striker-ui/out/_next/static/chunks/62-1cb6d52404130873.js
  30. 1
      striker-ui/out/_next/static/chunks/638-13a283c3a7da370b.js
  31. 2
      striker-ui/out/_next/static/chunks/707-705fb5e735d81042.js
  32. 2
      striker-ui/out/_next/static/chunks/86-d7025c9609028f44.js
  33. 1
      striker-ui/out/_next/static/chunks/94-8322ed453a3c08f0.js
  34. 1
      striker-ui/out/_next/static/chunks/94-f83c1e7821f76736.js
  35. 1
      striker-ui/out/_next/static/chunks/960-e28948d6eb4c8144.js
  36. 1
      striker-ui/out/_next/static/chunks/987-1ff0d82724b0e58b.js
  37. 2
      striker-ui/out/_next/static/chunks/pages/anvil-3bce568d47e8eaba.js
  38. 1
      striker-ui/out/_next/static/chunks/pages/config-511a465cb55668af.js
  39. 1
      striker-ui/out/_next/static/chunks/pages/config-f22ac92929f0daf0.js
  40. 1
      striker-ui/out/_next/static/chunks/pages/file-manager-53de9163caaf5a86.js
  41. 1
      striker-ui/out/_next/static/chunks/pages/file-manager-a085c3bead0f489f.js
  42. 1
      striker-ui/out/_next/static/chunks/pages/index-0bfb652a4f03dc4d.js
  43. 1
      striker-ui/out/_next/static/chunks/pages/index-e5b260a0ddaa050c.js
  44. 2
      striker-ui/out/_next/static/chunks/pages/init-59fe9f29b6489800.js
  45. 2
      striker-ui/out/_next/static/chunks/pages/login-183a6e481fd67cca.js
  46. 1
      striker-ui/out/_next/static/chunks/pages/manage-element-a689bf0140460775.js
  47. 1
      striker-ui/out/_next/static/chunks/pages/manage-element-d8b8ab9027cbbb98.js
  48. 2
      striker-ui/out/anvil.html
  49. 2
      striker-ui/out/config.html
  50. 2
      striker-ui/out/file-manager.html
  51. 2
      striker-ui/out/index.html
  52. 2
      striker-ui/out/init.html
  53. 2
      striker-ui/out/login.html
  54. 2
      striker-ui/out/manage-element.html
  55. 2
      striker-ui/out/server.html
  56. 1
      striker-ui/types/List.d.ts
  57. 1
      striker-ui/types/ManageFile.d.ts

File diff suppressed because one or more lines are too long

@ -463,7 +463,7 @@ const getVncinfo = async (serverUuid: string): Promise<ServerDetailVncInfo> => {
const [[vncinfo]] = rows; const [[vncinfo]] = rows;
const [domain, rPort] = vncinfo.split(':'); const [domain, rPort] = vncinfo.split(':');
const port = Number.parseInt(rPort); const port = Number(rPort);
const protocol = 'ws'; const protocol = 'ws';
return { domain, port, protocol }; return { domain, port, protocol };

@ -1,7 +1,7 @@
export const getEntityName = (id: string) => id.replace(/\d*$/, ''); export const getEntityName = (id: string) => id.replace(/\d*$/, '');
export const getEntityNumber = (id: string) => export const getEntityNumber = (id: string) =>
Number.parseInt(id.replace(/^[^\d]*/, '')); Number(id.replace(/^[^\d]*/, ''));
export const getEntityParts = (id: string) => { export const getEntityParts = (id: string) => {
let name = ''; let name = '';
@ -13,7 +13,7 @@ export const getEntityParts = (id: string) => {
const parts = matchResult; const parts = matchResult;
name = parts[1]; name = parts[1];
number = Number.parseInt(parts[2]); number = Number(parts[2]);
} }
return { name, number }; return { name, number };

@ -258,17 +258,17 @@ const buildQueryAnvilDetail = ({
stores = {}; stores = {};
} }
if (!previous[anvilUUID]) { if (anvilUUID && !previous[anvilUUID]) {
previous[anvilUUID] = { previous[anvilUUID] = {
anvilUUID, anvilUUID,
anvilName, anvilName,
anvilDescription, anvilDescription,
anvilTotalCPUCores: parseInt(anvilTotalCPUCores), anvilTotalCPUCores: Number(anvilTotalCPUCores),
anvilTotalMemory: String(anvilTotalMemory), anvilTotalMemory: String(anvilTotalMemory),
anvilTotalAllocatedCPUCores: parseInt( anvilTotalAllocatedCPUCores: Number(
anvilTotalAllocatedCPUCores, anvilTotalAllocatedCPUCores,
), ),
anvilTotalAvailableCPUCores: parseInt( anvilTotalAvailableCPUCores: Number(
anvilTotalAvailableCPUCores, anvilTotalAvailableCPUCores,
), ),
} as AnvilDetailForProvisionServer; } as AnvilDetailForProvisionServer;
@ -276,16 +276,16 @@ const buildQueryAnvilDetail = ({
puuid = anvilUUID; puuid = anvilUUID;
} }
if (!hosts[hostUUID]) { if (hostUUID && !hosts[hostUUID]) {
hosts[hostUUID] = { hosts[hostUUID] = {
hostUUID, hostUUID,
hostName, hostName,
hostCPUCores: parseInt(hostCPUCores), hostCPUCores: Number(hostCPUCores),
hostMemory: String(hostMemory), hostMemory: String(hostMemory),
}; };
} }
if (!servers[serverUUID]) { if (serverUUID && !servers[serverUUID]) {
const serverMemory = const serverMemory =
dSize(serverMemoryValue, { dSize(serverMemoryValue, {
fromUnit: serverMemoryUnit, fromUnit: serverMemoryUnit,
@ -297,12 +297,12 @@ const buildQueryAnvilDetail = ({
servers[serverUUID] = { servers[serverUUID] = {
serverUUID, serverUUID,
serverName, serverName,
serverCPUCores: parseInt(serverCPUCores), serverCPUCores: Number(serverCPUCores),
serverMemory, serverMemory,
}; };
} }
if (!stores[storageGroupUUID]) { if (storageGroupUUID && !stores[storageGroupUUID]) {
stores[storageGroupUUID] = { stores[storageGroupUUID] = {
storageGroupUUID, storageGroupUUID,
storageGroupName, storageGroupName,
@ -311,7 +311,7 @@ const buildQueryAnvilDetail = ({
}; };
} }
if (!files[fileUUID]) { if (fileUUID && !files[fileUUID]) {
files[fileUUID] = { files[fileUUID] = {
fileUUID, fileUUID,
fileName, fileName,

@ -15,7 +15,7 @@ const buildHostConnections = (
) => ) =>
Object.entries(databaseHash).reduce<HostConnectionOverview>( Object.entries(databaseHash).reduce<HostConnectionOverview>(
(previous, [hostUUID, { host: ipAddress, ping, port: rawPort, user }]) => { (previous, [hostUUID, { host: ipAddress, ping, port: rawPort, user }]) => {
const port = parseInt(rawPort); const port = Number(rawPort);
if (hostUUID === fromHostUUID) { if (hostUUID === fromHostUUID) {
previous.inbound.port = port; previous.inbound.port = port;
@ -91,8 +91,8 @@ export const getHostConnection = buildGetRequestHandler(
hostUUID, hostUUID,
ipAddress, ipAddress,
ipAddressUUID, ipAddressUUID,
networkLinkNumber: parseInt(rawNetworkLinkNumber), networkLinkNumber: Number(rawNetworkLinkNumber),
networkNumber: parseInt(rawNetworkNumber), networkNumber: Number(rawNetworkNumber),
networkType, networkType,
}; };
}, },

@ -217,7 +217,7 @@ export const getManifestDetail: RequestHandler = async (request, response) => {
name, name,
networkConfig: { networkConfig: {
dnsCsv, dnsCsv,
mtu: Number.parseInt(mtu), mtu: Number(mtu),
networks: Object.entries(networkList) networks: Object.entries(networkList)
.sort(handleSortNetworks) .sort(handleSortNetworks)
.reduce<ManifestDetailNetworkList>( .reduce<ManifestDetailNetworkList>(
@ -252,7 +252,7 @@ export const getManifestDetail: RequestHandler = async (request, response) => {
ntpCsv, ntpCsv,
}, },
prefix, prefix,
sequence: Number.parseInt(sequence), sequence: Number(sequence),
}; };
response.status(200).send(manifestData); response.status(200).send(manifestData);

@ -105,7 +105,7 @@ export const getManifestTemplate: RequestHandler = async (
} }
if (lastSequence) { if (lastSequence) {
previous.sequence = Number.parseInt(lastSequence) + 1; previous.sequence = Number(lastSequence) + 1;
} }
return previous; return previous;

@ -38,7 +38,7 @@ export const getSSHKeyConflict = buildGetRequestHandler(
previous[hostUUIDKey][stateUUID] = { previous[hostUUIDKey][stateUUID] = {
badFile, badFile,
badLine: parseInt(badLine), badLine: Number(badLine),
hostName, hostName,
hostUUID, hostUUID,
ipAddress, ipAddress,

@ -48,7 +48,7 @@ export const uuidgen = (...args: string[]) =>
systemCall(SERVER_PATHS.usr.bin.uuidgen.self, args); systemCall(SERVER_PATHS.usr.bin.uuidgen.self, args);
export const resolveId = (id: number | string, database: string) => export const resolveId = (id: number | string, database: string) =>
Number.parseInt(getent(database, String(id)).split(':', 3)[2]); Number(getent(database, String(id)).split(':', 3)[2]);
export const resolveGid = (id: number | string) => resolveId(id, 'group'); export const resolveGid = (id: number | string) => resolveId(id, 'group');

@ -66,7 +66,7 @@ const toEditFileRequestBody = (
}; };
const EditFileForm: FC<EditFileFormProps> = (props) => { const EditFileForm: FC<EditFileFormProps> = (props) => {
const { anvils, drHosts, previous: file } = props; const { anvils, drHosts, onSuccess, previous: file } = props;
const messageGroupRef = useRef<MessageGroupForwardedRefContent>({}); const messageGroupRef = useRef<MessageGroupForwardedRefContent>({});
@ -113,6 +113,8 @@ const EditFileForm: FC<EditFileFormProps> = (props) => {
.put(`/file/${file.uuid}`, body) .put(`/file/${file.uuid}`, body)
.then(() => { .then(() => {
setApiMessage({ children: <>File updated.</> }); setApiMessage({ children: <>File updated.</> });
onSuccess?.call(null);
}) })
.catch((error) => { .catch((error) => {
const emsg = handleAPIError(error); const emsg = handleAPIError(error);

@ -12,13 +12,13 @@ import { DialogWithHeader } from '../Dialog';
import Divider from '../Divider'; import Divider from '../Divider';
import EditFileForm from './EditFileForm'; import EditFileForm from './EditFileForm';
import FlexBox from '../FlexBox'; import FlexBox from '../FlexBox';
import handleAPIError from '../../lib/handleAPIError';
import List from '../List'; import List from '../List';
import MessageGroup, { MessageGroupForwardedRefContent } from '../MessageGroup'; import MessageGroup, { MessageGroupForwardedRefContent } from '../MessageGroup';
import { Panel, PanelHeader } from '../Panels'; import { Panel, PanelHeader } from '../Panels';
import periodicFetch from '../../lib/fetchers/periodicFetch'; import periodicFetch from '../../lib/fetchers/periodicFetch';
import Spinner from '../Spinner'; import Spinner from '../Spinner';
import { BodyText, HeaderText, MonoText } from '../Text'; import { BodyText, HeaderText, MonoText } from '../Text';
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';
@ -118,15 +118,29 @@ const ManageFilePanel: FC = () => {
const [file, setFile] = useProtectedState<APIFileDetail | undefined>( const [file, setFile] = useProtectedState<APIFileDetail | undefined>(
undefined, undefined,
); );
const [loadingFile, setLoadingFile] = useProtectedState<boolean>(false); const [files, setFiles] = useProtectedState<APIFileOverviewList | undefined>(
undefined,
);
const { data: rows, isLoading: loadingFiles } = periodicFetch<string[][]>( const { isLoading: loadingFilesPeriodic } = periodicFetch<string[][]>(
`${API_BASE_URL}/file`, `${API_BASE_URL}/file`,
{
onSuccess: (rows) => {
setFiles(toFileOverviewList(rows));
},
},
); );
const files = useMemo( const { fetch: getFiles, loading: loadingFilesActive } = useActiveFetch<
() => (rows ? toFileOverviewList(rows) : undefined), string[][]
[rows], >({
onData: (data) => setFiles(toFileOverviewList(data)),
url: '/file',
});
const loadingFiles = useMemo<boolean>(
() => loadingFilesPeriodic || loadingFilesActive,
[loadingFilesActive, loadingFilesPeriodic],
); );
const { const {
@ -136,6 +150,7 @@ const ManageFilePanel: FC = () => {
hasAllChecks, hasAllChecks,
hasChecks, hasChecks,
multipleItems, multipleItems,
resetChecks,
setAllChecks, setAllChecks,
setCheck, setCheck,
} = useChecklist({ } = useChecklist({
@ -148,28 +163,16 @@ const ManageFilePanel: FC = () => {
[], [],
); );
const getFileDetail = useCallback( const { fetch: getFile, loading: loadingFile } = useActiveFetch<string[][]>({
(fileUuid: string) => { onData: (data) => setFile(toFileDetail(data)),
setLoadingFile(true); onError: ({ children: previous, ...rest }) => {
setApiMessage({
api children: <>Failed to get file detail. {previous}</>,
.get<string[][]>(`file/${fileUuid}`) ...rest,
.then(({ data }) => { });
setFile(toFileDetail(data));
})
.catch((error) => {
const emsg = handleAPIError(error);
emsg.children = <>Failed to get file detail. {emsg.children}</>;
setApiMessage(emsg);
})
.finally(() => {
setLoadingFile(false);
});
}, },
[setApiMessage, setFile, setLoadingFile], url: '/file/',
); });
const { data: rawAnvils, loading: loadingAnvils } = const { data: rawAnvils, loading: loadingAnvils } =
useFetch<APIAnvilOverviewArray>('/anvil', { useFetch<APIAnvilOverviewArray>('/anvil', {
@ -226,7 +229,13 @@ const ManageFilePanel: FC = () => {
setConfirmDialogProps( setConfirmDialogProps(
buildDeleteDialogProps({ buildDeleteDialogProps({
onProceedAppend: () => { onProceedAppend: () => {
checks.forEach((fileUuid) => api.delete(`/file/${fileUuid}`)); const promises = checks.map((fileUuid) =>
api.delete(`/file/${fileUuid}`),
);
Promise.all(promises).then(() => getFiles());
resetChecks();
}, },
getConfirmDialogTitle: (count) => getConfirmDialogTitle: (count) =>
`Delete the following ${count} file(s)?`, `Delete the following ${count} file(s)?`,
@ -243,7 +252,7 @@ const ManageFilePanel: FC = () => {
}} }}
onItemClick={(value, uuid) => { onItemClick={(value, uuid) => {
editFormDialogRef.current?.setOpen(true); editFormDialogRef.current?.setOpen(true);
getFileDetail(uuid); getFile(uuid);
}} }}
renderListItem={(uuid, { checksum, name, size, type }) => ( renderListItem={(uuid, { checksum, name, size, type }) => (
<FlexBox columnSpacing={0} fullWidth md="row" xs="column"> <FlexBox columnSpacing={0} fullWidth md="row" xs="column">
@ -266,10 +275,12 @@ const ManageFilePanel: FC = () => {
edit, edit,
files, files,
getCheck, getCheck,
getFileDetail, getFile,
getFiles,
hasAllChecks, hasAllChecks,
hasChecks, hasChecks,
multipleItems, multipleItems,
resetChecks,
setAllChecks, setAllChecks,
setCheck, setCheck,
setConfirmDialogProps, setConfirmDialogProps,
@ -289,13 +300,14 @@ const ManageFilePanel: FC = () => {
); );
const loadingAddForm = useMemo<boolean>( const loadingAddForm = useMemo<boolean>(
() => loadingFiles || loadingAnvils || loadingDrHosts, () => loadingFilesPeriodic || loadingAnvils || loadingDrHosts,
[loadingAnvils, loadingDrHosts, loadingFiles], [loadingAnvils, loadingDrHosts, loadingFilesPeriodic],
); );
const loadingEditForm = useMemo<boolean>( const loadingEditForm = useMemo<boolean>(
() => loadingFiles || loadingAnvils || loadingDrHosts || loadingFile, () =>
[loadingAnvils, loadingDrHosts, loadingFile, loadingFiles], loadingFilesPeriodic || loadingAnvils || loadingDrHosts || loadingFile,
[loadingAnvils, loadingDrHosts, loadingFile, loadingFilesPeriodic],
); );
const addForm = useMemo( const addForm = useMemo(
@ -309,9 +321,16 @@ const ManageFilePanel: FC = () => {
anvils && anvils &&
drHosts && drHosts &&
file && ( file && (
<EditFileForm anvils={anvils} drHosts={drHosts} previous={file} /> <EditFileForm
anvils={anvils}
drHosts={drHosts}
onSuccess={() => {
getFiles();
}}
previous={file}
/>
), ),
[anvils, drHosts, file], [anvils, drHosts, file, getFiles],
); );
return ( return (

@ -22,6 +22,7 @@ import Checkbox from './Checkbox';
import Divider from './Divider'; import Divider from './Divider';
import FlexBox from './FlexBox'; import FlexBox from './FlexBox';
import IconButton from './IconButton'; import IconButton from './IconButton';
import Spinner from './Spinner';
import { BodyText } from './Text'; import { BodyText } from './Text';
const List = forwardRef( const List = forwardRef(
@ -43,6 +44,7 @@ const List = forwardRef(
listItemProps: { sx: listItemSx, ...restListItemProps } = {}, listItemProps: { sx: listItemSx, ...restListItemProps } = {},
listItems, listItems,
listProps: { sx: listSx, ...restListProps } = {}, listProps: { sx: listSx, ...restListProps } = {},
loading,
onAdd, onAdd,
onDelete, onDelete,
onEdit, onEdit,
@ -186,48 +188,47 @@ const List = forwardRef(
); );
const listItemElements = useMemo(() => { const listItemElements = useMemo(() => {
let result = listEmptyElement; if (loading) return <Spinner mt={0} />;
if (listItems) { if (!listItems) return listEmptyElement;
const entries = Object.entries(listItems);
if (entries.length > 0) { const entries = Object.entries(listItems);
result = entries.map(([key, value]) => {
const listItem = renderListItem(key, value);
return ( if (entries.length <= 0) return listEmptyElement;
<MUIListItem
{...restListItemProps} return entries.map(([key, value]) => {
key={`${listItemKeyPrefix}-${key}`} const listItem = renderListItem(key, value);
sx={{ paddingLeft: 0, paddingRight: 0, ...listItemSx }}
>
{listItemCheckbox(
key,
renderListItemCheckboxState?.call(null, key, value),
getListItemCheckboxProps?.call(null, key, value),
)}
{isAllowItemButton ? (
<ListItemButton
onClick={(...args) => {
onItemClick?.call(null, value, key, ...args);
}}
sx={{ borderRadius: BORDER_RADIUS }}
>
{listItem}
</ListItemButton>
) : (
listItem
)}
</MUIListItem>
);
});
}
}
return result; return (
<MUIListItem
{...restListItemProps}
key={`${listItemKeyPrefix}-${key}`}
sx={{ paddingLeft: 0, paddingRight: 0, ...listItemSx }}
>
{listItemCheckbox(
key,
renderListItemCheckboxState?.call(null, key, value),
getListItemCheckboxProps?.call(null, key, value),
)}
{isAllowItemButton ? (
<ListItemButton
onClick={(...args) => {
onItemClick?.call(null, value, key, ...args);
}}
sx={{ borderRadius: BORDER_RADIUS }}
>
{listItem}
</ListItemButton>
) : (
listItem
)}
</MUIListItem>
);
});
}, [ }, [
listEmptyElement, loading,
listItems, listItems,
listEmptyElement,
renderListItem, renderListItem,
restListItemProps, restListItemProps,
listItemKeyPrefix, listItemKeyPrefix,

@ -160,7 +160,7 @@ const ManageFencePanel: FC = () => {
checks, checks,
getCheck, getCheck,
hasChecks, hasChecks,
resetChecklist, resetChecks,
setCheck, setCheck,
} = useChecklist({ list: fenceOverviews }); } = useChecklist({ list: fenceOverviews });
@ -246,7 +246,7 @@ const ManageFencePanel: FC = () => {
method: 'delete', method: 'delete',
onSuccess: () => { onSuccess: () => {
getFenceOverviews(); getFenceOverviews();
resetChecklist(); resetChecks();
}, },
url: '/fence', url: '/fence',
}); });
@ -382,7 +382,7 @@ const ManageFencePanel: FC = () => {
getFormSummaryEntryLabel, getFormSummaryEntryLabel,
hasChecks, hasChecks,
isEditFences, isEditFences,
resetChecklist, resetChecks,
setCheck, setCheck,
setConfirmDialogProps, setConfirmDialogProps,
setFormDialogProps, setFormDialogProps,

@ -217,7 +217,7 @@ const ManageManifestPanel: FC = () => {
checks, checks,
getCheck, getCheck,
hasChecks, hasChecks,
resetChecklist, resetChecks,
setCheck, setCheck,
} = useChecklist({ } = useChecklist({
list: manifestOverviews, list: manifestOverviews,
@ -445,7 +445,7 @@ const ManageManifestPanel: FC = () => {
method: 'delete', method: 'delete',
onSuccess: () => { onSuccess: () => {
getManifestOverviews(); getManifestOverviews();
resetChecklist(); resetChecks();
}, },
url: `/manifest`, url: `/manifest`,
}); });
@ -503,7 +503,7 @@ const ManageManifestPanel: FC = () => {
hasChecks, hasChecks,
isEditManifests, isEditManifests,
manifestOverviews, manifestOverviews,
resetChecklist, resetChecks,
setCheck, setCheck,
setConfirmDialogProps, setConfirmDialogProps,
setManifestDetail, setManifestDetail,

@ -11,7 +11,6 @@ import INPUT_TYPES from '../../lib/consts/INPUT_TYPES';
import api from '../../lib/api'; import api from '../../lib/api';
import buildMapToMessageSetter from '../../lib/buildMapToMessageSetter'; import buildMapToMessageSetter from '../../lib/buildMapToMessageSetter';
import buildNumberTestBatch from '../../lib/test_input/buildNumberTestBatch';
import buildObjectStateSetterCallback from '../../lib/buildObjectStateSetterCallback'; import buildObjectStateSetterCallback from '../../lib/buildObjectStateSetterCallback';
import CheckboxWithLabel from '../CheckboxWithLabel'; import CheckboxWithLabel from '../CheckboxWithLabel';
import ConfirmDialog from '../ConfirmDialog'; import ConfirmDialog from '../ConfirmDialog';
@ -27,8 +26,7 @@ import {
buildIPAddressTestBatch, buildIPAddressTestBatch,
buildPeacefulStringTestBatch, buildPeacefulStringTestBatch,
} from '../../lib/test_input'; } from '../../lib/test_input';
import { BodyText, HeaderText } from '../Text'; import { HeaderText } from '../Text';
import useProtect from '../../hooks/useProtect';
import useProtectedState from '../../hooks/useProtectedState'; import useProtectedState from '../../hooks/useProtectedState';
const IT_IDS = { const IT_IDS = {
@ -51,8 +49,6 @@ const AddPeerDialog = forwardRef<
ConfirmDialogForwardedRefContent, ConfirmDialogForwardedRefContent,
AddPeerDialogProps AddPeerDialogProps
>(({ formGridColumns = 2 }, ref) => { >(({ formGridColumns = 2 }, ref) => {
const { protect } = useProtect();
const inputPeerDBPortRef = useRef<InputForwardedRefContent<'string'>>({}); const inputPeerDBPortRef = useRef<InputForwardedRefContent<'string'>>({});
const inputPeerIPAddressRef = useRef<InputForwardedRefContent<'string'>>({}); const inputPeerIPAddressRef = useRef<InputForwardedRefContent<'string'>>({});
const inputPeerPasswordRef = useRef<InputForwardedRefContent<'string'>>({}); const inputPeerPasswordRef = useRef<InputForwardedRefContent<'string'>>({});
@ -65,7 +61,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, protect); useProtectedState<boolean>(false);
const buildInputFirstRenderFunction = useCallback( const buildInputFirstRenderFunction = useCallback(
(key: string) => (key: string) =>
@ -100,42 +96,22 @@ const AddPeerDialog = forwardRef<
<Grid <Grid
columns={{ xs: 1, sm: formGridColumns }} columns={{ xs: 1, sm: formGridColumns }}
layout={{ layout={{
'add-peer-user-and-ip-address': { 'add-peer-ip-address': {
children: ( children: (
<FlexBox row spacing=".3em"> <FlexBox row spacing=".3em">
<InputWithRef
input={
<OutlinedInputWithLabel
formControlProps={{
sx: { minWidth: '4.6em', width: '25%' },
}}
id="add-peer-user-input"
inputProps={{ placeholder: 'admin' }}
label={LABEL.user}
/>
}
inputTestBatch={buildPeacefulStringTestBatch(
LABEL.user,
() => {
msgSetters.user();
},
{
onFinishBatch: buildFinishInputTestBatchFunction(
IT_IDS.user,
),
},
(message) => {
msgSetters.user({ children: message });
},
)}
onFirstRender={buildInputFirstRenderFunction(IT_IDS.user)}
ref={inputPeerUserRef}
/>
<BodyText>@</BodyText>
<InputWithRef <InputWithRef
input={ input={
<OutlinedInputWithLabel <OutlinedInputWithLabel
id="add-peer-ip-address-input" id="add-peer-ip-address-input"
inputProps={{
// Initiallize the field as read-only, then unlock
// when the user focuses; this avoids browser's
// auto-complete.
readOnly: true,
onFocus: (event) => {
event.target.readOnly = false;
},
}}
label={LABEL.ipAddress} label={LABEL.ipAddress}
/> />
} }
@ -193,64 +169,6 @@ const AddPeerDialog = forwardRef<
/> />
), ),
}, },
'add-peer-db-and-ssh-port': {
children: (
<FlexBox row>
<InputWithRef
input={
<OutlinedInputWithLabel
id="add-peer-db-port-input"
inputProps={{ placeholder: '5432' }}
label={LABEL.dbPort}
/>
}
inputTestBatch={buildNumberTestBatch(
LABEL.dbPort,
() => {
msgSetters.dbPort();
},
{
onFinishBatch: buildFinishInputTestBatchFunction(
IT_IDS.dbPort,
),
},
(message) => {
msgSetters.dbPort({ children: message });
},
)}
onFirstRender={buildInputFirstRenderFunction(IT_IDS.dbPort)}
ref={inputPeerDBPortRef}
/>
<InputWithRef
input={
<OutlinedInputWithLabel
id="add-peer-ssh-port-input"
inputProps={{ placeholder: '22' }}
label={LABEL.sshPort}
/>
}
inputTestBatch={buildNumberTestBatch(
LABEL.sshPort,
() => {
msgSetters.sshPort();
},
{
onFinishBatch: buildFinishInputTestBatchFunction(
IT_IDS.sshPort,
),
},
(message) => {
msgSetters.sshPort({ children: message });
},
)}
onFirstRender={buildInputFirstRenderFunction(
IT_IDS.sshPort,
)}
ref={inputPeerSSHPortRef}
/>
</FlexBox>
),
},
'add-peer-is-ping': { 'add-peer-is-ping': {
children: ( children: (
<CheckboxWithLabel <CheckboxWithLabel

@ -0,0 +1,55 @@
import { useCallback } from 'react';
import api from '../lib/api';
import handleAPIError from '../lib/handleAPIError';
import useProtectedState from './useProtectedState';
type ActiveFetchSetter<T> = (data: T) => void;
type ActiveFetcher = (url?: string) => void;
type ActiveFetchHookResponse = {
fetch: ActiveFetcher;
loading: boolean;
};
const useActiveFetch = <Data>(
options: {
onData?: ActiveFetchSetter<Data>;
onError?: (emsg: Message) => void;
url?: string;
} = {},
): ActiveFetchHookResponse => {
const { onError, onData, url: urlPrefix = '' } = options;
const [loading, setLoading] = useProtectedState<boolean>(false);
const fetch = useCallback<ActiveFetcher>(
(urlPostfix = '') => {
const url = `${urlPrefix}${urlPostfix}`;
if (!url) return;
setLoading(true);
api
.get<Data>(url)
.then(({ data }) => {
onData?.call(null, data);
})
.catch((error) => {
const emsg = handleAPIError(error);
onError?.call(null, emsg);
})
.finally(() => {
setLoading(false);
});
},
[urlPrefix, setLoading, onError, onData],
);
return { fetch, loading };
};
export default useActiveFetch;

@ -16,7 +16,7 @@ const useChecklist = ({
hasAllChecks: boolean; hasAllChecks: boolean;
hasChecks: boolean; hasChecks: boolean;
multipleItems: boolean; multipleItems: boolean;
resetChecklist: () => void; resetChecks: () => void;
setAllChecks: SetAllChecksFunction; setAllChecks: SetAllChecksFunction;
setCheck: SetCheckFunction; setCheck: SetCheckFunction;
} => { } => {
@ -62,7 +62,7 @@ const useChecklist = ({
[checklist], [checklist],
); );
const resetChecklist = useCallback(() => setChecklist({}), []); const resetChecks = useCallback(() => setChecklist({}), []);
const setAllChecks = useCallback<SetAllChecksFunction>( const setAllChecks = useCallback<SetAllChecksFunction>(
(checked) => (checked) =>
@ -92,7 +92,7 @@ const useChecklist = ({
hasAllChecks, hasAllChecks,
hasChecks, hasChecks,
multipleItems, multipleItems,
resetChecklist, resetChecks,
setAllChecks, setAllChecks,
setCheck, setCheck,
}; };

@ -0,0 +1 @@
self.__BUILD_MANIFEST=function(s,c,a,e,t,n,i,f,d,b,u,k,h,j,r,g,l){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,a,e,f,d,"static/chunks/82-b2661d1af04f38ff.js",c,t,n,i,h,j,"static/chunks/pages/index-0bfb652a4f03dc4d.js"],"/_error":["static/chunks/pages/_error-2280fa386d040b66.js"],"/anvil":[s,a,e,f,d,"static/chunks/638-13a283c3a7da370b.js",c,t,n,i,h,"static/chunks/pages/anvil-3bce568d47e8eaba.js"],"/config":[s,a,e,u,"static/chunks/519-4b7761e884c88eb9.js",c,t,n,i,b,k,r,"static/chunks/pages/config-511a465cb55668af.js"],"/file-manager":["static/chunks/29107295-fbcfe2172188e46f.js",s,a,e,f,"static/chunks/176-7308c25ba374961e.js",c,t,i,b,"static/chunks/pages/file-manager-a085c3bead0f489f.js"],"/init":[s,a,f,d,u,g,c,t,n,i,l,"static/chunks/pages/init-59fe9f29b6489800.js"],"/login":[s,a,e,c,t,n,b,k,"static/chunks/pages/login-183a6e481fd67cca.js"],"/manage-element":[s,a,e,f,d,u,g,"static/chunks/111-2605129c170ed35d.js",c,t,n,i,b,k,l,r,"static/chunks/pages/manage-element-d8b8ab9027cbbb98.js"],"/server":[s,e,"static/chunks/528-72edc50189f30fa9.js",c,j,"static/chunks/pages/server-8faafa80170f67f2.js"],sortedPages:["/","/_app","/_error","/anvil","/config","/file-manager","/init","/login","/manage-element","/server"]}}("static/chunks/412-d77d0985f9905450.js","static/chunks/62-09a1812bcc63d819.js","static/chunks/438-0147a63d98e89439.js","static/chunks/894-e57948de523bcf96.js","static/chunks/195-fa06e61dd4339031.js","static/chunks/27-7790e406eb2ea28d.js","static/chunks/157-d1418743accab385.js","static/chunks/182-08683bbe95fbb010.js","static/chunks/209-4e2794319babfeec.js","static/chunks/48-d4400834d0a31c6e.js","static/chunks/644-4eec2b397fdacb0c.js","static/chunks/336-33ece0c8120f3bd4.js","static/chunks/707-705fb5e735d81042.js","static/chunks/94-f83c1e7821f76736.js","static/chunks/560-a9c9ecda0eca25a9.js","static/chunks/404-b8e9ff2043a0d30c.js","static/chunks/86-d7025c9609028f44.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();

@ -1 +0,0 @@
self.__BUILD_MANIFEST=function(s,c,a,e,t,n,i,f,u,k,d,h,j,b,r,g,l){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,a,e,f,u,"static/chunks/82-b2661d1af04f38ff.js",c,t,n,i,j,b,"static/chunks/pages/index-e5b260a0ddaa050c.js"],"/_error":["static/chunks/pages/_error-2280fa386d040b66.js"],"/anvil":[s,a,e,f,u,"static/chunks/247-0dbdd6350b819672.js",c,t,n,i,j,"static/chunks/pages/anvil-48975a0cc7fcbd1f.js"],"/config":[s,a,e,d,"static/chunks/519-4b7761e884c88eb9.js",c,t,n,i,k,h,r,"static/chunks/pages/config-f22ac92929f0daf0.js"],"/file-manager":["static/chunks/29107295-fbcfe2172188e46f.js",s,a,e,f,"static/chunks/176-7308c25ba374961e.js",c,t,i,k,"static/chunks/pages/file-manager-53de9163caaf5a86.js"],"/init":[s,a,f,u,d,g,c,t,n,i,l,"static/chunks/pages/init-84d6e766b3c27e21.js"],"/login":[s,a,e,c,t,n,k,h,"static/chunks/pages/login-6f7a93d56a339079.js"],"/manage-element":[s,a,e,f,u,d,g,"static/chunks/111-2605129c170ed35d.js",c,t,n,i,k,h,l,r,"static/chunks/pages/manage-element-a689bf0140460775.js"],"/server":[s,e,"static/chunks/528-72edc50189f30fa9.js",c,b,"static/chunks/pages/server-8faafa80170f67f2.js"],sortedPages:["/","/_app","/_error","/anvil","/config","/file-manager","/init","/login","/manage-element","/server"]}}("static/chunks/412-d77d0985f9905450.js","static/chunks/62-1cb6d52404130873.js","static/chunks/438-0147a63d98e89439.js","static/chunks/894-e57948de523bcf96.js","static/chunks/195-fa06e61dd4339031.js","static/chunks/987-1ff0d82724b0e58b.js","static/chunks/157-d1418743accab385.js","static/chunks/182-08683bbe95fbb010.js","static/chunks/960-e28948d6eb4c8144.js","static/chunks/48-d4400834d0a31c6e.js","static/chunks/644-4eec2b397fdacb0c.js","static/chunks/336-24770f9b2621610a.js","static/chunks/707-445cd83859b24a36.js","static/chunks/94-8322ed453a3c08f0.js","static/chunks/560-0ed707609765e23a.js","static/chunks/692-f4e7771f3a43db26.js","static/chunks/86-366ac64963a6a0fd.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -27,6 +27,7 @@ type ListOptionalProps<T extends unknown = unknown> = {
listItemProps?: import('@mui/material').ListItemProps; listItemProps?: import('@mui/material').ListItemProps;
listItems?: Record<string, T>; listItems?: Record<string, T>;
listProps?: import('@mui/material').ListProps; listProps?: import('@mui/material').ListProps;
loading?: boolean;
onAdd?: import('../components/IconButton').IconButtonProps['onClick']; onAdd?: import('../components/IconButton').IconButtonProps['onClick'];
onDelete?: import('../components/IconButton').IconButtonProps['onClick']; onDelete?: import('../components/IconButton').IconButtonProps['onClick'];
onEdit?: import('../components/IconButton').IconButtonProps['onClick']; onEdit?: import('../components/IconButton').IconButtonProps['onClick'];

@ -52,6 +52,7 @@ type AddFileFormProps = Pick<FileInputGroupProps, 'anvils' | 'drHosts'>;
/** EditFileForm */ /** EditFileForm */
type EditFileFormProps = Pick<FileInputGroupProps, 'anvils' | 'drHosts'> & { type EditFileFormProps = Pick<FileInputGroupProps, 'anvils' | 'drHosts'> & {
onSuccess?: () => void;
previous: APIFileDetail; previous: APIFileDetail;
}; };

Loading…
Cancel
Save