Skip to content

Commit bf5024d

Browse files
Add support for application/service icon
1 parent bf37fe6 commit bf5024d

15 files changed

Lines changed: 146 additions & 18 deletions

File tree

app/controller/application/controller.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package application
22

33
import (
44
"context"
5+
"time"
56

67
"github.com/cloudness-io/cloudness/app/controller/gitpublic"
78
"github.com/cloudness-io/cloudness/app/controller/server"
@@ -112,6 +113,7 @@ func (c *Controller) updateWithoutTx(ctx context.Context, dto *createOrUpdateDto
112113
return nil, err
113114
}
114115

116+
application.Updated = time.Now().UTC().UnixMilli()
115117
application, err = c.applicationStore.UpdateSpec(ctx, application)
116118
if err != nil {
117119
return nil, err
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package application
2+
3+
import (
4+
"context"
5+
6+
"github.com/cloudness-io/cloudness/types"
7+
)
8+
9+
type UpdateIconInput struct {
10+
Icon string `json:"icon"`
11+
}
12+
13+
func (c *Controller) UpdateIcon(ctx context.Context, application *types.Application, in *UpdateIconInput) (*types.Application, error) {
14+
application.Spec.Icon = in.Icon
15+
err := application.UpdateSpecJSON()
16+
if err != nil {
17+
return nil, err
18+
}
19+
return c.applicationStore.UpdateSpec(ctx, application)
20+
}

app/router/web.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ func setupApplication(r chi.Router, appCtx context.Context, envCtrl *environment
361361
//Inject application here
362362
r.Use(middlewareinject.InjectApplication(appCtrl))
363363
r.Get("/", handlerapplication.HandleListDeployments(appCtrl, deploymentCtrl))
364+
r.Patch("/icon", handlerapplication.HandleUpdateIcon(appCtrl))
364365
r.Get("/deployments", handlerapplication.HandleListDeployments(appCtrl, deploymentCtrl))
365366
r.Get("/settings", handlerapplication.HandleGetSettings(appCtrl, ghAppCtrl))
366367
r.Patch("/settings", handlerapplication.HandleUpdateSettings(appCtrl, ghAppCtrl))

app/services/spec/input_mapper.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func (s *Service) ToApplication(ctx context.Context, in *types.ApplicationInput,
9898
}
9999

100100
func (s *Service) ToGeneralSettings(in *types.ApplicationInput, application *types.Application, spec *types.ApplicationSpec) {
101-
var name, description string
101+
var name, description, icon string
102102
//Name
103103
if in.Name != "" {
104104
name = in.Name
@@ -117,8 +117,18 @@ func (s *Service) ToGeneralSettings(in *types.ApplicationInput, application *typ
117117
description = spec.Description
118118
}
119119

120+
//Icon
121+
if in.Icon != "" {
122+
icon = in.Icon
123+
} else if application.Spec.Icon != "" {
124+
icon = application.Spec.Icon
125+
} else {
126+
icon = spec.Icon
127+
}
128+
120129
spec.Name = name
121130
spec.Description = description
131+
spec.Icon = icon
122132
}
123133

124134
func (s *Service) ToBuildConfigration(ctx context.Context, in *types.ApplicationInput, application *types.Application) (*types.BuildConfiguration, error) {

app/store/database/application.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,6 @@ func (s *ApplicationStore) UpdateSpec(ctx context.Context, application *types.Ap
137137
,application_deleted = :application_deleted
138138
WHERE application_id = :application_id`
139139

140-
application.Updated = time.Now().UTC().UnixMilli()
141-
142140
return s.update(ctx, application, applicationUpdate)
143141
}
144142

app/utils/routes/application.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ const (
3737

3838
AppNav = "/nav"
3939

40+
//General Header
41+
AppIcon = "icon"
42+
4043
AppSourceGithub = "source/github"
4144
AppSourceGitPublic = "source/git-public"
4245
AppSourceRegistry = "source/registry"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package application
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
7+
"github.com/cloudness-io/cloudness/app/controller/application"
8+
"github.com/cloudness-io/cloudness/app/request"
9+
"github.com/cloudness-io/cloudness/app/utils/routes"
10+
"github.com/cloudness-io/cloudness/app/web/render"
11+
12+
"github.com/rs/zerolog/log"
13+
)
14+
15+
func HandleUpdateIcon(appCtrl *application.Controller) http.HandlerFunc {
16+
return func(w http.ResponseWriter, r *http.Request) {
17+
ctx := r.Context()
18+
19+
in := new(application.UpdateIconInput)
20+
if err := json.NewDecoder(r.Body).Decode(in); err != nil {
21+
log.Ctx(ctx).Error().Err(err).Msg("Error decoding request body")
22+
render.ToastError(ctx, w, err)
23+
return
24+
}
25+
26+
app, _ := request.ApplicationFrom(ctx)
27+
28+
_, err := appCtrl.UpdateIcon(ctx, app, in)
29+
if err != nil {
30+
log.Ctx(ctx).Error().Err(err).Msg("Error updating icon")
31+
render.ToastError(ctx, w, err)
32+
return
33+
}
34+
35+
render.Redirect(w, routes.ApplicationCtx(ctx))
36+
}
37+
}

app/web/handler/create/oneclick.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/cloudness-io/cloudness/app/controller/template"
77
"github.com/cloudness-io/cloudness/app/web/render"
88
"github.com/cloudness-io/cloudness/app/web/views/components/vcreate"
9+
910
"github.com/rs/zerolog/log"
1011
)
1112

app/web/views/components/vapplication/header.templ

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package vapplication
22

33
import (
4+
"fmt"
5+
"github.com/cloudness-io/cloudness/app/utils/routes"
46
"github.com/cloudness-io/cloudness/app/web/views/components/icons"
57
"github.com/cloudness-io/cloudness/app/web/views/components/vfavorite"
68
"github.com/cloudness-io/cloudness/app/web/views/shared"
@@ -9,9 +11,25 @@ import (
911

1012
templ appHeader(app *types.Application) {
1113
<header class="relative h-16 shrink-0 box-border pl-1 md:pl-4">
12-
<div id="header-content" class="flex box-border h-full py-2">
13-
<span id="header-logo" class="flex grow shrink-0 basis-auto items-center justify-center mr-2 relative">
14-
@shared.Icon(icons.ApplicationIcon, "overflow-hidden icon-2xl size-6")
14+
<div id="header-content" class="flex box-border h-full py-2" x-data="{updateIconModel: false}">
15+
@shared.Modal("updateIconModel", updateIconForm(app))
16+
<span
17+
id="header-logo"
18+
class="flex grow shrink-0 basis-auto items-center justify-center mr-2 relative group"
19+
x-on:click="updateIconModel = true"
20+
>
21+
if app.Spec.Icon != "" {
22+
@shared.Icon(app.Spec.Icon, "overflow-hidden icon-2xl size-6")
23+
} else {
24+
@shared.Icon(icons.ApplicationIcon, "overflow-hidden icon-2xl size-6")
25+
}
26+
//show edit icon
27+
<span
28+
id="edit-icon"
29+
class="absolute top-[0.2rem] right-[-0.5rem] hidden group-hover:block"
30+
>
31+
<i class={ icons.EditIcon, "icon-sm" }></i>
32+
</span>
1533
</span>
1634
<div id="title" class="flex-auto w-full">
1735
<div id="title-top-row" class="flex items-baseline gap-2">
@@ -33,3 +51,34 @@ templ appHeader(app *types.Application) {
3351
</div>
3452
</header>
3553
}
54+
55+
templ updateIconForm(app *types.Application) {
56+
<form class="flex flex-col gap-2" x-data={ fmt.Sprintf("{old:'%[1]s', icon:'%[1]s'}", app.Spec.Icon) }>
57+
<h2 class="text-xl font-semibold">Update Icon</h2>
58+
<p class="w-full max-w-full">
59+
Icon should be an URL to an image file.
60+
</p>
61+
@shared.Input(&shared.InputProps{
62+
Name: "icon",
63+
Attrs: templ.Attributes{
64+
"x-model": "icon",
65+
},
66+
})
67+
<footer class="flex w-full">
68+
<div class="ml-auto flex w-full gap-x-4 sm:w-auto sm:whitespace-nowrap">
69+
<button type="button" class="button-neutral" x-on:click="updateIconModel= false">
70+
Close
71+
</button>
72+
<button
73+
type="submit"
74+
class="button-primary"
75+
:disabled="icon == old"
76+
hx-patch={ routes.AppIcon }
77+
hx-swap="none"
78+
>
79+
Update
80+
</button>
81+
</div>
82+
</footer>
83+
</form>
84+
}

app/web/views/components/vapplication/list.templ

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,21 @@ templ list(env *types.Environment, apps []*types.Application) {
2929
<thead>
3030
<tr class="text-tx-secondary">
3131
<th class="whitespace-nowrap px-4 py-2 font-medium w-[35%]">Name</th>
32-
<th class="whitespace-nowrap px-4 py-2 font-medium w-[35%] truncate overflow-hidden text-ellipsis">
33-
Live
34-
URL
35-
</th>
32+
<th class="whitespace-nowrap px-4 py-2 font-medium w-[35%] truncate overflow-hidden text-ellipsis">Live URL</th>
3633
<th class="whitespace-nowrap px-4 py-2 font-medium w-[30%]">Status</th>
3734
</tr>
3835
</thead>
3936
<tbody class="divide-y overflow-y-visible">
4037
for _,app := range apps {
4138
<tr class="hover:bg-secondary group cursor-pointer" hx-get={ routes.Application(env.UID, app.UID) }>
42-
<td class="whitespace-nowrap px-4 py-2 hover:text-brand">{ app.Name }</td>
39+
<td class="whitespace-nowrap px-4 py-2 hover:text-brand flex gap-x-1">
40+
if app.Spec.Icon != "" {
41+
@shared.Icon(app.Spec.Icon, "overflow-hidden")
42+
} else {
43+
@shared.Icon(icons.ApplicationIcon, "overflow-hidden")
44+
}
45+
{ app.Name }
46+
</td>
4347
<td
4448
class="whitespace-nowrap px-4 py-2 max-w-40 sm:max-w-full truncate overflow-hidden
4549
text-ellipsis"

0 commit comments

Comments
 (0)