-
Notifications
You must be signed in to change notification settings - Fork 929
feat: Add timeline in the workspace page #1533
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
Changes from 1 commit
339e8fe
1355674
89c042e
f9c27e0
db88444
c766228
92a7b01
5876cf9
9291730
281228a
2cf0e97
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import Box from "@material-ui/core/Box" | ||
import Table from "@material-ui/core/Table" | ||
import TableBody from "@material-ui/core/TableBody" | ||
import TableCell from "@material-ui/core/TableCell" | ||
import TableHead from "@material-ui/core/TableHead" | ||
import TableRow from "@material-ui/core/TableRow" | ||
import React from "react" | ||
import * as TypesGen from "../../api/typesGenerated" | ||
import { EmptyState } from "../EmptyState/EmptyState" | ||
import { TableHeaderRow } from "../TableHeaders/TableHeaders" | ||
import { TableLoader } from "../TableLoader/TableLoader" | ||
|
||
export const Language = { | ||
pageTitle: "Builds", | ||
usersTitle: "All users", | ||
emptyMessage: "No users found", | ||
usernameLabel: "User", | ||
suspendMenuItem: "Suspend", | ||
resetPasswordMenuItem: "Reset password", | ||
rolesLabel: "Roles", | ||
} | ||
|
||
export interface BuildsTableProps { | ||
builds?: TypesGen.WorkspaceBuild[] | ||
} | ||
|
||
export const BuildsTable: React.FC<BuildsTableProps> = ({ builds }) => { | ||
const isLoading = !builds | ||
|
||
return ( | ||
<Table> | ||
<TableHead> | ||
<TableHeaderRow> | ||
<TableCell size="small">Action</TableCell> | ||
<TableCell size="small">Duration</TableCell> | ||
<TableCell size="small">Started at</TableCell> | ||
<TableCell size="small">Status</TableCell> | ||
</TableHeaderRow> | ||
</TableHead> | ||
<TableBody> | ||
{isLoading && <TableLoader />} | ||
{builds && | ||
builds.map((b) => ( | ||
<TableRow key={b.id}> | ||
<TableCell>{b.transition}</TableCell> | ||
<TableCell>{b.created_at}</TableCell> | ||
<TableCell>{b.created_at}</TableCell> | ||
<TableCell>{b.job.status}</TableCell> | ||
</TableRow> | ||
))} | ||
|
||
{builds && builds.length === 0 && ( | ||
<TableRow> | ||
<TableCell colSpan={999}> | ||
<Box p={4}> | ||
<EmptyState message="No builds for this workspace" /> | ||
</Box> | ||
</TableCell> | ||
</TableRow> | ||
)} | ||
</TableBody> | ||
</Table> | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,10 @@ export interface WorkspaceContext { | |
// these are separate from getX errors because they don't make the page unusable | ||
refreshWorkspaceError: Error | unknown | ||
refreshTemplateError: Error | unknown | ||
// Builds | ||
builds?: TypesGen.WorkspaceBuild[] | ||
getBuildsError?: Error | unknown | ||
loadMoreBuildsError?: Error | unknown | ||
} | ||
|
||
export type WorkspaceEvent = | ||
|
@@ -29,6 +33,7 @@ export type WorkspaceEvent = | |
| { type: "STOP" } | ||
| { type: "RETRY" } | ||
| { type: "UPDATE" } | ||
| { type: "LOAD_MORE_BUILDS" } | ||
|
||
export const workspaceMachine = createMachine( | ||
{ | ||
|
@@ -55,6 +60,12 @@ export const workspaceMachine = createMachine( | |
refreshWorkspace: { | ||
data: TypesGen.Workspace | undefined | ||
} | ||
getBuilds: { | ||
data: TypesGen.WorkspaceBuild[] | ||
} | ||
loadMoreBuilds: { | ||
data: TypesGen.WorkspaceBuild[] | ||
} | ||
}, | ||
}, | ||
id: "workspaceState", | ||
|
@@ -200,6 +211,54 @@ export const workspaceMachine = createMachine( | |
}, | ||
}, | ||
}, | ||
|
||
builds: { | ||
initial: "gettingBuilds", | ||
states: { | ||
idle: {}, | ||
gettingBuilds: { | ||
entry: "clearGetBuildsError", | ||
invoke: { | ||
src: "getBuilds", | ||
onDone: { | ||
actions: ["assignBuilds"], | ||
target: "loadedBuilds", | ||
}, | ||
onError: { | ||
actions: ["assignGetBuildsError"], | ||
target: "idle", | ||
}, | ||
}, | ||
}, | ||
loadedBuilds: { | ||
initial: "idle", | ||
states: { | ||
idle: { | ||
on: { | ||
LOAD_MORE_BUILDS: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this for pagination? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeap! To load more/old builds. |
||
target: "loadingMoreBuilds", | ||
cond: "hasMoreBuilds", | ||
}, | ||
}, | ||
}, | ||
loadingMoreBuilds: { | ||
entry: "clearLoadMoreBuildsError", | ||
invoke: { | ||
src: "loadMoreBuilds", | ||
onDone: { | ||
actions: ["assignNewBuilds"], | ||
target: "idle", | ||
}, | ||
onError: { | ||
actions: ["assignLoadMoreBuildsError"], | ||
target: "idle", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
error: { | ||
|
@@ -274,9 +333,37 @@ export const workspaceMachine = createMachine( | |
assign({ | ||
refreshTemplateError: undefined, | ||
}), | ||
// Builds | ||
assignBuilds: assign({ | ||
builds: (_, event) => event.data, | ||
}), | ||
assignGetBuildsError: assign({ | ||
getBuildsError: (_, event) => event.data, | ||
}), | ||
clearGetBuildsError: assign({ | ||
getBuildsError: (_) => undefined, | ||
}), | ||
assignNewBuilds: assign({ | ||
builds: (context, event) => { | ||
const oldBuilds = context.builds | ||
|
||
if (!oldBuilds) { | ||
throw new Error("Builds not loaded") | ||
} | ||
|
||
return [...oldBuilds, ...event.data] | ||
}, | ||
}), | ||
assignLoadMoreBuildsError: assign({ | ||
loadMoreBuildsError: (_, event) => event.data, | ||
}), | ||
clearLoadMoreBuildsError: assign({ | ||
loadMoreBuildsError: (_) => undefined, | ||
}), | ||
}, | ||
guards: { | ||
triedToStart: (context) => context.workspace?.latest_build.transition === "start", | ||
hasMoreBuilds: (_) => false, | ||
}, | ||
services: { | ||
getWorkspace: async (_, event) => { | ||
|
@@ -317,6 +404,20 @@ export const workspaceMachine = createMachine( | |
throw Error("Cannot refresh workspace without id") | ||
} | ||
}, | ||
getBuilds: async (context) => { | ||
if (context.workspace) { | ||
return await API.getWorkspaceBuilds(context.workspace.id) | ||
} else { | ||
throw Error("Cannot refresh workspace without id") | ||
} | ||
}, | ||
loadMoreBuilds: async (context) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It will change when the BE is ready. |
||
if (context.workspace) { | ||
return await API.getWorkspaceBuilds(context.workspace.id) | ||
} else { | ||
throw Error("Cannot refresh workspace without id") | ||
} | ||
}, | ||
}, | ||
}, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will implement this when the BE is done