diff --git a/db/main.go b/db/main.go index 96e97bbd..cc1ecca8 100644 --- a/db/main.go +++ b/db/main.go @@ -114,7 +114,7 @@ func createTrailHandler(app *pocketbase.PocketBase, client meilisearch.ServiceMa if e.Record.GetBool("public") { notification := util.Notification{ Type: util.TrailCreate, - Metadata: map[string]interface{}{ + Metadata: map[string]string{ "id": e.Record.Id, "trail": e.Record.GetString("name"), }, @@ -163,7 +163,7 @@ func createTrailShareHandler(app *pocketbase.PocketBase, client meilisearch.Serv notification := util.Notification{ Type: util.TrailShare, - Metadata: map[string]interface{}{ + Metadata: map[string]string{ "id": shareTrail.Id, "trail": shareTrail.GetString("name"), "author": shareTrailAuthor.GetString("username"), @@ -185,7 +185,7 @@ func createListShareHandler(app *pocketbase.PocketBase) func(e *core.RecordCreat notification := util.Notification{ Type: util.ListShare, - Metadata: map[string]interface{}{ + Metadata: map[string]string{ "id": shareList.Id, "list": shareList.GetString("name"), "author": shareListAuthor.GetString("username"), @@ -211,7 +211,7 @@ func createListHandler(app *pocketbase.PocketBase) func(e *core.RecordCreateEven } notification := util.Notification{ Type: util.ListCreate, - Metadata: map[string]interface{}{ + Metadata: map[string]string{ "id": e.Record.Id, "list": e.Record.GetString("name"), }, @@ -231,7 +231,7 @@ func createFollowHandler(app *pocketbase.PocketBase) func(e *core.RecordCreateEv notification := util.Notification{ Type: util.NewFollower, - Metadata: map[string]interface{}{ + Metadata: map[string]string{ "follower": follower.GetString("username"), }, Seen: false, @@ -252,7 +252,7 @@ func createCommentHandler(app *pocketbase.PocketBase) func(e *core.RecordCreateE notification := util.Notification{ Type: util.TrailComment, - Metadata: map[string]interface{}{ + Metadata: map[string]string{ "id": commentTrail.Id, "author": commentAuthor.GetString("username"), "trail": commentTrail.GetString("name"), diff --git a/db/migrations/1713027641_created_trails_bounding_box.go b/db/migrations/1713027641_created_trails_bounding_box.go index 261f4d1b..1fc4366e 100644 --- a/db/migrations/1713027641_created_trails_bounding_box.go +++ b/db/migrations/1713027641_created_trails_bounding_box.go @@ -86,7 +86,7 @@ func init() { return daos.New(db).SaveCollection(collection) }, func(db dbx.Builder) error { - dao := daos.New(db); + dao := daos.New(db) collection, err := dao.FindCollectionByNameOrId("urytyc428mwlbqq") if err != nil { diff --git a/db/migrations/1735935107_updated_lists.go b/db/migrations/1735935107_updated_lists.go new file mode 100644 index 00000000..d35a1601 --- /dev/null +++ b/db/migrations/1735935107_updated_lists.go @@ -0,0 +1,76 @@ +package migrations + +import ( + "encoding/json" + + "github.com/pocketbase/dbx" + "github.com/pocketbase/pocketbase/daos" + m "github.com/pocketbase/pocketbase/migrations" + "github.com/pocketbase/pocketbase/models/schema" +) + +func init() { + m.Register(func(db dbx.Builder) error { + dao := daos.New(db); + + collection, err := dao.FindCollectionByNameOrId("r6gu2ajyidy1x69") + if err != nil { + return err + } + + // update + edit_author := &schema.SchemaField{} + if err := json.Unmarshal([]byte(`{ + "system": false, + "id": "kwm6zdet", + "name": "author", + "type": "relation", + "required": true, + "presentable": false, + "unique": false, + "options": { + "collectionId": "_pb_users_auth_", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": null + } + }`), edit_author); err != nil { + return err + } + collection.Schema.AddField(edit_author) + + return dao.SaveCollection(collection) + }, func(db dbx.Builder) error { + dao := daos.New(db); + + collection, err := dao.FindCollectionByNameOrId("r6gu2ajyidy1x69") + if err != nil { + return err + } + + // update + edit_author := &schema.SchemaField{} + if err := json.Unmarshal([]byte(`{ + "system": false, + "id": "kwm6zdet", + "name": "author", + "type": "relation", + "required": false, + "presentable": false, + "unique": false, + "options": { + "collectionId": "_pb_users_auth_", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": null + } + }`), edit_author); err != nil { + return err + } + collection.Schema.AddField(edit_author) + + return dao.SaveCollection(collection) + }) +} diff --git a/db/templates/mail/notification.html b/db/templates/mail/notification.html new file mode 100644 index 00000000..6a1e84f4 --- /dev/null +++ b/db/templates/mail/notification.html @@ -0,0 +1,122 @@ + + + + + + + + +
+ +
+ wanderer +
+ +
+

Hello {{.RecipientName}},

+

You have a new notification:

+
+ +
+ {{.Content}} +
+ + Check it out! + +
+
+ +
+

Kind regards,

+

Your wanderer team

+
+ + +
+ + + \ No newline at end of file diff --git a/db/util/email_templates.go b/db/util/email_templates.go new file mode 100644 index 00000000..817340cd --- /dev/null +++ b/db/util/email_templates.go @@ -0,0 +1,67 @@ +package util + +import ( + "bytes" + "errors" + t "html/template" + + "github.com/pocketbase/pocketbase/tools/template" +) + +type EmailData struct { + AppUrl string + RecipientName string + Content t.HTML + Link string + FollowerName string +} + +var notificationTemplates = map[NotificationType]string{ + TrailCreate: "{{.Author}} has created a new trail: {{.trail}}.", + TrailShare: "{{.Author}} has shared a trail with you: {{.trail}}.", + ListCreate: "{{.Author}} has created a new list: {{.list}}.", + ListShare: "{{.Author}} has shared a list with you: {{.list}}.", + NewFollower: "Good news! You have a new follower: {{.Author}}.", + TrailComment: "{{.Author}} commented on your trail '{{.trail}}': '{{.comment}}'.", +} + +func GenerateHTML(appUrl string, recipientName string, authorName string, notificationType NotificationType, metadata map[string]string) (string, error) { + registry := template.NewRegistry() + + // Get custom content template for the notification type + customTemplate, exists := notificationTemplates[notificationType] + if !exists { + return "", errors.New("unknown notification type") + } + + // Create content template with dynamic data + contentTmpl, err := t.New("content").Parse(customTemplate) + if err != nil { + return "", err + } + + // Render the custom content with data + metadata["Author"] = authorName + var contentBuffer bytes.Buffer + err = contentTmpl.Execute(&contentBuffer, metadata) + if err != nil { + return "", err + } + + // Assemble the final email with boilerplate and custom content + content := EmailData{ + AppUrl: appUrl, + RecipientName: recipientName, + Content: t.HTML(contentBuffer.String()), + } + + html, err := registry.LoadFiles( + "templates/mail/notification.html", + ).Render(content) + + if err != nil { + return "", err + } + + return html, nil +} diff --git a/db/util/notification.go b/db/util/notification.go index 0d552bb6..20c305a7 100644 --- a/db/util/notification.go +++ b/db/util/notification.go @@ -2,10 +2,12 @@ package util import ( "fmt" + "net/mail" "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/models" + "github.com/pocketbase/pocketbase/tools/mailer" ) type NotificationType string @@ -20,10 +22,10 @@ const ( ) type Notification struct { - Type NotificationType `json:"type"` - Metadata interface{} `json:"metadata,omitempty"` - Seen bool `json:"seen"` - Author string `json:"author"` + Type NotificationType `json:"type"` + Metadata map[string]string `json:"metadata,omitempty"` + Seen bool `json:"seen"` + Author string `json:"author"` } type NotificationSettings struct { @@ -59,22 +61,50 @@ func SendNotification(app *pocketbase.PocketBase, notification Notification, rec if err != nil { return err } - if !permissions.Web { - return nil - } + notifications, err := app.Dao().FindCollectionByNameOrId("notifications") if err != nil { return err } - n := models.NewRecord(notifications) - n.Set("type", string(notification.Type)) - n.Set("metadata", notification.Metadata) - n.Set("seen", notification.Seen) - n.Set("recipient", recipient) - n.Set("author", notification.Author) - if err := app.Dao().SaveRecord(n); err != nil { - return err + if permissions.Web { + n := models.NewRecord(notifications) + n.Set("type", string(notification.Type)) + n.Set("metadata", notification.Metadata) + n.Set("seen", notification.Seen) + n.Set("recipient", recipient) + n.Set("author", notification.Author) + + if err := app.Dao().SaveRecord(n); err != nil { + return err + } + } + + if permissions.Email { + recipientUser, err := app.Dao().FindRecordById("users", recipient) + if err != nil { + return err + } + authorUser, err := app.Dao().FindRecordById("users", notification.Author) + if err != nil { + return err + } + html, err := GenerateHTML(app.Settings().Meta.AppUrl, recipientUser.Username(), authorUser.Username(), notification.Type, notification.Metadata) + if err != nil { + return err + } + + message := &mailer.Message{ + From: mail.Address{ + Address: app.Settings().Meta.SenderAddress, + Name: app.Settings().Meta.SenderName, + }, + To: []mail.Address{{Address: recipientUser.Email()}}, + Subject: "wanderer - New Notification", + HTML: html, + } + + app.NewMailClient().Send(message) } return nil } @@ -85,32 +115,11 @@ func SendNotificationToFollowers(app *pocketbase.PocketBase, notification Notifi if err != nil { return err } - notifications, err := app.Dao().FindCollectionByNameOrId("notifications") - if err != nil { - return err - } + for _, f := range followers { recipient := f.GetString("follower") - if notification.Author == recipient { - continue - } - permissions, err := getNotificationPermissions(app, recipient, notification.Type) - if err != nil { - continue - } - if !permissions.Web { - continue - } - n := models.NewRecord(notifications) - n.Set("type", string(notification.Type)) - n.Set("metadata", notification.Metadata) - n.Set("seen", notification.Seen) - n.Set("recipient", recipient) - n.Set("author", notification.Author) + SendNotification(app, notification, recipient) - if err := app.Dao().SaveRecord(n); err != nil { - continue - } } return nil } diff --git a/docs/src/content/docs/getting-started/Installation.md b/docs/src/content/docs/getting-started/Installation.md index b7b36c18..e0ec5731 100644 --- a/docs/src/content/docs/getting-started/Installation.md +++ b/docs/src/content/docs/getting-started/Installation.md @@ -115,9 +115,10 @@ To update all containers to a new version simply run `docker compose pull && doc While not recommended it is absolutely possible to install wanderer from source. ### Prerequisites -1. git installed && `git clone https://github.com/Flomp/wanderer.git` +1. git installed && `git clone https://github.com/Flomp/wanderer.git --branch v0.12.0 --single-branch` 2. go >= 1.21.1 installed 3. node >= 18.17.0 installed +4. npm >= 8.15.0 installed ### meilisearch wanderer uses meilisearch without any further modifications. As a result, you can simply head over to [their website](https://www.meilisearch.com/docs/learn/getting_started/installation) and follow the instructions for your preferred platform. We assume that you put the binary in the `wanderer/search` directory. If you did not, adapt the launch script below accordingly. @@ -157,15 +158,26 @@ Caution: Ensure that you change the `MEILI_MASTER_KEY` to a different value if y ```bash trap "kill 0" EXIT +# learn more about the configuration: +# https://wanderer.to/getting-started/configuration/ +# required export ORIGIN=http://localhost:3000 export MEILI_URL=http://127.0.0.1:7700 -export MEILI_MASTER_KEY=CHANGE_ME! +export MEILI_MASTER_KEY=YOU_SHOULD_DEFINITELY_CHANGE_ME export PUBLIC_POCKETBASE_URL=http://127.0.0.1:8090 export PUBLIC_VALHALLA_URL=https://valhalla1.openstreetmap.de +# optional +# export MEILI_NO_ANALYTICS=true +# export BODY_SIZE_LIMIT=Infinity +# export PUBLIC_DISABLE_SIGNUP=false +# export UPLOAD_FOLDER=/app/uploads +# export UPLOAD_USER= +# export UPLOAD_PASSWORD= + cd search && ./meilisearch --master-key $MEILI_MASTER_KEY & cd db && ./pocketbase serve & -cd web/build && node build & +cd web && node build & wait ``` diff --git a/docs/wanderer.openapi.yaml b/docs/wanderer.openapi.yaml index e7f5882b..82b03983 100644 --- a/docs/wanderer.openapi.yaml +++ b/docs/wanderer.openapi.yaml @@ -325,7 +325,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -348,13 +348,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -583,7 +583,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -602,13 +602,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: undefined @@ -794,7 +794,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -817,13 +817,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -1232,7 +1232,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -1255,13 +1255,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -1659,7 +1659,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -1678,13 +1678,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -1834,7 +1834,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -1857,13 +1857,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2028,7 +2028,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2051,13 +2051,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2163,7 +2163,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2186,13 +2186,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2283,7 +2283,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2306,13 +2306,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2442,7 +2442,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2465,13 +2465,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2755,7 +2755,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2778,13 +2778,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -3060,7 +3060,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -3083,13 +3083,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -3192,7 +3192,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -3215,13 +3215,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -3379,7 +3379,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -3402,13 +3402,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -3514,7 +3514,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -3537,13 +3537,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -4044,7 +4044,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -4067,7 +4067,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -4449,7 +4449,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -4468,13 +4468,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -4577,7 +4577,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -4600,13 +4600,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -5006,7 +5006,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5029,7 +5029,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -5197,7 +5197,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5220,13 +5220,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -5421,7 +5421,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5444,13 +5444,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -5556,7 +5556,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5579,13 +5579,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -5810,7 +5810,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5829,13 +5829,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -5949,7 +5949,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5972,13 +5972,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -6135,7 +6135,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -6158,13 +6158,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -6366,7 +6366,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -6389,13 +6389,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -6501,7 +6501,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -6524,13 +6524,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -6985,7 +6985,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7008,7 +7008,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -7246,7 +7246,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7265,13 +7265,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -7449,7 +7449,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7472,13 +7472,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -7666,7 +7666,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7689,13 +7689,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -7801,7 +7801,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7824,13 +7824,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -8245,7 +8245,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -8268,13 +8268,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -8509,7 +8509,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -8528,13 +8528,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -8644,7 +8644,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -8667,13 +8667,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -8812,7 +8812,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -8835,13 +8835,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -8999,7 +8999,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -9022,13 +9022,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -9134,7 +9134,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -9157,13 +9157,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -9515,7 +9515,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -9534,13 +9534,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -9925,7 +9925,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -9948,7 +9948,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -10440,7 +10440,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -10463,7 +10463,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -10636,7 +10636,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -10659,13 +10659,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -11135,7 +11135,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -11158,7 +11158,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -11402,7 +11402,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -11423,13 +11423,13 @@ paths: - path required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_string validation: date message: Invalid date @@ -11624,7 +11624,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -11647,13 +11647,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -11861,7 +11861,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -11884,13 +11884,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -11996,7 +11996,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -12019,13 +12019,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -12202,7 +12202,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -12225,13 +12225,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -13027,7 +13027,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -13050,7 +13050,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -13388,7 +13388,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -13409,13 +13409,13 @@ paths: - path required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_string validation: date message: Invalid date @@ -13657,7 +13657,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -13680,13 +13680,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -13967,7 +13967,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -13990,7 +13990,7 @@ paths: type: string required: - message - - details + - detail headers: {} '404': description: '' @@ -14079,7 +14079,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -14102,13 +14102,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -14333,7 +14333,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -14356,13 +14356,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string diff --git a/web/src/lib/components/trail/map_with_elevation_maplibre.svelte b/web/src/lib/components/trail/map_with_elevation_maplibre.svelte index 013e3158..6303f672 100644 --- a/web/src/lib/components/trail/map_with_elevation_maplibre.svelte +++ b/web/src/lib/components/trail/map_with_elevation_maplibre.svelte @@ -140,7 +140,7 @@ const r: GeoJSON[] = []; trails.forEach((t) => { - if (t.expand.gpx_data) { + if (t.expand?.gpx_data) { r.push(toGeoJson(t.expand.gpx_data) as GeoJSON); } else if (t.lat && t.lon) { r.push({ @@ -165,7 +165,7 @@ if (data[activeTrail] && showElevation) { epc?.setData( data[activeTrail]!, - trails.at(activeTrail)!.expand.waypoints, + trails.at(activeTrail)!.expand?.waypoints, ); epc?.showProfile(); } @@ -409,7 +409,7 @@ if (data[activeTrail] && showElevation) { epc?.setData( data[activeTrail]!, - trails.at(activeTrail)!.expand.waypoints, + trails.at(activeTrail)!.expand?.waypoints, ); epc?.showProfile(); } @@ -490,7 +490,7 @@ if (!map) { return; } - for (const waypoint of trails[activeTrail]?.expand.waypoints ?? []) { + for (const waypoint of trails[activeTrail]?.expand?.waypoints ?? []) { const marker = createMarkerFromWaypoint(waypoint, onMarkerDragEnd); marker.addTo(map); markers.push(marker); diff --git a/web/src/lib/models/api/base_schema.ts b/web/src/lib/models/api/base_schema.ts index 3af4b5b8..845c5081 100644 --- a/web/src/lib/models/api/base_schema.ts +++ b/web/src/lib/models/api/base_schema.ts @@ -7,7 +7,7 @@ const RecordOptionsSchema = z.object({ }) const RecordListOptionsSchema = RecordOptionsSchema.extend({ - page: z.number({ coerce: true }).int().positive().optional(), + page: z.number({ coerce: true }).int().nonnegative().optional(), perPage: z.number({ coerce: true }).int().optional(), sort: z.string().optional(), filter: z.string().optional(), diff --git a/web/src/routes/map/+page.svelte b/web/src/routes/map/+page.svelte index d2f528ac..df9934ab 100644 --- a/web/src/routes/map/+page.svelte +++ b/web/src/routes/map/+page.svelte @@ -132,6 +132,15 @@ function handleMapInit() { if ( + $page.url.searchParams.has("lat") && + $page.url.searchParams.has("lon") + ) { + const lat = $page.url.searchParams.get("lat"); + const lon = $page.url.searchParams.get("lon"); + map.setCenter([parseFloat(lon!), parseFloat(lat!)]); + map.setZoom(14); + console.log("Set map center to: " + lat + " " + lon); + } else if ( $page.url.searchParams.has("tl_lat") && $page.url.searchParams.has("tl_lon") && $page.url.searchParams.has("br_lat") && @@ -148,14 +157,6 @@ ], ]; map.fitBounds(boundingBox, { animate: false }); - } else if ( - $page.url.searchParams.has("lat") && - $page.url.searchParams.has("lon") - ) { - const lat = $page.url.searchParams.get("lat"); - const lon = $page.url.searchParams.get("lon"); - map.setCenter([parseFloat(lon!), parseFloat(lat!)]); - map.setZoom(14); } else if (settings && settings.mapFocus == "trails") { const boundingBox: M.LngLatBoundsLike = [ [maxBoundingBox.min_lon, maxBoundingBox.max_lat], diff --git a/web/src/routes/profile/[id]/+layout.svelte b/web/src/routes/profile/[id]/+layout.svelte index 523a6fbb..d91cf6d9 100644 --- a/web/src/routes/profile/[id]/+layout.svelte +++ b/web/src/routes/profile/[id]/+layout.svelte @@ -17,7 +17,7 @@ text: $_("trail", { values: { n: 2 } }), value: `/profile/${$page.params.id}/trails`, }, - { text: $_('statistics'), value: `/profile/${$page.params.id}/stats` }, + { text: $_("statistics"), value: `/profile/${$page.params.id}/stats` }, ]; $: activeIndex = profileLinks.findIndex( @@ -80,14 +80,14 @@ href="/profile/{data.user.id}/users/followers" >

{data.followers}

-

{$_('followers')}

+

{$_("followers")}

{data.following}

-

{$_('following')}

+

{$_("following")}

{#if !data.isOwnProfile} @@ -113,6 +113,12 @@ > {/each} + {#if data.isOwnProfile} +
+ + {$_("settings")} +
+ {/if} diff --git a/web/src/routes/register/+page.svelte b/web/src/routes/register/+page.svelte index d17a20b0..bf9ea942 100644 --- a/web/src/routes/register/+page.svelte +++ b/web/src/routes/register/+page.svelte @@ -28,7 +28,7 @@ $_("must-be-at-least-n-characters-long", { values: { n: 3 }, }), - ), + ).regex(/^[\w][\w\.]*$/, $_("invalid-username")), email: z .string() .min(1, "required") diff --git a/web/static/docs/api/wanderer.openapi.yaml b/web/static/docs/api/wanderer.openapi.yaml index 12c8377f..90874e1e 100644 --- a/web/static/docs/api/wanderer.openapi.yaml +++ b/web/static/docs/api/wanderer.openapi.yaml @@ -325,7 +325,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -348,13 +348,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -583,7 +583,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -602,13 +602,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: undefined @@ -794,7 +794,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -817,13 +817,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -1232,7 +1232,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -1255,13 +1255,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -1659,7 +1659,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -1678,13 +1678,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -1834,7 +1834,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -1857,13 +1857,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2028,7 +2028,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2051,13 +2051,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2163,7 +2163,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2186,13 +2186,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2283,7 +2283,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2306,13 +2306,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2442,7 +2442,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2465,13 +2465,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -2755,7 +2755,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -2778,13 +2778,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -3060,7 +3060,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -3083,13 +3083,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -3192,7 +3192,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -3215,13 +3215,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -3379,7 +3379,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -3402,13 +3402,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -3514,7 +3514,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -3537,13 +3537,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -4044,7 +4044,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -4067,7 +4067,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -4449,7 +4449,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -4468,13 +4468,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -4577,7 +4577,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -4600,13 +4600,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -5006,7 +5006,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5029,7 +5029,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -5197,7 +5197,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5220,13 +5220,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -5421,7 +5421,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5444,13 +5444,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -5556,7 +5556,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5579,13 +5579,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -5810,7 +5810,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5829,13 +5829,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -5949,7 +5949,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -5972,13 +5972,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -6135,7 +6135,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -6158,13 +6158,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -6366,7 +6366,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -6389,13 +6389,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -6501,7 +6501,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -6524,13 +6524,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -6985,7 +6985,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7008,7 +7008,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -7246,7 +7246,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7265,13 +7265,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -7449,7 +7449,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7472,13 +7472,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -7666,7 +7666,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7689,13 +7689,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -7801,7 +7801,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -7824,13 +7824,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -8245,7 +8245,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -8268,13 +8268,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 0 type: number @@ -8509,7 +8509,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -8528,13 +8528,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -8644,7 +8644,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -8667,13 +8667,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -8812,7 +8812,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -8835,13 +8835,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -8999,7 +8999,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -9022,13 +9022,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -9134,7 +9134,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -9157,13 +9157,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -9515,7 +9515,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -9534,13 +9534,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_type expected: string received: number @@ -9925,7 +9925,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -9948,7 +9948,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -10440,7 +10440,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -10463,7 +10463,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -10636,7 +10636,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -10659,13 +10659,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -11135,7 +11135,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -11158,7 +11158,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -11402,7 +11402,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -11423,13 +11423,13 @@ paths: - path required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_string validation: date message: Invalid date @@ -11624,7 +11624,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -11647,13 +11647,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -11861,7 +11861,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -11884,13 +11884,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -11996,7 +11996,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -12019,13 +12019,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -12202,7 +12202,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -12225,13 +12225,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -13027,7 +13027,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -13050,7 +13050,7 @@ paths: type: string required: - message - - details + - detail headers: {} x-400:Invalid sort/expand/filter: description: '' @@ -13388,7 +13388,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -13409,13 +13409,13 @@ paths: - path required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: invalid_string validation: date message: Invalid date @@ -13657,7 +13657,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -13680,13 +13680,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -13967,7 +13967,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -13990,7 +13990,7 @@ paths: type: string required: - message - - details + - detail headers: {} '404': description: '' @@ -14079,7 +14079,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -14102,13 +14102,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string @@ -14333,7 +14333,7 @@ paths: properties: message: type: string - details: + detail: type: array items: type: object @@ -14356,13 +14356,13 @@ paths: type: string required: - message - - details + - detail examples: '1': summary: Exception value: message: invalid_params - details: + detail: - code: too_small minimum: 15 type: string diff --git a/web/static/imgs/logo_text_light.png b/web/static/imgs/logo_text_light.png new file mode 100644 index 00000000..158cb37a Binary files /dev/null and b/web/static/imgs/logo_text_light.png differ