Make forms look just a little bit better

This commit is contained in:
Florine W. Dekker 2022-12-12 00:03:39 +01:00
parent 12e7437335
commit 44b62d32d0
Signed by: FWDekker
GPG Key ID: D3DCFAA8A4560BE0
8 changed files with 185 additions and 158 deletions

View File

@ -1,7 +1,7 @@
{
"name": "fwdekker/death-notifier",
"description": "Get notified when a famous person dies.",
"version": "0.19.1", "_comment_version": "Also update version in `package.json`!",
"version": "0.19.2", "_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.1", "_comment_version": "Also update version in `composer.json`!",
"version": "0.19.2", "_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

@ -9,6 +9,10 @@ a.red-link {
color: var(--fandom-redlink);
}
.invisible {
opacity: 0;
}
/* Messages */
#global-message,
@ -16,6 +20,11 @@ a.red-link {
margin-bottom: 0;
}
#shared-home-link {
/*noinspection CssUnresolvedCustomProperty*/
margin-top: calc(var(--block-spacing-vertical) / 2);
}
/* Welcome */
#welcome-part {
@ -23,6 +32,32 @@ a.red-link {
}
/* Trackings table forms */
#add-tracking-name-container {
display: flex;
column-gap: .3em;
}
#add-tracking-name,
#add-tracking-submit {
width: unset;
}
#add-tracking-name {
flex-grow: 1;
}
@media (min-width: 992px) {
#filter-trackings-query {
float: right;
}
}
small[data-hint-for="add-tracking-name"] {
display: block;
}
/* Trackings table */
.placeholder {
font-style: italic;

View File

@ -9,7 +9,7 @@
<meta name="theme-color" content="#0033cc" />
<meta name="fwd:nav:target" content="#nav" />
<!-- Remove experimental after release -->
<!-- TODO: Remove experimental after release -->
<meta name="fwd:nav:highlight-path" content="/Tools/Experimental/Death Notifier/" />
<meta name="fwd:footer:target" content="#footer" />
<meta name="fwd:footer:vcs-url" content="https://git.fwdekker.com/tools/death-notifier/" />
@ -53,11 +53,13 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<p id="shared-home-link" class="hidden">
<a href="./">Click here to return to the main page</a>
<a href="./">Click here to return to the main page.</a>
</p>
<div id="welcome-part" class="grid hidden">
<article>
<!-- TODO: Add paragraph explaining what Death Notifier is on main page -->
<!-- TODO: Disable login form after logging in -->
<header>
<hgroup>
<h2>Log in</h2>
@ -71,27 +73,24 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<label for="login-email">Email</label>
<input id="login-email" type="email" name="email" autocomplete="email" />
<small id="login-email-hint" data-hint-for="login-email"></small>
<label for="login-email">Email</label>
<input id="login-email" type="email" name="email" autocomplete="email" />
<small id="login-email-hint" data-hint-for="login-email"></small>
<label for="login-password">Password</label>
<input id="login-password" type="password" name="password"
autocomplete="current-password" />
<small id="login-password-hint" data-hint-for="login-password"></small>
<label for="login-password">Password</label>
<input id="login-password" type="password" name="password"
autocomplete="current-password" />
<small id="login-password-hint" data-hint-for="login-password"></small>
<input type="checkbox" role="switch" id="login-password-toggle" class="password-toggle"
data-toggles="login-password" />
<label for="login-password-toggle">Show password</label>
</fieldset>
<input type="checkbox" role="switch" id="login-password-toggle" class="password-toggle"
data-toggles="login-password" />
<label for="login-password-toggle">Show password</label>
<br /><br />
<fieldset>
<button id="login-submit">Log in</button>
<a role="button" id="forgot-password-go-to" class="outline" href="#">
Forgot password?
</a>
</fieldset>
<button id="login-submit">Log in</button>
<a role="button" id="forgot-password-go-to" class="outline" href="#">
Forgot password?
</a>
</form>
</div>
</article>
@ -115,26 +114,23 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<label for="register-email">Email</label>
<input id="register-email" type="email" name="email" autocomplete="email" />
<small id="register-email-hint" data-hint-for="register-email"></small>
<label for="register-email">Email</label>
<input id="register-email" type="email" name="email" autocomplete="email" />
<small id="register-email-hint" data-hint-for="register-email"></small>
<label for="register-password">Password</label>
<input id="register-password" type="password" name="password"
autocomplete="new-password" />
<small id="register-password-hint" data-hint-for="register-password"
data-hint="Use at least 8 characters."></small>
<label for="register-password">Password</label>
<input id="register-password" type="password" name="password"
autocomplete="new-password" />
<small id="register-password-hint" data-hint-for="register-password"
data-hint="Use at least 8 characters."></small>
<input type="checkbox" role="switch" id="register-password-toggle"
class="password-toggle"
data-toggles="register-password" />
<label for="register-password-toggle">Show password</label>
</fieldset>
<input type="checkbox" role="switch" id="register-password-toggle"
class="password-toggle"
data-toggles="register-password" />
<label for="register-password-toggle">Show password</label>
<br /><br />
<fieldset>
<button id="register-submit">Create account</button>
</fieldset>
<button id="register-submit">Create account</button>
</form>
</div>
</article>
@ -154,16 +150,12 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<label for="send-password-reset-email">Email</label>
<input id="send-password-reset-email" type="email" name="email" autocomplete="email" />
<small id="send-password-reset-email-hint"
data-hint-for="send-password-reset-email"></small>
</fieldset>
<label for="send-password-reset-email">Email</label>
<input id="send-password-reset-email" type="email" name="email" autocomplete="email" />
<small id="send-password-reset-email-hint"
data-hint-for="send-password-reset-email"></small>
<fieldset>
<button id="send-password-reset-submit">Send email</button>
</fieldset>
<button id="send-password-reset-submit">Send email</button>
</form>
<a role="button" id="forgot-password-go-back" class="outline" href="#">Return to log in form</a>
</div>
@ -185,28 +177,25 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<input id="reset-password-token" type="hidden" name="token" />
<input id="reset-password-token" type="hidden" name="token" />
<label for="reset-password-email">Email</label>
<input id="reset-password-email" type="email" name="email" disabled />
<small id="reset-password-email-hint" data-hint-for="reset-password-email"></small>
<label for="reset-password-email">Email</label>
<input id="reset-password-email" type="email" name="email" disabled />
<small id="reset-password-email-hint" data-hint-for="reset-password-email"></small>
<label for="reset-password-password">Password</label>
<input id="reset-password-password" type="password" name="password"
autocomplete="new-password" />
<small id="reset-password-password-hint" data-hint-for="reset-password-password"
data-hint="Use at least 8 characters."></small>
<label for="reset-password-password">Password</label>
<input id="reset-password-password" type="password" name="password"
autocomplete="new-password" />
<small id="reset-password-password-hint" data-hint-for="reset-password-password"
data-hint="Use at least 8 characters."></small>
<input type="checkbox" role="switch" id="reset-password-password-toggle"
class="password-toggle"
data-toggles="reset-password-password" />
<label for="reset-password-password-toggle">Show password</label>
</fieldset>
<input type="checkbox" role="switch" id="reset-password-password-toggle"
class="password-toggle"
data-toggles="reset-password-password" />
<label for="reset-password-password-toggle">Show password</label>
<br /><br />
<fieldset>
<button id="reset-password-submit">Set password</button>
</fieldset>
<button id="reset-password-submit">Set password</button>
</form>
<a role="button" id="reset-password-go-back" class="outline" href="./">Return to log in form</a>
</article>
@ -221,12 +210,27 @@
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<form id="filter-trackings-form" novalidate>
<fieldset>
<article class="status-card hidden" data-status-for="add-tracking-form">
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<div class="grid">
<form id="add-tracking-form" novalidate>
<div id="add-tracking-name-container">
<!--suppress HtmlFormInputWithoutLabel -->
<input id="add-tracking-name" 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>
</form>
<form id="filter-trackings-form" novalidate>
<!-- TODO: Find intuitive way of distinguishing search and add -->
<!--suppress HtmlFormInputWithoutLabel -->
<input id="filter-trackings-query" type="search" name="query" />
</fieldset>
</form>
<input id="filter-trackings-query" type="search" name="query" placeholder="Search" />
</form>
</div>
<div id="trackings-wrapper">
<table id="trackings">
<thead>
@ -238,25 +242,10 @@
</tr>
</thead>
<tbody>
<!-- TODO: Show loading icon while fetching entries -->
<!-- TODO: Show loading icon while fetching entries (and in more places) -->
</tbody>
</table>
</div>
<form id="add-tracking-form" novalidate>
<article class="status-card hidden" data-status-for="add-tracking-form">
<output></output>
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<!-- TODO: Show random suggestions on who to track -->
<label for="add-tracking-name">Track another article</label>
<input id="add-tracking-name" type="text" name="person_name" autocomplete="name" />
<small id="add-tracking-name-hint" data-hint-for="add-tracking-name"></small>
<button id="add-tracking-submit">Add</button>
</fieldset>
</form>
</article>
<div id="settings-part" class="hidden">
@ -270,9 +259,7 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<button id="logoutButton">Log out</button>
</fieldset>
<button id="logoutButton">Log out</button>
</form>
</article>
@ -294,13 +281,11 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<label for="update-email-email">Email address</label>
<input id="update-email-email" type="email" name="email" autocomplete="email" />
<small id="update-email-email-hint" data-hint-for="update-email-email"></small>
<label for="update-email-email">Email address</label>
<input id="update-email-email" type="email" name="email" autocomplete="email" />
<small id="update-email-email-hint" data-hint-for="update-email-email"></small>
<button id="updateEmailButton">Change email</button>
</fieldset>
<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">
@ -308,14 +293,10 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<input type="checkbox" id="email-verified-checkbox" disabled />
<label for="email-verified-checkbox">Verified</label>
</fieldset>
<input type="checkbox" id="email-verified-checkbox" disabled />
<label for="email-verified-checkbox">Verified</label>
<fieldset>
<button id="resend-email-verification-submit" class="hidden">resend link</button>
</fieldset>
<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">
@ -323,10 +304,8 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<input type="checkbox" id="notifications-enabled-checkbox" />
<label for="notifications-enabled-checkbox">Notifications</label>
</fieldset>
<input type="checkbox" id="notifications-enabled-checkbox" />
<label for="notifications-enabled-checkbox">Notifications</label>
</form>
</article>
@ -341,35 +320,31 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<label for="update-password-password-old">Old password</label>
<input id="update-password-password-old" type="password" name="password"
autocomplete="current-password" />
<small id="update-password-password-old-hint"
data-hint-for="update-password-password-old"></small>
<label for="update-password-password-old">Old password</label>
<input id="update-password-password-old" type="password" name="password"
autocomplete="current-password" />
<small id="update-password-password-old-hint"
data-hint-for="update-password-password-old"></small>
<input type="checkbox" role="switch" id="update-password-password-old-toggle"
class="password-toggle"
data-toggles="update-password-password-old" />
<label for="update-password-password-old-toggle">Show password</label>
</fieldset>
<input type="checkbox" role="switch" id="update-password-password-old-toggle"
class="password-toggle"
data-toggles="update-password-password-old" />
<label for="update-password-password-old-toggle">Show password</label>
<br /><br />
<fieldset>
<label for="update-password-password-new">New password</label>
<input id="update-password-password-new" type="password" name="password"
autocomplete="new-password" />
<small id="update-password-password-new-hint" data-hint-for="update-password-password-new"
data-hint="Use at least 8 characters."></small>
<label for="update-password-password-new">New password</label>
<input id="update-password-password-new" type="password" name="password"
autocomplete="new-password" />
<small id="update-password-password-new-hint" data-hint-for="update-password-password-new"
data-hint="Use at least 8 characters."></small>
<input type="checkbox" role="switch" id="update-password-password-new-toggle"
class="password-toggle"
data-toggles="update-password-password-new" />
<label for="update-password-password-new-toggle">Show password</label>
</fieldset>
<input type="checkbox" role="switch" id="update-password-password-new-toggle"
class="password-toggle"
data-toggles="update-password-password-new" />
<label for="update-password-password-new-toggle">Show password</label>
<br /><br />
<fieldset>
<button id="updatePasswordButton">Change password</button>
</fieldset>
<button id="updatePasswordButton">Change password</button>
</form>
<!-- TODO: Add forgot password button after logging in -->
</article>
@ -388,10 +363,8 @@
<a class="close" href="#" aria-label="Close"></a>
</article>
<fieldset>
<input id="delete-email" type="hidden" name="email" />
<button id="delete-button">Delete account</button>
</fieldset>
<input id="delete-email" type="hidden" name="email" />
<button id="delete-button" class="outline">Delete account</button>
</form>
</article>
</div>

View File

@ -19,6 +19,33 @@ const loginHandler = new CustomEventHandler();
const logoutHandler = new CustomEventHandler();
/**
* 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.classList.add("invisible");
spacer.innerText = "&nbsp;";
spacerCell.appendChild(spacer);
row.appendChild(spacerCell);
return row;
}
/**
* Refreshes the list of trackings in the table.
*/
@ -85,7 +112,7 @@ function refreshTrackings(): void {
`Successfully removed <b>${tracking.name}</b>.`
);
}
)
);
});
const deleteButton = document.createElement("button");
deleteButton.innerText = "remove";
@ -96,15 +123,8 @@ function refreshTrackings(): void {
tableBody.appendChild(row);
});
if (response.payload.length === 0) {
const row = document.createElement("tr");
row.classList.add("placeholder");
const cell = document.createElement("td");
cell.colSpan = 3;
cell.innerText = "You haven't added any articles to track yet.";
row.appendChild(cell);
tableBody.appendChild(row);
}
if (response.payload.length === 0)
tableBody.appendChild(createPlaceholderRow("You haven't added any articles to track yet."));
// Scroll to top, re-apply filter
$("#trackings-wrapper").scrollTop = 0;
@ -146,13 +166,16 @@ function refreshUserData(): void {
// Password update time
const today = new Date();
today.setHours(0, 0, 0, 0)
today.setHours(0, 0, 0, 0);
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 + " days ago";
$("#password-last-changed").innerText =
diff === 0
? "today"
: (diff === 1 ? "1 day ago" : diff + " days ago");
}
)
);
}
/**
@ -258,14 +281,14 @@ doAfterLoad(() => {
refreshUserData();
refreshTrackings();
$("#welcome-part").classList.add("hidden")
$("#welcome-part").classList.add("hidden");
$("#tracking-part").classList.remove("hidden");
$("#settings-part").classList.remove("hidden");
});
logoutHandler.addListener(() => {
clearMessageStatus(sharedMessageElement);
$("#welcome-part").classList.remove("hidden")
$("#welcome-part").classList.remove("hidden");
$("#tracking-part").classList.add("hidden");
$("#settings-part").classList.add("hidden");
$("#login-email").focus();
@ -391,7 +414,7 @@ doAfterLoad(() => {
`Your password has been updated. You will be redirected after ${secondsLeft} second(s).`
);
}
)
);
}
);
});
@ -565,13 +588,8 @@ doAfterLoad(() => {
});
if (!foundMatches) {
const row = document.createElement("tr");
const row = createPlaceholderRow("No articles match your query.");
row.id = "trackings-no-matches";
row.classList.add("placeholder");
const cell = document.createElement("td");
cell.colSpan = 3;
cell.innerText = "No articles match your query.";
row.appendChild(cell);
$("#trackings tbody").appendChild(row);
}
});

View File

@ -105,6 +105,7 @@ class UpdateTrackingsAction extends Action
// TODO: Restrict number of notifications to 1 per hour (excluding "oops we're not sure" message)
// TODO: Reuse `stmt`s for listing trackers and queueing emails to reduce overheads
// TODO: Detect renaming vandalism
// TODO: Log noteworthy events in a separate log, including renames, deletions, alive again
foreach ($new_deletions as $new_deletion)
foreach ($this->tracking_list->list_trackers($new_deletion) as $user_email)
$this->mailer->queue_email(new NotifyArticleDeletedEmail($user_email, $new_deletion));