1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-22 09:00:10 +00:00

add preview to Announcements

This commit is contained in:
Harvey Tindall 2021-05-03 18:35:27 +01:00
parent 2c6d08319b
commit c0f316d049
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
8 changed files with 84 additions and 32 deletions

5
api.go
View File

@ -1712,6 +1712,9 @@ func (app *appContext) GetCustomEmailTemplate(gc *gin.Context) {
}
writeVars = func(variables []string) { app.storage.customEmails.UserExpired.Variables = variables }
values = app.email.userExpiredValues(app, false)
// Just send the email html
case "Announcement":
content = ""
default:
respondBool(400, false, gc)
return
@ -1747,7 +1750,7 @@ func (app *appContext) GetCustomEmailTemplate(gc *gin.Context) {
respondBool(500, false, gc)
return
}
email, err := app.email.constructTemplate("", "<div id=\"preview-content\"></div>", app)
email, err := app.email.constructTemplate("", "<div class=\"preview-content\"></div>", app)
if err != nil {
respondBool(500, false, gc)
return

View File

@ -156,9 +156,10 @@
</form>
</div>
<div id="modal-announce" class="modal">
<form class="modal-content card" id="form-announce" href="">
<form class="modal-content wide card" id="form-announce" href="">
<span class="heading"><span id="header-announce"></span> <span class="modal-close">&times;</span></span>
<div class="content mt-half">
<div class="row">
<div class="col flex-col content mt-half">
<label class="label supra" for="announce-subject"> {{ .strings.subject }}</label>
<input type="text" id="announce-subject" class="input ~neutral !normal mb-1 mt-half">
<label class="label supra" for="textarea-announce">{{ .strings.message }}</label>
@ -169,6 +170,11 @@
<span class="button ~urge !normal full-width center supra submit">{{ .strings.submit }}</span>
</label>
</div>
<div class="col card ~neutral !low">
<span class="subheading supra">{{ .strings.preview }}</span>
<div class="mt-half" id="announce-preview"></div>
</div>
</div>
</form>
</div>
<div id="modal-customize" class="modal">

13
package-lock.json generated
View File

@ -9,6 +9,7 @@
"license": "ISC",
"dependencies": {
"@ts-stack/markdown": "^1.3.0",
"@types/node": "^15.0.1",
"a17t": "^0.4.0",
"esbuild": "^0.8.57",
"lodash": "^4.17.19",
@ -35,9 +36,9 @@
}
},
"node_modules/@types/node": {
"version": "14.14.16",
"resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-14.14.16.tgz?cache=0&sync_timestamp=1608756036972&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-14.14.16.tgz",
"integrity": "sha1-PMNR+NSBAd6t/tTJ5PEWBI1De0s="
"version": "15.0.1",
"resolved": "https://registry.nlark.com/@types/node/download/@types/node-15.0.1.tgz?cache=0&sync_timestamp=1619534647758&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-15.0.1.tgz",
"integrity": "sha1-7zTeoIgQKNETmL5b9OhWdD49w1o="
},
"node_modules/a17t": {
"version": "0.4.0",
@ -1835,9 +1836,9 @@
}
},
"@types/node": {
"version": "14.14.16",
"resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-14.14.16.tgz?cache=0&sync_timestamp=1608756036972&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-14.14.16.tgz",
"integrity": "sha1-PMNR+NSBAd6t/tTJ5PEWBI1De0s="
"version": "15.0.1",
"resolved": "https://registry.nlark.com/@types/node/download/@types/node-15.0.1.tgz?cache=0&sync_timestamp=1619534647758&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-15.0.1.tgz",
"integrity": "sha1-7zTeoIgQKNETmL5b9OhWdD49w1o="
},
"a17t": {
"version": "0.4.0",

View File

@ -18,6 +18,7 @@
"homepage": "https://github.com/hrfee/jfa-go#readme",
"dependencies": {
"@ts-stack/markdown": "^1.3.0",
"@types/node": "^15.0.1",
"a17t": "^0.4.0",
"esbuild": "^0.8.57",
"lodash": "^4.17.19",

View File

@ -1,4 +1,7 @@
import { _get, _post, _delete, toggleLoader, toDateString } from "../modules/common.js";
import { templateEmail } from "../modules/settings.js";
import { Marked } from "@ts-stack/markdown";
import { stripMarkdown } from "../modules/stripmd.js";
interface User {
id: string;
@ -193,6 +196,9 @@ export class accountsList {
private _addUserButton = document.getElementById("accounts-add-user") as HTMLSpanElement;
private _announceButton = document.getElementById("accounts-announce") as HTMLSpanElement;
private _announcePreview: HTMLElement;
private _previewLoaded = false;
private _announceTextarea = document.getElementById("textarea-announce") as HTMLTextAreaElement;
private _deleteUser = document.getElementById("accounts-delete-user") as HTMLSpanElement;
private _disableEnable = document.getElementById("accounts-disable-enable") as HTMLSpanElement;
private _deleteNotify = document.getElementById("delete-user-notify") as HTMLInputElement;
@ -432,7 +438,16 @@ export class accountsList {
}
}, true);
}
loadPreview = () => {
let content = this._announceTextarea.value;
if (!this._previewLoaded) {
content = stripMarkdown(content);
this._announcePreview.textContent = content;
} else {
content = Marked.parse(content);
this._announcePreview.innerHTML = content;
}
}
announce = () => {
const modalHeader = document.getElementById("header-announce");
modalHeader.textContent = window.lang.quantity("announceTo", this._collectUsers().length);
@ -440,16 +455,16 @@ export class accountsList {
let list = this._collectUsers();
const button = form.querySelector("span.submit") as HTMLSpanElement;
const subject = document.getElementById("announce-subject") as HTMLInputElement;
const message = document.getElementById("textarea-announce") as HTMLTextAreaElement;
subject.value = "";
message.value = "";
this._announceTextarea.value = "";
form.onsubmit = (event: Event) => {
event.preventDefault();
toggleLoader(button);
let send = {
"users": list,
"subject": subject.value,
"message": message.value
"message": this._announceTextarea.value
}
_post("/users/announce", send, (req: XMLHttpRequest) => {
if (req.readyState == 4) {
@ -463,7 +478,29 @@ export class accountsList {
}
});
};
_get("/config/emails/Announcement", null, (req: XMLHttpRequest) => {
if (req.readyState == 4) {
const preview = document.getElementById("announce-preview") as HTMLDivElement;
if (req.status != 200) {
preview.innerHTML = `<pre class="preview-content" class="monospace"></pre>`;
window.modals.announce.show();
this._previewLoaded = false;
return;
}
let templ = req.response as templateEmail;
if (!templ.html) {
preview.innerHTML = `<pre class="preview-content" class="monospace"></pre>`;
this._previewLoaded = false;
} else {
preview.innerHTML = templ.html;
this._previewLoaded = true;
}
this._announcePreview = preview.getElementsByClassName("preview-content")[0] as HTMLElement;
this.loadPreview();
window.modals.announce.show();
}
});
}
enableDisableUsers = () => {
@ -750,6 +787,8 @@ export class accountsList {
}
this._checkCheckCount();
};
this._announceTextarea.onkeyup = this.loadPreview;
}
reload = () => _get("/users", null, (req: XMLHttpRequest) => {

View File

@ -157,7 +157,7 @@ class DOMInvite implements Invite {
this._createdUnix = unix;
const el = this._middle.querySelector("strong.inv-created");
if (unix == 0) {
el.textContent = "n/a";
el.textContent = window.lang.strings("unknown");
} else {
el.textContent = toDateString(new Date(unix*1000));
}
@ -479,7 +479,7 @@ export class inviteList implements inviteList {
}
function parseInvite(invite: { [f: string]: string | number | string[][] | boolean }): Invite {
function parseInvite(invite: { [f: string]: string | number | { [name: string]: number } | boolean }): Invite {
let parsed: Invite = {};
parsed.code = invite["code"] as string;
parsed.email = invite["email"] as string || "";
@ -509,8 +509,8 @@ function parseInvite(invite: { [f: string]: string | number | string[][] | boole
parsed.userExpiry = invite["user-expiry"] as boolean;
parsed.userExpiryTime = userExpiryTime.slice(0, -1);
parsed.remainingUses = invite["no-limit"] ? "∞" : String(invite["remaining-uses"])
parsed.usedBy = invite["used-by"] as string[][] || [];
parsed.created = invite["created"] as string || window.lang.strings("unknown");
parsed.usedBy = invite["used-by"] as { [name: string]: number } || {} ;
parsed.created = invite["created"] as number || 0;
parsed.profile = invite["profile"] as string || "";
parsed.notifyExpiry = invite["notify-expiry"] as boolean || false;
parsed.notifyCreation = invite["notify-creation"] as boolean || false;

View File

@ -766,7 +766,7 @@ class ombiDefaults {
}
}
interface templateEmail {
export interface templateEmail {
content: string;
variables: string[];
conditionals: string[];
@ -829,11 +829,11 @@ class EmailEditor {
this._templ = req.response as templateEmail;
this._textArea.value = this._templ.content;
if (this._templ.html == "") {
this._preview.innerHTML = `<pre id="preview-content" class="monospace"></pre>`;
this._preview.innerHTML = `<pre class="preview-content" class="monospace"></pre>`;
} else {
this._preview.innerHTML = this._templ.html;
}
this._previewContent = document.getElementById("preview-content");
this._previewContent = this._preview.getElementsByClassName("preview-content")[0] as HTMLElement;
this.loadPreview();
this._content = this._templ.content;
const colors = ["info", "urge", "positive", "neutral"];

View File

@ -53,13 +53,15 @@ func (app *appContext) pushResources(gc *gin.Context, admin bool) {
gc.Header("Link", cssHeader)
}
type Page int
const (
AdminPage = iota + 1
AdminPage Page = iota + 1
FormPage
PWRPage
)
func (app *appContext) getLang(gc *gin.Context, page int, chosen string) string {
func (app *appContext) getLang(gc *gin.Context, page Page, chosen string) string {
lang := gc.Query("lang")
cookie, err := gc.Cookie("lang")
if lang != "" {