diff --git a/api.go b/api.go index 1047d29..a44364b 100644 --- a/api.go +++ b/api.go @@ -1570,6 +1570,7 @@ func (app *appContext) GetEmail(gc *gin.Context) { var err error var msg *Email var variables []string + var conditionals []string var values map[string]interface{} var writeVars func(variables []string) newEmail := false @@ -1661,16 +1662,21 @@ func (app *appContext) GetEmail(gc *gin.Context) { // app.storage.customEmails.InviteEmail = content } else if id == "WelcomeEmail" { content = app.storage.customEmails.WelcomeEmail.Content + conditionals = []string{"{yourAccountWillExpire}"} + app.storage.customEmails.WelcomeEmail.Conditionals = conditionals if content == "" { newEmail = true msg, err = app.email.constructWelcome("", time.Time{}, app, true) content = msg.Text + conditionals = []string{"{yourAccountWillExpire}"} } else { variables = app.storage.customEmails.WelcomeEmail.Variables } - writeVars = func(variables []string) { app.storage.customEmails.WelcomeEmail.Variables = variables } + writeVars = func(variables []string) { + app.storage.customEmails.WelcomeEmail.Variables = variables + } // app.storage.customEmails.WelcomeEmail = content - values = app.email.welcomeValues(username, time.Time{}, app, false, true) + values = app.email.welcomeValues(username, time.Now(), app, false, true) } else if id == "EmailConfirmation" { content = app.storage.customEmails.EmailConfirmation.Content if content == "" { @@ -1734,7 +1740,7 @@ func (app *appContext) GetEmail(gc *gin.Context) { respondBool(500, false, gc) return } - gc.JSON(200, customEmailDTO{Content: content, Variables: variables, Values: values, HTML: email.HTML, Plaintext: email.Text}) + gc.JSON(200, customEmailDTO{Content: content, Variables: variables, Conditionals: conditionals, Values: values, HTML: email.HTML, Plaintext: email.Text}) } // @Summary Returns whether there's a new update, and extra info if there is. diff --git a/email.go b/email.go index ee86a27..e9d33c7 100644 --- a/email.go +++ b/email.go @@ -274,13 +274,12 @@ func (emailer *Emailer) constructConfirmation(code, username, key string, app *a var err error template := emailer.confirmationValues(code, username, key, app, noSub) if app.storage.customEmails.EmailConfirmation.Enabled { - content := app.storage.customEmails.EmailConfirmation.Content - for _, v := range app.storage.customEmails.EmailConfirmation.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.EmailConfirmation.Content, + app.storage.customEmails.EmailConfirmation.Variables, + nil, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "email_confirmation", "email_", template) @@ -346,13 +345,12 @@ func (emailer *Emailer) constructInvite(code string, invite Invite, app *appCont template := emailer.inviteValues(code, invite, app, noSub) var err error if app.storage.customEmails.InviteEmail.Enabled { - content := app.storage.customEmails.InviteEmail.Content - for _, v := range app.storage.customEmails.InviteEmail.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.InviteEmail.Content, + app.storage.customEmails.InviteEmail.Variables, + nil, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "invite_emails", "email_", template) @@ -386,13 +384,12 @@ func (emailer *Emailer) constructExpiry(code string, invite Invite, app *appCont var err error template := emailer.expiryValues(code, invite, app, noSub) if app.storage.customEmails.InviteExpiry.Enabled { - content := app.storage.customEmails.InviteExpiry.Content - for _, v := range app.storage.customEmails.InviteExpiry.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.InviteExpiry.Content, + app.storage.customEmails.InviteExpiry.Variables, + nil, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "notifications", "expiry_", template) @@ -441,13 +438,12 @@ func (emailer *Emailer) constructCreated(code, username, address string, invite template := emailer.createdValues(code, username, address, invite, app, noSub) var err error if app.storage.customEmails.UserCreated.Enabled { - content := app.storage.customEmails.UserCreated.Content - for _, v := range app.storage.customEmails.UserCreated.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.UserCreated.Content, + app.storage.customEmails.UserCreated.Variables, + nil, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "notifications", "created_", template) @@ -516,13 +512,12 @@ func (emailer *Emailer) constructReset(pwr PasswordReset, app *appContext, noSub template := emailer.resetValues(pwr, app, noSub) var err error if app.storage.customEmails.PasswordReset.Enabled { - content := app.storage.customEmails.PasswordReset.Content - for _, v := range app.storage.customEmails.PasswordReset.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.PasswordReset.Content, + app.storage.customEmails.PasswordReset.Variables, + nil, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "password_resets", "email_", template) @@ -558,13 +553,12 @@ func (emailer *Emailer) constructDeleted(reason string, app *appContext, noSub b var err error template := emailer.deletedValues(reason, app, noSub) if app.storage.customEmails.UserDeleted.Enabled { - content := app.storage.customEmails.UserDeleted.Content - for _, v := range app.storage.customEmails.UserDeleted.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.UserDeleted.Content, + app.storage.customEmails.UserDeleted.Variables, + nil, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "deletion", "email_", template) @@ -600,13 +594,12 @@ func (emailer *Emailer) constructDisabled(reason string, app *appContext, noSub var err error template := emailer.disabledValues(reason, app, noSub) if app.storage.customEmails.UserDisabled.Enabled { - content := app.storage.customEmails.UserDisabled.Content - for _, v := range app.storage.customEmails.UserDisabled.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.UserDisabled.Content, + app.storage.customEmails.UserDisabled.Variables, + nil, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "disable_enable", "disabled_", template) @@ -642,13 +635,12 @@ func (emailer *Emailer) constructEnabled(reason string, app *appContext, noSub b var err error template := emailer.enabledValues(reason, app, noSub) if app.storage.customEmails.UserEnabled.Enabled { - content := app.storage.customEmails.UserEnabled.Content - for _, v := range app.storage.customEmails.UserEnabled.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.UserEnabled.Content, + app.storage.customEmails.UserEnabled.Variables, + nil, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "disable_enable", "enabled_", template) @@ -677,12 +669,14 @@ func (emailer *Emailer) welcomeValues(username string, expiry time.Time, app *ap template["username"] = username template["message"] = app.config.Section("email").Key("message").String() exp := app.formatDatetime(expiry) - if custom { - template["yourAccountWillExpire"] = exp - } else if !expiry.IsZero() { - template["yourAccountWillExpire"] = emailer.lang.WelcomeEmail.template("yourAccountWillExpire", tmpl{ - "date": exp, - }) + if !expiry.IsZero() { + if custom { + template["yourAccountWillExpire"] = exp + } else if !expiry.IsZero() { + template["yourAccountWillExpire"] = emailer.lang.WelcomeEmail.template("yourAccountWillExpire", tmpl{ + "date": exp, + }) + } } } return template @@ -705,13 +699,12 @@ func (emailer *Emailer) constructWelcome(username string, expiry time.Time, app }) } if app.storage.customEmails.WelcomeEmail.Enabled { - content := app.storage.customEmails.WelcomeEmail.Content - for _, v := range app.storage.customEmails.WelcomeEmail.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.WelcomeEmail.Content, + app.storage.customEmails.WelcomeEmail.Variables, + app.storage.customEmails.WelcomeEmail.Conditionals, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "welcome_email", "email_", template) @@ -741,13 +734,12 @@ func (emailer *Emailer) constructUserExpired(app *appContext, noSub bool) (*Emai var err error template := emailer.userExpiredValues(app, noSub) if app.storage.customEmails.UserExpired.Enabled { - content := app.storage.customEmails.UserExpired.Content - for _, v := range app.storage.customEmails.UserExpired.Variables { - replaceWith, ok := template[v[1:len(v)-1]] - if ok { - content = strings.ReplaceAll(content, v, replaceWith.(string)) - } - } + content := templateEmail( + app.storage.customEmails.UserExpired.Content, + app.storage.customEmails.UserExpired.Variables, + nil, + template, + ) email, err = emailer.constructTemplate(email.Subject, content, app) } else { email.HTML, email.Text, err = emailer.construct(app, "user_expiry", "email_", template) diff --git a/html/admin.html b/html/admin.html index 95fbd50..0dac822 100644 --- a/html/admin.html +++ b/html/admin.html @@ -183,6 +183,8 @@
{{ .strings.variables }}
+ {{ .strings.conditionals }} +

{{ .strings.markdownSupported }}

diff --git a/lang/admin/en-us.json b/lang/admin/en-us.json index bcb023b..0c3ff06 100644 --- a/lang/admin/en-us.json +++ b/lang/admin/en-us.json @@ -49,6 +49,7 @@ "subject": "Email Subject", "message": "Message", "variables": "Variables", + "conditionals": "Conditionals", "preview": "Preview", "reset": "Reset", "edit": "Edit", diff --git a/models.go b/models.go index 71ed26d..0dd9be3 100644 --- a/models.go +++ b/models.go @@ -214,11 +214,12 @@ type emailTestDTO struct { } type customEmailDTO struct { - Content string `json:"content"` - Variables []string `json:"variables"` - Values map[string]interface{} `json:"values"` - HTML string `json:"html"` - Plaintext string `json:"plaintext"` + Content string `json:"content"` + Variables []string `json:"variables"` + Conditionals []string `json:"conditionals"` + Values map[string]interface{} `json:"values"` + HTML string `json:"html"` + Plaintext string `json:"plaintext"` } type extendExpiryDTO struct { diff --git a/storage.go b/storage.go index 9c34284..1bc7fef 100644 --- a/storage.go +++ b/storage.go @@ -43,9 +43,10 @@ type customEmails struct { } type customEmail struct { - Enabled bool `json:"enabled,omitempty"` - Content string `json:"content"` - Variables []string `json:"variables,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Content string `json:"content"` + Variables []string `json:"variables,omitempty"` + Conditionals []string `json:"conditionals,omitempty"` } // timePattern: %Y-%m-%dT%H:%M:%S.%f diff --git a/ts/modules/settings.ts b/ts/modules/settings.ts index 31238dc..a1e2e2b 100644 --- a/ts/modules/settings.ts +++ b/ts/modules/settings.ts @@ -769,6 +769,7 @@ class ombiDefaults { interface templateEmail { content: string; variables: string[]; + conditionals: string[]; values: { [key: string]: string }; html: string; plaintext: string; @@ -788,6 +789,8 @@ class EmailEditor { private _header = document.getElementById("header-editor") as HTMLSpanElement; private _variables = document.getElementById("editor-variables") as HTMLDivElement; private _variablesLabel = document.getElementById("label-editor-variables") as HTMLElement; + private _conditionals = document.getElementById("editor-conditionals") as HTMLDivElement; + private _conditionalsLabel = document.getElementById("label-editor-conditionals") as HTMLElement; private _textArea = document.getElementById("textarea-editor") as HTMLTextAreaElement; private _preview = document.getElementById("editor-preview") as HTMLDivElement; private _previewContent: HTMLElement; @@ -845,7 +848,7 @@ class EmailEditor { this._variablesLabel.classList.remove("unfocused"); } this._variables.innerHTML = innerHTML - const buttons = this._variables.querySelectorAll("span.button") as NodeListOf; + let buttons = this._variables.querySelectorAll("span.button") as NodeListOf; for (let i = 0; i < this._templ.variables.length; i++) { buttons[i].innerHTML = `` + this._templ.variables[i] + ``; buttons[i].onclick = () => { @@ -854,6 +857,28 @@ class EmailEditor { // this._timeout = setTimeout(this.loadPreview, this._finishInterval); } } + + innerHTML = ''; + for (let i = this._templ.conditionals.length-1; i >= 0; i--) { + let ci = i % colors.length; + innerHTML += '' + } + if (this._templ.conditionals.length == 0) { + this._conditionalsLabel.classList.add("unfocused"); + } else { + this._conditionalsLabel.classList.remove("unfocused"); + } + this._conditionals.innerHTML = innerHTML + buttons = this._conditionals.querySelectorAll("span.button") as NodeListOf; + for (let i = 0; i < this._templ.conditionals.length; i++) { + buttons[i].innerHTML = `{if ` + this._templ.conditionals[i].slice(1) + ``; + buttons[i].onclick = () => { + this.insert(this._textArea, "{if " + this._templ.conditionals[i].slice(1) + "{endif}"); + this.loadPreview(); + // this._timeout = setTimeout(this.loadPreview, this._finishInterval); + } + } + window.modals.editor.show(); } })