Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repository Config list page #19039

Merged
merged 17 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* See License.AGPL.txt in the project root for license information.
*/

import classNames from "classnames";
import { FunctionComponent, memo, ReactNode, useCallback } from "react";
import { useId } from "../../hooks/useId";
import { InputField } from "./InputField";
import { cn } from "@podkit/lib/cn";

type TextInputFieldTypes = "text" | "password" | "email" | "url";

Expand Down Expand Up @@ -97,7 +97,7 @@ export const TextInput: FunctionComponent<TextInputProps> = memo(
return (
<input
id={id}
className={classNames("w-full max-w-lg dark:text-[#A8A29E]", className)}
className={cn("w-full max-w-lg dark:text-[#A8A29E]", className)}
value={value}
type={type}
placeholder={placeholder}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ export const buttonVariants = cva(
outline: "border border-input bg-transparent hover:bg-kumquat-ripe hover:text-gray-600",
secondary:
"bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-500 dark:text-gray-100 hover:text-gray-600",
ghost: "hover:bg-kumquat-ripe hover:text-gray-600",
ghost: "bg-transparent hover:bg-gray-100 hover:text-gray-600 text-gray-500",
link: "text-gray-500 dark:text-gray-100 underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
icon: "h-9 w-9 p-0 rounded-sm",
},
},
defaultVariants: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License.AGPL.txt in the project root for license information.
*/

import { Heading1, Subheading } from "@podkit/typography/Headings";
import { FC, ReactNode } from "react";

type PageHeadingProps = {
title: string;
subtitle?: string;
action?: ReactNode;
};
export const PageHeading: FC<PageHeadingProps> = ({ title, subtitle, action }) => {
return (
<div className="flex flex-row flex-wrap justify-between py-8 gap-2">
<div>
<Heading1>{title}</Heading1>
{subtitle && <Subheading>{subtitle}</Subheading>}
</div>
{action && action}
</div>
);
};
68 changes: 68 additions & 0 deletions components/dashboard/src/components/podkit/tables/Table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License.AGPL.txt in the project root for license information.
*/

import { cn } from "@podkit/lib/cn";
import React from "react";

type HideableCellProps = {
hideOnSmallScreen?: boolean;
};

export const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(
({ className, ...props }, ref) => {
return (
<div className="relative w-full overflow-auto">
<table ref={ref} className={cn("w-full text-sm text-left", className)} {...props} />
</div>
);
},
);
Table.displayName = "Table";

export const TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
({ className, ...props }, ref) => {
return (
<thead
ref={ref}
className="[&_th]:p-3 [&_th]:bg-gray-100 dark:[&_th]:bg-gray-800 [&_th:first-child]:rounded-tl-md [&_th:last-child]:rounded-tr-md text-semibold"
{...props}
/>
);
},
);
TableHeader.displayName = "TableHeader";

export const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(
({ className, ...props }, ref) => {
return <tr ref={ref} className="border-b dark:border-gray-700" {...props} />;
},
);
TableRow.displayName = "TableRow";

export const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement> & HideableCellProps
>(({ hideOnSmallScreen, className, ...props }, ref) => {
return <th ref={ref} className={cn(hideOnSmallScreen && "hidden md:table-cell", className)} {...props} />;
});
TableHead.displayName = "TableHead";

export const TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
({ className, ...props }, ref) => {
return (
<tbody ref={ref} className="[&_td]:p-3 [&_td:last-child]:text-right [&_tr]:hover:bg-muted/5" {...props} />
);
},
);
TableBody.displayName = "TableBody";

