GitFOSS
.ts
TypeScript
(application/typescript)
// 1st-party
import type { ReactIsland } from "@ethicdevs/react-monolith";
// 3rd-party
import React from "react";
// generated via script[generate:prisma]
import type { Organization, Repository } from "@prisma/client";
// app
import type {
  AppThemeScheme,
  RepositoryFileDiff,
  RepositoryForkedFromRepoMeta,
} from "../types";
import { Grid } from "../components/Grid";
import { IslandWrapper } from "../components/IslandWrapper.styled";
// app islands
import RepositoryFilesDiffsList from "./RepositoryFilesDiffsList";

export enum PullRequestFormState {
  CONFIGURE = "configure",
  COMPARE = "compare",
  DETAILS = "input_details",
  ERROR = "error",
}

export interface RepositoryPullRequestCreateFormPropsCommon {
  errorMessage?: string | null;
}

export interface RepositoryPullRequestTarget {
  parentOrg: Organization;
  repo: Repository;
  branch: string;
}
export type RepositoryPullRequestCreateFormPropsByState<
  S extends PullRequestFormState = PullRequestFormState
> = S extends PullRequestFormState.CONFIGURE
  ? {
      source: {
        branches: string[];
        parentOrg: Organization;
        repo: Repository;
        isFork: boolean;
        forkedFromRepoMetas?: RepositoryForkedFromRepoMeta;
      };
      initialTarget?: RepositoryPullRequestTarget;
    }
  : S extends PullRequestFormState.COMPARE
  ? {
      fileDiffs: RepositoryFileDiff[];
      source: RepositoryPullRequestTarget;
      target: RepositoryPullRequestTarget;
    }
  : S extends PullRequestFormState.DETAILS
  ? {
      canCurrentUserSubmitPullRequest: boolean;
    }
  : S extends PullRequestFormState.ERROR
  ? {
      errorMessage: string;
    }
  : never;

export type RepositoryPullRequestCreateFormVariant =
  | {
      state: PullRequestFormState.CONFIGURE;
      data: RepositoryPullRequestCreateFormPropsByState<PullRequestFormState.CONFIGURE>;
    }
  | {
      state: PullRequestFormState.COMPARE;
      data: RepositoryPullRequestCreateFormPropsByState<PullRequestFormState.COMPARE>;
    }
  | {
      state: PullRequestFormState.DETAILS;
      data: RepositoryPullRequestCreateFormPropsByState<PullRequestFormState.DETAILS>;
    }
  | {
      state: PullRequestFormState.ERROR;
      data: RepositoryPullRequestCreateFormPropsByState<PullRequestFormState.ERROR>;
    };

export interface RepositoryPullRequestCreateFormProps
  extends RepositoryPullRequestCreateFormPropsCommon {
  themeScheme: AppThemeScheme;
  variant: RepositoryPullRequestCreateFormVariant;
}

// PullRequestFormState.CONFIGURE
const isConfigureState = (
  s: PullRequestFormState
): s is PullRequestFormState.CONFIGURE =>
  typeof s !== "undefined" && s != null && s === PullRequestFormState.CONFIGURE;
const isConfigureStateData = (
  s: PullRequestFormState,
  i: unknown
): i is RepositoryPullRequestCreateFormPropsByState<PullRequestFormState.CONFIGURE> =>
  typeof i !== "undefined" && i != null && s === PullRequestFormState.CONFIGURE;
// PullRequestFormState.COMPARE
const isCompareState = (
  s: PullRequestFormState
): s is PullRequestFormState.COMPARE =>
  typeof s !== "undefined" && s != null && s === PullRequestFormState.COMPARE;
const isCompareStateData = (
  s: PullRequestFormState,
  i: unknown
): i is RepositoryPullRequestCreateFormPropsByState<PullRequestFormState.COMPARE> =>
  typeof i !== "undefined" && i != null && s === PullRequestFormState.COMPARE;
// PullRequestFormState.DETAILS
const isDetailsState = (
  s: PullRequestFormState
): s is PullRequestFormState.DETAILS =>
  typeof s !== "undefined" && s != null && s === PullRequestFormState.DETAILS;
const isDetailsStateData = (
  s: PullRequestFormState,
  i: unknown
): i is RepositoryPullRequestCreateFormPropsByState<PullRequestFormState.DETAILS> =>
  typeof i !== "undefined" && i != null && s === PullRequestFormState.DETAILS;
// PullRequestFormState.ERROR
const isErrorState = (
  s: PullRequestFormState
): s is PullRequestFormState.ERROR =>
  typeof s !== "undefined" && s != null && s === PullRequestFormState.ERROR;
const isErrorStateData = (
  s: PullRequestFormState,
  i: unknown
): i is RepositoryPullRequestCreateFormPropsByState<PullRequestFormState.ERROR> =>
  typeof i !== "undefined" && i != null && s === PullRequestFormState.ERROR;

