Skip to content

Commit

Permalink
adds email notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Beutel committed Jan 4, 2025
1 parent 72d2bf6 commit 7886900
Show file tree
Hide file tree
Showing 15 changed files with 667 additions and 374 deletions.
12 changes: 6 additions & 6 deletions db/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
},
Expand Down Expand Up @@ -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"),
Expand All @@ -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"),
Expand All @@ -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"),
},
Expand All @@ -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,
Expand All @@ -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"),
Expand Down
2 changes: 1 addition & 1 deletion db/migrations/1713027641_created_trails_bounding_box.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
76 changes: 76 additions & 0 deletions db/migrations/1735935107_updated_lists.go
Original file line number Diff line number Diff line change
@@ -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)
})
}
122 changes: 122 additions & 0 deletions db/templates/mail/notification.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<!DOCTYPE html>
<html>

<head>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f9f9f9;
color: #333333;
}

.email-container {
margin: 20px auto;
padding: 20px;
max-width: 600px;
background-color: #ffffff;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}

.header {
background-color: #242734;
color: #ffffff;
text-align: center;
padding: 20px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}

.header img {
max-width: 150px;
margin-bottom: 10px;
}

.header h1 {
font-size: 24px;
margin: 0;
}

.greeting,
.goodbye {
margin-top: 20px;
font-size: 18px;
}

.content {
margin: 20px 0;
font-size: 16px;
line-height: 1.6;
background: #f1f1f1;
padding: 12px;
border-radius: 5px;
}

.button {
display: inline-block;
background-color: #242734;
color: #ffffff;
padding: 10px 20px;
border-radius: 5px;
text-decoration: none;
font-weight: bold;
margin: 8px 0;
}

.button:hover {
background-color: #333333;
}

.footer {
text-align: center;
font-size: 14px;
color: #777777;
margin-top: 20px;
}

.footer a {
color: #242734;
text-decoration: none;
}

.footer a:hover {
text-decoration: underline;
}
</style>
</head>

<body>
<div class="email-container">
<!-- Header Section -->
<div class="header">
<img src="{{.AppUrl}}/imgs/logo_text_light.png" alt="wanderer" />
</div>
<!-- Greeting -->
<div class="greeting">
<p>Hello {{.RecipientName}},</p>
<p>You have a new notification:</p>
</div>
<!-- Dynamic Content -->
<div class="content">
{{.Content}}
<div class="">
<a class="button" href="{{.AppUrl}}">
Check it out!
</a>
</div>
</div>

<div class="goodbye">
<p>Kind regards,</p>
<p>Your wanderer team</p>
</div>
<!-- Footer Section -->
<div class="footer">
<p>&copy; 2025 wanderer | <a href="{{.AppUrl}}/settings/notifications">Unsubscribe</a></p>
</div>
</div>
</body>

</html>
67 changes: 67 additions & 0 deletions db/util/email_templates.go
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit 7886900

Please sign in to comment.