Clean up interface

This commit is contained in:
Florine W. Dekker 2022-12-14 22:50:55 +01:00
parent 93c0a6f7e9
commit debe285cf5
Signed by: FWDekker
GPG Key ID: D3DCFAA8A4560BE0
18 changed files with 105 additions and 92 deletions

View File

@ -1,7 +1,7 @@
{
"name": "fwdekker/death-notifier",
"description": "Get notified when a famous person dies.",
"version": "0.19.4", "_comment_version": "Also update version in `package.json`!",
"version": "0.19.5", "_comment_version": "Also update version in `package.json`!",
"type": "project",
"license": "MIT",
"homepage": "https://git.fwdekker.com/tools/death-notifier",

BIN
composer.lock generated

Binary file not shown.

BIN
package-lock.json generated

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"name": "death-notifier",
"version": "0.19.4", "_comment_version": "Also update version in `composer.json`!",
"version": "0.19.5", "_comment_version": "Also update version in `composer.json`!",
"description": "Get notified when a famous person dies.",
"author": "Florine W. Dekker",
"browser": "dist/bundle.js",

View File

@ -14,6 +14,22 @@ a.red-link {
}
/* Flex form */
.flex-form {
display: flex;
column-gap: .3em;
}
.flex-form input,
.flex-form button {
width: unset;
}
.flex-form-grow {
flex-grow: 1;
}
/* Messages */
#global-message,
#shared-status-card {
@ -33,45 +49,22 @@ a.red-link {
/* Trackings table forms */
#add-tracking-name-container {
display: flex;
column-gap: .3em;
}
#add-tracking-name,
#add-tracking-submit {
#filter-trackings-query {
width: unset;
}
#add-tracking-name {
flex-grow: 1;
}
#add-tracking-name-hint {
/*noinspection CssUnresolvedCustomProperty*/
margin-top: calc(var(--spacing) * -.75);
}
@media (min-width: 992px) {
#filter-trackings-query {
float: right;
}
}
small[data-hint-for="add-tracking-name"] {
display: block;
}
/* Trackings table */
.placeholder {
font-style: italic;
}
#filter-trackings-query {
width: unset;
}
#trackings-wrapper {
max-height: 54rem;
/*noinspection CssUnresolvedCustomProperty*/

View File

@ -216,14 +216,14 @@
</article>
<div class="grid">
<form id="add-tracking-form" novalidate>
<div id="add-tracking-name-container">
<div class="flex-form">
<!--suppress HtmlFormInputWithoutLabel -->
<input id="add-tracking-name" type="text" name="person_name" autocomplete="name"
placeholder="Who do you want to track?" />
<input id="add-tracking-name" class="flex-form-grow" type="text" name="person_name"
autocomplete="name" placeholder="Who do you want to track?" />
<button id="add-tracking-submit">Add</button>
</div>
<small id="add-tracking-name-hint" data-hint-for="add-tracking-name"></small>
<small id="add-tracking-name-hint" class="input-hint" data-hint-for="add-tracking-name"></small>
</form>
<form id="filter-trackings-form" novalidate>
<!--suppress HtmlFormInputWithoutLabel -->
@ -241,7 +241,11 @@
</tr>
</thead>
<tbody>
<!-- TODO: Show loading icon while fetching entries (and in more places) -->
<tr>
<td colspan="100">
<progress></progress>
</td>
</tr>
</tbody>
</table>
</div>
@ -272,39 +276,48 @@
<button id="updateEmailButton">Change email</button>
</form>
<form id="resend-email-verification-form" novalidate>
<article class="status-card hidden" data-status-for="resend-email-verification-form">
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<footer>
<form id="resend-email-verification-form" novalidate>
<article class="status-card hidden" data-status-for="resend-email-verification-form">
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<input type="checkbox" id="email-verified-checkbox" disabled />
<label for="email-verified-checkbox">Verified</label>
<input type="checkbox" id="email-verified-checkbox" disabled />
<label for="email-verified-checkbox">Verified</label>
<button id="resend-email-verification-submit" class="hidden">resend link</button>
</form>
<form id="toggle-notifications-form" novalidate>
<article class="status-card hidden" data-status-for="toggle-notifications-form">
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<button id="resend-email-verification-submit" class="hidden inline-button">
resend link
</button>
</form>
<form id="toggle-notifications-form" novalidate>
<article class="status-card hidden" data-status-for="toggle-notifications-form">
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<input type="checkbox" id="notifications-enabled-checkbox" />
<label for="notifications-enabled-checkbox">Notifications</label>
</form>
<input type="checkbox" id="notifications-enabled-checkbox" />
<label for="notifications-enabled-checkbox">Notifications</label>
<small id="notifications-enabled-checkbox-hint"
data-hint-for="notifications-enabled-checkbox"></small>
</form>
</footer>
</article>
<article>
<header>
<h3>Password</h3>
</header>
<form><b>Last changed:</b> <span id="password-last-changed">...</span></form>
<form id="update-password-form" novalidate>
<article class="status-card hidden" data-status-for="update-password-form">
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<b>Last changed:</b>
<span id="password-last-changed"><span aria-busy="true"></span></span>
<br /><br />
<label for="update-password-password-old">Old password</label>
<input id="update-password-password-old" type="password" name="password_old"
autocomplete="current-password" />
@ -351,20 +364,20 @@
</form>
<footer>
<h4>Delete account</h4>
<p>
If you no longer want to use Death Notifier, you can permanently delete your account.
This choice is permanent and cannot be reverted.
</p>
<form id="delete-form" novalidate>
<article class="status-card hidden" data-status-for="delete-form">
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<h4>Delete account</h4>
<p>
If you no longer want to use Death Notifier, you can permanently delete your account.
This choice is permanent and cannot be reverted.
</p>
<form id="delete-form" novalidate>
<article class="status-card hidden" data-status-for="delete-form">
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<input id="delete-email" type="hidden" name="email" />
<button id="delete-button" class="outline">Delete account</button>
</form>
<input id="delete-email" type="hidden" name="email" />
<button id="delete-button" class="outline">Delete account</button>
</form>
</footer>
</article>
</div>

