death-notifier/src/main/js/Main.ts

660 lines
23 KiB
TypeScript
Raw Normal View History

2022-08-09 19:20:02 +02:00
// @ts-ignore
2022-11-20 22:26:38 +01:00
const {$, $a, doAfterLoad} = window.fwdekker;
const {
clearFormValidity, clearMessageStatus, showMessageInfo, showMessageError, showMessageSuccess, showMessageWarning
// @ts-ignore
} = window.fwdekker.validation;
2022-08-09 19:20:02 +02:00
import {csrfToken, emptyFunction, getApi, postApi, ServerResponse, sharedMessageElement} from "./API";
import {CustomEventHandler} from "./CustomEventHandler";
2022-08-09 19:20:02 +02:00
/**
* Handles listeners to be invoked when the user logs in.
*/
const loginHandler = new CustomEventHandler();
/**
* Handles listeners to be invoked when the user logs out.
*/
const logoutHandler = new CustomEventHandler();
2022-08-19 19:07:39 +02:00
/**
* Returns a placeholder row to be placed in the trackings table.
*
* @param text the text to show in the placeholder row
* @returns a placeholder row to be placed in the trackings table
*/
function createPlaceholderRow(text: string): HTMLTableRowElement {
const row = document.createElement("tr");
row.classList.add("placeholder");
const cell = document.createElement("td");
cell.colSpan = 3;
cell.innerText = text;
row.appendChild(cell);
// Is a button to give exact same height as non-placeholder rows
const spacerCell = document.createElement("td");
const spacer = document.createElement("button");
spacer.ariaHidden = "true";
spacer.tabIndex = -1;
spacer.classList.add("invisible");
spacer.innerText = " ";
spacerCell.appendChild(spacer);
row.appendChild(spacerCell);
return row;
}
/**
* Refreshes the list of trackings in the table.
*/
2022-08-19 19:07:39 +02:00
function refreshTrackings(): void {
getApi(
{action: "list-trackings", token: csrfToken ?? ""},
2022-08-19 17:23:24 +02:00
sharedMessageElement,
(response) => {
2022-08-19 17:23:24 +02:00
// Remove old rows
2022-11-18 15:28:54 +01:00
$a("#trackings tbody tr").forEach((it: HTMLTableRowElement) => it.remove());
2022-08-12 16:38:17 +02:00
2022-08-19 17:23:24 +02:00
// Insert new rows
const tableBody = $("#trackings tbody");
response.payload.forEach((tracking: any) => {
2022-08-19 17:23:24 +02:00
const row = document.createElement("tr");
const nameCell = document.createElement("td");
const nameLink = document.createElement("a");
nameLink.href = "https://en.wikipedia.org/wiki/" + tracking.name;
nameLink.innerText = tracking.name;
2022-08-22 22:55:19 +02:00
if (tracking.deleted)
2022-11-20 22:26:38 +01:00
nameLink.classList.add("red-link");
2022-08-19 17:23:24 +02:00
nameCell.append(nameLink);
row.append(nameCell);
const statusCell = document.createElement("td");
2022-11-15 19:51:21 +01:00
let statusText;
if (tracking.deleted) {
statusText = "article not found";
2022-11-15 19:51:21 +01:00
} else {
2022-12-07 20:10:51 +01:00
switch (window.btoa(tracking.name)) {
case "QWRvbGYgSGl0bGVy":
statusText = "dead 🥳";
2022-11-15 19:51:21 +01:00
break;
2022-12-07 20:10:51 +01:00
case "VmxhZGltaXIgUHV0aW4=":
statusText = tracking.status === "alive" ? "alive ☹️" : "dead 🥳";
2022-11-15 19:51:21 +01:00
break;
default:
statusText = tracking.status;
break;
}
}
statusCell.innerText = statusText;
2022-08-19 17:23:24 +02:00
row.append(statusCell);
2022-12-07 20:00:07 +01:00
const sinceCell = document.createElement("td");
sinceCell.innerText = (new Date(tracking.since * 1000)).toLocaleDateString();
row.append(sinceCell);
2022-08-19 17:23:24 +02:00
const deleteCell = document.createElement("td");
const deleteForm = document.createElement("form");
2022-08-19 19:07:39 +02:00
deleteForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
2022-11-18 13:22:58 +01:00
if (!window.confirm(`Are you sure you want to stop tracking ${tracking.name}?`)) return;
postApi(
{action: "remove-tracking", token: csrfToken, person_name: tracking.name},
2022-08-19 17:23:24 +02:00
deleteForm,
2022-11-18 13:22:58 +01:00
() => {
refreshTrackings();
2022-11-20 22:26:38 +01:00
showMessageSuccess(
$("#remove-trackings-status-card"),
2022-11-18 13:22:58 +01:00
`Successfully removed <b>${tracking.name}</b>.`
);
}
);
});
2022-08-19 19:07:39 +02:00
const deleteButton = document.createElement("button");
deleteButton.innerText = "remove";
2022-11-20 22:26:38 +01:00
deleteButton.classList.add("outline");
2022-08-19 17:23:24 +02:00
deleteForm.append(deleteButton);
deleteCell.append(deleteForm);
row.append(deleteCell);
2022-11-18 15:28:54 +01:00
tableBody.appendChild(row);
2022-08-12 16:38:17 +02:00
});
if (response.payload.length === 0)
tableBody.appendChild(createPlaceholderRow("You haven't added any articles to track yet."));
2022-11-18 13:22:58 +01:00
2022-11-18 15:28:54 +01:00
// Scroll to top, re-apply filter
2022-11-20 22:26:38 +01:00
$("#trackings-wrapper").scrollTop = 0;
$("#filter-trackings-query").dispatchEvent(new InputEvent("input"));
}
);
}
2022-08-19 19:07:39 +02:00
/**
* Refreshes displays of the user's data.
*/
function refreshUserData(): void {
getApi(
{action: "get-user-data", token: csrfToken ?? ""},
sharedMessageElement,
(response) => {
const userData = response.payload;
2022-11-14 23:28:01 +01:00
// Account deletion
2022-11-20 22:26:38 +01:00
$("#delete-email").value = userData.email;
2022-11-14 23:28:01 +01:00
// Email
2022-11-20 22:26:38 +01:00
$("#update-email-email").value = userData.email;
$("#email-verified-checkbox").checked = userData.email_verified;
2022-11-14 23:28:01 +01:00
if (!userData.email_verified)
2022-11-20 22:26:38 +01:00
showMessageWarning(
sharedMessageElement,
"You will not receive any email notifications until you verify your email address. " +
"Check your inbox for further instructions."
);
2022-11-14 23:28:01 +01:00
else
2022-11-20 22:26:38 +01:00
clearMessageStatus(sharedMessageElement);
$("#resend-email-verification-submit").classList.toggle("hidden", userData.email_verified);
2022-11-14 23:28:01 +01:00
// Notifications
2022-11-20 22:26:38 +01:00
const notificationsCheckbox = $("#notifications-enabled-checkbox");
notificationsCheckbox.disabled = !userData.email_verified;
notificationsCheckbox.checked = userData.email_verified && userData.email_notifications_enabled;
// Password update time
const today = new Date();
today.setHours(0, 0, 0, 0);
2022-11-12 14:18:00 +01:00
const updateTime = new Date(userData.password_last_change * 1000);
updateTime.setHours(0, 0, 0, 0);
const diff = (+today - +updateTime) / 86400000;
$("#password-last-changed").innerText =
diff === 0
? "today"
: (diff === 1 ? "1 day ago" : diff + " days ago");
}
);
2022-08-19 19:07:39 +02:00
}
2022-11-14 17:09:44 +01:00
/**
* Handles the action specified in the URL's get parameters.
*
* @param params the URL's get parameters
*/
function handleAction(params: URLSearchParams): void {
2022-11-20 22:26:38 +01:00
const sharedHomeLink = $("#shared-home-link");
2022-11-14 17:09:44 +01:00
let params_are_valid = true;
switch (params.get("action")) {
case "verify-email":
if (!params.has("email") || !params.has("token")) {
params_are_valid = false;
break;
}
postApi(
{
action: "verify-email",
token: csrfToken,
email: params.get("email"),
verify_token: params.get("token"),
},
sharedMessageElement,
() => {
sharedHomeLink.classList.remove("hidden");
redirectWithTimeout(
"./", 3, (secondsLeft) => {
2022-11-20 22:26:38 +01:00
showMessageSuccess(
2022-11-14 17:09:44 +01:00
sharedMessageElement,
`Your email address has been verified. ` +
`You will be redirected after ${secondsLeft} second(s).`
);
});
},
() => sharedHomeLink.classList.remove("hidden")
);
break;
case "reset-password":
if (!params.has("email") || !params.has("token")) {
params_are_valid = false;
break;
}
getApi(
{
action: "validate-password-reset-token",
token: csrfToken ?? "",
email: params.get("email") ?? "",
reset_token: params.get("token") ?? "",
},
sharedMessageElement,
() => {
2022-11-20 22:26:38 +01:00
$("#reset-password-token").value = params.get("token");
$("#reset-password-email").value = params.get("email");
$("#reset-password-part").classList.remove("hidden");
$("#reset-password-password").focus();
2022-11-14 17:09:44 +01:00
},
() => sharedHomeLink.classList.remove("hidden")
);
break;
case null:
break;
default:
params_are_valid = false;
break;
}
if (!params_are_valid) {
sharedHomeLink.classList.remove("hidden");
2022-11-20 22:26:38 +01:00
showMessageError(sharedMessageElement, `Invalid URL.`);
2022-11-14 17:09:44 +01:00
}
}
2022-11-12 14:18:00 +01:00
/**
* Redirects the user to `target` after `seconds` seconds, calling `doEachSecond` after every second.
*
* @param target the location to redirect the user to after the timeout
* @param seconds the number of seconds before redirecting the user
* @param doEachSecond the function to invoke each second; the only argument is the number of seconds left at that time
*/
function redirectWithTimeout(target: string, seconds: number, doEachSecond: (secondsLeft: number) => void): void {
let secondsLeft = seconds;
const update = () => {
doEachSecond(secondsLeft);
secondsLeft--;
setTimeout(update, 1000);
};
update();
setTimeout(() => window.location.href = target, seconds * 1000);
}
// Register event handlers
doAfterLoad(() => {
// Switch between logged-out and logged-in views
loginHandler.addListener(() => {
2022-11-20 22:26:38 +01:00
clearMessageStatus(sharedMessageElement);
2022-11-15 19:51:21 +01:00
refreshUserData();
2022-08-19 19:07:39 +02:00
refreshTrackings();
$("#welcome-part").classList.add("hidden");
2022-11-20 22:26:38 +01:00
$("#tracking-part").classList.remove("hidden");
$("#settings-part").classList.remove("hidden");
});
logoutHandler.addListener(() => {
2022-11-20 22:26:38 +01:00
clearMessageStatus(sharedMessageElement);
2022-11-15 19:51:21 +01:00
$("#welcome-part").classList.remove("hidden");
2022-11-20 22:26:38 +01:00
$("#tracking-part").classList.add("hidden");
$("#settings-part").classList.add("hidden");
$("#login-email").focus();
});
2022-08-19 19:07:39 +02:00
// Password visibility toggling
2022-11-20 22:26:38 +01:00
$a(".password-toggle").forEach((toggle: HTMLElement) => {
const passwordField = $(`#${toggle.dataset.toggles}`);
2022-11-20 22:26:38 +01:00
const setState = (showPassword: boolean) => passwordField.type = showPassword ? "text" : "password";
passwordField.form.addEventListener("reset", () => setState(false));
toggle.addEventListener("click", () => setState(passwordField.type === "password"));
});
2022-11-12 14:18:00 +01:00
// Login
2022-11-20 22:26:38 +01:00
const loginForm = $("#login-form");
loginForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
postApi(
{
action: "login",
token: csrfToken,
2022-11-20 22:26:38 +01:00
email: $("#login-email").value,
password: $("#login-password").value,
},
event.target as HTMLFormElement,
() => loginHandler.invokeListeners()
);
});
loginHandler.addListener(() => {
loginForm.reset();
2022-11-20 22:26:38 +01:00
clearMessageStatus(loginForm);
});
2022-11-20 22:26:38 +01:00
const registerForm = $("#register-form");
registerForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
postApi(
{
action: "register",
token: csrfToken,
2022-11-20 22:26:38 +01:00
email: $("#register-email").value,
password: $("#register-password").value
},
registerForm,
() => {
2022-08-21 14:43:46 +02:00
// TODO: Add client-side form validation
registerForm.reset();
2022-11-20 22:26:38 +01:00
showMessageSuccess(registerForm, "Account created successfully! You may now log in.");
$("#login-email").focus();
}
);
});
loginHandler.addListener(() => {
registerForm.reset();
2022-11-20 22:26:38 +01:00
clearFormValidity(registerForm);
});
2022-11-20 22:26:38 +01:00
const logoutForm = $("#logout-form");
2022-08-19 17:23:24 +02:00
logoutForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
postApi(
{
action: "logout",
token: csrfToken,
2022-08-19 17:23:24 +02:00
},
logoutForm,
() => {
logoutForm.reset();
logoutHandler.invokeListeners();
}
2022-08-19 17:23:24 +02:00
);
});
2022-11-12 14:18:00 +01:00
// Forgot password
2022-11-20 22:26:38 +01:00
const sendPasswordResetForm = $("#send-password-reset-form");
2022-11-12 14:18:00 +01:00
sendPasswordResetForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
postApi(
{
action: "send-password-reset",
token: csrfToken,
2022-11-20 22:26:38 +01:00
email: $("#send-password-reset-email").value,
2022-11-12 14:18:00 +01:00
},
sendPasswordResetForm,
() => {
sendPasswordResetForm.reset();
2022-11-20 22:26:38 +01:00
showMessageSuccess(sendPasswordResetForm, "Password reset email sent successfully!");
2022-11-12 14:18:00 +01:00
}
);
});
2022-11-14 17:09:44 +01:00
loginHandler.addListener(() => {
sendPasswordResetForm.reset();
2022-11-20 22:26:38 +01:00
clearFormValidity(sendPasswordResetForm);
2022-11-14 17:09:44 +01:00
});
2022-11-12 14:18:00 +01:00
2022-11-20 22:26:38 +01:00
const resetPasswordForm = $("#reset-password-form");
2022-11-12 14:18:00 +01:00
resetPasswordForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
postApi(
{
action: "reset-password",
token: csrfToken,
2022-11-20 22:26:38 +01:00
email: $("#reset-password-email").value,
reset_token: $("#reset-password-token").value,
password: $("#reset-password-password").value,
2022-11-12 14:18:00 +01:00
},
resetPasswordForm,
() => {
2022-11-20 22:26:38 +01:00
resetPasswordForm.reset();
2022-11-12 14:18:00 +01:00
redirectWithTimeout(
"./", 3, (secondsLeft) => {
2022-11-20 22:26:38 +01:00
showMessageSuccess(
resetPasswordForm,
2022-11-14 17:09:44 +01:00
`Your password has been updated. You will be redirected after ${secondsLeft} second(s).`
2022-11-12 14:18:00 +01:00
);
}
);
2022-11-12 14:18:00 +01:00
}
);
});
2022-11-20 22:26:38 +01:00
$("#forgot-password-go-to").addEventListener("click", (event: MouseEvent) => {
2022-11-12 14:18:00 +01:00
event.preventDefault();
2022-11-20 22:26:38 +01:00
$("#welcome-part").classList.add("hidden");
$("#send-forgot-password-part").classList.remove("hidden");
2022-11-14 23:55:06 +01:00
2022-11-20 22:26:38 +01:00
const resetEmail = $("#send-password-reset-email");
resetEmail.value = $("#login-email").value;
2022-11-14 23:55:06 +01:00
resetEmail.focus();
2022-11-12 14:18:00 +01:00
});
2022-11-20 22:26:38 +01:00
$("#forgot-password-go-back").addEventListener("click", (event: MouseEvent) => {
2022-11-12 14:18:00 +01:00
event.preventDefault();
2022-11-20 22:26:38 +01:00
$("#send-password-reset-form").reset();
$("#send-forgot-password-part").classList.add("hidden");
$("#welcome-part").classList.remove("hidden");
2022-11-14 23:55:06 +01:00
2022-11-20 22:26:38 +01:00
const loginEmail = $("#login-email");
loginEmail.value = $("#send-password-reset-email").value;
2022-11-14 23:55:06 +01:00
loginEmail.focus();
2022-11-12 14:18:00 +01:00
});
// Account management
2022-11-20 22:26:38 +01:00
const deleteForm = $("#delete-form");
2022-11-13 20:34:28 +01:00
deleteForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
2022-11-20 22:26:38 +01:00
const actual_email = $("#delete-email").value;
2022-11-13 20:34:28 +01:00
const entered_email = window.prompt(
`Are you sure you want to delete your account? ` +
`This action cannot be undone. ` +
`Enter ${actual_email} to confirm.`
);
2022-11-14 23:55:06 +01:00
if (entered_email === null) {
return;
} else if (entered_email !== actual_email) {
2022-11-20 22:26:38 +01:00
showMessageError(deleteForm, "Incorrect email address.");
2022-11-13 20:34:28 +01:00
return;
}
postApi(
{action: "user-delete", token: csrfToken},
deleteForm,
() => {
logoutHandler.invokeListeners();
2022-11-20 22:26:38 +01:00
showMessageSuccess(sharedMessageElement, "Your account has been deleted.");
2022-11-13 20:34:28 +01:00
}
);
});
2022-11-20 22:26:38 +01:00
logoutHandler.addListener(() => clearFormValidity(deleteForm));
2022-11-13 20:34:28 +01:00
2022-11-20 22:26:38 +01:00
const resendEmailVerificationForm = $("#resend-email-verification-form");
2022-11-14 23:28:01 +01:00
resendEmailVerificationForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
postApi(
{action: "resend-verify-email", token: csrfToken},
resendEmailVerificationForm,
() => {
refreshUserData();
2022-11-20 22:26:38 +01:00
showMessageSuccess(resendEmailVerificationForm, "Email verification resent successfully!");
2022-11-14 23:28:01 +01:00
}
);
});
2022-11-20 22:26:38 +01:00
logoutHandler.addListener(() => clearFormValidity(resendEmailVerificationForm));
2022-11-14 23:28:01 +01:00
2022-11-20 22:26:38 +01:00
const toggleNotificationsForm = $("#toggle-notifications-form");
const notificationsEnabledCheckbox = $("#notifications-enabled-checkbox");
notificationsEnabledCheckbox.addEventListener("change", (event: Event) => {
2022-11-14 23:28:01 +01:00
event.preventDefault();
const enableNotifications = notificationsEnabledCheckbox.checked;
2022-11-14 23:28:01 +01:00
postApi(
{
action: "toggle-notifications",
enable_notifications: enableNotifications,
token: csrfToken
},
2022-11-14 23:28:01 +01:00
toggleNotificationsForm,
() => {
refreshUserData();
if (enableNotifications)
2022-11-20 22:26:38 +01:00
showMessageSuccess(toggleNotificationsForm, "Notifications have been enabled.");
else
2022-11-20 22:26:38 +01:00
showMessageSuccess(
toggleNotificationsForm,
"Notifications have been disabled. " +
"You will still receive security notifications, for example if you change your email address " +
"or password.");
}
2022-11-14 23:28:01 +01:00
);
});
2022-11-20 22:26:38 +01:00
logoutHandler.addListener(() => clearFormValidity(toggleNotificationsForm));
2022-11-14 23:28:01 +01:00
2022-11-20 22:26:38 +01:00
const updateEmailForm = $("#update-email-form");
2022-08-19 17:23:24 +02:00
updateEmailForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
2022-08-19 17:23:24 +02:00
postApi(
{
action: "update-email",
token: csrfToken,
2022-11-20 22:26:38 +01:00
email: $("#update-email-email").value,
2022-08-19 17:23:24 +02:00
},
updateEmailForm,
2022-08-19 19:07:39 +02:00
() => {
updateEmailForm.reset();
refreshUserData();
2022-11-20 22:26:38 +01:00
showMessageSuccess(
updateEmailForm,
"Email address updated successfully! " +
"Check your inbox for the verification email. " +
"You will not receive notifications until you verify your email address."
);
}
);
});
logoutHandler.addListener(() => {
updateEmailForm.reset();
2022-11-20 22:26:38 +01:00
clearFormValidity(updateEmailForm);
});
2022-11-20 22:26:38 +01:00
const updatePasswordForm = $("#update-password-form");
2022-08-19 17:23:24 +02:00
updatePasswordForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
2022-08-19 17:23:24 +02:00
postApi(
{
action: "update-password",
token: csrfToken,
2022-11-20 22:26:38 +01:00
password_old: $("#update-password-password-old").value,
password_new: $("#update-password-password-new").value,
2022-08-19 17:23:24 +02:00
},
event.target as HTMLFormElement,
2022-08-19 19:07:39 +02:00
() => {
updatePasswordForm.reset();
refreshUserData();
2022-11-20 22:26:38 +01:00
showMessageSuccess(updatePasswordForm, "Password updated successfully!");
2022-08-19 19:07:39 +02:00
}
2022-08-19 17:23:24 +02:00
);
});
logoutHandler.addListener(() => {
updatePasswordForm.reset();
2022-11-20 22:26:38 +01:00
clearFormValidity(updatePasswordForm);
});
2022-11-12 14:18:00 +01:00
// Tracking management
2022-11-20 22:26:38 +01:00
const queryInput = $("#filter-trackings-query");
$("#filter-trackings-form").addEventListener("submit", (event: SubmitEvent) => event.preventDefault());
2022-11-18 15:41:06 +01:00
queryInput.addEventListener("input", (event: InputEvent) => {
2022-11-18 15:28:54 +01:00
event.preventDefault();
2022-11-20 22:26:38 +01:00
$("#trackings-no-matches")?.remove();
2022-11-18 15:28:54 +01:00
2022-11-20 22:26:38 +01:00
const queryWords = queryInput.value.trim().toLowerCase().split(" ");
2022-11-18 15:28:54 +01:00
let foundMatches = false;
$a("#trackings tbody tr").forEach((row: HTMLTableRowElement) => {
const rowText = row.innerText.toLowerCase();
2022-11-18 15:36:15 +01:00
const matches = row.classList.contains("placeholder")
? (queryWords.length === 1 && queryWords[0] === "")
: queryWords.every((word: string) => rowText.includes(word));
2022-11-18 15:28:54 +01:00
foundMatches = foundMatches || matches;
row.classList.toggle("hidden", !matches);
});
if (!foundMatches) {
const row = createPlaceholderRow("No articles match your query.");
2022-11-20 22:26:38 +01:00
row.id = "trackings-no-matches";
2022-11-18 15:28:54 +01:00
$("#trackings tbody").appendChild(row);
}
});
2022-11-20 22:26:38 +01:00
const addTrackingForm = $("#add-tracking-form");
2022-08-19 17:23:24 +02:00
addTrackingForm.addEventListener("submit", (event: SubmitEvent) => {
event.preventDefault();
const inputName = $("#add-tracking-name").value;
2022-08-19 17:23:24 +02:00
postApi(
{
action: "add-tracking",
token: csrfToken,
person_name: inputName,
2022-08-19 17:23:24 +02:00
},
addTrackingForm,
(response: ServerResponse) => {
2022-08-19 17:23:24 +02:00
addTrackingForm.reset();
refreshTrackings();
2022-11-20 22:26:38 +01:00
showMessageSuccess(
addTrackingForm,
inputName.toLowerCase() !== response.payload["normalized_name"].toLowerCase()
? (
`Successfully added <b>${inputName}</b> as ` +
`<b>${response.payload["normalized_name"]}</b>!`
)
: `Successfully added <b>${response.payload["normalized_name"]}</b>!`
);
2022-08-19 17:23:24 +02:00
}
);
});
logoutHandler.addListener(() => {
addTrackingForm.reset();
2022-11-20 22:26:38 +01:00
clearFormValidity(addTrackingForm);
});
});
// Run initialization code
doAfterLoad(() => {
2022-11-14 17:09:44 +01:00
const params = new URLSearchParams(window.location.search);
2022-11-12 14:18:00 +01:00
getApi(
{action: "start-session"},
sharedMessageElement,
(response: ServerResponse) => {
if (!params.has("action")) {
if (response.payload["logged_in"] === true)
loginHandler.invokeListeners();
else
logoutHandler.invokeListeners();
}
2022-11-12 17:48:37 +01:00
},
2022-11-14 17:09:44 +01:00
emptyFunction,
emptyFunction,
2022-11-14 15:44:21 +01:00
(response) => {
2022-11-14 17:09:44 +01:00
// Always execute the following
2022-11-20 22:26:38 +01:00
$("main").classList.remove("hidden");
const message = (response?.payload ?? {})["global_message"];
if (message != null)
2022-11-20 22:26:38 +01:00
showMessageInfo($("#global-message"), message);
2022-11-14 15:44:21 +01:00
2022-11-14 17:09:44 +01:00
handleAction(params);
2022-11-12 17:48:37 +01:00
}
);
2022-08-09 19:20:02 +02:00
});