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") }) } diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 4953c9885fe65..3c215b4c957a7 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/000068_update_template_version_created_by.down.sql b/coderd/database/migrations/000068_update_template_version_created_by.down.sql new file mode 100644 index 0000000000000..a6921e97a6f71 --- /dev/null +++ b/coderd/database/migrations/000068_update_template_version_created_by.down.sql @@ -0,0 +1 @@ +ALTER TABLE template_versions ALTER COLUMN created_by DROP NOT 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 new file mode 100644 index 0000000000000..af6a2bb9000fb --- /dev/null +++ b/coderd/database/migrations/000068_update_template_version_created_by.up.sql @@ -0,0 +1,4 @@ +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/coderd/database/models.go b/coderd/database/models.go index ec0d04e06beac..1c10b7437996b 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 58f89cad9fd70..786a8abcb43ca 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/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) diff --git a/coderd/templateversions.go b/coderd/templateversions.go index e434482ad8b69..bc0a3c91bf7fe 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 := store.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..3aee18ec80a18 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. diff --git a/enterprise/audit/diff_internal_test.go b/enterprise/audit/diff_internal_test.go index ff21b0b18b32f..d5ee1f0e369c5 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,11 +296,11 @@ 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()}, - "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"}, }, }, diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 6b8affde3d827..3d1e0dd33badf 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 76ab9b93c17a2..9ccd57d4ea675 100644 --- a/site/src/components/BuildsTable/BuildsTable.tsx +++ b/site/src/components/BuildsTable/BuildsTable.tsx @@ -4,73 +4,37 @@ 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 = { emptyMessage: "No builds found", - inProgressLabel: "In progress", - actionLabel: "Action", - durationLabel: "Duration", - startedAtLabel: "Started at", - statusLabel: "Status", } 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() - - // Unsure why this is here but we probably need to fix it. - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- see above - 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..6e4e205d6e85c --- /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 -- Is not a guarantee a value is defined when access it dynamically + 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/components/VersionsTable/VersionRow.tsx b/site/src/components/VersionsTable/VersionRow.tsx new file mode 100644 index 0000000000000..018e793e7287b --- /dev/null +++ b/site/src/components/VersionsTable/VersionRow.tsx @@ -0,0 +1,88 @@ +import { makeStyles } from "@material-ui/core/styles" +import TableCell from "@material-ui/core/TableCell" +import TableRow from "@material-ui/core/TableRow" +import { TemplateVersion } from "api/typesGenerated" +import { Stack } from "components/Stack/Stack" +import { UserAvatar } from "components/UserAvatar/UserAvatar" +import { useTranslation } from "react-i18next" + +export interface VersionRowProps { + version: TemplateVersion +} + +export const VersionRow: React.FC = ({ version }) => { + const styles = useStyles() + const { t } = useTranslation("templatePage") + + return ( + + + + + + + + {version.created_by.username}{" "} + {t("createdVersion")} {version.name} + + + + {new Date(version.created_at).toLocaleTimeString()} + + + + + + + ) +} + +const useStyles = makeStyles((theme) => ({ + versionRow: { + "&:not(:last-child) td:before": { + position: "absolute", + top: 20, + left: 50, + display: "block", + content: "''", + height: "100%", + width: 2, + background: theme.palette.divider, + }, + }, + + versionWrapper: { + padding: theme.spacing(2, 4), + }, + + versionCell: { + padding: "0 !important", + position: "relative", + borderBottom: 0, + }, + + versionSummary: { + ...theme.typography.body1, + fontFamily: "inherit", + }, + + versionTime: { + color: theme.palette.text.secondary, + fontSize: 12, + }, +})) diff --git a/site/src/components/VersionsTable/VersionsTable.tsx b/site/src/components/VersionsTable/VersionsTable.tsx index 94ce57e652f1b..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,45 +25,21 @@ export interface VersionsTableProps { export const VersionsTable: FC> = ({ versions, }) => { - const isLoading = !versions - const theme: Theme = useTheme() - return (
- - - {Language.nameLabel} - {Language.createdAtLabel} - {Language.createdByLabel} - - - {isLoading && } - {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" } diff --git a/site/src/pages/AuditPage/AuditPageView.tsx b/site/src/pages/AuditPage/AuditPageView.tsx index b48a76aa0160e..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 -- TODO look into this - 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 && ( diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index f0f51152b963b..81cfe8f6a5041 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -175,8 +175,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 = {