From 92714976e0433062b036952f3ee2f421dbcd67e7 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 18:20:54 +0000 Subject: [PATCH 01/16] Return user on created by --- coderd/database/dump.sql | 2 +- ...00066_template_version_created_by.down.sql | 1 + .../000066_template_version_created_by.up.sql | 1 + coderd/database/models.go | 2 +- coderd/database/queries.sql.go | 2 +- coderd/templateversions.go | 52 ++++++++----------- codersdk/templateversions.go | 3 +- 7 files changed, 29 insertions(+), 34 deletions(-) create mode 100644 coderd/database/migrations/000066_template_version_created_by.down.sql create mode 100644 coderd/database/migrations/000066_template_version_created_by.up.sql diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 5d521ae725fb8..4ecae20f60552 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -327,7 +327,7 @@ CREATE TABLE template_versions ( name character varying(64) NOT NULL, readme character varying(1048576) NOT NULL, job_id uuid NOT NULL, - created_by uuid + created_by uuid NOT NULL ); CREATE TABLE templates ( diff --git a/coderd/database/migrations/000066_template_version_created_by.down.sql b/coderd/database/migrations/000066_template_version_created_by.down.sql new file mode 100644 index 0000000000000..48b3e93bffc29 --- /dev/null +++ b/coderd/database/migrations/000066_template_version_created_by.down.sql @@ -0,0 +1 @@ +ALTER TABLE template_versions ALTER COLUMN created_by SET NULL diff --git a/coderd/database/migrations/000066_template_version_created_by.up.sql b/coderd/database/migrations/000066_template_version_created_by.up.sql new file mode 100644 index 0000000000000..0627d0181cebd --- /dev/null +++ b/coderd/database/migrations/000066_template_version_created_by.up.sql @@ -0,0 +1 @@ +ALTER TABLE template_versions ALTER COLUMN created_by SET NOT NULL diff --git a/coderd/database/models.go b/coderd/database/models.go index f59e09a1aeba8..9180279eee890 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -600,7 +600,7 @@ type TemplateVersion struct { Name string `db:"name" json:"name"` Readme string `db:"readme" json:"readme"` JobID uuid.UUID `db:"job_id" json:"job_id"` - CreatedBy uuid.NullUUID `db:"created_by" json:"created_by"` + CreatedBy uuid.UUID `db:"created_by" json:"created_by"` } type User struct { diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index b99d651016fb3..fb1419808d5ac 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -3634,7 +3634,7 @@ type InsertTemplateVersionParams struct { Name string `db:"name" json:"name"` Readme string `db:"readme" json:"readme"` JobID uuid.UUID `db:"job_id" json:"job_id"` - CreatedBy uuid.NullUUID `db:"created_by" json:"created_by"` + CreatedBy uuid.UUID `db:"created_by" json:"created_by"` } func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTemplateVersionParams) (TemplateVersion, error) { diff --git a/coderd/templateversions.go b/coderd/templateversions.go index e434482ad8b69..5c9d89e93769a 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -1,7 +1,6 @@ package coderd import ( - "context" "database/sql" "encoding/json" "errors" @@ -43,16 +42,16 @@ func (api *API) templateVersion(rw http.ResponseWriter, r *http.Request) { return } - createdByName, err := getUsernameByUserID(ctx, api.Database, templateVersion.CreatedBy) + user, err := api.Database.GetUserByID(ctx, templateVersion.CreatedBy) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Internal error fetching creator name.", + Message: "Internal error on fetching user.", Detail: err.Error(), }) return } - httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), createdByName)) + httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), user)) } func (api *API) patchCancelTemplateVersion(rw http.ResponseWriter, r *http.Request) { @@ -523,15 +522,15 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque }) return err } - createdByName, err := getUsernameByUserID(ctx, store, version.CreatedBy) + user, err := api.Database.GetUserByID(ctx, version.CreatedBy) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Internal error fetching creator name.", + Message: "Internal error on fetching user.", Detail: err.Error(), }) return err } - apiVersions = append(apiVersions, convertTemplateVersion(version, convertProvisionerJob(job), createdByName)) + apiVersions = append(apiVersions, convertTemplateVersion(version, convertProvisionerJob(job), user)) } return nil @@ -581,16 +580,16 @@ func (api *API) templateVersionByName(rw http.ResponseWriter, r *http.Request) { return } - createdByName, err := getUsernameByUserID(ctx, api.Database, templateVersion.CreatedBy) + user, err := api.Database.GetUserByID(ctx, templateVersion.CreatedBy) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Internal error fetching creator name.", + Message: "Internal error on fetching user.", Detail: err.Error(), }) return } - httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), createdByName)) + httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), user)) } func (api *API) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Request) { @@ -841,10 +840,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht Name: req.Name, Readme: "", JobID: provisionerJob.ID, - CreatedBy: uuid.NullUUID{ - UUID: apiKey.UserID, - Valid: true, - }, + CreatedBy: apiKey.UserID, }) if err != nil { return xerrors.Errorf("insert template version: %w", err) @@ -859,16 +855,16 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht } aReq.New = templateVersion - createdByName, err := getUsernameByUserID(ctx, api.Database, templateVersion.CreatedBy) + user, err := api.Database.GetUserByID(ctx, templateVersion.CreatedBy) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Internal error fetching creator name.", + Message: "Internal error on fetching user.", Detail: err.Error(), }) return } - httpapi.Write(ctx, rw, http.StatusCreated, convertTemplateVersion(templateVersion, convertProvisionerJob(provisionerJob), createdByName)) + httpapi.Write(ctx, rw, http.StatusCreated, convertTemplateVersion(templateVersion, convertProvisionerJob(provisionerJob), user)) } // templateVersionResources returns the workspace agent resources associated @@ -926,18 +922,17 @@ func (api *API) templateVersionLogs(rw http.ResponseWriter, r *http.Request) { api.provisionerJobLogs(rw, r, job) } -func getUsernameByUserID(ctx context.Context, db database.Store, userID uuid.NullUUID) (string, error) { - if !userID.Valid { - return "", nil - } - user, err := db.GetUserByID(ctx, userID.UUID) - if err != nil { - return "", err +func convertTemplateVersion(version database.TemplateVersion, job codersdk.ProvisionerJob, user database.User) codersdk.TemplateVersion { + createdBy := &codersdk.User{ + ID: user.ID, + Username: user.Username, + Email: user.Email, + CreatedAt: user.CreatedAt, + Status: codersdk.UserStatus(user.Status), + Roles: []codersdk.Role{}, + AvatarURL: user.AvatarURL.String, } - return user.Username, nil -} -func convertTemplateVersion(version database.TemplateVersion, job codersdk.ProvisionerJob, createdByName string) codersdk.TemplateVersion { return codersdk.TemplateVersion{ ID: version.ID, TemplateID: &version.TemplateID.UUID, @@ -947,7 +942,6 @@ func convertTemplateVersion(version database.TemplateVersion, job codersdk.Provi Name: version.Name, Job: job, Readme: version.Readme, - CreatedByID: version.CreatedBy.UUID, - CreatedByName: createdByName, + CreatedBy: createdBy, } } diff --git a/codersdk/templateversions.go b/codersdk/templateversions.go index 7e861c356933c..51463579afd55 100644 --- a/codersdk/templateversions.go +++ b/codersdk/templateversions.go @@ -21,8 +21,7 @@ type TemplateVersion struct { Name string `json:"name"` Job ProvisionerJob `json:"job"` Readme string `json:"readme"` - CreatedByID uuid.UUID `json:"created_by_id"` - CreatedByName string `json:"created_by_name"` + CreatedBy *User `json:"created_by"` } // TemplateVersion returns a template version by ID. From 0f51a2326f9371c0c785b2345d0ef828b415d496 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 18:21:07 +0000 Subject: [PATCH 02/16] Extra timeline --- site/src/api/typesGenerated.ts | 3 +- .../components/BuildsTable/BuildDateRow.tsx | 46 ---------------- .../components/BuildsTable/BuildsTable.tsx | 52 ++++-------------- site/src/components/Timeline/Timeline.tsx | 53 +++++++++++++++++++ .../TimelineDateRow.tsx} | 4 +- site/src/pages/AuditPage/AuditPageView.tsx | 46 ++++------------ 6 files changed, 76 insertions(+), 128 deletions(-) delete mode 100644 site/src/components/BuildsTable/BuildDateRow.tsx create mode 100644 site/src/components/Timeline/Timeline.tsx rename site/src/components/{TableDateRow/TableDateRow.tsx => Timeline/TimelineDateRow.tsx} (91%) diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 905e1b6de5a30..8433eb307f917 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -656,8 +656,7 @@ export interface TemplateVersion { readonly name: string readonly job: ProvisionerJob readonly readme: string - readonly created_by_id: string - readonly created_by_name: string + readonly created_by?: User } // From codersdk/templates.go diff --git a/site/src/components/BuildsTable/BuildDateRow.tsx b/site/src/components/BuildsTable/BuildDateRow.tsx deleted file mode 100644 index c7675d16d3348..0000000000000 --- a/site/src/components/BuildsTable/BuildDateRow.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { makeStyles } from "@material-ui/core/styles" -import TableCell from "@material-ui/core/TableCell" -import TableRow from "@material-ui/core/TableRow" -import formatRelative from "date-fns/formatRelative" -import { FC } from "react" - -export interface BuildDateRow { - date: Date -} - -export const BuildDateRow: FC = ({ date }) => { - const styles = useStyles() - // We only want the message related to the date since the time is displayed - // inside of the build row - const displayDate = formatRelative(date, new Date()).split("at")[0] - - return ( - - - {displayDate} - - - ) -} - -const useStyles = makeStyles((theme) => ({ - buildDateRow: { - background: theme.palette.background.paper, - - "&:not(:first-child) td": { - borderTop: `1px solid ${theme.palette.divider}`, - }, - }, - - buildDateCell: { - padding: `${theme.spacing(1, 4)} !important`, - background: `${theme.palette.background.paperLight} !important`, - fontSize: 12, - position: "relative", - color: theme.palette.text.secondary, - textTransform: "capitalize", - }, -})) diff --git a/site/src/components/BuildsTable/BuildsTable.tsx b/site/src/components/BuildsTable/BuildsTable.tsx index 6bf20ef3d2a92..cf084014e1360 100644 --- a/site/src/components/BuildsTable/BuildsTable.tsx +++ b/site/src/components/BuildsTable/BuildsTable.tsx @@ -4,11 +4,11 @@ import TableBody from "@material-ui/core/TableBody" import TableCell from "@material-ui/core/TableCell" import TableContainer from "@material-ui/core/TableContainer" import TableRow from "@material-ui/core/TableRow" -import { FC, Fragment } from "react" +import { Timeline } from "components/Timeline/Timeline" +import { FC } from "react" import * as TypesGen from "../../api/typesGenerated" import { EmptyState } from "../EmptyState/EmptyState" import { TableLoader } from "../TableLoader/TableLoader" -import { BuildDateRow } from "./BuildDateRow" import { BuildRow } from "./BuildRow" export const Language = { @@ -24,52 +24,22 @@ export interface BuildsTableProps { builds?: TypesGen.WorkspaceBuild[] } -const groupBuildsByDate = (builds?: TypesGen.WorkspaceBuild[]) => { - const buildsByDate: Record = {} - - if (!builds) { - return - } - - builds.forEach((build) => { - const dateKey = new Date(build.created_at).toDateString() - - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (buildsByDate[dateKey]) { - buildsByDate[dateKey].push(build) - } else { - buildsByDate[dateKey] = [build] - } - }) - - return buildsByDate -} - export const BuildsTable: FC> = ({ builds, }) => { - const isLoading = !builds - const buildsByDate = groupBuildsByDate(builds) - return ( - {isLoading && } - - {buildsByDate && - Object.keys(buildsByDate).map((dateStr) => { - const builds = buildsByDate[dateStr] - - return ( - - - {builds.map((build) => ( - - ))} - - ) - })} + {builds ? ( + new Date(build.created_at)} + row={(build) => } + /> + ) : ( + + )} {builds && builds.length === 0 && ( diff --git a/site/src/components/Timeline/Timeline.tsx b/site/src/components/Timeline/Timeline.tsx new file mode 100644 index 0000000000000..e8e13be1f65d4 --- /dev/null +++ b/site/src/components/Timeline/Timeline.tsx @@ -0,0 +1,53 @@ +import { TimelineDateRow } from "components/Timeline/TimelineDateRow" +import { Fragment } from "react" + +type GetDateFn = (data: TData) => Date + +const groupByDate = ( + items: TData[], + getDate: GetDateFn, +): Record => { + const itemsByDate: Record = {} + + items.forEach((item) => { + const dateKey = getDate(item).toDateString() + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (itemsByDate[dateKey]) { + itemsByDate[dateKey].push(item) + } else { + itemsByDate[dateKey] = [item] + } + }) + + return itemsByDate +} + +export interface TimelineProps { + items: TData[] + getDate: GetDateFn + row: (item: TData) => JSX.Element +} + +export const Timeline = ({ + items, + getDate, + row, +}: TimelineProps): JSX.Element => { + const itemsByDate = groupByDate(items, getDate) + + return ( + <> + {Object.keys(itemsByDate).map((dateStr) => { + const items = itemsByDate[dateStr] + + return ( + + + {items.map(row)} + + ) + })} + + ) +} diff --git a/site/src/components/TableDateRow/TableDateRow.tsx b/site/src/components/Timeline/TimelineDateRow.tsx similarity index 91% rename from site/src/components/TableDateRow/TableDateRow.tsx rename to site/src/components/Timeline/TimelineDateRow.tsx index 8895d6fb0b48d..0ef1c86ce8d4d 100644 --- a/site/src/components/TableDateRow/TableDateRow.tsx +++ b/site/src/components/Timeline/TimelineDateRow.tsx @@ -4,11 +4,11 @@ import TableRow from "@material-ui/core/TableRow" import formatRelative from "date-fns/formatRelative" import { FC } from "react" -export interface TableDateRow { +export interface TimelineDateRow { date: Date } -export const TableDateRow: FC = ({ date }) => { +export const TimelineDateRow: FC = ({ date }) => { const styles = useStyles() // We only want the message related to the date since the time is displayed // inside of the build row diff --git a/site/src/pages/AuditPage/AuditPageView.tsx b/site/src/pages/AuditPage/AuditPageView.tsx index 824cd9e4df01c..8ab90b8420db0 100644 --- a/site/src/pages/AuditPage/AuditPageView.tsx +++ b/site/src/pages/AuditPage/AuditPageView.tsx @@ -15,10 +15,10 @@ import { import { PaginationWidget } from "components/PaginationWidget/PaginationWidget" import { SearchBarWithFilter } from "components/SearchBarWithFilter/SearchBarWithFilter" import { Stack } from "components/Stack/Stack" -import { TableDateRow } from "components/TableDateRow/TableDateRow" import { TableLoader } from "components/TableLoader/TableLoader" +import { Timeline } from "components/Timeline/Timeline" import { AuditHelpTooltip } from "components/Tooltips" -import { FC, Fragment } from "react" +import { FC } from "react" import { PaginationMachineRef } from "xServices/pagination/paginationXService" export const Language = { @@ -37,27 +37,6 @@ const presetFilters = [ { query: "resource_type:user action:delete", name: "Deleted users" }, ] -const groupAuditLogsByDate = (auditLogs?: AuditLog[]) => { - const auditLogsByDate: Record = {} - - if (!auditLogs) { - return - } - - auditLogs.forEach((auditLog) => { - const dateKey = new Date(auditLog.time).toDateString() - - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (auditLogsByDate[dateKey]) { - auditLogsByDate[dateKey].push(auditLog) - } else { - auditLogsByDate[dateKey] = [auditLog] - } - }) - - return auditLogsByDate -} - export interface AuditPageViewProps { auditLogs?: AuditLog[] count?: number @@ -75,7 +54,6 @@ export const AuditPageView: FC = ({ }) => { const isLoading = auditLogs === undefined || count === undefined const isEmpty = !isLoading && auditLogs.length === 0 - const auditLogsByDate = groupAuditLogsByDate(auditLogs) return ( @@ -101,19 +79,13 @@ export const AuditPageView: FC = ({ {isLoading && } - {auditLogsByDate && - Object.keys(auditLogsByDate).map((dateStr) => { - const auditLogs = auditLogsByDate[dateStr] - - return ( - - - {auditLogs.map((log) => ( - - ))} - - ) - })} + {auditLogs && ( + new Date(log.time)} + row={(log) => } + /> + )} {isEmpty && ( From 8ff38c861ef3565b61a6072f1b2bb3d608385285 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 18:21:35 +0000 Subject: [PATCH 03/16] Fix templates --- coderd/templates.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/coderd/templates.go b/coderd/templates.go index a1108dfc43082..163464db39b12 100644 --- a/coderd/templates.go +++ b/coderd/templates.go @@ -658,10 +658,7 @@ func (api *API) autoImportTemplate(ctx context.Context, opts autoImportTemplateO Name: namesgenerator.GetRandomName(1), Readme: "", JobID: job.ID, - CreatedBy: uuid.NullUUID{ - UUID: opts.userID, - Valid: true, - }, + CreatedBy: opts.userID, }) if err != nil { return xerrors.Errorf("insert template version: %w", err) From 0f8445582ce8483f361979dd22be4cb2f921e5b9 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 18:24:28 +0000 Subject: [PATCH 04/16] Fix tests --- cli/templateversions.go | 2 +- cli/templateversions_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/templateversions.go b/cli/templateversions.go index 3b13aea8f2c7d..147a15753b930 100644 --- a/cli/templateversions.go +++ b/cli/templateversions.go @@ -94,7 +94,7 @@ func displayTemplateVersions(activeVersionID uuid.UUID, templateVersions ...code rows[i] = templateVersionRow{ Name: templateVersion.Name, CreatedAt: templateVersion.CreatedAt, - CreatedBy: templateVersion.CreatedByName, + CreatedBy: templateVersion.CreatedBy.Username, Status: strings.Title(string(templateVersion.Job.Status)), Active: activeStatus, } diff --git a/cli/templateversions_test.go b/cli/templateversions_test.go index 137ba61457cea..750c718591788 100644 --- a/cli/templateversions_test.go +++ b/cli/templateversions_test.go @@ -35,7 +35,7 @@ func TestTemplateVersions(t *testing.T) { require.NoError(t, <-errC) pty.ExpectMatch(version.Name) - pty.ExpectMatch(version.CreatedByName) + pty.ExpectMatch(version.CreatedBy.Username) pty.ExpectMatch("Active") }) } From ffa188d871716ad34e2f2d6760fdbc540b0c7508 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 18:33:57 +0000 Subject: [PATCH 05/16] Fix types --- coderd/templateversions.go | 2 +- codersdk/templateversions.go | 2 +- site/src/api/typesGenerated.ts | 2 +- .../components/VersionsTable/VersionRow.tsx | 143 ++++++++++++++++++ .../VersionsTable/VersionsTable.tsx | 8 +- 5 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 site/src/components/VersionsTable/VersionRow.tsx diff --git a/coderd/templateversions.go b/coderd/templateversions.go index 5c9d89e93769a..0d46e7b4e1023 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -923,7 +923,7 @@ func (api *API) templateVersionLogs(rw http.ResponseWriter, r *http.Request) { } func convertTemplateVersion(version database.TemplateVersion, job codersdk.ProvisionerJob, user database.User) codersdk.TemplateVersion { - createdBy := &codersdk.User{ + createdBy := codersdk.User{ ID: user.ID, Username: user.Username, Email: user.Email, diff --git a/codersdk/templateversions.go b/codersdk/templateversions.go index 51463579afd55..3aee18ec80a18 100644 --- a/codersdk/templateversions.go +++ b/codersdk/templateversions.go @@ -21,7 +21,7 @@ type TemplateVersion struct { Name string `json:"name"` Job ProvisionerJob `json:"job"` Readme string `json:"readme"` - CreatedBy *User `json:"created_by"` + CreatedBy User `json:"created_by"` } // TemplateVersion returns a template version by ID. diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 8433eb307f917..792e974ceb5f1 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -656,7 +656,7 @@ export interface TemplateVersion { readonly name: string readonly job: ProvisionerJob readonly readme: string - readonly created_by?: User + readonly created_by: User } // From codersdk/templates.go diff --git a/site/src/components/VersionsTable/VersionRow.tsx b/site/src/components/VersionsTable/VersionRow.tsx new file mode 100644 index 0000000000000..ae984664ed2fd --- /dev/null +++ b/site/src/components/VersionsTable/VersionRow.tsx @@ -0,0 +1,143 @@ +import { makeStyles } from "@material-ui/core/styles" +import TableCell from "@material-ui/core/TableCell" +import TableRow from "@material-ui/core/TableRow" +import { WorkspaceBuild } from "api/typesGenerated" +import { Stack } from "components/Stack/Stack" +import { useClickable } from "hooks/useClickable" +import { useTranslation } from "react-i18next" +import { useNavigate } from "react-router-dom" +import { MONOSPACE_FONT_FAMILY } from "theme/constants" +import { + displayWorkspaceBuildDuration, + getDisplayWorkspaceBuildInitiatedBy, +} from "util/workspace" + +export interface VersionRowProps { + version: WorkspaceVersion +} + +export const VersionRow: React.FC = ({ build }) => { + const styles = useStyles() + const { t } = useTranslation("workspacePage") + const initiatedBy = getDisplayWorkspaceBuildInitiatedBy(build) + const navigate = useNavigate() + const clickableProps = useClickable(() => + navigate(`builds/${build.build_number}`), + ) + + return ( + + + + + +
+ + + {initiatedBy}{" "} + {build.reason !== "initiator" + ? t("buildMessage.automatically") + : ""} + {t(`buildMessage.${build.transition}`)}{" "} + {t("buildMessage.theWorkspace")} + + + + {new Date(build.created_at).toLocaleTimeString()} + + + + + + {t("buildData.reason")}: {build.reason} + + + + {t("buildData.duration")}:{" "} + {displayWorkspaceBuildDuration(build)} + + +
+
+
+
+
+ ) +} + +const useStyles = makeStyles((theme) => ({ + buildRow: { + cursor: "pointer", + + "&:focus": { + outlineStyle: "solid", + outlineOffset: -1, + outlineWidth: 2, + outlineColor: theme.palette.secondary.dark, + }, + + "&:not(:last-child) td:before": { + position: "absolute", + top: 20, + left: 50, + display: "block", + content: "''", + height: "100%", + width: 2, + background: theme.palette.divider, + }, + }, + + buildWrapper: { + padding: theme.spacing(2, 4), + }, + + buildCell: { + padding: "0 !important", + position: "relative", + borderBottom: 0, + }, + + buildSummary: { + ...theme.typography.body1, + fontFamily: "inherit", + }, + + buildInfo: { + ...theme.typography.body2, + fontSize: 12, + fontFamily: "inherit", + color: theme.palette.text.secondary, + display: "block", + }, + + buildTime: { + color: theme.palette.text.secondary, + fontSize: 12, + }, + + buildRight: { + width: "auto", + }, + + buildExtraInfo: { + ...theme.typography.body2, + fontFamily: MONOSPACE_FONT_FAMILY, + color: theme.palette.text.secondary, + whiteSpace: "nowrap", + }, +})) diff --git a/site/src/components/VersionsTable/VersionsTable.tsx b/site/src/components/VersionsTable/VersionsTable.tsx index 94ce57e652f1b..97b35222532da 100644 --- a/site/src/components/VersionsTable/VersionsTable.tsx +++ b/site/src/components/VersionsTable/VersionsTable.tsx @@ -32,15 +32,9 @@ export const VersionsTable: FC> = ({ return (
- - - {Language.nameLabel} - {Language.createdAtLabel} - {Language.createdByLabel} - - {isLoading && } + {versions && } {versions && versions .slice() From ec029e87bbb7ed48cb93050332f3683b9711dc33 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 18:40:26 +0000 Subject: [PATCH 06/16] Update versions to timeline --- .../components/VersionsTable/VersionRow.tsx | 121 +++++------------- .../VersionsTable/VersionsTable.tsx | 45 ++----- site/src/i18n/en/templatePage.json | 3 +- 3 files changed, 48 insertions(+), 121 deletions(-) diff --git a/site/src/components/VersionsTable/VersionRow.tsx b/site/src/components/VersionsTable/VersionRow.tsx index ae984664ed2fd..018e793e7287b 100644 --- a/site/src/components/VersionsTable/VersionRow.tsx +++ b/site/src/components/VersionsTable/VersionRow.tsx @@ -1,77 +1,50 @@ import { makeStyles } from "@material-ui/core/styles" import TableCell from "@material-ui/core/TableCell" import TableRow from "@material-ui/core/TableRow" -import { WorkspaceBuild } from "api/typesGenerated" +import { TemplateVersion } from "api/typesGenerated" import { Stack } from "components/Stack/Stack" -import { useClickable } from "hooks/useClickable" +import { UserAvatar } from "components/UserAvatar/UserAvatar" import { useTranslation } from "react-i18next" -import { useNavigate } from "react-router-dom" -import { MONOSPACE_FONT_FAMILY } from "theme/constants" -import { - displayWorkspaceBuildDuration, - getDisplayWorkspaceBuildInitiatedBy, -} from "util/workspace" export interface VersionRowProps { - version: WorkspaceVersion + version: TemplateVersion } -export const VersionRow: React.FC = ({ build }) => { +export const VersionRow: React.FC = ({ version }) => { const styles = useStyles() - const { t } = useTranslation("workspacePage") - const initiatedBy = getDisplayWorkspaceBuildInitiatedBy(build) - const navigate = useNavigate() - const clickableProps = useClickable(() => - navigate(`builds/${build.build_number}`), - ) + const { t } = useTranslation("templatePage") return ( - + - -
- - - {initiatedBy}{" "} - {build.reason !== "initiator" - ? t("buildMessage.automatically") - : ""} - {t(`buildMessage.${build.transition}`)}{" "} - {t("buildMessage.theWorkspace")} - - - - {new Date(build.created_at).toLocaleTimeString()} - - - - - - {t("buildData.reason")}: {build.reason} - - - - {t("buildData.duration")}:{" "} - {displayWorkspaceBuildDuration(build)} - - -
+ + + + {version.created_by.username}{" "} + {t("createdVersion")} {version.name} + + + + {new Date(version.created_at).toLocaleTimeString()} + +
@@ -80,16 +53,7 @@ export const VersionRow: React.FC = ({ build }) => { } const useStyles = makeStyles((theme) => ({ - buildRow: { - cursor: "pointer", - - "&:focus": { - outlineStyle: "solid", - outlineOffset: -1, - outlineWidth: 2, - outlineColor: theme.palette.secondary.dark, - }, - + versionRow: { "&:not(:last-child) td:before": { position: "absolute", top: 20, @@ -102,42 +66,23 @@ const useStyles = makeStyles((theme) => ({ }, }, - buildWrapper: { + versionWrapper: { padding: theme.spacing(2, 4), }, - buildCell: { + versionCell: { padding: "0 !important", position: "relative", borderBottom: 0, }, - buildSummary: { + versionSummary: { ...theme.typography.body1, fontFamily: "inherit", }, - buildInfo: { - ...theme.typography.body2, - fontSize: 12, - fontFamily: "inherit", - color: theme.palette.text.secondary, - display: "block", - }, - - buildTime: { + versionTime: { color: theme.palette.text.secondary, fontSize: 12, }, - - buildRight: { - width: "auto", - }, - - buildExtraInfo: { - ...theme.typography.body2, - fontFamily: MONOSPACE_FONT_FAMILY, - color: theme.palette.text.secondary, - whiteSpace: "nowrap", - }, })) diff --git a/site/src/components/VersionsTable/VersionsTable.tsx b/site/src/components/VersionsTable/VersionsTable.tsx index 97b35222532da..9aabf87522de3 100644 --- a/site/src/components/VersionsTable/VersionsTable.tsx +++ b/site/src/components/VersionsTable/VersionsTable.tsx @@ -1,16 +1,15 @@ import Box from "@material-ui/core/Box" -import { Theme } from "@material-ui/core/styles" import Table from "@material-ui/core/Table" import TableBody from "@material-ui/core/TableBody" import TableCell from "@material-ui/core/TableCell" import TableContainer from "@material-ui/core/TableContainer" -import TableHead from "@material-ui/core/TableHead" import TableRow from "@material-ui/core/TableRow" -import useTheme from "@material-ui/styles/useTheme" +import { Timeline } from "components/Timeline/Timeline" import { FC } from "react" import * as TypesGen from "../../api/typesGenerated" import { EmptyState } from "../EmptyState/EmptyState" import { TableLoader } from "../TableLoader/TableLoader" +import { VersionRow } from "./VersionRow" export const Language = { emptyMessage: "No versions found", @@ -26,39 +25,21 @@ export interface VersionsTableProps { export const VersionsTable: FC> = ({ versions, }) => { - const isLoading = !versions - const theme: Theme = useTheme() - return (
- {isLoading && } - {versions && } - {versions && - versions - .slice() - .reverse() - .map((version) => { - return ( - - {version.name} - - - {new Date(version.created_at).toLocaleString()} - - - - - {version.created_by_name} - - - - ) - })} + {versions ? ( + new Date(version.created_at)} + row={(version) => ( + + )} + /> + ) : ( + + )} {versions && versions.length === 0 && ( diff --git a/site/src/i18n/en/templatePage.json b/site/src/i18n/en/templatePage.json index 9116f007b8992..03daf50eb649f 100644 --- a/site/src/i18n/en/templatePage.json +++ b/site/src/i18n/en/templatePage.json @@ -1,3 +1,4 @@ { - "deleteSuccess": "Template successfully deleted." + "deleteSuccess": "Template successfully deleted.", + "createdVersion": "created the version" } From cf599aa1915b97d931f797ccff5ca6ae2536ad5f Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 18:41:48 +0000 Subject: [PATCH 07/16] Fix entities --- site/src/testHelpers/entities.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index d4670f66baead..0b46624e413b1 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -171,8 +171,7 @@ name:Template test You can add instructions here [Some link info](https://coder.com)`, - created_by_id: "test-creator-id", - created_by_name: "test_creator", + created_by: MockUser, } export const MockTemplate: TypesGen.Template = { From 09359694a9d1f989a77637d0aca6859ad60073ad Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 19:13:58 +0000 Subject: [PATCH 08/16] Fix test --- enterprise/audit/diff_internal_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/enterprise/audit/diff_internal_test.go b/enterprise/audit/diff_internal_test.go index ff21b0b18b32f..6d7a3ed643bcf 100644 --- a/enterprise/audit/diff_internal_test.go +++ b/enterprise/audit/diff_internal_test.go @@ -277,7 +277,7 @@ func Test_diff(t *testing.T) { UpdatedAt: time.Now(), OrganizationID: uuid.UUID{3}, Name: "rust", - CreatedBy: uuid.NullUUID{UUID: uuid.UUID{4}, Valid: true}, + CreatedBy: uuid.UUID{4}, }, exp: audit.Map{ "id": audit.OldNew{Old: "", New: uuid.UUID{1}.String()}, @@ -296,7 +296,7 @@ func Test_diff(t *testing.T) { UpdatedAt: time.Now(), OrganizationID: uuid.UUID{3}, Name: "rust", - CreatedBy: uuid.NullUUID{UUID: uuid.UUID{4}, Valid: true}, + CreatedBy: uuid.UUID{4}, }, exp: audit.Map{ "id": audit.OldNew{Old: "", New: uuid.UUID{1}.String()}, From 053dc9beb477fb68da70a0051a85f44c1747417d Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 19:21:24 +0000 Subject: [PATCH 09/16] fix: migration --- ...own.sql => 000068_update_template_version_created_by.down.sql} | 0 ...by.up.sql => 000068_update_template_version_created_by.up.sql} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename coderd/database/migrations/{000066_template_version_created_by.down.sql => 000068_update_template_version_created_by.down.sql} (100%) rename coderd/database/migrations/{000066_template_version_created_by.up.sql => 000068_update_template_version_created_by.up.sql} (100%) diff --git a/coderd/database/migrations/000066_template_version_created_by.down.sql b/coderd/database/migrations/000068_update_template_version_created_by.down.sql similarity index 100% rename from coderd/database/migrations/000066_template_version_created_by.down.sql rename to coderd/database/migrations/000068_update_template_version_created_by.down.sql diff --git a/coderd/database/migrations/000066_template_version_created_by.up.sql b/coderd/database/migrations/000068_update_template_version_created_by.up.sql similarity index 100% rename from coderd/database/migrations/000066_template_version_created_by.up.sql rename to coderd/database/migrations/000068_update_template_version_created_by.up.sql From 5b835bae1c1fcd6f944727dda51779db1c58cd92 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 19:30:09 +0000 Subject: [PATCH 10/16] Fix migration --- .../000068_update_template_version_created_by.down.sql | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/coderd/database/migrations/000068_update_template_version_created_by.down.sql b/coderd/database/migrations/000068_update_template_version_created_by.down.sql index 48b3e93bffc29..6e9ec22a2aff7 100644 --- a/coderd/database/migrations/000068_update_template_version_created_by.down.sql +++ b/coderd/database/migrations/000068_update_template_version_created_by.down.sql @@ -1 +1,4 @@ -ALTER TABLE template_versions ALTER COLUMN created_by SET NULL +BEGIN; + ALTER TABLE template_versions ALTER COLUMN created_by SET NULL; + UPDATE template_versions SET created_by = '00000000-0000-0000-0000-000000000000'::uuid WHERE created_by IS NULL; +COMMIT; From 2cc3127b614ab854f8379ffdb82520b1bb2ad6ce Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 19:59:23 +0000 Subject: [PATCH 11/16] Fix tests and migrations --- .../000068_update_template_version_created_by.down.sql | 5 +---- .../000068_update_template_version_created_by.up.sql | 5 ++++- enterprise/audit/diff_internal_test.go | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/coderd/database/migrations/000068_update_template_version_created_by.down.sql b/coderd/database/migrations/000068_update_template_version_created_by.down.sql index 6e9ec22a2aff7..96954c128c60d 100644 --- a/coderd/database/migrations/000068_update_template_version_created_by.down.sql +++ b/coderd/database/migrations/000068_update_template_version_created_by.down.sql @@ -1,4 +1 @@ -BEGIN; - ALTER TABLE template_versions ALTER COLUMN created_by SET NULL; - UPDATE template_versions SET created_by = '00000000-0000-0000-0000-000000000000'::uuid WHERE created_by IS NULL; -COMMIT; +ALTER TABLE template_versions ALTER COLUMN created_by SET NULL; diff --git a/coderd/database/migrations/000068_update_template_version_created_by.up.sql b/coderd/database/migrations/000068_update_template_version_created_by.up.sql index 0627d0181cebd..af6a2bb9000fb 100644 --- a/coderd/database/migrations/000068_update_template_version_created_by.up.sql +++ b/coderd/database/migrations/000068_update_template_version_created_by.up.sql @@ -1 +1,4 @@ -ALTER TABLE template_versions ALTER COLUMN created_by SET NOT NULL +BEGIN; + ALTER TABLE template_versions ALTER COLUMN created_by SET NOT NULL; + UPDATE template_versions SET created_by = '00000000-0000-0000-0000-000000000000'::uuid WHERE created_by IS NULL; +COMMIT; diff --git a/enterprise/audit/diff_internal_test.go b/enterprise/audit/diff_internal_test.go index 6d7a3ed643bcf..d5ee1f0e369c5 100644 --- a/enterprise/audit/diff_internal_test.go +++ b/enterprise/audit/diff_internal_test.go @@ -300,7 +300,7 @@ func Test_diff(t *testing.T) { }, exp: audit.Map{ "id": audit.OldNew{Old: "", New: uuid.UUID{1}.String()}, - "created_by": audit.OldNew{Old: "null", New: uuid.UUID{4}.String()}, + "created_by": audit.OldNew{Old: "", New: uuid.UUID{4}.String()}, "name": audit.OldNew{Old: "", New: "rust"}, }, }, From 15c7d9c37a23c1ecc00ee9a2eed632899b122c2d Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 28 Oct 2022 20:12:35 +0000 Subject: [PATCH 12/16] Fix down migration --- .../000068_update_template_version_created_by.down.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/database/migrations/000068_update_template_version_created_by.down.sql b/coderd/database/migrations/000068_update_template_version_created_by.down.sql index 96954c128c60d..a6921e97a6f71 100644 --- a/coderd/database/migrations/000068_update_template_version_created_by.down.sql +++ b/coderd/database/migrations/000068_update_template_version_created_by.down.sql @@ -1 +1 @@ -ALTER TABLE template_versions ALTER COLUMN created_by SET NULL; +ALTER TABLE template_versions ALTER COLUMN created_by DROP NOT NULL; From acdb08157459a61360abd7ab3e1b990383535112 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Mon, 31 Oct 2022 15:56:46 +0000 Subject: [PATCH 13/16] Use store --- coderd/templateversions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/templateversions.go b/coderd/templateversions.go index 0d46e7b4e1023..bc0a3c91bf7fe 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -522,7 +522,7 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque }) return err } - user, err := api.Database.GetUserByID(ctx, version.CreatedBy) + user, err := store.GetUserByID(ctx, version.CreatedBy) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Internal error on fetching user.", From 67e51f06e6a9e72404489b15ba41e45412010ebf Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Mon, 31 Oct 2022 16:03:22 +0000 Subject: [PATCH 14/16] Remove unecessary eslint comment --- site/src/components/Timeline/Timeline.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/site/src/components/Timeline/Timeline.tsx b/site/src/components/Timeline/Timeline.tsx index e8e13be1f65d4..1a73000a2f3a2 100644 --- a/site/src/components/Timeline/Timeline.tsx +++ b/site/src/components/Timeline/Timeline.tsx @@ -12,7 +12,6 @@ const groupByDate = ( items.forEach((item) => { const dateKey = getDate(item).toDateString() - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (itemsByDate[dateKey]) { itemsByDate[dateKey].push(item) } else { From b0729cea2f64b2a4d763698889f9c13de834529f Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Mon, 31 Oct 2022 16:11:32 +0000 Subject: [PATCH 15/16] Fix eslint --- site/src/components/Timeline/Timeline.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/site/src/components/Timeline/Timeline.tsx b/site/src/components/Timeline/Timeline.tsx index 1a73000a2f3a2..c1d7a7c40d636 100644 --- a/site/src/components/Timeline/Timeline.tsx +++ b/site/src/components/Timeline/Timeline.tsx @@ -12,6 +12,8 @@ const groupByDate = ( items.forEach((item) => { const dateKey = getDate(item).toDateString() + // Is not a guarantee a value is defined when access it dynamically + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (itemsByDate[dateKey]) { itemsByDate[dateKey].push(item) } else { From cf6484cdc9de89e254bc490b78730ead3976b12b Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Mon, 31 Oct 2022 16:21:11 +0000 Subject: [PATCH 16/16] Add line --- site/src/components/Timeline/Timeline.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/site/src/components/Timeline/Timeline.tsx b/site/src/components/Timeline/Timeline.tsx index c1d7a7c40d636..6e4e205d6e85c 100644 --- a/site/src/components/Timeline/Timeline.tsx +++ b/site/src/components/Timeline/Timeline.tsx @@ -12,8 +12,7 @@ const groupByDate = ( items.forEach((item) => { const dateKey = getDate(item).toDateString() - // Is not a guarantee a value is defined when access it dynamically - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Is not a guarantee a value is defined when access it dynamically if (itemsByDate[dateKey]) { itemsByDate[dateKey].push(item) } else {