.ts
TypeScript
(application/typescript)
// 1st-party
import type { ReactIsland } from "@ethicdevs/react-monolith";
// 3rd-party
import React, { useCallback } from "react";
import styled from "styled-components";
// app
import type { RepositoryFile, RepositoryLog } from "../types";
import { Grid, TextEllipsis } from "../components";
// import RepositoryCommitSummaryLine from "./RepositoryCommitSummaryLine";

export interface RepositoryTreeViewProps {
  currentPath: string;
  currentRef: string;
  lastCommit: RepositoryLog;
  orgSlug: string;
  repoFiles: RepositoryFile[];
  repoSlug: string;
}

const RepositoryTreeView: ReactIsland<RepositoryTreeViewProps> = ({
  currentPath,
  currentRef,
  // lastCommit,
  orgSlug,
  repoFiles,
  repoSlug,
}) => {
  const buildRepoFileLink = useCallback(
    (file: RepositoryFile) => {
      const fileName = `${file.name}${file.type === "tree" ? "/" : ""}`;
      return {
        text: fileName,
        href:
          currentPath === "/"
            ? `/${orgSlug}/${repoSlug}/${encodeURIComponent(
                currentRef
              )}/tree/${encodeURIComponent(fileName)}`
            : `/${orgSlug}/${repoSlug}/${encodeURIComponent(currentRef)}/tree/${
                currentPath.endsWith("/") || currentPath === ""
                  ? currentPath
                  : `${currentPath}/`
              }${fileName}`,
      };
    },
    [orgSlug, repoSlug, currentPath]
  );

  const currPathParts = currentPath.split("/");

  let prevPath: string | null = currPathParts
    .slice(0, currPathParts.length - 2)
    .join("/");
  prevPath = prevPath.trim() === "" ? null : prevPath;
  prevPath = prevPath == null ? "/" : prevPath;

  const prevPathLink =
    prevPath === "/"
      ? `/${orgSlug}/${repoSlug}`
      : `/${orgSlug}/${repoSlug}/${encodeURIComponent(currentRef)}/tree/${
          prevPath.endsWith("/") ? prevPath : `${prevPath}/`
        }`;
  const shouldShowPrevPath = currentPath !== "/";

  return (
    <StyledRepositoryTreeViewContainer>
      <Grid.Col fluid>
        <Grid.Row
          gap={8}
          alignItems={"center"}
          justifyContent={"flex-end"}
          style={{
            marginTop: 8,
            width: "100%",
            padding: "0 8px 8px 8px",
            borderBottom: "1px solid gray",
          }}
        >
          <a
            href={`/${orgSlug}/${repoSlug}/${encodeURIComponent(
              currentRef
            )}/commits`}
          >
            Commits History
          </a>
        </Grid.Row>
        <Grid.Col fluid nowrap>
          <ul style={{ listStyle: "none", padding: 0, width: "100%" }}>
            {shouldShowPrevPath && (
              <li key={"go-previous"}>
                <StyledTreeViewAnchorItem href={prevPathLink}>
                  ..
                </StyledTreeViewAnchorItem>
              </li>
            )}
            {repoFiles.map((file) => {
              const fileLink = buildRepoFileLink(file);
              return (
                <li key={[file.id, file.name].join(":")}>
                  <StyledTreeViewAnchorItem href={fileLink.href}>
                    <span style={{ flex: "0 0 240px" }}>{fileLink.text}</span>
                    {file.lastCommit != null && (
                      <>
                        <span style={{ flex: 1, marginLeft: 16 }}>
                          <TextEllipsis>{file.lastCommit.subject}</TextEllipsis>
                        </span>
                        <span style={{ marginLeft: 16 }}>
                          {file.lastCommit.abbreviated_commit}
                        </span>
                      </>
                    )}
                  </StyledTreeViewAnchorItem>
                </li>
              );
            })}
          </ul>
        </Grid.Col>
      </Grid.Col>
    </StyledRepositoryTreeViewContainer>
  );
};

const StyledTreeViewAnchorItem = styled.a`
  display: flex;
  flex-flow: row nowrap;
  justify-content: flex-start;
  align-items: center;

  height: 30px;
  width: 100%;

  padding: 0 8px;

  border-bottom: 1px solid gray;

  &:hover {
    background-color: rgba(0, 0, 0, 0.2);
  }
`;

const StyledRepositoryTreeViewContainer = styled.div`
  width: 100%;
`;

RepositoryTreeView.displayName = "RepositoryTreeView";
export default RepositoryTreeView;