const RepositoryPullRequestCreateForm: ReactIsland<RepositoryPullRequestCreateFormProps> =
  ({ themeScheme, variant: { state, data } }) => {
    // PullRequestFormState.CONFIGURE
    if (isConfigureState(state) && isConfigureStateData(state, data)) {
      return (
        <Grid.Col fluid nowrap>
          <h1>Configure input and output (org, repo, branch)</h1>
          <form
            method={"POST"}
            action={`/${data.source.parentOrg.slug}/${data.source.repo.slug}/pulls/new`}
          >
            <input type={"hidden"} name={"state_from"} value={state} />
            <input
              type={"hidden"}
              name={"state_dest"}
              value={PullRequestFormState.COMPARE}
            />
            <input
              type={"hidden"}
              name={"source_parent_org_slug"}
              value={data.source.parentOrg.slug}
            />
            <input
              type={"hidden"}
              name={"source_repository_slug"}
              value={data.source.repo.slug}
            />
            <input
              type={"hidden"}
              name={"target_parent_org_slug"}
              value={
                data.initialTarget?.parentOrg.slug || data.source.parentOrg.slug
              }
            />
            <input
              type={"hidden"}
              name={"target_repository_slug"}
              value={
                data.initialTarget?.parentOrg.slug || data.source.repo.slug
              }
            />

            <div>
              <span>Source:</span>
            </div>
            <input
              disabled
              type={"text"}
              name={"source_parent_org_display_name"}
              value={
                data.source.parentOrg.displayName || data.source.parentOrg.slug
              }
            />
            {" / "}
            <input
              disabled
              type={"text"}
              name={"source_repository_display_name"}
              value={data.source.repo.displayName || data.source.repo.slug}
            />
            {" / "}
            <select name={"source_repository_from_branch"}>
              {data.source.branches.map((branch, idx) => (
                <option key={[branch, idx].join(":")} value={branch}>
                  {branch}
                </option>
              ))}
            </select>

            {/* VS. */}

            <div>
              <span>Target:</span>
            </div>

            <input
              disabled
              type={"text"}
              name={"target_parent_org_display_name"}
              value={
                data.initialTarget?.parentOrg.displayName ||
                data.initialTarget?.parentOrg.slug ||
                data.source.parentOrg.displayName ||
                data.source.parentOrg.slug
              }
            />
            {" / "}
            <input
              disabled
              type={"text"}
              name={"target_repository_display_name"}
              value={
                data.initialTarget?.repo.displayName ||
                data.initialTarget?.repo.slug ||
                data.source.repo.displayName ||
                data.source.repo.slug
              }
            />
            {" / "}
            <select
              name={"target_repository_dest_branch"}
              defaultValue={
                data.initialTarget != null
                  ? data.initialTarget.branch
                  : data.source.branches.length >= 1
                  ? data.source.branches[0]
                  : undefined
              }
            >
              {data.initialTarget != null && (
                <option
                  key={data.initialTarget.branch}
                  value={data.initialTarget.branch}
                >
                  {data.initialTarget.branch}
                </option>
              )}
              {data.source.branches.map((branch, idx) => (
                <option key={[branch, idx].join(":")} value={branch}>
                  {branch}
                </option>
              ))}
            </select>

            <button type={"submit"}>Go to COMPARE step</button>
          </form>
        </Grid.Col>
      );
    }
    // PullRequestFormState.COMPARE
    if (isCompareState(state) && isCompareStateData(state, data)) {
      return (
        <Grid.Col fluid nowrap>
          <h1>Compare input and output (org, repo, branch)</h1>
          <form
            method={"POST"}
            action={`/${data.source.parentOrg.slug}/${data.source.repo.slug}/pulls/new`}
          >
            <input type={"hidden"} name={"state_from"} value={state} />
            <input
              type={"hidden"}
              name={"state_dest"}
              value={PullRequestFormState.DETAILS}
            />
            <button type={"submit"}>Go to DETAILS step</button>
          </form>
          <IslandWrapper data-islandid={`${RepositoryFilesDiffsList.name}$$0`}>
            <RepositoryFilesDiffsList
              filesDiffs={data.fileDiffs}
              themeScheme={themeScheme}
              orgSlug={data.source.parentOrg.slug}
              repoSlug={data.source.repo.slug}
              commitHash={""}
            />
          </IslandWrapper>
        </Grid.Col>
      );
    }
    // PullRequestFormState.DETAILS
    if (isDetailsState(state) && isDetailsStateData(state, data)) {
      return (
        <Grid.Col fluid nowrap>
          <h1>Add details about the Pull Request:</h1>
          <form
            method={"POST"}
            // action={`/${data.source.parentOrg.slug}/${data.source.repo.slug}/pulls/new`}
          >
            <input type={"hidden"} name={"state_from"} value={state} />
            <button type={"submit"}>Submit the Pull Request</button>
          </form>
          <div>
            <pre>
              <code>{JSON.stringify(data, null, 2)}</code>
            </pre>
          </div>
        </Grid.Col>
      );
    }
    // PullRequestFormState.ERROR
    if (isErrorState(state) && isErrorStateData(state, data)) {
      const { errorMessage } = data;
      return (
        <Grid.Col fluid nowrap>
          <h1>Woops, an error occurred:</h1>
          <div>{errorMessage}</div>
        </Grid.Col>
      );
    }
    return null;
  };

RepositoryPullRequestCreateForm.displayName = "RepositoryPullRequestCreateForm";
export default RepositoryPullRequestCreateForm;