Skip to content

Commit 80f042f

Browse files
feat: Add icon to templates (#3561)
1 parent 57f3410 commit 80f042f

17 files changed

+66
-12
lines changed

cli/templateedit.go

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func templateEdit() *cobra.Command {
1515
var (
1616
name string
1717
description string
18+
icon string
1819
maxTTL time.Duration
1920
minAutostartInterval time.Duration
2021
)
@@ -41,6 +42,7 @@ func templateEdit() *cobra.Command {
4142
req := codersdk.UpdateTemplateMeta{
4243
Name: name,
4344
Description: description,
45+
Icon: icon,
4446
MaxTTLMillis: maxTTL.Milliseconds(),
4547
MinAutostartIntervalMillis: minAutostartInterval.Milliseconds(),
4648
}
@@ -56,6 +58,7 @@ func templateEdit() *cobra.Command {
5658

5759
cmd.Flags().StringVarP(&name, "name", "", "", "Edit the template name")
5860
cmd.Flags().StringVarP(&description, "description", "", "", "Edit the template description")
61+
cmd.Flags().StringVarP(&icon, "icon", "", "", "Edit the template icon path")
5962
cmd.Flags().DurationVarP(&maxTTL, "max-ttl", "", 0, "Edit the template maximum time before shutdown")
6063
cmd.Flags().DurationVarP(&minAutostartInterval, "min-autostart-interval", "", 0, "Edit the template minimum autostart interval")
6164
cliui.AllowSkipPrompt(cmd)

cli/templateedit_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ func TestTemplateEdit(t *testing.T) {
2525
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
2626
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) {
2727
ctr.Description = "original description"
28+
ctr.Icon = "/icons/default-icon.png"
2829
ctr.MaxTTLMillis = ptr.Ref(24 * time.Hour.Milliseconds())
2930
ctr.MinAutostartIntervalMillis = ptr.Ref(time.Hour.Milliseconds())
3031
})
3132

3233
// Test the cli command.
3334
name := "new-template-name"
3435
desc := "lorem ipsum dolor sit amet et cetera"
36+
icon := "/icons/new-icon.png"
3537
maxTTL := 12 * time.Hour
3638
minAutostartInterval := time.Minute
3739
cmdArgs := []string{
@@ -40,6 +42,7 @@ func TestTemplateEdit(t *testing.T) {
4042
template.Name,
4143
"--name", name,
4244
"--description", desc,
45+
"--icon", icon,
4346
"--max-ttl", maxTTL.String(),
4447
"--min-autostart-interval", minAutostartInterval.String(),
4548
}
@@ -55,6 +58,7 @@ func TestTemplateEdit(t *testing.T) {
5558
require.NoError(t, err)
5659
assert.Equal(t, name, updated.Name)
5760
assert.Equal(t, desc, updated.Description)
61+
assert.Equal(t, icon, updated.Icon)
5862
assert.Equal(t, maxTTL.Milliseconds(), updated.MaxTTLMillis)
5963
assert.Equal(t, minAutostartInterval.Milliseconds(), updated.MinAutostartIntervalMillis)
6064
})
@@ -67,6 +71,7 @@ func TestTemplateEdit(t *testing.T) {
6771
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
6872
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) {
6973
ctr.Description = "original description"
74+
ctr.Icon = "/icons/default-icon.png"
7075
ctr.MaxTTLMillis = ptr.Ref(24 * time.Hour.Milliseconds())
7176
ctr.MinAutostartIntervalMillis = ptr.Ref(time.Hour.Milliseconds())
7277
})
@@ -78,6 +83,7 @@ func TestTemplateEdit(t *testing.T) {
7883
template.Name,
7984
"--name", template.Name,
8085
"--description", template.Description,
86+
"--icon", template.Icon,
8187
"--max-ttl", (time.Duration(template.MaxTTLMillis) * time.Millisecond).String(),
8288
"--min-autostart-interval", (time.Duration(template.MinAutostartIntervalMillis) * time.Millisecond).String(),
8389
}
@@ -93,6 +99,7 @@ func TestTemplateEdit(t *testing.T) {
9399
require.NoError(t, err)
94100
assert.Equal(t, template.Name, updated.Name)
95101
assert.Equal(t, template.Description, updated.Description)
102+
assert.Equal(t, template.Icon, updated.Icon)
96103
assert.Equal(t, template.MaxTTLMillis, updated.MaxTTLMillis)
97104
assert.Equal(t, template.MinAutostartIntervalMillis, updated.MinAutostartIntervalMillis)
98105
})

coderd/audit/table.go

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ var AuditableResources = auditMap(map[any]map[string]Action{
7070
"provisioner": ActionTrack,
7171
"active_version_id": ActionTrack,
7272
"description": ActionTrack,
73+
"icon": ActionTrack,
7374
"max_ttl": ActionTrack,
7475
"min_autostart_interval": ActionTrack,
7576
"created_by": ActionTrack,

coderd/database/databasefake/databasefake.go

+1
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,7 @@ func (q *fakeQuerier) UpdateTemplateMetaByID(_ context.Context, arg database.Upd
883883
tpl.UpdatedAt = database.Now()
884884
tpl.Name = arg.Name
885885
tpl.Description = arg.Description
886+
tpl.Icon = arg.Icon
886887
tpl.MaxTtl = arg.MaxTtl
887888
tpl.MinAutostartInterval = arg.MinAutostartInterval
888889
q.templates[idx] = tpl

coderd/database/dump.sql

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE templates DROP COLUMN icon;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE templates ADD COLUMN icon VARCHAR(256) NOT NULL DEFAULT '';

coderd/database/models.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

+19-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/templates.sql

+5-3
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ INSERT INTO
6767
description,
6868
max_ttl,
6969
min_autostart_interval,
70-
created_by
70+
created_by,
71+
icon
7172
)
7273
VALUES
73-
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING *;
74+
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING *;
7475

7576
-- name: UpdateTemplateActiveVersionByID :exec
7677
UPDATE
@@ -98,7 +99,8 @@ SET
9899
description = $3,
99100
max_ttl = $4,
100101
min_autostart_interval = $5,
101-
name = $6
102+
name = $6,
103+
icon = $7
102104
WHERE
103105
id = $1
104106
RETURNING

coderd/templates.go

+7
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
411411

412412
if req.Name == template.Name &&
413413
req.Description == template.Description &&
414+
req.Icon == template.Icon &&
414415
req.MaxTTLMillis == time.Duration(template.MaxTtl).Milliseconds() &&
415416
req.MinAutostartIntervalMillis == time.Duration(template.MinAutostartInterval).Milliseconds() {
416417
return nil
@@ -419,6 +420,7 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
419420
// Update template metadata -- empty fields are not overwritten.
420421
name := req.Name
421422
desc := req.Description
423+
icon := req.Icon
422424
maxTTL := time.Duration(req.MaxTTLMillis) * time.Millisecond
423425
minAutostartInterval := time.Duration(req.MinAutostartIntervalMillis) * time.Millisecond
424426

@@ -428,6 +430,9 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
428430
if desc == "" {
429431
desc = template.Description
430432
}
433+
if icon == "" {
434+
name = template.Icon
435+
}
431436
if maxTTL == 0 {
432437
maxTTL = time.Duration(template.MaxTtl)
433438
}
@@ -440,6 +445,7 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
440445
UpdatedAt: database.Now(),
441446
Name: name,
442447
Description: desc,
448+
Icon: icon,
443449
MaxTtl: int64(maxTTL),
444450
MinAutostartInterval: int64(minAutostartInterval),
445451
}); err != nil {
@@ -519,6 +525,7 @@ func convertTemplate(template database.Template, workspaceOwnerCount uint32, cre
519525
ActiveVersionID: template.ActiveVersionID,
520526
WorkspaceOwnerCount: workspaceOwnerCount,
521527
Description: template.Description,
528+
Icon: template.Icon,
522529
MaxTTLMillis: time.Duration(template.MaxTtl).Milliseconds(),
523530
MinAutostartIntervalMillis: time.Duration(template.MinAutostartInterval).Milliseconds(),
524531
CreatedByID: template.CreatedBy,

coderd/templates_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,14 @@ func TestPatchTemplateMeta(t *testing.T) {
233233
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
234234
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) {
235235
ctr.Description = "original description"
236+
ctr.Icon = "/icons/original-icon.png"
236237
ctr.MaxTTLMillis = ptr.Ref(24 * time.Hour.Milliseconds())
237238
ctr.MinAutostartIntervalMillis = ptr.Ref(time.Hour.Milliseconds())
238239
})
239240
req := codersdk.UpdateTemplateMeta{
240241
Name: "new-template-name",
241242
Description: "lorem ipsum dolor sit amet et cetera",
243+
Icon: "/icons/new-icon.png",
242244
MaxTTLMillis: 12 * time.Hour.Milliseconds(),
243245
MinAutostartIntervalMillis: time.Minute.Milliseconds(),
244246
}
@@ -254,6 +256,7 @@ func TestPatchTemplateMeta(t *testing.T) {
254256
assert.Greater(t, updated.UpdatedAt, template.UpdatedAt)
255257
assert.Equal(t, req.Name, updated.Name)
256258
assert.Equal(t, req.Description, updated.Description)
259+
assert.Equal(t, req.Icon, updated.Icon)
257260
assert.Equal(t, req.MaxTTLMillis, updated.MaxTTLMillis)
258261
assert.Equal(t, req.MinAutostartIntervalMillis, updated.MinAutostartIntervalMillis)
259262

@@ -263,6 +266,7 @@ func TestPatchTemplateMeta(t *testing.T) {
263266
assert.Greater(t, updated.UpdatedAt, template.UpdatedAt)
264267
assert.Equal(t, req.Name, updated.Name)
265268
assert.Equal(t, req.Description, updated.Description)
269+
assert.Equal(t, req.Icon, updated.Icon)
266270
assert.Equal(t, req.MaxTTLMillis, updated.MaxTTLMillis)
267271
assert.Equal(t, req.MinAutostartIntervalMillis, updated.MinAutostartIntervalMillis)
268272
})
@@ -275,6 +279,7 @@ func TestPatchTemplateMeta(t *testing.T) {
275279
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
276280
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) {
277281
ctr.Description = "original description"
282+
ctr.Icon = "/icons/original-icon.png"
278283
ctr.MaxTTLMillis = ptr.Ref(24 * time.Hour.Milliseconds())
279284
ctr.MinAutostartIntervalMillis = ptr.Ref(time.Hour.Milliseconds())
280285
})
@@ -285,6 +290,7 @@ func TestPatchTemplateMeta(t *testing.T) {
285290
req := codersdk.UpdateTemplateMeta{
286291
Name: template.Name,
287292
Description: template.Description,
293+
Icon: template.Icon,
288294
MaxTTLMillis: template.MaxTTLMillis,
289295
MinAutostartIntervalMillis: template.MinAutostartIntervalMillis,
290296
}
@@ -295,6 +301,7 @@ func TestPatchTemplateMeta(t *testing.T) {
295301
assert.Equal(t, updated.UpdatedAt, template.UpdatedAt)
296302
assert.Equal(t, template.Name, updated.Name)
297303
assert.Equal(t, template.Description, updated.Description)
304+
assert.Equal(t, template.Icon, updated.Icon)
298305
assert.Equal(t, template.MaxTTLMillis, updated.MaxTTLMillis)
299306
assert.Equal(t, template.MinAutostartIntervalMillis, updated.MinAutostartIntervalMillis)
300307
})
@@ -331,6 +338,7 @@ func TestPatchTemplateMeta(t *testing.T) {
331338
assert.WithinDuration(t, template.UpdatedAt, updated.UpdatedAt, time.Minute)
332339
assert.Equal(t, template.Name, updated.Name)
333340
assert.Equal(t, template.Description, updated.Description)
341+
assert.Equal(t, template.Icon, updated.Icon)
334342
assert.Equal(t, template.MaxTTLMillis, updated.MaxTTLMillis)
335343
assert.Equal(t, template.MinAutostartIntervalMillis, updated.MinAutostartIntervalMillis)
336344
})

codersdk/organizations.go

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ type CreateTemplateRequest struct {
5252
// Description is a description of what the template contains. It must be
5353
// less than 128 bytes.
5454
Description string `json:"description,omitempty" validate:"lt=128"`
55+
// Icon is a relative path or external URL that specifies
56+
// an icon to be displayed in the dashboard.
57+
Icon string `json:"icon,omitempty"`
5558

5659
// VersionID is an in-progress or completed job to use as an initial version
5760
// of the template.

0 commit comments

Comments
 (0)