LibraryActions

tcmts.studio.LibraryActions · #tj52o5gi · term · runs in the browser

uses useState

What to do with a library: Upgrade, which first says what upgrading would change (tcm lib upgrade --check), then does it; Remove, asking first, with what uses it (which would then use code nothing names).

import { checkLib, removeLib, toldOf, upgradeLib } from "#codebase/tcmts/studio";
import { useState } from "react";
import { Button, Dialog, DialogTrigger, Heading, Popover } from "react-aria-components";

export function LibraryActions({ path, users }: { path: string; users: string[] }) {
  const [check, setCheck] = useState<{ text: string; ok: boolean } | undefined>();
  const [busy, setBusy] = useState(false);
  return (
    <span className="actions rowacts">
      <DialogTrigger
        onOpenChange={(open) => {
          if (!open) return;
          setCheck(undefined);
          checkLib(path).then(
            (text) => setCheck({ text, ok: true }),
            (e: Error) => setCheck({ text: e.message, ok: false }),
          );
        }}
      >
        <Button className="btn small">Upgrade</Button>
        <Popover className="menu-pop getit wide" placement="bottom end" offset={6}>
          <Dialog className="getit-body" aria-label={`Upgrade ${path}`}>
            {({ close }) => {
              const current = !!check && check.ok && /\balready\b/.test(check.text);
              return (
                <>
                  <Heading slot="title" className="getit-title">
                    Upgrade {path}
                  </Heading>
                  {!check ? (
                    <p className="muted">Asking what its newest release changes…</p>
                  ) : (
                    <pre className={`code applog${check.ok ? "" : " bad"}`}>{check.text}</pre>
                  )}
                  <div className="actions">
                    <Button className="btn" onPress={close}>
                      {current || (check && !check.ok) ? "Close" : "Cancel"}
                    </Button>
                    {check?.ok && !current && (
                      <Button
                        className="btn primary"
                        isPending={busy}
                        onPress={async () => {
                          setBusy(true);
                          if (
                            await toldOf(
                              upgradeLib(path),
                              `Upgraded ${path}`,
                              `Couldn't upgrade ${path}`,
                            )
                          )
                            close();
                          setBusy(false);
                        }}
                      >
                        Upgrade
                      </Button>
                    )}
                  </div>
                </>
              );
            }}
          </Dialog>
        </Popover>
      </DialogTrigger>
      <DialogTrigger>
        <Button className="btn small danger">Remove</Button>
        <Popover className="menu-pop getit" placement="bottom end" offset={6}>
          <Dialog className="getit-body" aria-label={`Remove ${path}`}>
            {({ close }) => (
              <>
                <Heading slot="title" className="getit-title">
                  Remove {path}?
                </Heading>
                <p>
                  {users.length
                    ? `${users.length} definition${users.length === 1 ? " uses" : "s use"} it (${users.slice(0, 4).join(", ")}${users.length > 4 ? ", …" : ""}): ${users.length === 1 ? "it keeps" : "they keep"} working, by hash, using code nothing names then.`
                    : "Nothing outside it uses it. Its names go, and its entry in the record beside it; history keeps it."}
                </p>
                <div className="actions">
                  <Button className="btn" onPress={close}>
                    Keep it
                  </Button>
                  <Button
                    className="btn danger"
                    onPress={() => {
                      close();
                      void toldOf(removeLib(path), `Removed ${path}`, `Couldn't remove ${path}`);
                    }}
                  >
                    Remove
                  </Button>
                </div>
              </>
            )}
          </Dialog>
        </Popover>
      </DialogTrigger>
    </span>
  );
}

uses

used by