export const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement> & HideableCellProps
>(({ hideOnSmallScreen, className, ...props }, ref) => {
return <td ref={ref} className={cn(hideOnSmallScreen && "hidden md:table-cell", className)} {...props} />;
});
TableCell.displayName = "TableCell";
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const Heading1: FC<HeadingProps> = ({ id, color, tracking, className, chi
return (
<Comp
id={id}
className={cn(getHeadingColor(color), getTracking(tracking), "font-bold text-4xl truncate", className)}
className={cn(getHeadingColor(color), getTracking(tracking), "font-bold text-3xl truncate", className)}
>
{children}
</Comp>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ export const useListConfigurations = ({ searchTerm = "", page, pageSize }: ListC
pagination: { page, pageSize },
});

return { configurations, pagination };
return {
configurations,
pagination,
};
},
{
enabled: !!org,
keepPreviousData: true,
},
);
};
Expand Down
4 changes: 2 additions & 2 deletions components/dashboard/src/menu/OrganizationSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export default function OrganizationSelector() {
if (currentOrg.data) {
if (repoConfigListAndDetail) {
linkEntries.push({
title: "Configurations",
customContent: <LinkEntry>Configurations</LinkEntry>,
title: "Repositories",
customContent: <LinkEntry>Repositories</LinkEntry>,
active: false,
separator: false,
link: "/repositories",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License.AGPL.txt in the project root for license information.
*/

import { Button } from "@podkit/buttons/Button";
import { cn } from "@podkit/lib/cn";
import { TextMuted } from "@podkit/typography/TextMuted";
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
import { FC, useCallback } from "react";

type Props = {
currentPage: number;
totalPages: number;
pageSize: number;
totalRows: number;
currentRows: number;
onPageChanged: (page: number) => void;
};
export const PaginationControls: FC<Props> = ({
filiptronicek marked this conversation as resolved.
Show resolved Hide resolved
currentPage,
totalPages,
pageSize,
totalRows,
currentRows,
onPageChanged,
}) => {
const prevPage = useCallback(() => {
onPageChanged(currentPage - 1);
}, [currentPage, onPageChanged]);

const nextPage = useCallback(() => {
onPageChanged(currentPage + 1);
}, [currentPage, onPageChanged]);

return (
<div className="flex flex-row justify-center items-center py-2 gap-2 text-sm">
{/* TODO: Rows per page select */}
<PaginationCountText
className="w-24"
currentPage={currentPage}
pageSize={pageSize}
currentRows={currentRows}
totalRows={totalRows}
/>
<Button variant="ghost" size="icon" onClick={prevPage} disabled={currentPage === 1}>
<ChevronLeftIcon size={20} />
</Button>
<Button variant="ghost" size="icon" onClick={nextPage} disabled={currentPage >= totalPages}>
<ChevronRightIcon size={20} />
</Button>
</div>
);
};

type PaginationCountTextProps = {
currentPage: number;
pageSize: number;
currentRows: number;
totalRows: number;
className?: string;
includePrefix?: boolean;
};
export const PaginationCountText: FC<PaginationCountTextProps> = ({
currentPage,
pageSize,
currentRows,
totalRows,
className,
includePrefix = false,
}) => {
const start = (currentPage - 1) * pageSize + 1;
const end = start + currentRows - 1;

return (
<TextMuted className={cn("min-w-max text-right", className)}>
{includePrefix ? `Showing ${start} - ${end} of ${totalRows}` : `${start} - ${end} of ${totalRows}`}
</TextMuted>
);
};
56 changes: 43 additions & 13 deletions components/dashboard/src/repositories/list/RepoListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,58 @@ import { FC } from "react";
import { usePrettyRepoURL } from "../../hooks/use-pretty-repo-url";
import { TextMuted } from "@podkit/typography/TextMuted";
import { Text } from "@podkit/typography/Text";
import { Link } from "react-router-dom";
import { Button } from "../../components/Button";
import { LinkButton } from "@podkit/buttons/LinkButton";
import type { Configuration } from "@gitpod/public-api/lib/gitpod/v1/configuration_pb";
import { cn } from "@podkit/lib/cn";
import { AlertTriangleIcon, CheckCircle2Icon } from "lucide-react";
import { TableCell, TableRow } from "@podkit/tables/Table";

type Props = {
configuration: Configuration;
};
export const RepositoryListItem: FC<Props> = ({ configuration }) => {
const url = usePrettyRepoURL(configuration.cloneUrl);
const prebuildsEnabled = !!configuration.prebuildSettings?.enabled;
const created =
configuration.creationTime
?.toDate()
.toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" }) ?? "";

return (
<li key={configuration.id} className="flex flex-row w-full space-between items-center">
<div className="flex flex-col flex-grow gap-1">
<Text className="font-semibold">{configuration.name}</Text>
<TableRow>
<TableCell>
<div className="flex flex-col gap-1">
<Text className="font-semibold">{configuration.name}</Text>
{/* We show the url on a 2nd line for smaller screens since we hide the column */}
<TextMuted className="inline md:hidden text-sm">{url}</TextMuted>
</div>
</TableCell>

<TableCell hideOnSmallScreen>
<TextMuted className="text-sm">{url}</TextMuted>
</div>

<div>
<Link to={`/repositories/${configuration.id}`}>
<Button type="secondary">View</Button>
</Link>
</div>
</li>
</TableCell>

<TableCell hideOnSmallScreen>{created}</TableCell>

<TableCell hideOnSmallScreen>
<div className="flex flex-row gap-1 items-center">
{prebuildsEnabled ? (
<CheckCircle2Icon size={20} className="text-green-500" />
) : (
<AlertTriangleIcon size={20} className="text-red-500" />
)}

<TextMuted className={cn(!prebuildsEnabled && "text-red-500 dark:text-red-500")}>
{prebuildsEnabled ? "Enabled" : "Disabled"}
</TextMuted>
</div>
</TableCell>

<TableCell>
<LinkButton href={`/repositories/${configuration.id}`} variant="secondary">
View
</LinkButton>
</TableCell>
</TableRow>
);
};
Loading
Loading