Skip to content
Snippets Groups Projects
BucketInspector.tsx 3.01 KiB
Newer Older
import { getHumanSize } from "../commons/utils";
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
import { BucketObject } from "../models/bucket";
import { Button } from "./Button";
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
import { Inspector, InspectorProps } from "./Inspector";
import {
  ArrowDownCircleIcon,
  InformationCircleIcon,
  TrashIcon,
  XMarkIcon
} from "@heroicons/react/24/outline";
import { useS3Service } from "../services/S3Service";

Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
interface BucketInspectorProps extends InspectorProps {
  bucket: string;
  objects: BucketObject[]

interface DetailProps {
  title: string;
  value?: string;
}

const Detail = ({ title, value }: DetailProps) => {
  return (
    <div className="my-4">
      <div className="text-lg font-semibold">{title}</div>
      <div className="break-all">{value}</div>
    </div>
  )
}

const ObjectDetail = (object: BucketObject) => {
  return (
    <>
      <div className="flex items-center">
        <div className="text-lg font-semibold">Object Info</div>
        <div className="ml-4 w-5"><InformationCircleIcon /></div>
      </div>
      <Detail title={"Key"} value={object.Key} />
      <Detail title={"ETag"} value={object.ETag} />
      <Detail title={"Last Modified"} value={object.LastModified?.toString()} />
      <Detail title={"Owner"} value={object.Owner?.ID} />
      <Detail title={"Size"} value={getHumanSize(object.Size ?? 0)} />
    </>
  )
}

Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
export const BucketInspector = (props: BucketInspectorProps) => {

  const { bucket, objects } = props;
  const title = objects.length === 1 ? objects[0].Key : "Multiple objects";
  const object = objects[0];
  const { fetchObject } = useS3Service();

  const downloadObject = async () => {
    try {
      const response = await fetchObject(bucket, object.Key!);
      const body = await response.transformToByteArray();
      const newBlob = new Blob([body]);
      const blobUrl = window.URL.createObjectURL(newBlob);
      const link = document.createElement('a');
      link.href = blobUrl;
      link.setAttribute('download', object.Key!);
      document.body.appendChild(link);
      link.click();
      link.parentNode?.removeChild(link);
      window.URL.revokeObjectURL(blobUrl);
    } catch (err) {
      console.error(err);
    }
  }

  const Title = () => {
    return (
      <div className="text-xl font-semibold">
        {title}
      </div>
    )
  }

Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
  return (
    <Inspector
      isOpen={props.isOpen}>
      <div className="flex items-center p-4">
        <Title />
        <button>
          <div
            className="w-8 p-[5px] bg-neutral-300 text-neutral-500
             hover:bg-neutral-400 rounded-full">
            <XMarkIcon />
          </div>
        </button>
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
      </div>
      <div className="p-4">
        <Button
          className="w-full"
          title="Download"
          icon={<ArrowDownCircleIcon />}
          onClick={downloadObject}
        />
        <Button className="w-full mt-4" title="Delete" icon={<TrashIcon />} />
        <hr className="h-px w-full my-8 bg-gray-200 border-0 dark:bg-gray-700"></hr>
        <ObjectDetail {...object} />
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
    </Inspector>
  )