Branding: bulk rename across 50+ files (Go, JS, CSS, HTML, YAML, JSON, shell scripts). Fix Helm chart description and git repo URLs. Fix test helper taglines. Admin surface: strip 14 gutted tabs (providers, models, personas, roles, knowledge, memory, tasks, health, routing, capabilities, channels, dashboard, usage, stats). Collapse to 4 categories: People, Workflows, System, Monitoring. Settings surface: strip 11 gutted tabs (models, personas, providers, roles, knowledge, memory, usage, workflows, tasks, data, gitkeys). Keep: general, appearance, profile, teams, connections, notifications. Team-admin surface: strip 5 gutted tabs (personas, providers, knowledge, tasks, usage). Keep: members, groups, connections, workflows, settings, activity. Components: delete chat-pane/ (13 files, 1938 lines) and notes-pane/ (10 files, 2381 lines). main.go: remove stale Health.Prune maintenance goroutine. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
109 lines
3.2 KiB
Go
109 lines
3.2 KiB
Go
package notifications
|
|
|
|
import (
|
|
"bytes"
|
|
"html/template"
|
|
"strings"
|
|
|
|
"switchboard-core/models"
|
|
)
|
|
|
|
// ── Template Data ───────────────────────────
|
|
|
|
type emailData struct {
|
|
Title string
|
|
Body string
|
|
Type string
|
|
ResourceType string
|
|
InstanceName string
|
|
}
|
|
|
|
// ── HTML Template ───────────────────────────
|
|
|
|
var htmlTmpl = template.Must(template.New("email").Parse(`<!DOCTYPE html>
|
|
<html>
|
|
<head><meta charset="UTF-8"></head>
|
|
<body style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; color: #333;">
|
|
<div style="border-bottom: 2px solid #4a8af4; padding-bottom: 12px; margin-bottom: 20px;">
|
|
<h2 style="margin: 0; color: #4a8af4;">{{.InstanceName}}</h2>
|
|
</div>
|
|
<div style="background: #f8f9fa; border-radius: 8px; padding: 16px; margin-bottom: 16px;">
|
|
<h3 style="margin: 0 0 8px;">{{.Title}}</h3>
|
|
{{if .Body}}<p style="margin: 0; color: #555;">{{.Body}}</p>{{end}}
|
|
</div>
|
|
<p style="font-size: 0.85em; color: #999;">
|
|
This notification was sent by {{.InstanceName}}. You can adjust your notification preferences in Settings.
|
|
</p>
|
|
</body>
|
|
</html>`))
|
|
|
|
// ── Plaintext Template ──────────────────────
|
|
|
|
var textTmpl = template.Must(template.New("email_text").Parse(`{{.InstanceName}} — Notification
|
|
|
|
{{.Title}}
|
|
{{if .Body}}
|
|
{{.Body}}
|
|
{{end}}
|
|
---
|
|
Adjust your notification preferences in Settings.
|
|
`))
|
|
|
|
// ── Render Functions ────────────────────────
|
|
|
|
// RenderHTML renders an HTML email body for a notification.
|
|
func RenderHTML(n *models.Notification, instanceName string) string {
|
|
if instanceName == "" {
|
|
instanceName = "Switchboard Core"
|
|
}
|
|
data := emailData{
|
|
Title: n.Title,
|
|
Body: n.Body,
|
|
Type: n.Type,
|
|
ResourceType: n.ResourceType,
|
|
InstanceName: instanceName,
|
|
}
|
|
var buf bytes.Buffer
|
|
if err := htmlTmpl.Execute(&buf, data); err != nil {
|
|
return "<p>" + template.HTMLEscapeString(n.Title) + "</p>"
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
// RenderText renders a plaintext email body for a notification.
|
|
func RenderText(n *models.Notification, instanceName string) string {
|
|
if instanceName == "" {
|
|
instanceName = "Switchboard Core"
|
|
}
|
|
data := emailData{
|
|
Title: n.Title,
|
|
Body: n.Body,
|
|
Type: n.Type,
|
|
ResourceType: n.ResourceType,
|
|
InstanceName: instanceName,
|
|
}
|
|
var buf bytes.Buffer
|
|
if err := textTmpl.Execute(&buf, data); err != nil {
|
|
return n.Title
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
// SubjectForNotification returns an email subject line.
|
|
func SubjectForNotification(n *models.Notification, instanceName string) string {
|
|
if instanceName == "" {
|
|
instanceName = "Switchboard Core"
|
|
}
|
|
prefix := "[" + instanceName + "] "
|
|
switch {
|
|
case strings.HasPrefix(n.Type, "kb."):
|
|
return prefix + "Knowledge Base: " + n.Title
|
|
case strings.HasPrefix(n.Type, "role."):
|
|
return prefix + "Model Alert: " + n.Title
|
|
case strings.HasPrefix(n.Type, "grant."):
|
|
return prefix + "Access Change: " + n.Title
|
|
default:
|
|
return prefix + n.Title
|
|
}
|
|
}
|