Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/dashboard/src/prebuilds/list/PrebuildTable.tsx
2501 views
1
/**
2
* Copyright (c) 2024 Gitpod GmbH. All rights reserved.
3
* Licensed under the GNU Affero General Public License (AGPL).
4
* See License.AGPL.txt in the project root for license information.
5
*/
6
7
import { FC } from "react";
8
import { Table, TableBody, TableHead, TableHeader, TableRow } from "@podkit/tables/Table";
9
import { PrebuildListItem } from "./PrebuildListItem";
10
import { LoadingButton } from "@podkit/buttons/LoadingButton";
11
import { TextMuted } from "@podkit/typography/TextMuted";
12
import { Subheading } from "@podkit/typography/Headings";
13
import { cn } from "@podkit/lib/cn";
14
import { LoadingState } from "@podkit/loading/LoadingState";
15
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@podkit/select/Select";
16
import { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb";
17
import { Filter, Sort, SortField, StatusOption } from "./PrebuildList";
18
import { SortCallback, SortableTableHead, TableSortOrder } from "@podkit/tables/SortableTable";
19
import { ConfigurationDropdown } from "../configuration-input/ConfigurationInput";
20
import { Button } from "@podkit/buttons/Button";
21
22
type Props = {
23
prebuilds: Prebuild[];
24
filter?: Filter;
25
sort: Sort;
26
hasNextPage: boolean;
27
hasMoreThanOnePage: boolean;
28
isSearching: boolean;
29
isFetchingNextPage: boolean;
30
/**
31
* If true, the configuration dropdown and the "Run Prebuild" button will be hidden.
32
*/
33
hideOrgSpecificControls: boolean;
34
onFilterChange: (val: Filter) => void;
35
onLoadNextPage: () => void;
36
onSort: (columnName: SortField, direction: TableSortOrder) => void;
37
onTriggerPrebuild: () => void;
38
};
39
export const PrebuildsTable: FC<Props> = ({
40
prebuilds,
41
hasNextPage,
42
hasMoreThanOnePage,
43
isSearching,
44
isFetchingNextPage,
45
filter,
46
sort,
47
hideOrgSpecificControls,
48
onFilterChange,
49
onLoadNextPage,
50
onSort,
51
onTriggerPrebuild,
52
}) => {
53
return (
54
<>
55
{/* Search/Filter bar */}
56
<div className="flex flex-col-reverse md:flex-row flex-wrap justify-between items-center gap-2">
57
<div className="flex flex-row flex-wrap gap-2 items-center w-full md:w-auto">
58
{!hideOrgSpecificControls && (
59
<ConfigurationDropdown
60
selectedConfigurationId={filter?.configurationId}
61
onChange={(configurationId) => {
62
onFilterChange({ ...filter, configurationId });
63
}}
64
/>
65
)}
66
<Select
67
value={filter?.status ?? "any"}
68
onValueChange={(status) => {
69
if (status === "any") {
70
onFilterChange({ ...filter, status: undefined });
71
return;
72
}
73
onFilterChange({ ...filter, status: status as StatusOption });
74
}}
75
>
76
<SelectTrigger className="w-[120px]">
77
<SelectValue placeholder="Status" />
78
</SelectTrigger>
79
<SelectContent>
80
<SelectItem value="any">All</SelectItem>
81
<SelectItem value="failed">Failing</SelectItem>
82
<SelectItem value="succeeded">Successful</SelectItem>
83
<SelectItem value="unfinished">In progress</SelectItem>
84
</SelectContent>
85
</Select>
86
</div>
87
{!hideOrgSpecificControls && (
88
<Button className="w-full md:w-auto" onClick={onTriggerPrebuild}>
89
Run prebuild
90
</Button>
91
)}
92
</div>
93
<div className="relative w-full overflow-auto mt-4">
94
{prebuilds.length > 0 ? (
95
<Table>
96
<TableHeader>
97
<TableRow>
98
<TableHead className="w-52">Repository</TableHead>
99
<TableHead hideOnSmallScreen>Commit</TableHead>
100
<SortableTableHead
101
columnName={sort.sortBy}
102
sortOrder={sort.sortOrder}
103
onSort={onSort as SortCallback}
104
className="w-40"
105
hideOnSmallScreen
106
>
107
Triggered
108
</SortableTableHead>
109
<TableHead className="w-24">Status</TableHead>
110
{/* Action column, loading status in header */}
111
<TableHead className="w-24 text-right">
112
{isSearching && (
113
<div className="flex flex-right justify-end items-center">
114
<LoadingState delay={false} size={16} />
115
</div>
116
)}
117
</TableHead>
118
</TableRow>
119
</TableHeader>
120
<TableBody>
121
{prebuilds.map((configuration) => (
122
<PrebuildListItem key={configuration.id} prebuild={configuration} />
123
))}
124
</TableBody>
125
</Table>
126
) : (
127
<div
128
className={cn(
129
"w-full flex justify-center rounded-xl bg-pk-surface-secondary px-4 py-10 animate-fade-in-fast",
130
)}
131
>
132
<Subheading className="max-w-md">No results found. Try adjusting your search terms.</Subheading>
133
</div>
134
)}
135
{prebuilds.length > 1 && (
136
<div className="mt-4 mb-8 flex flex-row justify-center">
137
{hasNextPage ? (
138
<LoadingButton variant="secondary" onClick={onLoadNextPage} loading={isFetchingNextPage}>
139
Load more
140
</LoadingButton>
141
) : (
142
hasMoreThanOnePage && <TextMuted>All prebuilds are loaded</TextMuted>
143
)}
144
</div>
145
)}
146
</div>
147
</>
148
);
149
};
150
151