Upgrade template to v3

This commit is contained in:
Florine W. Dekker 2022-11-22 00:21:32 +01:00
parent ad8bd1e207
commit 5bc5be0564
Signed by: FWDekker
GPG Key ID: D3DCFAA8A4560BE0
6 changed files with 113 additions and 105 deletions

View File

@ -4,7 +4,7 @@ module.exports = grunt => {
grunt.initConfig({ grunt.initConfig({
pkg: grunt.file.readJSON("package.json"), pkg: grunt.file.readJSON("package.json"),
clean: { clean: {
default: ["dist/"], default: ["dist/*", "!dist/.fo76-dumps-ids.db"],
}, },
copy: { copy: {
css: { css: {

BIN
package-lock.json generated

Binary file not shown.

View File

@ -1,7 +1,7 @@
{ {
"name": "random-fo76", "name": "random-fo76",
"version": "1.0.19", "version": "1.0.20",
"description": "Random Fallout 76 record.", "description": "Random Fallout 76 record picker.",
"author": "Florine W. Dekker", "author": "Florine W. Dekker",
"browser": "dist/bundle.js", "browser": "dist/bundle.js",
"repository": { "repository": {
@ -16,15 +16,15 @@
"deploy": "grunt deploy" "deploy": "grunt deploy"
}, },
"devDependencies": { "devDependencies": {
"grunt": "^1.4.1", "grunt": "^1.5.3",
"grunt-cli": "^1.4.3", "grunt-cli": "^1.4.3",
"grunt-contrib-clean": "^2.0.0", "grunt-contrib-clean": "^2.0.1",
"grunt-contrib-copy": "^1.0.0", "grunt-contrib-copy": "^1.0.0",
"grunt-contrib-watch": "^1.1.0", "grunt-contrib-watch": "^1.1.0",
"grunt-focus": "^1.0.0", "grunt-focus": "^1.0.0",
"grunt-text-replace": "^0.4.0", "grunt-text-replace": "^0.4.0",
"grunt-webpack": "^5.0.0", "grunt-webpack": "^5.0.0",
"webpack": "^5.69.1", "webpack": "^5.75.0",
"webpack-cli": "^4.9.2" "webpack-cli": "^5.0.0"
} }
} }

View File

@ -1,7 +1,17 @@
table#metadata {
max-width: 300px;
}
.error { .error {
color: red; color: red;
} }
#signatures {
display: flex;
flex-wrap: wrap;
}
#signatures > div {
flex-basis: 15%;
}
button {
width: unset;
display: inline-block;
}

View File

@ -4,21 +4,27 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="author" content="Florine W. Dekker" /> <meta name="author" content="Florine W. Dekker" />
<meta name="application-name" content="Random Fallout 76 record" /> <meta name="application-name" content="Random Fallout 76 record picker" />
<meta name="description" content="Returns a random Fallout 76 record." /> <meta name="description" content="Returns a random Fallout 76 record." />
<meta name="theme-color" content="#0033cc" /> <meta name="theme-color" content="#0033cc" />
<title>Random Fallout 76 record | FWDekker</title> <meta name="fwd:auto:show-main" />
<meta name="fwd:nav:target" content="#nav" />
<meta name="fwd:nav:highlight-path" content="/Tools/Random FO76/" />
<meta name="fwd:footer:target" content="#footer" />
<meta name="fwd:footer:vcs-url" content="https://git.fwdekker.com/tools/random-fo76/" />
<meta name="fwd:footer:version" content="v%%VERSION_NUMBER%%" />
<link rel="stylesheet" href="https://static.fwdekker.com/fonts/roboto/roboto.css" /> <title>Random Fallout 76 record picker | FWDekker</title>
<link rel="stylesheet" href="https://static.fwdekker.com/lib/template/2.x.x/template.css" />
<link rel="stylesheet" href="https://static.fwdekker.com/lib/template/3.x.x/template.css?v=%%VERSION_NUMBER%%" />
<!--suppress HtmlUnknownTarget --> <!--suppress HtmlUnknownTarget -->
<link rel="stylesheet" href="main.css?v=%%VERSION_NUMBER%%" /> <link rel="stylesheet" href="main.css?v=%%VERSION_NUMBER%%" />
<script async src="https://stats.fwdekker.com/count.js" <script async src="https://stats.fwdekker.com/count.js"
data-goatcounter="https://stats.fwdekker.com/count"></script> data-goatcounter="https://stats.fwdekker.com/count"></script>
</head> </head>
<body> <body>
<noscript> <noscript class="fwd-js-notice">
<img src="https://stats.fwdekker.com/count?p=/tools/random-fo76/" alt="Counting pixel" /> <img src="https://stats.fwdekker.com/count?p=/tools/random-fo76/" alt="Counting pixel" />
<p> <p>
@ -27,46 +33,59 @@
instructions on how to enable JavaScript in your web browser</a>. instructions on how to enable JavaScript in your web browser</a>.
</p> </p>
</noscript> </noscript>
<main class="hidden"> <nav id="nav"></nav>
<div id="nav"></div> <main class="container container-with-aside-right">
<div id="contents"> <div role="document">
<div id="header"></div> <section>
<article>
<header class="fwd-header">
<hgroup>
<h1><a href=".">Random <i>Fallout 76</i> record picker</a></h1>
<h2>
Retrieve a random record from the <i>Fallout 76</i> game files using
<a href="https://github.com/FWDekker/fo76-dumps" target="_blank">my data dumps</a>.
</h2>
</hgroup>
</header>
<table class="metadata">
<tr>
<th>Game version</th>
<td id="game-version" aria-busy="true"></td>
</tr>
<tr>
<th>Dumps version</th>
<td id="dumps-version" aria-busy="true"></td>
</tr>
</table>
</article>
<!-- Metadata --> <article>
<section class="container"> <h2>Pick a record</h2>
<table class="metadata"> <p>Select the signatures that should be included in the random selection.</p>
<tr> <hr />
<th>Game version</th> <br />
<td id="gameVersion">loading...</td>
</tr> <form id="signature-form">
<tr> <button id="signature-toggle" class="outline" type="button">
<th>Dumps version</th> Select all signatures
<td id="dumpsVersion">loading...</td> </button>
</tr> <div id="signatures" aria-busy="true">Loading... please wait.</div>
</table>
</section> <hr />
<br />
<!-- Input --> <button id="submit" type="button">Fetch random record</button>
<section class="container"> </form>
<h2>Settings</h2>
<form id="signatureForm"> <hr />
<button id="signatureToggle" class="button button-outline" type="button">Select all signatures</button> <h2>Record</h2>
<fieldset id="signatures">Loading... please wait.</fieldset> <pre><code id="output">No record has been fetched yet</code></pre>
</article>
<button id="submit" type="button">Fetch random record</button>
</form>
</section>
<!-- Output -->
<section class="container">
<h2>Record</h2>
<pre><code id="output">No record has been fetched yet</code></pre>
</section> </section>
<footer id="footer"></footer>
</div> </div>
<div id="footer"></div>
</main> </main>
<script src="https://static.fwdekker.com/lib/template/2.x.x/template.js"></script> <script src="https://static.fwdekker.com/lib/template/3.x.x/template.js?v=%%VERSION_NUMBER%%"></script>
<!--suppress HtmlUnknownTarget --> <!--suppress HtmlUnknownTarget -->
<script src="bundle.js?v=%%VERSION_NUMBER%%"></script> <script src="bundle.js?v=%%VERSION_NUMBER%%"></script>
</body> </body>

View File

@ -1,9 +1,12 @@
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
const {$, doAfterLoad, footer, header, nav} = window.fwdekker; const {$, $a, doAfterLoad} = window.fwdekker;
/**
* The key to store the selected signatures under in local storage.
* @type {string}
*/
const storageKey = "/tools/random-fo76//selected-signatures"; const storageKey = "/tools/random-fo76//selected-signatures";
const signatureColCount = 8;
/** /**
@ -34,7 +37,7 @@ const fetchFromApi = (query, callback, handle) => {
const getSelectedSignatures = () => { const getSelectedSignatures = () => {
const signatures = []; const signatures = [];
const selectedCheckboxes = document.querySelectorAll("#signatures input:checked"); const selectedCheckboxes = $a("#signatures input:checked");
for (let i = 0; i < selectedCheckboxes.length; i++) { for (let i = 0; i < selectedCheckboxes.length; i++) {
const selectedCheckbox = selectedCheckboxes[i]; const selectedCheckbox = selectedCheckboxes[i];
signatures.push(selectedCheckbox.value); signatures.push(selectedCheckbox.value);
@ -49,7 +52,7 @@ const getSelectedSignatures = () => {
* @param signatures the array of signatures to select * @param signatures the array of signatures to select
*/ */
const setSelectedSignatures = signatures => { const setSelectedSignatures = signatures => {
const checkboxes = document.querySelectorAll("#signatures input"); const checkboxes = $a("#signatures input");
for (let i = 0; i < checkboxes.length; i++) for (let i = 0; i < checkboxes.length; i++)
checkboxes[i].checked = false; checkboxes[i].checked = false;
@ -63,11 +66,11 @@ const setSelectedSignatures = signatures => {
* Selects all signatures. * Selects all signatures.
*/ */
const setAllSignatures = checked => { const setAllSignatures = checked => {
const checkboxes = document.querySelectorAll("#signatures input"); const checkboxes = $a("#signatures input");
for (let i = 0; i < checkboxes.length; i++) for (let i = 0; i < checkboxes.length; i++)
checkboxes[i].checked = checked; checkboxes[i].checked = checked; // Does not invoke callback
saveSelectedSignaturesToStorage();
saveSelectedSignaturesToStorage();
updateSignatureToggle(); updateSignatureToggle();
}; };
@ -76,11 +79,7 @@ const setAllSignatures = checked => {
*/ */
const loadSelectedSignaturesFromStorage = () => { const loadSelectedSignaturesFromStorage = () => {
const item = localStorage.getItem(storageKey); const item = localStorage.getItem(storageKey);
let signatures; const signatures = (item == null || item.trim() === "") ? [] : item.split(",");
if (item === null)
signatures = [];
else
signatures = item.split(",");
setSelectedSignatures(signatures); setSelectedSignatures(signatures);
}; };
@ -94,9 +93,9 @@ const saveSelectedSignaturesToStorage = () => localStorage.setItem(storageKey, g
* Updates the button used to toggle all signatures on or off. * Updates the button used to toggle all signatures on or off.
*/ */
const updateSignatureToggle = () => { const updateSignatureToggle = () => {
const signatureToggle = $("#signatureToggle"); const signatureToggle = $("#signature-toggle");
if (getSelectedSignatures().length === document.querySelectorAll("#signatures input").length) { if (getSelectedSignatures().length === $a("#signatures input").length) {
signatureToggle.innerHTML = "Deselect all signatures"; signatureToggle.innerHTML = "Deselect all signatures";
signatureToggle.addEventListener("click", () => setAllSignatures(false)); signatureToggle.addEventListener("click", () => setAllSignatures(false));
} else { } else {
@ -115,25 +114,10 @@ const createSignatureButtons = signatures => {
const form = $("#signatures"); const form = $("#signatures");
form.innerHTML = ""; form.innerHTML = "";
let row;
for (let i = 0; i < signatures.length; i++) { for (let i = 0; i < signatures.length; i++) {
const signature = signatures[i]; const signature = signatures[i];
if (i % signatureColCount === 0) { const cell = document.createElement("div");
if (row !== undefined)
form.appendChild(row);
row = document.createElement("div");
row.className = "row";
}
const col = document.createElement("div");
col.className = "column";
const label = document.createElement("label");
label.htmlFor = `signature-${signature}`;
label.innerHTML = signature;
col.appendChild(label);
const checkbox = document.createElement("input"); const checkbox = document.createElement("input");
checkbox.type = "checkbox"; checkbox.type = "checkbox";
@ -144,12 +128,15 @@ const createSignatureButtons = signatures => {
updateSignatureToggle(); updateSignatureToggle();
saveSelectedSignaturesToStorage(); saveSelectedSignaturesToStorage();
}); });
col.appendChild(checkbox); cell.appendChild(checkbox);
row.appendChild(col); const label = document.createElement("label");
label.htmlFor = `signature-${signature}`;
label.innerHTML = signature;
cell.appendChild(label);
form.appendChild(cell);
} }
if (row !== undefined)
form.appendChild(row);
}; };
/** /**
@ -165,37 +152,29 @@ const showRecord = (record) => {
}; };
// Apply template
doAfterLoad(() => {
$("#nav").appendChild(nav("/Tools/Random FO76/"));
$("#header").appendChild(header({
title: "Random Fallout 76 record",
description: "" +
"Retrieve a random record from the <i>Fallout 76</i> game files using " +
"<a href=\"https://github.com/FWDekker/fo76-dumps\">&#9099;&nbsp;my data dumps</a>"
}));
$("#footer").appendChild(footer({
vcsURL: "https://git.fwdekker.com/tools/random-fo76/",
version: "v%%VERSION_NUMBER%%"
}));
$("main").classList.remove("hidden");
});
// Load page from API // Load page from API
doAfterLoad(() => { doAfterLoad(() => {
const gameVersion = $("#game-version");
const dumpsVersion = $("#dumps-version");
fetchFromApi("action=get-meta", fetchFromApi("action=get-meta",
meta => { meta => {
$("#gameVersion").innerHTML = meta["game_version"]; gameVersion.innerHTML = meta["game_version"];
$("#dumpsVersion").innerHTML = meta["dumps_version"]; gameVersion.removeAttribute("aria-busy");
dumpsVersion.innerHTML = meta["dumps_version"];
dumpsVersion.removeAttribute("aria-busy");
}, },
() => { () => {
$("#gameVersion").innerHTML = "Error"; gameVersion.innerHTML = "Error";
$("#dumpsVersion").innerHTML = "Error"; gameVersion.removeAttribute("aria-busy");
dumpsVersion.innerHTML = "Error";
dumpsVersion.removeAttribute("aria-busy");
} }
); );
fetchFromApi("action=list-signatures", fetchFromApi("action=list-signatures",
signatures => { signatures => {
$("#signatures").removeAttribute("aria-busy");
createSignatureButtons(signatures); createSignatureButtons(signatures);
loadSelectedSignaturesFromStorage(); loadSelectedSignaturesFromStorage();
}, },