@@ -2,41 +2,288 @@
import type { ReactView } from "@ethicdevs/react-monolith";
// 3rd-party
import React from "react";
-// generated via script[prisma:generate]
-import type { Pipeline } from "@prisma/client";
+// generated via script[generate:prisma]
+import type { Organization, Pipeline } from "@prisma/client";
// app
-import type { CommonProps } from "../../types";
-// import { AppRoute } from "../../routes.defs";
+import type { CommonProps, RepositoryWithForkedFromRepo } from "../../types";
+import { AppRoute } from "../../routes.defs";
+import { Card } from "../../components/Card.styled";
+import { Chip } from "../../components/Chip";
+import { Grid } from "../../components/Grid";
+import { Layout } from "../../components/Layout";
+import { PageWrapper } from "../../components/PageWrapper";
+import { buildRouteLink } from "../../utils/shared";
+import { Colors, NamedColors } from "../../utils/style";
+// app islands
+import { IslandWrapper } from "../../components/IslandWrapper.styled";
+import RepositoryHero from "../../islands/RepositoryHero";
-export interface PipelinesViewProps extends CommonProps {
+type PipelinesFilter = "all" | "pending" | "running" | "failed" | "canceled";
+
+export interface RepositoryPipelinesViewProps extends CommonProps {
+ parentOrg: Organization;
pipelines: Pipeline[];
- orgSlug: string;
- repoSlug: string;
+ repo: RepositoryWithForkedFromRepo;
+ pipelinesFilter?: PipelinesFilter;
}
-const PipelinesView: ReactView<PipelinesViewProps> = ({
- // commonProps,
+const RepositoryPipelinesView: ReactView<RepositoryPipelinesViewProps> = ({
+ commonProps,
+ parentOrg,
pipelines,
- orgSlug,
- repoSlug,
+ repo,
+ pipelinesFilter = "success",
}) => {
return (
- <div>
- <h2>
- Pipelines for {orgSlug}/{repoSlug}
- </h2>
- <ul>
- {pipelines.map((p) => (
- <li key={p.id}>
- <span>
- {p.name ?? `Pipeline ${p.id}`} — status: {p.status ?? "unknown"}
- </span>
- </li>
- ))}
- </ul>
- </div>
+ <Layout
+ {...commonProps}
+ showDrawerPrimary
+ orgSlug={parentOrg.slug}
+ repoSlug={repo.slug}
+ >
+ <PageWrapper>
+ <IslandWrapper data-islandid={`${RepositoryHero.name}$$0`}>
+ <RepositoryHero
+ themeScheme={commonProps.themeScheme}
+ forkedFromRepo={repo.forkedFromRepo}
+ forksCount={repo.forks.length}
+ parentOrg={parentOrg}
+ path={`Pipelines`}
+ repo={repo}
+ showForkButton={false}
+ showNewButton
+ newButtonText={"Trigger Pipeline"}
+ // newButtonText={
+ // <>
+ // <span>New Pull Request</span>
+ // <GitPullIcon
+ // color={Colors.WHITE_01}
+ // size={24}
+ // />
+ // </>
+ // }
+ newButtonUrl={buildRouteLink(
+ AppRoute.REPOSITORY_PIPELINE_TRIGGER_ACTION,
+ {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ pipelineId: "", // @fixme: ???
+ },
+ )}
+ />
+ </IslandWrapper>
+ <Grid.Col
+ fluid
+ style={{
+ padding: "12px 0",
+ borderBottom: `1px solid ${NamedColors.BORDER_DEFAULT[commonProps.themeScheme]}`,
+ }}
+ >
+ <Grid.Row
+ fluid
+ alignItems={"center"}
+ gap={12}
+ style={{ padding: "0 8px" }}
+ >
+ <a
+ style={{
+ fontWeight: pipelinesFilter === "all" ? "bold" : "normal",
+ textDecoration:
+ pipelinesFilter === "all" ? "underline" : "none",
+ }}
+ href={`/${parentOrg.slug}/${repo.slug}/pipelines?filter=${
+ "all" as PipelinesFilter
+ }`}
+ >
+ <Grid.Row nowrap gap={8} alignItems={"center"}>
+ <span>All</span>
+ <Chip themeScheme={commonProps.themeScheme}>
+ {commonProps.layoutCounters!.pullsTotal}
+ </Chip>
+ </Grid.Row>
+ </a>
+ <a
+ style={{
+ fontWeight: pipelinesFilter === "passed" ? "bold" : "normal",
+ textDecoration:
+ pipelinesFilter === "passed" ? "underline" : "none",
+ }}
+ href={`/${parentOrg.slug}/${repo.slug}/pipelines?filter=${
+ "passed" as PipelinesFilter
+ }`}
+ >
+ <Grid.Row nowrap gap={8} alignItems={"center"}>
+ <span>Passed!</span>
+ <Chip themeScheme={commonProps.themeScheme}>
+ {commonProps.layoutCounters!.pullsOpen}
+ </Chip>
+ </Grid.Row>
+ </a>
+ <a
+ style={{
+ fontWeight: pipelinesFilter === "pending" ? "bold" : "normal",
+ textDecoration:
+ pipelinesFilter === "pending" ? "underline" : "none",
+ }}
+ href={`/${parentOrg.slug}/${repo.slug}/pipelines?filter=${
+ "pending" as PipelinesFilter
+ }`}
+ >
+ <Grid.Row nowrap gap={8} alignItems={"center"}>
+ <span>Pending</span>
+ <Chip themeScheme={commonProps.themeScheme}>
+ {commonProps.layoutCounters!.pullsMerged}
+ </Chip>
+ </Grid.Row>
+ </a>
+ <a
+ style={{
+ fontWeight: pipelinesFilter === "running" ? "bold" : "normal",
+ textDecoration:
+ pipelinesFilter === "running" ? "underline" : "none",
+ }}
+ href={`/${parentOrg.slug}/${repo.slug}/pipelines?filter=${
+ "running" as PipelinesFilter
+ }`}
+ >
+ <Grid.Row nowrap gap={8} alignItems={"center"}>
+ <span>Closed</span>
+ <Chip themeScheme={commonProps.themeScheme}>
+ {commonProps.layoutCounters!.pullsClosed}
+ </Chip>
+ </Grid.Row>
+ </a>
+ <a
+ style={{
+ fontWeight: pipelinesFilter === "failed" ? "bold" : "normal",
+ textDecoration:
+ pipelinesFilter === "failed" ? "underline" : "none",
+ }}
+ href={`/${parentOrg.slug}/${repo.slug}/pipelines?filter=${
+ "failed" as PipelinesFilter
+ }`}
+ >
+ <Grid.Row nowrap gap={8} alignItems={"center"}>
+ <span>Failed</span>
+ <Chip themeScheme={commonProps.themeScheme}>
+ {commonProps.layoutCounters!.pullsClosed}
+ </Chip>
+ </Grid.Row>
+ </a>
+ <a
+ style={{
+ fontWeight: pipelinesFilter === "canceled" ? "bold" : "normal",
+ textDecoration:
+ pipelinesFilter === "canceled" ? "underline" : "none",
+ }}
+ href={`/${parentOrg.slug}/${repo.slug}/pipelines?filter=${
+ "canceled" as PipelinesFilter
+ }`}
+ >
+ <Grid.Row nowrap gap={8} alignItems={"center"}>
+ <span>Canceled</span>
+ <Chip themeScheme={commonProps.themeScheme}>
+ {commonProps.layoutCounters!.pullsClosed}
+ </Chip>
+ </Grid.Row>
+ </a>
+ </Grid.Row>
+ </Grid.Col>
+ <Grid.Col fluid gap={4} style={{ marginTop: 12 }}>
+ {pipelines != null && pipelines.length >= 1 ? (
+ pipelines.map((pipeline) => (
+ <Card
+ key={pipeline.id}
+ themeScheme={commonProps.themeScheme}
+ style={{ width: "100%", padding: 8 }}
+ >
+ <Grid.Col fluid>
+ <a
+ style={{ width: "100%" }}
+ href={buildRouteLink(AppRoute.REPOSITORY_PIPELINE_DETAILS, {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ pipelineId: pipeline.id,
+ })}
+ >
+ <Grid.Row fluid alignItems={"center"} gap={4}>
+ <span>id: {pipeline.id}</span>
+ <span>•</span>
+ <span style={{ flex: 1 }}>{pipeline.name}</span>
+ <Chip
+ themeScheme={commonProps.themeScheme}
+ color={
+ {
+ PENDING: Colors.PRIMARY_01,
+ RUNNING: Colors.CYAN_01,
+ PASSED: Colors.GREEN_01,
+ FAILED: Colors.RED_01,
+ CANCELED: Colors.BLACK_01,
+ }[pipeline.status]
+ }
+ >
+ {
+ {
+ PENDING: "Pending",
+ RUNNING: "Running",
+ PASSED: "Passed",
+ FAILED: "Failed",
+ CANCELED: "Canceled",
+ }[pipeline.status]
+ }
+ </Chip>
+ </Grid.Row>
+ </a>
+ <Grid.Row
+ fluid
+ nowrap
+ gap={8}
+ alignItems={"center"}
+ style={{ opacity: 0.67 }}
+ >
+ triggered by
+ <Chip
+ themeScheme={commonProps.themeScheme}
+ style={{ textTransform: "none" }}
+ >
+ <code>{""}</code>
+ </Chip>
+ </Grid.Row>
+ </Grid.Col>
+ </Card>
+ ))
+ ) : (
+ <Grid.Col
+ fluid
+ nowrap
+ justifyContent={"center"}
+ alignItems={"center"}
+ style={{ minHeight: "70vh" }}
+ >
+ <h1 style={{ margin: 0 }}>No Pull Request Yet</h1>
+ <p style={{ maxWidth: "62%", textAlign: "center" }}>
+ <span>Be the change you want to see, </span>
+ <a
+ href={buildRouteLink(
+ AppRoute.REPOSITORY_PIPELINE_TRIGGER_ACTION,
+ {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ pipelineId: "", // @fixme: ???
+ },
+ )}
+ >
+ trigger the first Pipeline run
+ </a>
+ <span> to this repository 🚀.</span>
+ </p>
+ </Grid.Col>
+ )}
+ </Grid.Col>
+ </PageWrapper>
+ </Layout>
);
};
-PipelinesView.displayName = "PipelinesView";
-export default PipelinesView;
+RepositoryPipelinesView.displayName = "RepositoryPipelinesView";
+export default RepositoryPipelinesView;