vorteil/direktiv

View on GitHub
ui/src/pages/namespace/Explorer/Workflow/ApiCommands/index.tsx

Summary

Maintainability
C
1 day
Test Coverage
import { BookOpen, TerminalSquare } from "lucide-react";
import {
  DialogClose,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "~/design/Dialog";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "~/design/Select";
import { useApiCommandTemplate, useCurlCommand } from "./utils";
import { useEffect, useState } from "react";

import Badge from "~/design/Badge";
import Button from "~/design/Button";
import { Card } from "~/design/Card";
import CopyButton from "~/design/CopyButton";
import Editor from "~/design/Editor";
import Input from "~/design/Input";
import { useTheme } from "~/util/store/theme";
import { useTranslation } from "react-i18next";

const ApiCommands = ({
  namespace: namespaceFromUrl,
  path: pathFromUrl,
}: {
  namespace: string;
  path: string;
}) => {
  const theme = useTheme();
  const { t } = useTranslation();

  const [path, setPath] = useState(pathFromUrl);
  const [namespace, setNamespace] = useState(namespaceFromUrl);

  const apiCommandTemplates = useApiCommandTemplate(namespace, path);
  const interactions = apiCommandTemplates.map((t) => t.key);
  const [selectedInteraction, setSelectedInteraction] = useState(
    interactions[0]
  );

  const selectedTemplate = apiCommandTemplates.find(
    (template) => template.key === selectedInteraction
  );

  const [body, setBody] = useState(selectedTemplate?.body ?? "");

  const curlCommand = useCurlCommand({
    url: selectedTemplate?.url ?? "",
    body: selectedTemplate?.bodyProcessing?.(body) ?? body,
    method: selectedTemplate?.method ?? "",
  });

  useEffect(() => {
    if (selectedTemplate) {
      setBody(selectedTemplate.body);
    }
  }, [selectedTemplate]);

  const disableCopyButton = !namespace || !path;

  return (
    <>
      <DialogHeader>
        <DialogTitle>
          <TerminalSquare />
          {t("pages.explorer.workflow.apiCommands.title")}
        </DialogTitle>
      </DialogHeader>
      <div className="my-3">
        <div className="flex flex-col gap-y-5">
          <fieldset className="flex items-center gap-5">
            <label
              className="w-[100px] text-right text-[14px]"
              htmlFor="namespace-name"
            >
              {t("pages.explorer.workflow.apiCommands.namespace")}
            </label>
            <Input
              id="namespace-name"
              value={namespace}
              onChange={(e) => setNamespace(e.target.value)}
              placeholder={t(
                "pages.explorer.workflow.apiCommands.namespacePlaceholder"
              )}
            />
          </fieldset>
          <fieldset className="flex items-center gap-5">
            <label
              className="w-[100px] text-right text-[14px]"
              htmlFor="workflow-name"
            >
              {t("pages.explorer.workflow.apiCommands.workflow")}
            </label>
            <Input
              id="workflow-name"
              value={path}
              onChange={(e) => setPath(e.target.value)}
              placeholder={t(
                "pages.explorer.workflow.apiCommands.workflowPlaceholder"
              )}
            />
          </fieldset>
          <fieldset className="flex items-center gap-5">
            <label
              className="w-[100px] text-right text-[14px]"
              htmlFor="template"
            >
              {t("pages.explorer.workflow.apiCommands.interaction")}
            </label>
            <Select
              onValueChange={(value) => {
                const matchingTemplate = apiCommandTemplates.find(
                  (template) => template.key === value
                );
                if (matchingTemplate) {
                  setSelectedInteraction(matchingTemplate.key);
                }
              }}
            >
              <SelectTrigger id="template" variant="outline" block>
                <SelectValue
                  defaultValue={selectedInteraction}
                  placeholder={
                    selectedInteraction
                      ? t(
                          `pages.explorer.workflow.apiCommands.labels.${selectedInteraction}`
                        )
                      : t(
                          `pages.explorer.workflow.apiCommands.interactionPlaceholder`
                        )
                  }
                />
              </SelectTrigger>
              <SelectContent>
                {interactions.map((command) => (
                  <SelectItem value={command} key={command}>
                    {t(`pages.explorer.workflow.apiCommands.labels.${command}`)}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </fieldset>
          <Card
            className="grid grid-cols-[auto_1fr] items-center gap-5 break-all p-4 text-sm"
            noShadow
            background="weight-1"
          >
            <Badge variant="success" className="w-max">
              {selectedTemplate?.method}
            </Badge>
            <pre className="whitespace-pre-wrap text-primary-500">
              {selectedTemplate?.url}
            </pre>
          </Card>
          <Card className="h-44 p-4" noShadow background="weight-1">
            <Editor
              value={selectedTemplate?.body}
              language={selectedTemplate?.payloadSyntax}
              onChange={(data) => {
                if (data && selectedTemplate) {
                  setBody(data);
                }
              }}
              theme={theme ?? undefined}
            />
          </Card>
        </div>
      </div>
      <DialogFooter>
        <DialogClose asChild>
          <Button variant="ghost">Close</Button>
        </DialogClose>
        <Button variant="outline" asChild isAnchor>
          <a
            href="https://docs.direktiv.io/api/"
            target="_blank"
            rel="noopener noreferrer"
          >
            <BookOpen />
            {t("pages.explorer.workflow.apiCommands.openDocsBtn")}
          </a>
        </Button>
        <CopyButton
          value={curlCommand}
          buttonProps={{
            variant: "outline",
            className: "w-60",
            disabled: disableCopyButton,
          }}
        >
          {(copied) =>
            copied
              ? t("pages.explorer.workflow.apiCommands.copyBtnCopied")
              : t("pages.explorer.workflow.apiCommands.copyBtn")
          }
        </CopyButton>
      </DialogFooter>
    </>
  );
};

export default ApiCommands;