feat: support icon and description in preset (#18977)

## Description 

This PR adds support for `description` and `icon` fields to
`template_version_presets`. These fields will allow displaying richer
information for presets in the UI, improving the user experience when
creating a workspace.
Both fields are optional, non-nullable, and default to empty strings.

## Changes

* Database migration with the addition of `description VARCHAR(128)` and
`icon VARCHAR(256)` columns to the `template_version_presets` table.
* Updated the `CreateWorkspacePageView` in the UI

Note: UI changes will be addressed in a separate PR
This commit is contained in:
Susana Ferreira
2025-07-28 15:02:26 +01:00
committed by GitHub
parent 58123e17ca
commit 0672bf5084
24 changed files with 707 additions and 579 deletions
+2
View File
@@ -417,6 +417,8 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
InvalidateAfterSecs: preset.InvalidateAfterSecs,
SchedulingTimezone: preset.SchedulingTimezone,
IsDefault: false,
Description: preset.Description,
Icon: preset.Icon,
})
}
+2
View File
@@ -1392,6 +1392,8 @@ func Preset(t testing.TB, db database.Store, seed database.InsertPresetParams) d
InvalidateAfterSecs: seed.InvalidateAfterSecs,
SchedulingTimezone: seed.SchedulingTimezone,
IsDefault: seed.IsDefault,
Description: seed.Description,
Icon: seed.Icon,
})
require.NoError(t, err, "insert preset")
return preset
+7 -1
View File
@@ -1618,9 +1618,15 @@ CREATE TABLE template_version_presets (
invalidate_after_secs integer DEFAULT 0,
prebuild_status prebuild_status DEFAULT 'healthy'::prebuild_status NOT NULL,
scheduling_timezone text DEFAULT ''::text NOT NULL,
is_default boolean DEFAULT false NOT NULL
is_default boolean DEFAULT false NOT NULL,
description character varying(128) DEFAULT ''::character varying NOT NULL,
icon character varying(256) DEFAULT ''::character varying NOT NULL
);
COMMENT ON COLUMN template_version_presets.description IS 'Short text describing the preset (max 128 characters).';
COMMENT ON COLUMN template_version_presets.icon IS 'URL or path to an icon representing the preset (max 256 characters).';
CREATE TABLE template_version_terraform_values (
template_version_id uuid NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
@@ -0,0 +1,3 @@
ALTER TABLE template_version_presets
DROP COLUMN IF EXISTS description,
DROP COLUMN IF EXISTS icon;
@@ -0,0 +1,6 @@
ALTER TABLE template_version_presets
ADD COLUMN IF NOT EXISTS description VARCHAR(128) NOT NULL DEFAULT '',
ADD COLUMN IF NOT EXISTS icon VARCHAR(256) NOT NULL DEFAULT '';
COMMENT ON COLUMN template_version_presets.description IS 'Short text describing the preset (max 128 characters).';
COMMENT ON COLUMN template_version_presets.icon IS 'URL or path to an icon representing the preset (max 256 characters).';
+4
View File
@@ -3621,6 +3621,10 @@ type TemplateVersionPreset struct {
PrebuildStatus PrebuildStatus `db:"prebuild_status" json:"prebuild_status"`
SchedulingTimezone string `db:"scheduling_timezone" json:"scheduling_timezone"`
IsDefault bool `db:"is_default" json:"is_default"`
// Short text describing the preset (max 128 characters).
Description string `db:"description" json:"description"`
// URL or path to an icon representing the preset (max 256 characters).
Icon string `db:"icon" json:"icon"`
}
type TemplateVersionPresetParameter struct {
+24 -6
View File
@@ -7628,7 +7628,7 @@ func (q *sqlQuerier) GetActivePresetPrebuildSchedules(ctx context.Context) ([]Te
}
const getPresetByID = `-- name: GetPresetByID :one
SELECT tvp.id, tvp.template_version_id, tvp.name, tvp.created_at, tvp.desired_instances, tvp.invalidate_after_secs, tvp.prebuild_status, tvp.scheduling_timezone, tvp.is_default, tv.template_id, tv.organization_id FROM
SELECT tvp.id, tvp.template_version_id, tvp.name, tvp.created_at, tvp.desired_instances, tvp.invalidate_after_secs, tvp.prebuild_status, tvp.scheduling_timezone, tvp.is_default, tvp.description, tvp.icon, tv.template_id, tv.organization_id FROM
template_version_presets tvp
INNER JOIN template_versions tv ON tvp.template_version_id = tv.id
WHERE tvp.id = $1
@@ -7644,6 +7644,8 @@ type GetPresetByIDRow struct {
PrebuildStatus PrebuildStatus `db:"prebuild_status" json:"prebuild_status"`
SchedulingTimezone string `db:"scheduling_timezone" json:"scheduling_timezone"`
IsDefault bool `db:"is_default" json:"is_default"`
Description string `db:"description" json:"description"`
Icon string `db:"icon" json:"icon"`
TemplateID uuid.NullUUID `db:"template_id" json:"template_id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
}
@@ -7661,6 +7663,8 @@ func (q *sqlQuerier) GetPresetByID(ctx context.Context, presetID uuid.UUID) (Get
&i.PrebuildStatus,
&i.SchedulingTimezone,
&i.IsDefault,
&i.Description,
&i.Icon,
&i.TemplateID,
&i.OrganizationID,
)
@@ -7669,7 +7673,7 @@ func (q *sqlQuerier) GetPresetByID(ctx context.Context, presetID uuid.UUID) (Get
const getPresetByWorkspaceBuildID = `-- name: GetPresetByWorkspaceBuildID :one
SELECT
template_version_presets.id, template_version_presets.template_version_id, template_version_presets.name, template_version_presets.created_at, template_version_presets.desired_instances, template_version_presets.invalidate_after_secs, template_version_presets.prebuild_status, template_version_presets.scheduling_timezone, template_version_presets.is_default
template_version_presets.id, template_version_presets.template_version_id, template_version_presets.name, template_version_presets.created_at, template_version_presets.desired_instances, template_version_presets.invalidate_after_secs, template_version_presets.prebuild_status, template_version_presets.scheduling_timezone, template_version_presets.is_default, template_version_presets.description, template_version_presets.icon
FROM
template_version_presets
INNER JOIN workspace_builds ON workspace_builds.template_version_preset_id = template_version_presets.id
@@ -7690,6 +7694,8 @@ func (q *sqlQuerier) GetPresetByWorkspaceBuildID(ctx context.Context, workspaceB
&i.PrebuildStatus,
&i.SchedulingTimezone,
&i.IsDefault,
&i.Description,
&i.Icon,
)
return i, err
}
@@ -7771,7 +7777,7 @@ func (q *sqlQuerier) GetPresetParametersByTemplateVersionID(ctx context.Context,
const getPresetsByTemplateVersionID = `-- name: GetPresetsByTemplateVersionID :many
SELECT
id, template_version_id, name, created_at, desired_instances, invalidate_after_secs, prebuild_status, scheduling_timezone, is_default
id, template_version_id, name, created_at, desired_instances, invalidate_after_secs, prebuild_status, scheduling_timezone, is_default, description, icon
FROM
template_version_presets
WHERE
@@ -7797,6 +7803,8 @@ func (q *sqlQuerier) GetPresetsByTemplateVersionID(ctx context.Context, template
&i.PrebuildStatus,
&i.SchedulingTimezone,
&i.IsDefault,
&i.Description,
&i.Icon,
); err != nil {
return nil, err
}
@@ -7820,7 +7828,9 @@ INSERT INTO template_version_presets (
desired_instances,
invalidate_after_secs,
scheduling_timezone,
is_default
is_default,
description,
icon
)
VALUES (
$1,
@@ -7830,8 +7840,10 @@ VALUES (
$5,
$6,
$7,
$8
) RETURNING id, template_version_id, name, created_at, desired_instances, invalidate_after_secs, prebuild_status, scheduling_timezone, is_default
$8,
$9,
$10
) RETURNING id, template_version_id, name, created_at, desired_instances, invalidate_after_secs, prebuild_status, scheduling_timezone, is_default, description, icon
`
type InsertPresetParams struct {
@@ -7843,6 +7855,8 @@ type InsertPresetParams struct {
InvalidateAfterSecs sql.NullInt32 `db:"invalidate_after_secs" json:"invalidate_after_secs"`
SchedulingTimezone string `db:"scheduling_timezone" json:"scheduling_timezone"`
IsDefault bool `db:"is_default" json:"is_default"`
Description string `db:"description" json:"description"`
Icon string `db:"icon" json:"icon"`
}
func (q *sqlQuerier) InsertPreset(ctx context.Context, arg InsertPresetParams) (TemplateVersionPreset, error) {
@@ -7855,6 +7869,8 @@ func (q *sqlQuerier) InsertPreset(ctx context.Context, arg InsertPresetParams) (
arg.InvalidateAfterSecs,
arg.SchedulingTimezone,
arg.IsDefault,
arg.Description,
arg.Icon,
)
var i TemplateVersionPreset
err := row.Scan(
@@ -7867,6 +7883,8 @@ func (q *sqlQuerier) InsertPreset(ctx context.Context, arg InsertPresetParams) (
&i.PrebuildStatus,
&i.SchedulingTimezone,
&i.IsDefault,
&i.Description,
&i.Icon,
)
return i, err
}
+6 -2
View File
@@ -7,7 +7,9 @@ INSERT INTO template_version_presets (
desired_instances,
invalidate_after_secs,
scheduling_timezone,
is_default
is_default,
description,
icon
)
VALUES (
@id,
@@ -17,7 +19,9 @@ VALUES (
@desired_instances,
@invalidate_after_secs,
@scheduling_timezone,
@is_default
@is_default,
@description,
@icon
) RETURNING *;
-- name: InsertPresetParameters :many