View File

@ -1,7 +1,8 @@
// @ts-ignore
const {$, $a, doAfterLoad} = window.fwdekker;
const {
clearFormValidity, clearMessageStatus, showMessageInfo, showMessageError, showMessageSuccess, showMessageWarning
clearFormValidity, clearMessageStatus, showInputValid, showMessageInfo, showMessageError, showMessageSuccess,
showMessageWarning
// @ts-ignore
} = window.fwdekker.validation;
@ -150,20 +151,24 @@ function refreshUserData(): void {
// Email
$("#update-email-email").value = userData.email;
$("#email-verified-checkbox").checked = userData.email_verified;
if (!userData.email_verified)
if (!userData.email_verified) {
showMessageWarning(
sharedMessageElement,
"You will not receive any email notifications until you verify your email address. " +
"Check your inbox for further instructions."
);
else
} else {
clearMessageStatus(sharedMessageElement);
}
$("#resend-email-verification-submit").classList.toggle("hidden", userData.email_verified);
// Notifications
const notificationsCheckbox = $("#notifications-enabled-checkbox");
notificationsCheckbox.disabled = !userData.email_verified;
notificationsCheckbox.checked = userData.email_verified && userData.email_notifications_enabled;
if (!userData.email_verified)
$("#notifications-enabled-checkbox-hint").innerText =
"You cannot enable notifications until you verify your email address.";
// Password update time
const today = new Date();
@ -504,13 +509,14 @@ doAfterLoad(() => {
refreshUserData();
if (enableNotifications)
showMessageSuccess(toggleNotificationsForm, "Notifications have been enabled.");
showInputValid($("#notifications-enabled-checkbox"), "Notifications have been enabled.");
else
showMessageSuccess(
toggleNotificationsForm,
showInputValid(
$("#notifications-enabled-checkbox"),
"Notifications have been disabled. " +
"You will still receive security notifications, for example if you change your email address " +
"or password.");
"or password."
);
}
);
});

View File

