.ts
TypeScript
(application/typescript)
// 1st-party
import type { ReactIsland } from "@ethicdevs/react-monolith";
// 3rd-party
import React, { useCallback, useState } from "react";
// generated via script[generate:prisma]
import type { Organization } from "@prisma/client";
// app
import { Grid } from "../components/Grid";

export interface RepositoryCreateFormProps {
  availableParentOrgs: Organization[];
  editMode?: boolean;
  initialValues?: {
    parent_org_slug?: string;
    repo_slug?: string;
    repo_display_name?: string;
    repo_short_description?: string;
    repo_website_url?: string;
    repo_keywords?: string[];
  };
}

const RepositoryCreateForm: ReactIsland<RepositoryCreateFormProps> = ({
  availableParentOrgs,
  editMode = false,
  initialValues = undefined,
}) => {
  const [keywords, setKeywords] = useState<string[]>([
    ...(initialValues?.repo_keywords || []),
  ]);
  const [repoInitLicenseFileChecked, setRepoInitLicenseFileChecked] =
    useState<boolean>(false);

  editMode;

  const onKeywordsInputChange = useCallback(
    (ev: React.ChangeEvent<HTMLInputElement>) => {
      if (ev == null || ev.target == null || ev.target.value == null) {
        return undefined;
      }
      setKeywords(ev.target.value.split(",").map((w) => w.trim()));
      return undefined;
    },
    [setKeywords]
  );

  const onRepoInitLicenseFileChange = useCallback(
    (ev: React.ChangeEvent<HTMLInputElement>) => {
      if (ev == null || ev.target == null || ev.target.value == null) {
        return undefined;
      }
      setRepoInitLicenseFileChecked(ev.target.checked);
      return undefined;
    },
    [setRepoInitLicenseFileChecked]
  );

  return (
    <div>
      <fieldset>
        <legend>Repository details</legend>
        {/* Parent Organization Select */}
        <Grid.Col fluid nowrap>
          <label htmlFor={"repo_display_name"}>
            Owner Organization <span>(*)</span>:
          </label>
          <select
            style={styles.inputMaxWidth}
            defaultValue={initialValues?.parent_org_slug}
            name={"parent_org_slug"}
            required
          >
            {availableParentOrgs.map((org) => (
              <option key={org.id} value={org.slug}>
                {org.displayName || org.slug}
              </option>
            ))}
          </select>
        </Grid.Col>
        {/* Repository Name */}
        <Grid.Col fluid nowrap>
          <label htmlFor={"repo_display_name"}>
            Repository Name <span>(*)</span>:
          </label>
          <input
            style={styles.inputMaxWidth}
            defaultValue={initialValues?.repo_display_name}
            name={"repo_display_name"}
            placeholder={"i.e. My Super Project"}
            required
            type={"text"}
          />
        </Grid.Col>
        {/* Repository Slug */}
        <Grid.Col fluid nowrap>
          <label htmlFor={"repo_slug"}>
            Repository Slug <span>(*)</span>:
          </label>
          <input
            style={styles.inputMaxWidth}
            defaultValue={initialValues?.repo_slug}
            name={"repo_slug"}
            placeholder={"i.e. my-super-project"}
            required
            type={"text"}
          />
        </Grid.Col>
      </fieldset>
      <fieldset>
        <legend>Repository description</legend>
        {/* Short Description */}
        <Grid.Col fluid nowrap>
          <label htmlFor={"repo_short_description"}>Short Description:</label>
          <textarea
            style={styles.inputMaxWidth}
            defaultValue={initialValues?.repo_short_description}
            name={"repo_short_description"}
            placeholder={"i.e. A super project about things that are super!"}
          ></textarea>
        </Grid.Col>
        {/* Website URL */}
        <Grid.Col fluid nowrap>
          <label htmlFor={"repo_website_url"}>Website URL:</label>
          <input
            style={styles.inputMaxWidth}
            defaultValue={initialValues?.repo_website_url}
            name={"repo_website_url"}
            placeholder={"i.e. https://www.super-project.com"}
            type={"text"}
          />
        </Grid.Col>
        {/* Keywords */}
        <Grid.Col fluid nowrap>
          <label htmlFor={"repo_keywords_add"}>Keywords:</label>
          <input type={"hidden"} name={"repo_keywords"} value={keywords} />
          <input
            style={styles.inputMaxWidth}
            name={"repo_keywords_add"}
            placeholder={"Keywords separated by a coma (,)..."}
            type={"text"}
            onChange={onKeywordsInputChange}
          />
          {keywords.map((word, idx) => (
            <input
              style={styles.inputMaxWidth}
              key={[idx, word].join(":")}
              disabled
              type={"text"}
              value={word}
            />
          ))}
        </Grid.Col>
      </fieldset>
      <fieldset>
        <legend>Repository setup</legend>
        {/* Initialise Read Me file? */}
        <Grid.Row fluid nowrap>
          <label htmlFor={"repo_init_readme_file"} style={styles.inputMaxWidth}>
            Initialize with empty README.md file?
          </label>
          <input
            type={"checkbox"}
            name={"repo_init_readme_file"}
            defaultChecked={false}
          />
        </Grid.Row>
        <Grid.Row fluid nowrap>
          {/* Initialise License file? */}
          <label htmlFor={"repo_init_readme_file"} style={styles.inputMaxWidth}>
            Initialize with a LICENSE file?
          </label>
          <select
            disabled={repoInitLicenseFileChecked === false}
            name={"repo_init_license_kind"}
            defaultValue={"MIT"}
          >
            <option key={"license:mit"} value={"mit"}>
              MIT License
            </option>
            <option key={"license:gnu-gpl-v3"} value={"gnu-gpl-v3"}>
              GNU GPL v.3.0
            </option>
            <option key={"license:gnu-agpl-v3"} value={"gnu-agpl-v3"}>
              AGPL v.3.0
            </option>
            <option key={"license:gnu-lgpl-v3"} value={"gnu-lgpl-v3"}>
              LGPL v.3.0
            </option>
          </select>
          <input
            type={"checkbox"}
            name={"repo_init_license_file"}
            onChange={onRepoInitLicenseFileChange}
            checked={repoInitLicenseFileChecked}
          />
        </Grid.Row>
      </fieldset>
    </div>
  );
};

const styles = {
  inputMaxWidth: {
    width: "100%",
  },
};

RepositoryCreateForm.displayName = "RepositoryCreateForm";
export default RepositoryCreateForm;