From aacbeb1a3de8dfe38db1b31a5d806f8c3239170f Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Thu, 1 Sep 2022 20:40:01 +0000 Subject: [PATCH 1/7] Add DB plumbing --- coderd/database/databasefake/databasefake.go | 16 ++++++++ coderd/database/dump.sql | 3 +- .../000043_workspace_last_used.down.sql | 2 + .../000043_workspace_last_used.up.sql | 2 + coderd/database/models.go | 1 + coderd/database/querier.go | 1 + coderd/database/queries.sql.go | 37 ++++++++++++++++--- coderd/database/queries/workspaces.sql | 8 ++++ 8 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 coderd/database/migrations/000043_workspace_last_used.down.sql create mode 100644 coderd/database/migrations/000043_workspace_last_used.up.sql diff --git a/coderd/database/databasefake/databasefake.go b/coderd/database/databasefake/databasefake.go index 7fc3aea9e71c2..0958d2e7ffde9 100644 --- a/coderd/database/databasefake/databasefake.go +++ b/coderd/database/databasefake/databasefake.go @@ -2208,6 +2208,22 @@ func (q *fakeQuerier) UpdateWorkspaceTTL(_ context.Context, arg database.UpdateW return sql.ErrNoRows } +func (q *fakeQuerier) UpdateWorkspaceLastUsedAt(_ context.Context, arg database.UpdateWorkspaceLastUsedAtParams) error { + q.mutex.Lock() + defer q.mutex.Unlock() + + for index, workspace := range q.workspaces { + if workspace.ID != arg.ID { + continue + } + workspace.LastUsedAt = arg.LastUsedAt + q.workspaces[index] = workspace + return nil + } + + return sql.ErrNoRows +} + func (q *fakeQuerier) UpdateWorkspaceBuildByID(_ context.Context, arg database.UpdateWorkspaceBuildByIDParams) error { q.mutex.Lock() defer q.mutex.Unlock() diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 86a1f91cc8c96..6f2853e183888 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -377,7 +377,8 @@ CREATE TABLE workspaces ( deleted boolean DEFAULT false NOT NULL, name character varying(64) NOT NULL, autostart_schedule text, - ttl bigint + ttl bigint, + last_used_at timestamp without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL ); ALTER TABLE ONLY licenses ALTER COLUMN id SET DEFAULT nextval('public.licenses_id_seq'::regclass); diff --git a/coderd/database/migrations/000043_workspace_last_used.down.sql b/coderd/database/migrations/000043_workspace_last_used.down.sql new file mode 100644 index 0000000000000..591a65a707ca4 --- /dev/null +++ b/coderd/database/migrations/000043_workspace_last_used.down.sql @@ -0,0 +1,2 @@ +ALTER TABLE workspaces + DROP COLUMN last_used_at; diff --git a/coderd/database/migrations/000043_workspace_last_used.up.sql b/coderd/database/migrations/000043_workspace_last_used.up.sql new file mode 100644 index 0000000000000..33026756c785b --- /dev/null +++ b/coderd/database/migrations/000043_workspace_last_used.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE workspaces + ADD COLUMN last_used_at timestamp NOT NULL DEFAULT '0001-01-01 00:00:00+00:00'; diff --git a/coderd/database/models.go b/coderd/database/models.go index 0a56fe560c15f..b64be8b3a995f 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -525,6 +525,7 @@ type Workspace struct { Name string `db:"name" json:"name"` AutostartSchedule sql.NullString `db:"autostart_schedule" json:"autostart_schedule"` Ttl sql.NullInt64 `db:"ttl" json:"ttl"` + LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"` } type WorkspaceAgent struct { diff --git a/coderd/database/querier.go b/coderd/database/querier.go index 12400d3924c81..12985422f5f06 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -150,6 +150,7 @@ type querier interface { UpdateWorkspaceAutostart(ctx context.Context, arg UpdateWorkspaceAutostartParams) error UpdateWorkspaceBuildByID(ctx context.Context, arg UpdateWorkspaceBuildByIDParams) error UpdateWorkspaceDeletedByID(ctx context.Context, arg UpdateWorkspaceDeletedByIDParams) error + UpdateWorkspaceLastUsedAt(ctx context.Context, arg UpdateWorkspaceLastUsedAtParams) error UpdateWorkspaceTTL(ctx context.Context, arg UpdateWorkspaceTTLParams) error } diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 76f42cef55e46..9d63a7e49424f 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -4562,7 +4562,7 @@ func (q *sqlQuerier) InsertWorkspaceResourceMetadata(ctx context.Context, arg In const getWorkspaceByID = `-- name: GetWorkspaceByID :one SELECT - id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl + id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at FROM workspaces WHERE @@ -4585,13 +4585,14 @@ func (q *sqlQuerier) GetWorkspaceByID(ctx context.Context, id uuid.UUID) (Worksp &i.Name, &i.AutostartSchedule, &i.Ttl, + &i.LastUsedAt, ) return i, err } const getWorkspaceByOwnerIDAndName = `-- name: GetWorkspaceByOwnerIDAndName :one SELECT - id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl + id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at FROM workspaces WHERE @@ -4621,6 +4622,7 @@ func (q *sqlQuerier) GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWo &i.Name, &i.AutostartSchedule, &i.Ttl, + &i.LastUsedAt, ) return i, err } @@ -4669,7 +4671,7 @@ func (q *sqlQuerier) GetWorkspaceOwnerCountsByTemplateIDs(ctx context.Context, i const getWorkspaces = `-- name: GetWorkspaces :many SELECT - id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl + id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at FROM workspaces WHERE @@ -4745,6 +4747,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams) &i.Name, &i.AutostartSchedule, &i.Ttl, + &i.LastUsedAt, ); err != nil { return nil, err } @@ -4761,7 +4764,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams) const getWorkspacesAutostart = `-- name: GetWorkspacesAutostart :many SELECT - id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl + id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at FROM workspaces WHERE @@ -4794,6 +4797,7 @@ func (q *sqlQuerier) GetWorkspacesAutostart(ctx context.Context) ([]Workspace, e &i.Name, &i.AutostartSchedule, &i.Ttl, + &i.LastUsedAt, ); err != nil { return nil, err } @@ -4822,7 +4826,7 @@ INSERT INTO ttl ) VALUES - ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl + ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at ` type InsertWorkspaceParams struct { @@ -4861,6 +4865,7 @@ func (q *sqlQuerier) InsertWorkspace(ctx context.Context, arg InsertWorkspacePar &i.Name, &i.AutostartSchedule, &i.Ttl, + &i.LastUsedAt, ) return i, err } @@ -4873,7 +4878,7 @@ SET WHERE id = $1 AND deleted = false -RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl +RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at ` type UpdateWorkspaceParams struct { @@ -4895,6 +4900,7 @@ func (q *sqlQuerier) UpdateWorkspace(ctx context.Context, arg UpdateWorkspacePar &i.Name, &i.AutostartSchedule, &i.Ttl, + &i.LastUsedAt, ) return i, err } @@ -4937,6 +4943,25 @@ func (q *sqlQuerier) UpdateWorkspaceDeletedByID(ctx context.Context, arg UpdateW return err } +const updateWorkspaceLastUsedAt = `-- name: UpdateWorkspaceLastUsedAt :exec +UPDATE + workspaces +SET + last_used_at = $2 +WHERE + id = $1 +` + +type UpdateWorkspaceLastUsedAtParams struct { + ID uuid.UUID `db:"id" json:"id"` + LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"` +} + +func (q *sqlQuerier) UpdateWorkspaceLastUsedAt(ctx context.Context, arg UpdateWorkspaceLastUsedAtParams) error { + _, err := q.db.ExecContext(ctx, updateWorkspaceLastUsedAt, arg.ID, arg.LastUsedAt) + return err +} + const updateWorkspaceTTL = `-- name: UpdateWorkspaceTTL :exec UPDATE workspaces diff --git a/coderd/database/queries/workspaces.sql b/coderd/database/queries/workspaces.sql index 8de76e258415e..3af1ca49655d5 100644 --- a/coderd/database/queries/workspaces.sql +++ b/coderd/database/queries/workspaces.sql @@ -137,3 +137,11 @@ SET ttl = $2 WHERE id = $1; + +-- name: UpdateWorkspaceLastUsedAt :exec +UPDATE + workspaces +SET + last_used_at = $2 +WHERE + id = $1; From eeebe0ca0bdf33f9d0701abd9b26ab60a2a759b4 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Thu, 1 Sep 2022 21:01:19 +0000 Subject: [PATCH 2/7] Add API --- coderd/templates_test.go | 10 ++++++++++ coderd/workspaceagents.go | 20 +++++++++++++++++--- coderd/workspaces.go | 1 + codersdk/workspaces.go | 1 + 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/coderd/templates_test.go b/coderd/templates_test.go index ae1976c6472ef..3eea3a9387a21 100644 --- a/coderd/templates_test.go +++ b/coderd/templates_test.go @@ -608,6 +608,10 @@ func TestTemplateDAUs(t *testing.T) { Entries: []codersdk.DAUEntry{}, }, daus, "no DAUs when stats are empty") + workspaces, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{}) + require.NoError(t, err) + assert.Zero(t, workspaces[0].LastUsedAt) + conn, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, opts) require.NoError(t, err) defer func() { @@ -641,4 +645,10 @@ func TestTemplateDAUs(t *testing.T) { testutil.WaitShort, testutil.IntervalFast, "got %+v != %+v", daus, want, ) + + workspaces, err = client.Workspaces(ctx, codersdk.WorkspaceFilter{}) + require.NoError(t, err) + assert.WithinDuration(t, + time.Now(), workspaces[0].LastUsedAt, time.Minute, + ) } diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go index 509365e8a0092..bb48da0bab4d5 100644 --- a/coderd/workspaceagents.go +++ b/coderd/workspaceagents.go @@ -830,18 +830,20 @@ func (api *API) workspaceAgentReportStats(rw http.ResponseWriter, r *http.Reques // We will see duplicate reports when on idle connections // (e.g. web terminal left open) or when there are no connections at // all. - var insert = !reflect.DeepEqual(lastReport, rep) + // We also don't want to update the workspace last used at on duplicate + // reports. + var updateDB = !reflect.DeepEqual(lastReport, rep) api.Logger.Debug(ctx, "read stats report", slog.F("interval", api.AgentStatsRefreshInterval), slog.F("agent", workspaceAgent.ID), slog.F("resource", resource.ID), slog.F("workspace", workspace.ID), - slog.F("insert", insert), + slog.F("update_db", updateDB), slog.F("payload", rep), ) - if insert { + if updateDB { lastReport = rep _, err = api.Database.InsertAgentStat(ctx, database.InsertAgentStatParams{ @@ -860,6 +862,18 @@ func (api *API) workspaceAgentReportStats(rw http.ResponseWriter, r *http.Reques }) return } + + err = api.Database.UpdateWorkspaceLastUsedAt(ctx, database.UpdateWorkspaceLastUsedAtParams{ + ID: build.WorkspaceID, + LastUsedAt: time.Now(), + }) + if err != nil { + httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{ + Message: "Failed to update workspace last used at.", + Detail: err.Error(), + }) + return + } } select { diff --git a/coderd/workspaces.go b/coderd/workspaces.go index d524dc634027f..b1e7e4e999137 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -941,6 +941,7 @@ func convertWorkspace( Name: workspace.Name, AutostartSchedule: autostartSchedule, TTLMillis: ttlMillis, + LastUsedAt: workspace.LastUsedAt, } } diff --git a/codersdk/workspaces.go b/codersdk/workspaces.go index 07da2e394dabc..a4ab1fd54dee9 100644 --- a/codersdk/workspaces.go +++ b/codersdk/workspaces.go @@ -30,6 +30,7 @@ type Workspace struct { Name string `json:"name"` AutostartSchedule *string `json:"autostart_schedule,omitempty"` TTLMillis *int64 `json:"ttl_ms,omitempty"` + LastUsedAt time.Time `json:"last_used_at"` } // CreateWorkspaceBuildRequest provides options to update the latest workspace build. From 8571215cc33aff4d739ffd97bbdfefa46d5c25a4 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Thu, 1 Sep 2022 21:06:23 +0000 Subject: [PATCH 3/7] Fix auditing --- enterprise/audit/table.go | 1 + 1 file changed, 1 insertion(+) diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go index aa63096366860..8385d8282b371 100644 --- a/enterprise/audit/table.go +++ b/enterprise/audit/table.go @@ -95,6 +95,7 @@ var AuditableResources = auditMap(map[any]map[string]Action{ "name": ActionTrack, "autostart_schedule": ActionTrack, "ttl": ActionTrack, + "last_used_at": ActionIgnore, }, }) From 0f31418852e4db57b0c1f3f1c4c7b5406f3bb85a Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Thu, 1 Sep 2022 22:19:03 +0000 Subject: [PATCH 4/7] Add frontend --- agent/agent_test.go | 2 +- site/src/api/typesGenerated.ts | 1 + .../WorkspacesTable/WorkspaceLastUsed.tsx | 36 +++++++++++++++++++ .../WorkspacesTable/WorkspacesRow.tsx | 7 ++++ .../WorkspacesTable/WorkspacesTable.tsx | 2 ++ .../WorkspacesPageView.stories.tsx | 11 ++++++ site/src/testHelpers/entities.ts | 1 + 7 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx diff --git a/agent/agent_test.go b/agent/agent_test.go index a2a4fc28c445a..49f57214ab6eb 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -105,7 +105,7 @@ func TestAgent(t *testing.T) { var ok bool s, ok = (<-stats) return ok && s.NumConns > 0 && s.RxBytes > 0 && s.TxBytes > 0 - }, testutil.WaitShort, testutil.IntervalFast, + }, testutil.WaitLong, testutil.IntervalFast, "never saw stats: %+v", s, ) }) diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 5102485e11bba..e2998a383ebde 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -514,6 +514,7 @@ export interface Workspace { readonly name: string readonly autostart_schedule?: string readonly ttl_ms?: number + readonly last_used_at: string } // From codersdk/workspaceresources.go diff --git a/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx b/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx new file mode 100644 index 0000000000000..a69a2f6412595 --- /dev/null +++ b/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx @@ -0,0 +1,36 @@ +import { Theme, useTheme } from "@material-ui/core/styles" +import { FC } from "react" + +import dayjs from "dayjs" +import relativeTime from "dayjs/plugin/relativeTime" + +dayjs.extend(relativeTime) + +interface WorkspaceLastUsedProps { + lastUsedAt: string +} + +export const WorkspaceLastUsed: FC = ({ lastUsedAt }) => { + const theme: Theme = useTheme() + + const t = dayjs(lastUsedAt) + const now = dayjs() + + let color = theme.palette.text.secondary + let message = t.fromNow() + + if (t.isBefore(now.subtract(100, "year"))) { + color = theme.palette.error.main + message = "Never" + } else if (t.isBefore(now.subtract(1, "month"))) { + color = theme.palette.warning.light + } else if (t.isAfter(now.subtract(24, "hour"))) { + // Since the agent reports on a regular interval, + // we default to "Today" instead of showing a + // potentially inaccurate value. + color = theme.palette.success.main + message = "Today" + } + + return {message} +} diff --git a/site/src/components/WorkspacesTable/WorkspacesRow.tsx b/site/src/components/WorkspacesTable/WorkspacesRow.tsx index d6bc5c47e5dcd..cf6b92d1da480 100644 --- a/site/src/components/WorkspacesTable/WorkspacesRow.tsx +++ b/site/src/components/WorkspacesTable/WorkspacesRow.tsx @@ -15,6 +15,7 @@ import { } from "../TableCellData/TableCellData" import { TableCellLink } from "../TableCellLink/TableCellLink" import { OutdatedHelpTooltip } from "../Tooltips" +import { WorkspaceLastUsed } from "./WorkspaceLastUsed" const Language = { upToDateLabel: "Up to date", @@ -64,6 +65,12 @@ export const WorkspacesRow: FC< } /> + + + + + + {workspace.outdated ? ( diff --git a/site/src/components/WorkspacesTable/WorkspacesTable.tsx b/site/src/components/WorkspacesTable/WorkspacesTable.tsx index 3561febff3d60..b2b7f175c8591 100644 --- a/site/src/components/WorkspacesTable/WorkspacesTable.tsx +++ b/site/src/components/WorkspacesTable/WorkspacesTable.tsx @@ -11,6 +11,7 @@ import { WorkspacesTableBody } from "./WorkspacesTableBody" const Language = { name: "Name", template: "Template", + lastUsed: "Last Used", version: "Version", status: "Status", lastBuiltBy: "Last Built By", @@ -34,6 +35,7 @@ export const WorkspacesTable: FC> {Language.name} {Language.template} + {Language.lastUsed} {Language.version} {Language.status} diff --git a/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx b/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx index 2c0a3c5602e66..3ae9dc102b1bf 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx @@ -1,4 +1,5 @@ import { ComponentMeta, Story } from "@storybook/react" +import dayjs from "dayjs" import { spawn } from "xstate" import { ProvisionerJobStatus, WorkspaceTransition } from "../../api/typesGenerated" import { MockWorkspace } from "../../testHelpers/entities" @@ -13,6 +14,7 @@ const createWorkspaceItemRef = ( status: ProvisionerJobStatus, transition: WorkspaceTransition = "start", outdated = false, + lastUsedAt = "0001-01-01", ): WorkspaceItemMachineRef => { return spawn( workspaceItemMachine.withContext({ @@ -27,6 +29,7 @@ const createWorkspaceItemRef = ( status: status, }, }, + last_used_at: lastUsedAt, }, }), ) @@ -48,6 +51,14 @@ const additionalWorkspaces: Record = { succeededAndStop: createWorkspaceItemRef("succeeded", "stop"), runningAndDelete: createWorkspaceItemRef("running", "delete"), outdated: createWorkspaceItemRef("running", "delete", true), + active: createWorkspaceItemRef("running", undefined, true, dayjs().toString()), + old: createWorkspaceItemRef("running", undefined, true, dayjs().subtract(1, "week").toString()), + veryOld: createWorkspaceItemRef( + "running", + undefined, + true, + dayjs().subtract(1, "month").subtract(4, "day").toString(), + ), } export default { diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index c3013aff41ad6..8dfd5e7aad7a0 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -236,6 +236,7 @@ export const MockWorkspace: TypesGen.Workspace = { autostart_schedule: MockWorkspaceAutostartEnabled.schedule, ttl_ms: 2 * 60 * 60 * 1000, // 2 hours as milliseconds latest_build: MockWorkspaceBuild, + last_used_at: "", } export const MockStoppedWorkspace: TypesGen.Workspace = { From abbbf271b7bd9dac6f6f83dae93bd26fc48f1f2e Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Thu, 1 Sep 2022 22:32:10 +0000 Subject: [PATCH 5/7] Improve colors --- .../WorkspacesTable/WorkspaceLastUsed.tsx | 23 +++++++++++-------- .../WorkspacesPageView.stories.tsx | 1 + 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx b/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx index a69a2f6412595..c48f185179bad 100644 --- a/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx +++ b/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx @@ -19,17 +19,22 @@ export const WorkspaceLastUsed: FC = ({ lastUsedAt }) => let color = theme.palette.text.secondary let message = t.fromNow() - if (t.isBefore(now.subtract(100, "year"))) { - color = theme.palette.error.main - message = "Never" - } else if (t.isBefore(now.subtract(1, "month"))) { - color = theme.palette.warning.light - } else if (t.isAfter(now.subtract(24, "hour"))) { - // Since the agent reports on a regular interval, + if (t.isAfter(now.subtract(1, "hour"))) { + color = theme.palette.success.main + // Since the agent reports on a 10m interval, + // the last_used_at can be inaccurate when recent. // we default to "Today" instead of showing a // potentially inaccurate value. - color = theme.palette.success.main - message = "Today" + message = "Last Hour" + } else if (t.isAfter(now.subtract(1, "day"))) { + color = theme.palette.primary.main + } else if (t.isAfter(now.subtract(1, "month"))) { + color = theme.palette.text.secondary + } else if (t.isAfter(now.subtract(100, "year"))) { + color = theme.palette.warning.light + } else { + color = theme.palette.error.light + message = "Never" } return {message} diff --git a/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx b/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx index 3ae9dc102b1bf..6624f2aa51be7 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx @@ -52,6 +52,7 @@ const additionalWorkspaces: Record = { runningAndDelete: createWorkspaceItemRef("running", "delete"), outdated: createWorkspaceItemRef("running", "delete", true), active: createWorkspaceItemRef("running", undefined, true, dayjs().toString()), + today: createWorkspaceItemRef("running", undefined, true, dayjs().subtract(3, "hour").toString()), old: createWorkspaceItemRef("running", undefined, true, dayjs().subtract(1, "week").toString()), veryOld: createWorkspaceItemRef( "running", From 406bcbe225d840d1bfc5f1bb858d50d2f37cadd6 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Thu, 1 Sep 2022 22:33:17 +0000 Subject: [PATCH 6/7] fixup! Improve colors --- site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx b/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx index c48f185179bad..50a967dcfaed8 100644 --- a/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx +++ b/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx @@ -23,8 +23,6 @@ export const WorkspaceLastUsed: FC = ({ lastUsedAt }) => color = theme.palette.success.main // Since the agent reports on a 10m interval, // the last_used_at can be inaccurate when recent. - // we default to "Today" instead of showing a - // potentially inaccurate value. message = "Last Hour" } else if (t.isAfter(now.subtract(1, "day"))) { color = theme.palette.primary.main From 4c46a7a65e050c82f3487e69844de901dc892b35 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Thu, 1 Sep 2022 23:27:59 +0000 Subject: [PATCH 7/7] Correct spelling re. comment --- site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx b/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx index 50a967dcfaed8..c64af30eac471 100644 --- a/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx +++ b/site/src/components/WorkspacesTable/WorkspaceLastUsed.tsx @@ -23,7 +23,7 @@ export const WorkspaceLastUsed: FC = ({ lastUsedAt }) => color = theme.palette.success.main // Since the agent reports on a 10m interval, // the last_used_at can be inaccurate when recent. - message = "Last Hour" + message = "In the last hour" } else if (t.isAfter(now.subtract(1, "day"))) { color = theme.palette.primary.main } else if (t.isAfter(now.subtract(1, "month"))) {