Skip to content

Commit

Permalink
[projects] Add Prebuild Events
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexTugarev committed Sep 1, 2021
1 parent 1b5ddcb commit e62458b
Show file tree
Hide file tree
Showing 19 changed files with 406 additions and 158 deletions.
14 changes: 7 additions & 7 deletions components/dashboard/src/projects/Prebuild.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import moment from "moment";
import { PrebuildInfo } from "@gitpod/gitpod-protocol";
import { PrebuildWithStatus } from "@gitpod/gitpod-protocol";
import { useContext, useEffect, useState } from "react";
import { useLocation, useRouteMatch } from "react-router";
import Header from "../components/Header";
Expand All @@ -25,7 +25,7 @@ export default function () {
const projectName = match?.params?.project;
const prebuildId = match?.params?.prebuildId;

const [ prebuild, setPrebuild ] = useState<PrebuildInfo | undefined>();
const [ prebuild, setPrebuild ] = useState<PrebuildWithStatus | undefined>();

useEffect(() => {
if (!teams || !projectName || !prebuildId) {
Expand All @@ -52,7 +52,7 @@ export default function () {
if (!prebuild) {
return "unknown prebuild";
}
return (<h1 className="tracking-tight">{prebuild.branch} </h1>);
return (<h1 className="tracking-tight">{prebuild.info.branch} </h1>);
};

const renderSubtitle = () => {
Expand All @@ -61,19 +61,19 @@ export default function () {
}
const statusIcon = prebuildStatusIcon(prebuild.status);
const status = prebuildStatusLabel(prebuild.status);
const startedByAvatar = prebuild.startedByAvatar && <img className="rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src={prebuild.startedByAvatar || ''} alt={prebuild.startedBy} />;
const startedByAvatar = prebuild.info.startedByAvatar && <img className="rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src={prebuild.info.startedByAvatar || ''} alt={prebuild.info.startedBy} />;
return (<div className="flex">
<div className="text-base text-gray-900 dark:text-gray-50 font-medium uppercase">
<div className="inline-block align-text-bottom mr-2 w-4 h-4">{statusIcon}</div>
{status}
</div>
<p className="mx-2 my-auto">·</p>
<div className="my-auto">
<p>{startedByAvatar}Triggered {moment(prebuild.startedAt).fromNow()}</p>
<p>{startedByAvatar}Triggered {moment(prebuild.info.startedAt).fromNow()}</p>
</div>
<p className="mx-2 my-auto">·</p>
<div className="my-auto">
<p className="text-gray-500 dark:text-gray-50">{shortCommitMessage(prebuild.changeTitle)}</p>
<p className="text-gray-500 dark:text-gray-50">{shortCommitMessage(prebuild.info.changeTitle)}</p>
</div>
</div>)
};
Expand All @@ -84,7 +84,7 @@ export default function () {
<Header title={renderTitle()} subtitle={renderSubtitle()} />
<div className="lg:px-28 px-10 mt-8">
<div className="h-96 rounded-xl overflow-hidden bg-gray-100 dark:bg-gray-800 flex flex-col">
<PrebuildLogs workspaceId={prebuild?.buildWorkspaceId}/>
<PrebuildLogs workspaceId={prebuild?.info?.buildWorkspaceId}/>
</div>
</div>
</>;
Expand Down
66 changes: 40 additions & 26 deletions components/dashboard/src/projects/Prebuilds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import moment from "moment";
import { PrebuildInfo, PrebuiltWorkspaceState, Project } from "@gitpod/gitpod-protocol";
import { PrebuildInfo, PrebuildWithStatus, PrebuiltWorkspaceState, Project } from "@gitpod/gitpod-protocol";
import { useContext, useEffect, useState } from "react";
import { useHistory, useLocation, useRouteMatch } from "react-router";
import Header from "../components/Header";
Expand All @@ -26,14 +26,33 @@ export default function () {
const match = useRouteMatch<{ team: string, resource: string }>("/:team/:resource");
const projectName = match?.params?.resource;

// @ts-ignore
const [project, setProject] = useState<Project | undefined>();
const [defaultBranch, setDefaultBranch] = useState<string | undefined>();

const [searchFilter, setSearchFilter] = useState<string | undefined>();
const [statusFilter, setStatusFilter] = useState<PrebuiltWorkspaceState | undefined>();

const [prebuilds, setPrebuilds] = useState<PrebuildInfo[]>([]);
const [prebuilds, setPrebuilds] = useState<PrebuildWithStatus[]>([]);

useEffect(() => {
if (!project) {
return;
}
const registration = getGitpodService().registerClient({
onPrebuildUpdate: (update: PrebuildWithStatus) => {
setPrebuilds(prev => [update, ...prev.filter(p => p.info.id !== update.info.id)])
}
});

(async () => {
const prebuilds = await getGitpodService().server.findPrebuilds({ projectId: project.id });
setPrebuilds(prebuilds);
})();

return () => {
registration.dispose();
}
}, [project]);

useEffect(() => {
if (!teams) {
Expand All @@ -44,31 +63,28 @@ export default function () {
? await getGitpodService().server.getTeamProjects(team.id)
: await getGitpodService().server.getUserProjects());

const project = projectName && projects.find(p => p.name === projectName);
if (project) {
setProject(project);

const prebuilds = await getGitpodService().server.findPrebuilds({ projectId: project.id });
setPrebuilds(prebuilds);
const newProject = projectName && projects.find(p => p.name === projectName);
if (newProject) {
setProject(newProject);

const details = await getGitpodService().server.getProjectOverview(project.id);
const details = await getGitpodService().server.getProjectOverview(newProject.id);
if (details?.branches) {
setDefaultBranch(details.branches.find(b => b.isDefault)?.name);
}
}
})();
}, [ teams ]);
}, [teams]);

const prebuildContextMenu = (p: PrebuildInfo) => {
const prebuildContextMenu = (p: PrebuildWithStatus) => {
const running = p.status === "building";
const entries: ContextMenuEntry[] = [];
entries.push({
title: "View Prebuild",
onClick: () => openPrebuild(p)
onClick: () => openPrebuild(p.info)
});
entries.push({
title: "Trigger Prebuild",
onClick: () => triggerPrebuild(p.branch),
onClick: () => triggerPrebuild(p.info.branch),
separator: running
});
if (running) {
Expand All @@ -94,18 +110,16 @@ export default function () {
return entries;
}

const filter = (p: PrebuildInfo) => {
const filter = (p: PrebuildWithStatus) => {
if (statusFilter && statusFilter !== p.status) {
return false;
}
if (searchFilter && `${p.changeTitle} ${p.branch}`.toLowerCase().includes(searchFilter.toLowerCase()) === false) {
if (searchFilter && `${p.info.changeTitle} ${p.info.branch}`.toLowerCase().includes(searchFilter.toLowerCase()) === false) {
return false;
}
return true;
}

const filteredPrebuilds = prebuilds.filter(filter);

const openPrebuild = (pb: PrebuildInfo) => {
history.push(`/${!!team ? team.slug : 'projects'}/${projectName}/${pb.id}`);
}
Expand Down Expand Up @@ -149,25 +163,25 @@ export default function () {
<ItemFieldContextMenu />
</ItemField>
</Item>
{filteredPrebuilds.map((p: PrebuildInfo) => <Item className="grid grid-cols-3">
{prebuilds.filter(filter).map((p, index) => <Item key={`prebuild-${p.info.id}`} className="grid grid-cols-3">
<ItemField className="flex items-center">
<div className="cursor-pointer" onClick={() => openPrebuild(p)}>
<div className="cursor-pointer" onClick={() => openPrebuild(p.info)}>
<div className="text-base text-gray-900 dark:text-gray-50 font-medium uppercase mb-1">
<div className="inline-block align-text-bottom mr-2 w-4 h-4">{prebuildStatusIcon(p.status)}</div>
{prebuildStatusLabel(p.status)}
</div>
<p>{p.startedByAvatar && <img className="rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src={p.startedByAvatar || ''} alt={p.startedBy} />}Triggered {formatDate(p.startedAt)}</p>
<p>{p.info.startedByAvatar && <img className="rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src={p.info.startedByAvatar || ''} alt={p.info.startedBy} />}Triggered {formatDate(p.info.startedAt)}</p>
</div>
</ItemField>
<ItemField className="flex items-center">
<div>
<div className="text-base text-gray-500 dark:text-gray-50 font-medium mb-1">{shortCommitMessage(p.changeTitle)}</div>
<p>{p.changeAuthorAvatar && <img className="rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src={p.changeAuthorAvatar || ''} alt={p.changeAuthor} />}Authored {formatDate(p.changeDate)} · {p.changeHash?.substring(0, 8)}</p>
<div className="text-base text-gray-500 dark:text-gray-50 font-medium mb-1">{shortCommitMessage(p.info.changeTitle)}</div>
<p>{p.info.changeAuthorAvatar && <img className="rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src={p.info.changeAuthorAvatar || ''} alt={p.info.changeAuthor} />}Authored {formatDate(p.info.changeDate)} · {p.info.changeHash?.substring(0, 8)}</p>
</div>
</ItemField>
<ItemField className="flex items-center">
<div className="flex space-x-2">
<span className="font-medium text-gray-500 dark:text-gray-50">{p.branch}</span>
<span className="font-medium text-gray-500 dark:text-gray-50">{p.info.branch}</span>
</div>
<span className="flex-grow" />
<ItemFieldContextMenu menuEntries={prebuildContextMenu(p)} />
Expand All @@ -179,7 +193,7 @@ export default function () {
</>;
}

export function prebuildStatusLabel(status: PrebuiltWorkspaceState) {
export function prebuildStatusLabel(status: PrebuiltWorkspaceState | undefined) {
switch (status) {
case "aborted":
return (<span className="font-medium text-red-500 uppercase">failed</span>);
Expand All @@ -193,7 +207,7 @@ export function prebuildStatusLabel(status: PrebuiltWorkspaceState) {
break;
}
}
export function prebuildStatusIcon(status: PrebuiltWorkspaceState) {
export function prebuildStatusIcon(status: PrebuiltWorkspaceState | undefined) {
switch (status) {
case "aborted":
return (<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
Expand Down
10 changes: 5 additions & 5 deletions components/dashboard/src/projects/Project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import moment from "moment";
import { PrebuildInfo, Project } from "@gitpod/gitpod-protocol";
import { PrebuildInfo, PrebuildWithStatus, Project } from "@gitpod/gitpod-protocol";
import { useContext, useEffect, useState } from "react";
import { useHistory, useLocation, useRouteMatch } from "react-router";
import Header from "../components/Header";
Expand All @@ -29,7 +29,7 @@ export default function () {
const [project, setProject] = useState<Project | undefined>();

const [branches, setBranches] = useState<Project.BranchDetails[]>([]);
const [lastPrebuilds, setLastPrebuilds] = useState<Map<string, PrebuildInfo | undefined>>(new Map());
const [lastPrebuilds, setLastPrebuilds] = useState<Map<string, PrebuildWithStatus | undefined>>(new Map());
const [prebuildLoaders] = useState<Set<string>>(new Set());

const [searchFilter, setSearchFilter] = useState<string | undefined>();
Expand Down Expand Up @@ -160,8 +160,8 @@ export default function () {
const prebuild = lastPrebuild(branch); // this might lazily trigger fetching of prebuild details

const avatar = branch.changeAuthorAvatar && <img className="rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src={branch.changeAuthorAvatar || ''} alt={branch.changeAuthor} />;
const statusIcon = prebuild?.status && prebuildStatusIcon(prebuild.status);
const status = prebuild?.status && prebuildStatusLabel(prebuild.status);
const statusIcon = prebuildStatusIcon(prebuild?.status);
const status = prebuildStatusLabel(prebuild?.status);

return <Item key={`branch-${index}-${branchName}`} className="grid grid-cols-3 group">
<ItemField className="flex items-center">
Expand All @@ -179,7 +179,7 @@ export default function () {
</div>
</ItemField>
<ItemField className="flex items-center">
<div className="text-base text-gray-900 dark:text-gray-50 font-medium uppercase mb-1 cursor-pointer" onClick={() => prebuild && openPrebuild(prebuild)}>
<div className="text-base text-gray-900 dark:text-gray-50 font-medium uppercase mb-1 cursor-pointer" onClick={() => prebuild && openPrebuild(prebuild.info)}>
{prebuild ? (<><div className="inline-block align-text-bottom mr-2 w-4 h-4">{statusIcon}</div>{status}</>) : (<span> </span>)}
</div>
<span className="flex-grow" />
Expand Down
10 changes: 5 additions & 5 deletions components/dashboard/src/projects/Projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useContext, useEffect, useState } from "react";
import { getGitpodService } from "../service/service";
import { getCurrentTeam, TeamsContext } from "../teams/teams-context";
import { ThemeContext } from "../theme-context";
import { PrebuildInfo, PrebuiltWorkspaceState, Project } from "@gitpod/gitpod-protocol";
import { PrebuildWithStatus, PrebuiltWorkspaceState, Project } from "@gitpod/gitpod-protocol";
import { toRemoteURL } from "./render-utils";
import ContextMenu from "../components/ContextMenu";
import StatusDone from "../icons/StatusDone.svg";
Expand All @@ -29,7 +29,7 @@ export default function () {
const { teams } = useContext(TeamsContext);
const team = getCurrentTeam(location, teams);
const [ projects, setProjects ] = useState<Project[]>([]);
const [ lastPrebuilds, setLastPrebuilds ] = useState<Map<string, PrebuildInfo>>(new Map());
const [ lastPrebuilds, setLastPrebuilds ] = useState<Map<string, PrebuildWithStatus>>(new Map());

const { isDark } = useContext(ThemeContext);

Expand Down Expand Up @@ -160,11 +160,11 @@ export default function () {
<div className="h-10 px-4 border rounded-b-xl dark:border-gray-800 bg-gray-100 border-gray-100 dark:bg-gray-800">
{lastPrebuilds.get(p.id)
? (<div className="flex flex-row h-full text-sm justify-between">
<Link to={`/${teamOrUserSlug}/${p.name}/${lastPrebuilds.get(p.id)!.id}`} className="flex my-auto group space-x-2">
<Link to={`/${teamOrUserSlug}/${p.name}/${lastPrebuilds.get(p.id)?.info?.id}`} className="flex my-auto group space-x-2">
<img className="h-4 w-4 my-auto" src={getPrebuildStatusIcon(lastPrebuilds.get(p.id)!.status)} />
<div className="my-auto font-semibold text-gray-500 dark:text-gray-400 truncate w-24" title={lastPrebuilds.get(p.id)!.branch}>{lastPrebuilds.get(p.id)!.branch}</div>
<div className="my-auto font-semibold text-gray-500 dark:text-gray-400 truncate w-24" title={lastPrebuilds.get(p.id)?.info?.branch}>{lastPrebuilds.get(p.id)?.info?.branch}</div>
<span className="mx-1 my-auto text-gray-400 dark:text-gray-600">·</span>
<div className="my-auto text-gray-400 dark:text-gray-500 flex-grow hover:text-gray-800 dark:hover:text-gray-300">{moment(lastPrebuilds.get(p.id)!.startedAt, "YYYYMMDD").fromNow()}</div>
<div className="my-auto text-gray-400 dark:text-gray-500 flex-grow hover:text-gray-800 dark:hover:text-gray-300">{moment(lastPrebuilds.get(p.id)?.info?.startedAt, "YYYYMMDD").fromNow()}</div>
</Link>
<Link to={`/${teamOrUserSlug}/${p.name}/prebuilds`} className="my-auto group">
<div className="flex my-auto text-gray-400 flex-grow text-right group-hover:text-gray-600 dark:hover:text-gray-300">View All &rarr;</div>
Expand Down
74 changes: 38 additions & 36 deletions components/dashboard/src/service/service-mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,43 +106,45 @@ const gitpodServiceMock = createServiceMock({
findPrebuilds: async (p) => {
const { projectId } = p;
return [{
id: "pb1",
branch: "main",
buildWorkspaceId: "123",
teamId: "t1",
projectId,
projectName: "pb1",
cloneUrl: pr1.cloneUrl,
startedAt: t1,
startedBy: u1.id,
startedByAvatar: u1.avatarUrl,
status: "available",
changeTitle: "[Comp] Add new functionality for",
changeDate: t1,
changeAuthor: u1.fullName!,
changeAuthorAvatar: u1.avatarUrl,
changePR: "4647",
changeUrl: "https://github.com/gitpod-io/gitpod/pull/4738",
changeHash: "2C0FFE"
info: {
id: "pb1",
branch: "main",
buildWorkspaceId: "123",
teamId: "t1",
projectId,
projectName: "pb1",
cloneUrl: pr1.cloneUrl,
startedAt: t1,
startedBy: u1.id,
startedByAvatar: u1.avatarUrl,
changeTitle: "[Comp] Add new functionality for",
changeDate: t1,
changeAuthor: u1.fullName!,
changeAuthorAvatar: u1.avatarUrl,
changePR: "4647",
changeUrl: "https://github.com/gitpod-io/gitpod/pull/4738",
changeHash: "2C0FFE"
}, status: "available"
}, {
id: "pb1",
branch: "foo/bar",
buildWorkspaceId: "1234",
teamId: "t1",
projectId,
projectName: "pb1",
cloneUrl: pr1.cloneUrl,
startedAt: t1,
startedBy: u1.id,
startedByAvatar: u1.avatarUrl,
status: "aborted",
changeTitle: "Fix Bug Nr 1",
changeDate: t1,
changeAuthor: u1.fullName!,
changeAuthorAvatar: u1.avatarUrl,
changePR: "4245",
changeUrl: "https://github.com/gitpod-io/gitpod/pull/4738",
changeHash: "1C0FFE"
info: {
id: "pb1",
branch: "foo/bar",
buildWorkspaceId: "1234",
teamId: "t1",
projectId,
projectName: "pb1",
cloneUrl: pr1.cloneUrl,
startedAt: t1,
startedBy: u1.id,
startedByAvatar: u1.avatarUrl,
changeTitle: "Fix Bug Nr 1",
changeDate: t1,
changeAuthor: u1.fullName!,
changeAuthorAvatar: u1.avatarUrl,
changePR: "4245",
changeUrl: "https://github.com/gitpod-io/gitpod/pull/4738",
changeHash: "1C0FFE"
}, status: "available"
}
]
},
Expand Down
Loading

0 comments on commit e62458b

Please sign in to comment.