@ -18,7 +18,7 @@ abstract class Email
*/
public readonly string $type_key;
/**
* @var string the intended recipient of the email
* @var string the intended recipient of this email
*/
public readonly string $recipient;
@ -27,7 +27,7 @@ abstract class Email
* Constructs a new `Email`.
*
* @param string $type_key the identifier of this email
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
*/
public function __construct(string $type_key, string $recipient)
{

View File

@ -36,8 +36,8 @@ class EmailQueue
public function install(): void
{
$conn = $this->database->conn;
$conn->exec("CREATE TABLE email_tasks(recipient TEXT NOT NULL,
type_key TEXT NOT NULL,
$conn->exec("CREATE TABLE email_tasks(type_key TEXT NOT NULL,
recipient TEXT NOT NULL,
subject TEXT NOT NULL,
body TEXT NOT NULL,
PRIMARY KEY (type_key, recipient));");
@ -68,8 +68,8 @@ class EmailQueue
*/
public function queue_emails(array $emails): void
{
$stmt = $this->database->conn->prepare("INSERT OR REPLACE INTO email_tasks (recipient, type_key, subject, body)
VALUES (:recipient, :type_key, :subject, :body);");
$stmt = $this->database->conn->prepare("INSERT OR REPLACE INTO email_tasks (type_key, recipient, subject, body)
VALUES (:type_key, :recipient, :subject, :body);");
$stmt->bindParam(":recipient", $recipient);
$stmt->bindParam(":type_key", $type_key);
$stmt->bindParam(":subject", $subject);

View File

@ -97,8 +97,6 @@ class AddTrackingAction extends Action
$info = $this->wikipedia->query_person_info([$person_name]);
$normalized_name = $info->redirects[$person_name];
$type = $info->results[$normalized_name]["type"];
$status = $info->results[$normalized_name]["status"];
} catch (WikipediaException $exception) {
throw new UnexpectedException(
"Could not reach Wikipedia. Maybe the website is down?",
@ -115,7 +113,11 @@ class AddTrackingAction extends Action
"Maybe you need to capitalise the surname?",
"person_name"
);
} else if ($type === ArticleType::Disambiguation) {
}
$type = $info->results[$normalized_name]["type"];
$status = $info->results[$normalized_name]["status"];
if ($type === ArticleType::Disambiguation) {
throw new InvalidValueException(
$this->override_message ??
"<b><a href='https://en.wikipedia.org/wiki/" . rawurlencode($normalized_name) . "'>" .
@ -132,10 +134,9 @@ class AddTrackingAction extends Action
htmlentities($normalized_name) . "</a></b> is not about a real-world person.",
"person_name"
);
}
if ($status === null)
} else if ($status === null) {
throw new IllegalStateError("Person page does not have a status.");
}
return [$normalized_name, $status];
}

View File

@ -163,7 +163,7 @@ class NotifyStatusChangedEmail extends Email
/**
* Constructs a new `NotifyStatusChangedEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
* @param string $name the name of the person who died
* @param string $new_status the new status of the person
*/
@ -219,7 +219,7 @@ class NotifyArticleDeletedEmail extends Email
/**
* Constructs a new `NotifyArticleDeletedEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
* @param string $name the name of the article that was deleted
*/
public function __construct(string $recipient, string $name)
@ -274,7 +274,7 @@ class NotifyArticleUndeletedEmail extends Email
/**
* Constructs a new `NotifyArticleUndeletedEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
* @param string $name the name of the article that was re-created
*/
public function __construct(string $recipient, string $name)

View File

@ -112,7 +112,7 @@ class ChangeEmailFromEmail extends Email
/**
* Constructs a new `ChangeEmailFromEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
* @param string $new_email the new email address
*/
public function __construct(string $recipient, string $new_email)
@ -170,7 +170,7 @@ class ChangeEmailToEmail extends Email
/**
* Constructs a new `ChangeEmailEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
* @param string $old_email the old email address
* @param string $token the token to verify the email address with
*/

View File

@ -101,7 +101,7 @@ class ChangePasswordEmail extends Email
/**
* Constructs a new `ChangedPasswordEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
*/
public function __construct(string $recipient)
{

View File

@ -100,7 +100,7 @@ class RegisterEmail extends Email
/**
* Constructs a new `RegisterEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
* @param string $token the token to verify the email address with
*/
public function __construct(string $recipient, string $token)

View File

@ -111,7 +111,7 @@ class ResendVerifyEmailEmail extends Email
/**
* Constructs a new `ResendVerifyEmailEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
* @param string $token the token to verify the email address with
*/
public function __construct(string $recipient, string $token)

View File

@ -105,7 +105,7 @@ class ResetPasswordEmail extends Email
/**
* Constructs a new `ChangedPasswordEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
*/
public function __construct(string $recipient)
{

View File

@ -109,7 +109,7 @@ class SendPasswordResetEmail extends Email
/**
* Constructs a new `ResetPasswordEmail`.
*
* @param string $recipient the intended recipient of the email
* @param string $recipient the intended recipient of this email
* @param string $token the token to reset the password with
*/
public function __construct(string $recipient, string $token)

View File

@ -202,7 +202,7 @@ class Wikipedia
foreach ($output_base->missing as $missing_title) {
$title_after_move = $this->api_query_title_after_move($missing_title);
if ($title_after_move === null)
$not_moved[] = $title_after_move;
$not_moved[] = $missing_title;
else
$moves[$missing_title] = $title_after_move;
}