Clean up interface
This commit is contained in:
parent
93c0a6f7e9
commit
debe285cf5
|
@ -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",
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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",
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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."
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue