Add ISO catalog
This commit is contained in:
		@@ -5,6 +5,15 @@ export interface IsoFile {
 | 
			
		||||
  size: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ISO catalog entries
 | 
			
		||||
 */
 | 
			
		||||
export interface ISOCatalogEntry {
 | 
			
		||||
  name: string;
 | 
			
		||||
  url: string;
 | 
			
		||||
  image: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class IsoFilesApi {
 | 
			
		||||
  /**
 | 
			
		||||
   * Upload a new ISO file to the server
 | 
			
		||||
@@ -74,4 +83,23 @@ export class IsoFilesApi {
 | 
			
		||||
      uri: `/iso/${file.filename}`,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get iso catalog
 | 
			
		||||
   */
 | 
			
		||||
  static async Catalog(): Promise<ISOCatalogEntry[]> {
 | 
			
		||||
    return (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "GET",
 | 
			
		||||
        uri: "/assets/iso_catalog.json",
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get catalog image URL
 | 
			
		||||
   */
 | 
			
		||||
  static CatalogImageURL(entry: ISOCatalogEntry): string {
 | 
			
		||||
    return APIClient.backendURL() + entry.image;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										75
									
								
								virtweb_frontend/src/dialogs/IsoCatalogDialog.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								virtweb_frontend/src/dialogs/IsoCatalogDialog.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
import {
 | 
			
		||||
  Avatar,
 | 
			
		||||
  Button,
 | 
			
		||||
  Dialog,
 | 
			
		||||
  DialogActions,
 | 
			
		||||
  DialogContent,
 | 
			
		||||
  DialogTitle,
 | 
			
		||||
  List,
 | 
			
		||||
  ListItem,
 | 
			
		||||
  ListItemAvatar,
 | 
			
		||||
  ListItemButton,
 | 
			
		||||
  ListItemText,
 | 
			
		||||
} from "@mui/material";
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { ISOCatalogEntry, IsoFilesApi } from "../api/IsoFilesApi";
 | 
			
		||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
			
		||||
 | 
			
		||||
export function IsoCatalogDialog(p: {
 | 
			
		||||
  open: boolean;
 | 
			
		||||
  onClose: () => void;
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  const [catalog, setCatalog] = React.useState<ISOCatalogEntry[] | undefined>();
 | 
			
		||||
 | 
			
		||||
  const load = async () => {
 | 
			
		||||
    setCatalog(await IsoFilesApi.Catalog());
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Dialog open={p.open} onClose={p.onClose}>
 | 
			
		||||
      <DialogTitle>Iso catalog</DialogTitle>
 | 
			
		||||
      <DialogContent>
 | 
			
		||||
        <AsyncWidget
 | 
			
		||||
          loadKey={1}
 | 
			
		||||
          load={load}
 | 
			
		||||
          errMsg="Failed to load catalog"
 | 
			
		||||
          build={() => <IsoCatalogDialogInner catalog={catalog!} />}
 | 
			
		||||
        />
 | 
			
		||||
      </DialogContent>
 | 
			
		||||
      <DialogActions>
 | 
			
		||||
        <Button autoFocus onClick={p.onClose}>
 | 
			
		||||
          Close
 | 
			
		||||
        </Button>
 | 
			
		||||
      </DialogActions>
 | 
			
		||||
    </Dialog>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function IsoCatalogDialogInner(p: {
 | 
			
		||||
  catalog: ISOCatalogEntry[];
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <List dense>
 | 
			
		||||
      {p.catalog.map((entry) => (
 | 
			
		||||
        <a
 | 
			
		||||
          href={entry.url}
 | 
			
		||||
          target="_blank"
 | 
			
		||||
          rel="noopener"
 | 
			
		||||
          style={{ color: "inherit", textDecoration: "none" }}
 | 
			
		||||
        >
 | 
			
		||||
          <ListItem key={entry.name}>
 | 
			
		||||
            <ListItemButton>
 | 
			
		||||
              <ListItemAvatar>
 | 
			
		||||
                <img
 | 
			
		||||
                  src={IsoFilesApi.CatalogImageURL(entry)}
 | 
			
		||||
                  style={{ width: "2em" }}
 | 
			
		||||
                />
 | 
			
		||||
              </ListItemAvatar>
 | 
			
		||||
              <ListItemText primary={entry.name} />
 | 
			
		||||
            </ListItemButton>
 | 
			
		||||
          </ListItem>
 | 
			
		||||
        </a>
 | 
			
		||||
      ))}
 | 
			
		||||
    </List>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@@ -24,9 +24,12 @@ import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
			
		||||
import { FileInput } from "../widgets/forms/FileInput";
 | 
			
		||||
import { VirtWebPaper } from "../widgets/VirtWebPaper";
 | 
			
		||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
 | 
			
		||||
import MenuBookIcon from "@mui/icons-material/MenuBook";
 | 
			
		||||
import { IsoCatalogDialog } from "../dialogs/IsoCatalogDialog";
 | 
			
		||||
 | 
			
		||||
export function IsoFilesRoute(): React.ReactElement {
 | 
			
		||||
  const [list, setList] = React.useState<IsoFile[] | undefined>();
 | 
			
		||||
  const [isoCatalog, setIsoCatalog] = React.useState(false);
 | 
			
		||||
 | 
			
		||||
  const loadKey = React.useRef(1);
 | 
			
		||||
 | 
			
		||||
@@ -40,19 +43,34 @@ export function IsoFilesRoute(): React.ReactElement {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <AsyncWidget
 | 
			
		||||
      loadKey={loadKey.current}
 | 
			
		||||
      errMsg="Failed to load ISO files list!"
 | 
			
		||||
      load={load}
 | 
			
		||||
      ready={list !== undefined}
 | 
			
		||||
      build={() => (
 | 
			
		||||
        <VirtWebRouteContainer label="ISO files management">
 | 
			
		||||
          <UploadIsoFileCard onFileUploaded={reload} />
 | 
			
		||||
          <UploadIsoFileFromUrlCard onFileUploaded={reload} />
 | 
			
		||||
          <IsoFilesList list={list!} onReload={reload} />
 | 
			
		||||
        </VirtWebRouteContainer>
 | 
			
		||||
      )}
 | 
			
		||||
    />
 | 
			
		||||
    <>
 | 
			
		||||
      <AsyncWidget
 | 
			
		||||
        loadKey={loadKey.current}
 | 
			
		||||
        errMsg="Failed to load ISO files list!"
 | 
			
		||||
        load={load}
 | 
			
		||||
        ready={list !== undefined}
 | 
			
		||||
        build={() => (
 | 
			
		||||
          <VirtWebRouteContainer
 | 
			
		||||
            label="ISO files management"
 | 
			
		||||
            actions={
 | 
			
		||||
              <Tooltip title="Open the ISO catalog">
 | 
			
		||||
                <IconButton onClick={() => setIsoCatalog(true)}>
 | 
			
		||||
                  <MenuBookIcon />
 | 
			
		||||
                </IconButton>
 | 
			
		||||
              </Tooltip>
 | 
			
		||||
            }
 | 
			
		||||
          >
 | 
			
		||||
            <UploadIsoFileCard onFileUploaded={reload} />
 | 
			
		||||
            <UploadIsoFileFromUrlCard onFileUploaded={reload} />
 | 
			
		||||
            <IsoFilesList list={list!} onReload={reload} />
 | 
			
		||||
          </VirtWebRouteContainer>
 | 
			
		||||
        )}
 | 
			
		||||
      />
 | 
			
		||||
      <IsoCatalogDialog
 | 
			
		||||
        open={isoCatalog}
 | 
			
		||||
        onClose={() => setIsoCatalog(false)}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user