feat(coderd): allow workspace owners to mark workspaces as favorite (#11791)

- Adds column `favorite` to workspaces table
- Adds API endpoints to favorite/unfavorite workspaces
- Modifies sorting order to return owners' favorite workspaces first
This commit is contained in:
Cian Johnston
2024-01-24 13:39:19 +00:00
committed by GitHub
parent 6145da8a9e
commit f92336c4d5
27 changed files with 646 additions and 50 deletions

View File

@ -10849,6 +10849,15 @@ func (q *sqlQuerier) BatchUpdateWorkspaceLastUsedAt(ctx context.Context, arg Bat
return err
}
const favoriteWorkspace = `-- name: FavoriteWorkspace :exec
UPDATE workspaces SET favorite = true WHERE id = $1
`
func (q *sqlQuerier) FavoriteWorkspace(ctx context.Context, id uuid.UUID) error {
_, err := q.db.ExecContext(ctx, favoriteWorkspace, id)
return err
}
const getDeploymentWorkspaceStats = `-- name: GetDeploymentWorkspaceStats :one
WITH workspaces_with_jobs AS (
SELECT
@ -10935,7 +10944,7 @@ func (q *sqlQuerier) GetDeploymentWorkspaceStats(ctx context.Context) (GetDeploy
const getWorkspaceByAgentID = `-- name: GetWorkspaceByAgentID :one
SELECT
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates,
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite,
templates.name as template_name
FROM
workspaces
@ -10989,6 +10998,7 @@ func (q *sqlQuerier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUI
&i.Workspace.DormantAt,
&i.Workspace.DeletingAt,
&i.Workspace.AutomaticUpdates,
&i.Workspace.Favorite,
&i.TemplateName,
)
return i, err
@ -10996,7 +11006,7 @@ func (q *sqlQuerier) GetWorkspaceByAgentID(ctx context.Context, agentID uuid.UUI
const getWorkspaceByID = `-- name: GetWorkspaceByID :one
SELECT
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite
FROM
workspaces
WHERE
@ -11023,13 +11033,14 @@ func (q *sqlQuerier) GetWorkspaceByID(ctx context.Context, id uuid.UUID) (Worksp
&i.DormantAt,
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
)
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, last_used_at, dormant_at, deleting_at, automatic_updates
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite
FROM
workspaces
WHERE
@ -11063,13 +11074,14 @@ func (q *sqlQuerier) GetWorkspaceByOwnerIDAndName(ctx context.Context, arg GetWo
&i.DormantAt,
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
)
return i, err
}
const getWorkspaceByWorkspaceAppID = `-- name: GetWorkspaceByWorkspaceAppID :one
SELECT
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates
id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite
FROM
workspaces
WHERE
@ -11122,6 +11134,7 @@ func (q *sqlQuerier) GetWorkspaceByWorkspaceAppID(ctx context.Context, workspace
&i.DormantAt,
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
)
return i, err
}
@ -11166,7 +11179,7 @@ func (q *sqlQuerier) GetWorkspaceUniqueOwnerCountByTemplateIDs(ctx context.Conte
const getWorkspaces = `-- name: GetWorkspaces :many
SELECT
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates,
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite,
COALESCE(template.name, 'unknown') as template_name,
latest_build.template_version_id,
latest_build.template_version_name,
@ -11355,6 +11368,8 @@ WHERE
-- Authorize Filter clause will be injected below in GetAuthorizedWorkspaces
-- @authorize_filter
ORDER BY
-- To ensure that 'favorite' workspaces show up first in the list only for their owner.
CASE WHEN workspaces.owner_id = $14 AND workspaces.favorite THEN 0 ELSE 1 END ASC,
(latest_build.completed_at IS NOT NULL AND
latest_build.canceled_at IS NULL AND
latest_build.error IS NULL AND
@ -11363,11 +11378,11 @@ ORDER BY
LOWER(workspaces.name) ASC
LIMIT
CASE
WHEN $15 :: integer > 0 THEN
$15
WHEN $16 :: integer > 0 THEN
$16
END
OFFSET
$14
$15
`
type GetWorkspacesParams struct {
@ -11384,6 +11399,7 @@ type GetWorkspacesParams struct {
LastUsedBefore time.Time `db:"last_used_before" json:"last_used_before"`
LastUsedAfter time.Time `db:"last_used_after" json:"last_used_after"`
UsingActive sql.NullBool `db:"using_active" json:"using_active"`
RequesterID uuid.UUID `db:"requester_id" json:"requester_id"`
Offset int32 `db:"offset_" json:"offset_"`
Limit int32 `db:"limit_" json:"limit_"`
}
@ -11403,6 +11419,7 @@ type GetWorkspacesRow struct {
DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"`
DeletingAt sql.NullTime `db:"deleting_at" json:"deleting_at"`
AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"`
Favorite bool `db:"favorite" json:"favorite"`
TemplateName string `db:"template_name" json:"template_name"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
TemplateVersionName sql.NullString `db:"template_version_name" json:"template_version_name"`
@ -11424,6 +11441,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
arg.LastUsedBefore,
arg.LastUsedAfter,
arg.UsingActive,
arg.RequesterID,
arg.Offset,
arg.Limit,
)
@ -11449,6 +11467,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
&i.DormantAt,
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
&i.TemplateName,
&i.TemplateVersionID,
&i.TemplateVersionName,
@ -11469,7 +11488,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
const getWorkspacesEligibleForTransition = `-- name: GetWorkspacesEligibleForTransition :many
SELECT
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite
FROM
workspaces
LEFT JOIN
@ -11557,6 +11576,7 @@ func (q *sqlQuerier) GetWorkspacesEligibleForTransition(ctx context.Context, now
&i.DormantAt,
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
); err != nil {
return nil, err
}
@ -11587,7 +11607,7 @@ INSERT INTO
automatic_updates
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite
`
type InsertWorkspaceParams struct {
@ -11634,10 +11654,20 @@ func (q *sqlQuerier) InsertWorkspace(ctx context.Context, arg InsertWorkspacePar
&i.DormantAt,
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
)
return i, err
}
const unfavoriteWorkspace = `-- name: UnfavoriteWorkspace :exec
UPDATE workspaces SET favorite = false WHERE id = $1
`
func (q *sqlQuerier) UnfavoriteWorkspace(ctx context.Context, id uuid.UUID) error {
_, err := q.db.ExecContext(ctx, unfavoriteWorkspace, id)
return err
}
const updateTemplateWorkspacesLastUsedAt = `-- name: UpdateTemplateWorkspacesLastUsedAt :exec
UPDATE workspaces
SET
@ -11664,7 +11694,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, last_used_at, dormant_at, deleting_at, automatic_updates
RETURNING id, created_at, updated_at, owner_id, organization_id, template_id, deleted, name, autostart_schedule, ttl, last_used_at, dormant_at, deleting_at, automatic_updates, favorite
`
type UpdateWorkspaceParams struct {
@ -11690,6 +11720,7 @@ func (q *sqlQuerier) UpdateWorkspace(ctx context.Context, arg UpdateWorkspacePar
&i.DormantAt,
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
)
return i, err
}
@ -11776,7 +11807,7 @@ WHERE
workspaces.id = $1
AND templates.id = workspaces.template_id
RETURNING
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite
`
type UpdateWorkspaceDormantDeletingAtParams struct {
@ -11802,6 +11833,7 @@ func (q *sqlQuerier) UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg U
&i.DormantAt,
&i.DeletingAt,
&i.AutomaticUpdates,
&i.Favorite,
)
return i, err
}