Refine resource loader status grouping and PDF import handling
All checks were successful
Build Org Website / build (push) Successful in 39s

This commit is contained in:
gitea-actions
2026-08-19 15:36:00 +01:00
parent b8bb1944dd
commit 8dbeca7570
11 changed files with 173 additions and 91 deletions

View File

@@ -23,6 +23,15 @@
pdfUrls: new Map(), pdfUrls: new Map(),
thumbnailUrls: new Map(), thumbnailUrls: new Map(),
}; };
let pdfJsPromise;
const STATUS_GROUPS = [
{ id: "active", label: "In progress", description: "Resources you are actively reading or watching." },
{ id: "backlog", label: "Backlog", description: "Resources you intend to start later." },
{ id: "shelf", label: "On the shelf", description: "Resources kept close at hand, but not currently active." },
{ id: "completed", label: "Completed", description: "Resources you have finished." },
{ id: "archived", label: "Archived", description: "Resources retained outside your current library flow." },
];
const els = { const els = {
vaultSelect: $("#rl-vault-select"), vaultSelect: $("#rl-vault-select"),
@@ -217,7 +226,7 @@
const progress = Model.progressFor(resource); const progress = Model.progressFor(resource);
const initial = (resource.title || "?").trim().charAt(0).toUpperCase(); const initial = (resource.title || "?").trim().charAt(0).toUpperCase();
const creators = (resource.creators || []).join(", ") || "Unknown creator"; const creators = (resource.creators || []).join(", ") || "Unknown creator";
return `<article class="rl-resource-card" tabindex="0" role="button" data-resource-id="${escapeHtml(resource.id)}" aria-label="Open ${escapeHtml(resource.title)}"> return `<article class="rl-resource-card rl-resource-card--${escapeHtml(resource.status)}" tabindex="0" role="button" data-resource-id="${escapeHtml(resource.id)}" aria-label="Open ${escapeHtml(resource.title)}">
<span class="rl-resource-cover" data-thumb="${escapeHtml(resource.thumbnailId || "")}">${escapeHtml(initial)}</span> <span class="rl-resource-cover" data-thumb="${escapeHtml(resource.thumbnailId || "")}">${escapeHtml(initial)}</span>
<span class="rl-resource-title"><strong>${escapeHtml(resource.title)}</strong><small>${escapeHtml(creators)}</small><small>${escapeHtml((resource.tags || []).slice(0, 3).join(" · "))}</small></span> <span class="rl-resource-title"><strong>${escapeHtml(resource.title)}</strong><small>${escapeHtml(creators)}</small><small>${escapeHtml((resource.tags || []).slice(0, 3).join(" · "))}</small></span>
<span class="rl-badges"><span class="rl-badge">${escapeHtml(resource.type)}</span><span class="rl-badge">${escapeHtml(resource.status)}</span><span class="rl-badge">${escapeHtml(resource.format)}</span></span> <span class="rl-badges"><span class="rl-badge">${escapeHtml(resource.type)}</span><span class="rl-badge">${escapeHtml(resource.status)}</span><span class="rl-badge">${escapeHtml(resource.format)}</span></span>
@@ -226,6 +235,19 @@
</article>`; </article>`;
} }
function statusGroupMarkup(group, resources) {
const headingId = `rl-status-${group.id}`;
const countLabel = `${resources.length} ${resources.length === 1 ? "resource" : "resources"}`;
return `<section class="rl-status-group rl-status-group--${group.id}" aria-labelledby="${headingId}">
<header class="rl-status-group__head">
<span class="rl-status-group__marker" aria-hidden="true"></span>
<span class="rl-status-group__title"><strong id="${headingId}">${escapeHtml(group.label)}</strong><small>${escapeHtml(group.description)}</small></span>
<span class="rl-status-group__count" aria-label="${countLabel}">${resources.length}</span>
</header>
<div class="rl-status-resources">${resources.map(cardMarkup).join("")}</div>
</section>`;
}
async function hydrateThumbnails(container) { async function hydrateThumbnails(container) {
const targets = Array.from(container.querySelectorAll("[data-thumb]")).filter((item) => item.dataset.thumb); const targets = Array.from(container.querySelectorAll("[data-thumb]")).filter((item) => item.dataset.thumb);
await Promise.all(targets.map(async (target) => { await Promise.all(targets.map(async (target) => {
@@ -260,7 +282,10 @@
els.resourceList.querySelector("[data-empty-add]").addEventListener("click", () => openResourceDialog()); els.resourceList.querySelector("[data-empty-add]").addEventListener("click", () => openResourceDialog());
return; return;
} }
els.resourceList.innerHTML = resources.map(cardMarkup).join(""); els.resourceList.innerHTML = STATUS_GROUPS.map((group) => {
const matching = resources.filter((resource) => resource.status === group.id);
return matching.length ? statusGroupMarkup(group, matching) : "";
}).join("");
bindResourceCards(); bindResourceCards();
hydrateThumbnails(els.resourceList); hydrateThumbnails(els.resourceList);
} }
@@ -291,6 +316,20 @@
$("#rl-cover-preview").innerHTML = "<span>Cover</span>"; $("#rl-cover-preview").innerHTML = "<span>Cover</span>";
} }
function updateResourceFormForType() {
const type = $("#rl-field-type").value;
const isBook = type === "book";
els.resourceDialog.classList.toggle("is-compact", !isBook);
els.resourceDialog.querySelectorAll("[data-resource-types]").forEach((element) => {
element.hidden = !element.dataset.resourceTypes.split(/\s+/).includes(type);
});
$("#rl-creators-label").textContent = type === "video" ? "Presenter / creator" : "Author(s)";
$("#rl-publisher-label").textContent = type === "video" ? "Channel" : "Publisher";
if (!isBook) $("#rl-field-format").value = "web";
if (!isBook) $("#rl-field-pages").value = "";
if (type !== "video") $("#rl-field-duration").value = "";
}
async function showCover(id) { async function showCover(id) {
resetCover(); resetCover();
const url = await thumbnailUrl(id); const url = await thumbnailUrl(id);
@@ -341,6 +380,7 @@
setValue("rl-field-tags", item && (item.tags || []).join(", ")); setValue("rl-field-tags", item && (item.tags || []).join(", "));
setValue("rl-field-description", item && item.description); setValue("rl-field-description", item && item.description);
setValue("rl-field-notes", item && item.notes); setValue("rl-field-notes", item && item.notes);
updateResourceFormForType();
populateFolderField(item && item.folderId ? item.folderId : (!["all", "unfiled"].includes(state.folderId) ? state.folderId : "")); populateFolderField(item && item.folderId ? item.folderId : (!["all", "unfiled"].includes(state.folderId) ? state.folderId : ""));
$("#rl-delete-resource").hidden = !resource; $("#rl-delete-resource").hidden = !resource;
$("#rl-open-resource").hidden = !(item && (item.url || item.attachmentId)); $("#rl-open-resource").hidden = !(item && (item.url || item.attachmentId));
@@ -597,6 +637,20 @@
return new Promise((resolve) => canvas.toBlob(resolve, "image/jpeg", .78)); return new Promise((resolve) => canvas.toBlob(resolve, "image/jpeg", .78));
} }
function loadPdfJs() {
if (globalThis.pdfjsLib) return Promise.resolve(globalThis.pdfjsLib);
if (pdfJsPromise) return pdfJsPromise;
pdfJsPromise = new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = "/assets/scripts/vendor/pdf.min.js";
script.async = true;
script.onload = () => globalThis.pdfjsLib ? resolve(globalThis.pdfjsLib) : reject(new Error("PDF.js loaded without exposing its API."));
script.onerror = () => reject(new Error("The local PDF.js library could not be loaded."));
document.head.appendChild(script);
});
return pdfJsPromise;
}
async function importPdf(file) { async function importPdf(file) {
if (!file || (file.type && file.type !== "application/pdf") || !file.name.toLowerCase().endsWith(".pdf")) { if (!file || (file.type && file.type !== "application/pdf") || !file.name.toLowerCase().endsWith(".pdf")) {
toast("Choose a PDF file.", true); return; toast("Choose a PDF file.", true); return;
@@ -605,8 +659,8 @@
let attachmentId; let attachmentId;
let thumbnailId; let thumbnailId;
try { try {
const pdfjs = await import("/assets/scripts/vendor/pdf.min.mjs"); const pdfjs = await loadPdfJs();
pdfjs.GlobalWorkerOptions.workerSrc = "/assets/scripts/vendor/pdf.worker.min.mjs"; pdfjs.GlobalWorkerOptions.workerSrc = "/assets/scripts/vendor/pdf.worker.min.js";
const bytes = new Uint8Array(await file.arrayBuffer()); const bytes = new Uint8Array(await file.arrayBuffer());
const documentTask = pdfjs.getDocument({ data: bytes }); const documentTask = pdfjs.getDocument({ data: bytes });
const pdf = await documentTask.promise; const pdf = await documentTask.promise;
@@ -638,7 +692,8 @@
if (attachmentId) await deleteAttachment(attachmentId).catch(() => {}); if (attachmentId) await deleteAttachment(attachmentId).catch(() => {});
if (thumbnailId) await deleteAttachment(thumbnailId).catch(() => {}); if (thumbnailId) await deleteAttachment(thumbnailId).catch(() => {});
const reason = error && error.name === "PasswordException" ? "The PDF is password protected." : error && error.name === "QuotaExceededError" ? "Browser storage is full." : "The PDF could not be read."; const reason = error && error.name === "PasswordException" ? "The PDF is password protected." : error && error.name === "QuotaExceededError" ? "Browser storage is full." : "The PDF could not be read.";
toast(`${reason} No resource was created.`, true); const detail = error && error.message ? ` ${error.message}` : "";
toast(`${reason}${detail} No resource was created.`, true);
console.error(error); console.error(error);
} finally { } finally {
els.pdfInput.value = ""; els.pdfInput.value = "";
@@ -687,6 +742,7 @@
$("#rl-delete-resource").addEventListener("click", removeResource); $("#rl-delete-resource").addEventListener("click", removeResource);
$("#rl-open-resource").addEventListener("click", openLinkedResource); $("#rl-open-resource").addEventListener("click", openLinkedResource);
$("#rl-add-session").addEventListener("click", openSessionDialog); $("#rl-add-session").addEventListener("click", openSessionDialog);
$("#rl-field-type").addEventListener("change", updateResourceFormForType);
$("#rl-session-form").addEventListener("submit", saveSession); $("#rl-session-form").addEventListener("submit", saveSession);
$("#rl-name-form").addEventListener("submit", submitName); $("#rl-name-form").addEventListener("submit", submitName);
$("#rl-name-delete").addEventListener("click", deleteNamedFolder); $("#rl-name-delete").addEventListener("click", deleteNamedFolder);

22
assets/scripts/vendor/pdf.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

22
assets/scripts/vendor/pdf.worker.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -236,14 +236,44 @@
.rl-filters select, .rl-filters select,
.rl-vault-picker select { width: 100%; min-height: 2.65rem; padding: .55rem .7rem; } .rl-vault-picker select { width: 100%; min-height: 2.65rem; padding: .55rem .7rem; }
.rl-resource-list { display: grid; gap: .6rem; } .rl-resource-list { display: grid; gap: 1.15rem; min-width: 0; }
.rl-resource-list.is-grid { grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr)); } .rl-status-group {
--rl-status-colour: var(--rl-accent);
min-width: 0;
overflow: hidden;
border: 1px solid var(--rl-line);
border-radius: 14px;
background: color-mix(in oklab, var(--surface) 94%, var(--rl-status-colour) 6%);
}
.rl-status-group--active { --rl-status-colour: #3f7f5d; }
.rl-status-group--backlog { --rl-status-colour: #9b6b43; }
.rl-status-group--shelf { --rl-status-colour: #52769a; }
.rl-status-group--completed { --rl-status-colour: #7162a2; }
.rl-status-group--archived { --rl-status-colour: #77736d; }
.rl-status-group__head {
display: grid;
grid-template-columns: .7rem minmax(0, 1fr) auto;
align-items: center;
gap: .7rem;
padding: .75rem .85rem;
border-bottom: 1px solid var(--rl-line);
background: color-mix(in oklab, var(--surface) 82%, var(--rl-status-colour) 18%);
}
.rl-status-group__marker { width: .62rem; height: .62rem; border-radius: 50%; background: var(--rl-status-colour); box-shadow: 0 0 0 4px color-mix(in oklab, var(--rl-status-colour) 18%, transparent); }
.rl-status-group__title { min-width: 0; }
.rl-status-group__title strong { display: block; color: var(--heading); font-family: Georgia, serif; font-size: 1rem; }
.rl-status-group__title small { display: block; margin-top: .12rem; overflow: hidden; color: var(--rl-muted); font-size: .72rem; text-overflow: ellipsis; white-space: nowrap; }
.rl-status-group__count { min-width: 1.75rem; padding: .18rem .45rem; border-radius: 999px; color: var(--heading); background: color-mix(in oklab, var(--surface) 76%, transparent); font-size: .72rem; font-weight: 850; text-align: center; }
.rl-status-resources { display: grid; gap: .6rem; min-width: 0; padding: .65rem; }
.rl-resource-list.is-grid .rl-status-resources { grid-template-columns: repeat(auto-fit, minmax(min(13.5rem, 100%), 1fr)); }
.rl-resource-card { .rl-resource-card {
box-sizing: border-box;
display: grid; display: grid;
grid-template-columns: 3.5rem minmax(0, 1.25fr) minmax(8rem, .8fr) minmax(8rem, .65fr) auto; grid-template-columns: 3.5rem minmax(0, 1.25fr) minmax(8rem, .8fr) minmax(8rem, .65fr) auto;
align-items: center; align-items: center;
gap: .9rem; gap: .9rem;
min-width: 0;
width: 100%; width: 100%;
padding: .65rem; padding: .65rem;
border: 1px solid var(--rl-line); border: 1px solid var(--rl-line);
@@ -254,6 +284,7 @@
text-align: left; text-align: left;
cursor: pointer; cursor: pointer;
} }
.rl-resource-card > * { min-width: 0; }
.rl-resource-card:hover { transform: translateY(-1px); border-color: var(--rl-accent); } .rl-resource-card:hover { transform: translateY(-1px); border-color: var(--rl-accent); }
.rl-resource-cover { .rl-resource-cover {
display: grid; display: grid;
@@ -281,7 +312,7 @@
.rl-progress small { display: block; margin-top: .3rem; color: var(--rl-muted); font-size: .7rem; text-align: right; } .rl-progress small { display: block; margin-top: .3rem; color: var(--rl-muted); font-size: .7rem; text-align: right; }
.rl-card-arrow { color: var(--rl-muted); font-size: 1.2rem; } .rl-card-arrow { color: var(--rl-muted); font-size: 1.2rem; }
.rl-resource-list.is-grid .rl-resource-card { grid-template-columns: 3.8rem minmax(0, 1fr); align-items: start; min-height: 9rem; } .rl-resource-list.is-grid .rl-resource-card { grid-template-columns: 3.8rem minmax(0, 1fr); align-items: start; min-height: 9rem; height: auto; }
.rl-resource-list.is-grid .rl-badges, .rl-resource-list.is-grid .rl-badges,
.rl-resource-list.is-grid .rl-progress { grid-column: 1 / -1; } .rl-resource-list.is-grid .rl-progress { grid-column: 1 / -1; }
.rl-resource-list.is-grid .rl-card-arrow { display: none; } .rl-resource-list.is-grid .rl-card-arrow { display: none; }
@@ -305,6 +336,9 @@
.rl-danger { color: #a12d2d !important; border-color: color-mix(in oklab, #a12d2d 45%, var(--rl-line)) !important; } .rl-danger { color: #a12d2d !important; border-color: color-mix(in oklab, #a12d2d 45%, var(--rl-line)) !important; }
.rl-resource-dialog .rl-dialog__body { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: 1.2rem; } .rl-resource-dialog .rl-dialog__body { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: 1.2rem; }
.rl-resource-dialog.is-compact { width: min(46rem, calc(100% - 2rem)); }
.rl-resource-dialog.is-compact .rl-dialog__body { grid-template-columns: minmax(0, 1fr); }
.rl-resource-dialog.is-compact .rl-form-grid { max-width: 42rem; width: 100%; margin-inline: auto; }
.rl-cover-preview { display: grid; place-items: center; align-self: start; aspect-ratio: 3/4; overflow: hidden; border: 1px solid var(--rl-line); border-radius: 10px; color: var(--rl-muted); background: var(--rl-paper-deep); font-family: Georgia, serif; } .rl-cover-preview { display: grid; place-items: center; align-self: start; aspect-ratio: 3/4; overflow: hidden; border: 1px solid var(--rl-line); border-radius: 10px; color: var(--rl-muted); background: var(--rl-paper-deep); font-family: Georgia, serif; }
.rl-cover-preview img { width: 100%; height: 100%; object-fit: cover; } .rl-cover-preview img { width: 100%; height: 100%; object-fit: cover; }
.rl-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .85rem; } .rl-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .85rem; }
@@ -363,7 +397,8 @@
.rl-library__toolbar { align-items: flex-start; } .rl-library__toolbar { align-items: flex-start; }
.rl-filters { grid-template-columns: 1fr; } .rl-filters { grid-template-columns: 1fr; }
.rl-search { grid-column: auto; } .rl-search { grid-column: auto; }
.rl-resource-list.is-grid { grid-template-columns: 1fr; } .rl-resource-list.is-grid .rl-status-resources { grid-template-columns: 1fr; }
.rl-status-group__title small { white-space: normal; }
.rl-resource-card { grid-template-columns: 3.5rem minmax(0, 1fr); } .rl-resource-card { grid-template-columns: 3.5rem minmax(0, 1fr); }
.rl-resource-card .rl-badges, .rl-resource-card .rl-badges,
.rl-resource-card .rl-progress { grid-column: 1 / -1; } .rl-resource-card .rl-progress { grid-column: 1 / -1; }

View File

@@ -913,3 +913,9 @@ at <ScriptBlock>, /home/zaine/master-folder/org-platform/org_web/build-logs/gite
2026-08-19T12:04:11.2002015+01:00 [INFO] Running authoring server tests with /home/zaine/master-folder/org-platform/authoring-service/.venv/bin/python. 2026-08-19T12:04:11.2002015+01:00 [INFO] Running authoring server tests with /home/zaine/master-folder/org-platform/authoring-service/.venv/bin/python.
2026-08-19T12:04:11.2739438+01:00 [INFO] Authoring server tests passed: ran=0, failures=0, errors=0, skipped=0, exit=0 2026-08-19T12:04:11.2739438+01:00 [INFO] Authoring server tests passed: ran=0, failures=0, errors=0, skipped=0, exit=0
2026-08-19T12:04:11.5577806+01:00 [INFO] Sent authoring server test notification. 2026-08-19T12:04:11.5577806+01:00 [INFO] Sent authoring server test notification.
2026-08-19T15:04:23.4595909+01:00 [INFO] Prepared current build status for zaine/org_web: severity=Info, status=success
2026-08-19T15:04:23.4912190+01:00 [INFO] Fetching recent Gitea Actions runs for zaine/org_web.
2026-08-19T15:04:24.7931457+01:00 [INFO] Sent build status notification with 1 embed(s).
2026-08-19T15:04:24.8154673+01:00 [INFO] Running authoring server tests with /home/zaine/master-folder/org-platform/authoring-service/.venv/bin/python.
2026-08-19T15:04:24.9273258+01:00 [INFO] Authoring server tests passed: ran=0, failures=0, errors=0, skipped=0, exit=0
2026-08-19T15:04:25.2285917+01:00 [INFO] Sent authoring server test notification.

View File

@@ -31,7 +31,7 @@
("org-assets" ("org-assets"
:base-directory ,(site-path "assets/") :base-directory ,(site-path "assets/")
:base-extension "css\\|js\\|mjs\\|txt\\|png\\|jpg\\|jpeg\\|gif\\|webp\\|svg\\|pdf\\|mp4\\|webm\\|mov\\|ogg\\|wav\\|woff\\|woff2\\|ttf" :base-extension "css\\|js\\|txt\\|png\\|jpg\\|jpeg\\|gif\\|webp\\|svg\\|pdf\\|mp4\\|webm\\|mov\\|ogg\\|wav\\|woff\\|woff2\\|ttf"
:publishing-directory ,(output-path "assets/") :publishing-directory ,(output-path "assets/")
:recursive t :recursive t
:publishing-function org-publish-attachment) :publishing-function org-publish-attachment)

View File

@@ -4,7 +4,7 @@
See the categories: @@html:<a href="../home/categories.html">Categories</a>@@ See the categories: @@html:<a href="../home/categories.html">Categories</a>@@
* Posts: * Posts:
- [[file:career/career-list.org][Career List]] @@html:<span class="post-date">19-08-2026 12:47</span>@@ - [[file:career/career-list.org][Career List]] @@html:<span class="post-date">19-08-2026 15:31</span>@@
- [[file:career/cross-site-scripting-xss.org][Cross-Site Scripting (XSS)]] @@html:<span class="post-date">01-06-2026 10:21</span>@@ @@html:<a href="/tags/learning.html"><span class="post-tag">learning</span></a>@@ @@html:<a href="/tags/notes.html"><span class="post-tag">notes</span></a>@@ - [[file:career/cross-site-scripting-xss.org][Cross-Site Scripting (XSS)]] @@html:<span class="post-date">01-06-2026 10:21</span>@@ @@html:<a href="/tags/learning.html"><span class="post-tag">learning</span></a>@@ @@html:<a href="/tags/notes.html"><span class="post-tag">notes</span></a>@@
- [[file:career/ha-dr.org][High Availability, Disaster Recovery and Business Continuity]] @@html:<span class="post-date">11-03-2026 17:18</span>@@ @@html:<a href="/tags/learning.html"><span class="post-tag">learning</span></a>@@ @@html:<a href="/tags/notes.html"><span class="post-tag">notes</span></a>@@ - [[file:career/ha-dr.org][High Availability, Disaster Recovery and Business Continuity]] @@html:<span class="post-date">11-03-2026 17:18</span>@@ @@html:<a href="/tags/learning.html"><span class="post-tag">learning</span></a>@@ @@html:<a href="/tags/notes.html"><span class="post-tag">notes</span></a>@@
- [[file:career/javascript.org][Understands the Javascript language]] @@html:<span class="post-date">11-03-2026 16:52</span>@@ @@html:<a href="/tags/learning.html"><span class="post-tag">learning</span></a>@@ @@html:<a href="/tags/notes.html"><span class="post-tag">notes</span></a>@@ - [[file:career/javascript.org][Understands the Javascript language]] @@html:<span class="post-date">11-03-2026 16:52</span>@@ @@html:<a href="/tags/learning.html"><span class="post-tag">learning</span></a>@@ @@html:<a href="/tags/notes.html"><span class="post-tag">notes</span></a>@@

View File

@@ -94,21 +94,21 @@
<input type="hidden" id="rl-resource-id" /> <input type="hidden" id="rl-resource-id" />
<input type="hidden" id="rl-attachment-id" /> <input type="hidden" id="rl-attachment-id" />
<input type="hidden" id="rl-thumbnail-id" /> <input type="hidden" id="rl-thumbnail-id" />
<div class="rl-cover-preview" id="rl-cover-preview" aria-label="Cover preview"><span>Cover</span></div> <div class="rl-cover-preview" id="rl-cover-preview" data-resource-types="book" aria-label="Cover preview"><span>Cover</span></div>
<div class="rl-form-grid"> <div class="rl-form-grid">
<label class="rl-field rl-field--wide">Title <input id="rl-field-title" required maxlength="300" /></label> <label class="rl-field rl-field--wide">Title <input id="rl-field-title" required maxlength="300" /></label>
<label class="rl-field rl-field--wide">Creators <input id="rl-field-creators" placeholder="Separate names with commas" /></label> <label class="rl-field rl-field--wide"><span id="rl-creators-label">Creators</span><input id="rl-field-creators" placeholder="Separate names with commas" /></label>
<label class="rl-field">Type <select id="rl-field-type"><option value="book">Book</option><option value="article">Article</option><option value="video">Video</option></select></label> <label class="rl-field">Type <select id="rl-field-type"><option value="book">Book</option><option value="article">Article</option><option value="video">Video</option></select></label>
<label class="rl-field">Format <select id="rl-field-format"><option value="physical">Physical</option><option value="pdf">PDF</option><option value="web">Web</option></select></label> <label class="rl-field" data-resource-types="book">Format <select id="rl-field-format"><option value="physical">Physical</option><option value="pdf">PDF</option><option value="web">Web</option></select></label>
<label class="rl-field">Status <select id="rl-field-status"><option value="backlog">Backlog</option><option value="shelf">Shelf</option><option value="active">Active</option><option value="completed">Completed</option><option value="archived">Archived</option></select></label> <label class="rl-field">Status <select id="rl-field-status"><option value="backlog">Backlog</option><option value="shelf">Shelf</option><option value="active">Active</option><option value="completed">Completed</option><option value="archived">Archived</option></select></label>
<label class="rl-field">Folder <select id="rl-field-folder"><option value="">Unfiled</option></select></label> <label class="rl-field">Folder <select id="rl-field-folder"><option value="">Unfiled</option></select></label>
<label class="rl-field">Pages <input id="rl-field-pages" type="number" min="0" inputmode="numeric" /></label> <label class="rl-field" data-resource-types="book">Pages <input id="rl-field-pages" type="number" min="0" inputmode="numeric" /></label>
<label class="rl-field">Duration (minutes) <input id="rl-field-duration" type="number" min="0" inputmode="numeric" /></label> <label class="rl-field" data-resource-types="video">Duration (minutes) <input id="rl-field-duration" type="number" min="0" inputmode="numeric" /></label>
<label class="rl-field rl-field--wide">URL <input id="rl-field-url" type="url" placeholder="https://…" /></label> <label class="rl-field rl-field--wide">URL <input id="rl-field-url" type="url" placeholder="https://…" /></label>
<label class="rl-field">Publisher / channel <input id="rl-field-publisher" /></label> <label class="rl-field"><span id="rl-publisher-label">Publisher / channel</span><input id="rl-field-publisher" /></label>
<label class="rl-field">Published <input id="rl-field-published" placeholder="Year or date" /></label> <label class="rl-field">Published <input id="rl-field-published" placeholder="Year or date" /></label>
<label class="rl-field rl-field--wide">Tags <input id="rl-field-tags" placeholder="Separate tags with commas" /></label> <label class="rl-field rl-field--wide">Tags <input id="rl-field-tags" placeholder="Separate tags with commas" /></label>
<label class="rl-field rl-field--wide">Description <textarea id="rl-field-description" rows="3"></textarea></label> <label class="rl-field rl-field--wide" data-resource-types="book">Description <textarea id="rl-field-description" rows="3"></textarea></label>
<label class="rl-field rl-field--wide">Notes <textarea id="rl-field-notes" rows="4"></textarea></label> <label class="rl-field rl-field--wide">Notes <textarea id="rl-field-notes" rows="4"></textarea></label>
</div> </div>
<section class="rl-sessions" id="rl-session-section" hidden> <section class="rl-sessions" id="rl-session-section" hidden>

View File

@@ -80,17 +80,17 @@ flowchart TD
n30 --> n37 n30 --> n37
n38["Tag: life"] n38["Tag: life"]
n30 --> n38 n30 --> n38
n39["Tag: education"] n39["Tag: update"]
n30 --> n39 n30 --> n39
n40["Tag: update"] n40["Tag: insights"]
n30 --> n40 n30 --> n40
n41["Tag: insights"] n41["Tag: emacs"]
n30 --> n41 n30 --> n41
n42["Tag: emacs"] n42["Tag: education"]
n30 --> n42 n30 --> n42
n43["Tag: maths"] n43["Tag: reading"]
n30 --> n43 n30 --> n43
n44["Tag: reading"] n44["Tag: maths"]
n30 --> n44 n30 --> n44
n45{{"posts"}} n45{{"posts"}}
root --> n45 root --> n45
@@ -212,12 +212,12 @@ flowchart TD
click n36 "tags/review.html" "Tag: review" click n36 "tags/review.html" "Tag: review"
click n37 "tags/website.html" "Tag: website" click n37 "tags/website.html" "Tag: website"
click n38 "tags/life.html" "Tag: life" click n38 "tags/life.html" "Tag: life"
click n39 "tags/education.html" "Tag: education" click n39 "tags/update.html" "Tag: update"
click n40 "tags/update.html" "Tag: update" click n40 "tags/insights.html" "Tag: insights"
click n41 "tags/insights.html" "Tag: insights" click n41 "tags/emacs.html" "Tag: emacs"
click n42 "tags/emacs.html" "Tag: emacs" click n42 "tags/education.html" "Tag: education"
click n43 "tags/maths.html" "Tag: maths" click n43 "tags/reading.html" "Tag: reading"
click n44 "tags/reading.html" "Tag: reading" click n44 "tags/maths.html" "Tag: maths"
click n46 "posts/posts-intro.html" "Posts Introduction" click n46 "posts/posts-intro.html" "Posts Introduction"
click n47 "posts/posts-list.html" "Posts List" click n47 "posts/posts-list.html" "Posts List"
click n49 "posts/career/solid-principles.html" "SOLID Principles" click n49 "posts/career/solid-principles.html" "SOLID Principles"
@@ -302,12 +302,12 @@ flowchart TD
- [[file:tags/review.org][Tag: review]] - [[file:tags/review.org][Tag: review]]
- [[file:tags/website.org][Tag: website]] - [[file:tags/website.org][Tag: website]]
- [[file:tags/life.org][Tag: life]] - [[file:tags/life.org][Tag: life]]
- [[file:tags/education.org][Tag: education]]
- [[file:tags/update.org][Tag: update]] - [[file:tags/update.org][Tag: update]]
- [[file:tags/insights.org][Tag: insights]] - [[file:tags/insights.org][Tag: insights]]
- [[file:tags/emacs.org][Tag: emacs]] - [[file:tags/emacs.org][Tag: emacs]]
- [[file:tags/maths.org][Tag: maths]] - [[file:tags/education.org][Tag: education]]
- [[file:tags/reading.org][Tag: reading]] - [[file:tags/reading.org][Tag: reading]]
- [[file:tags/maths.org][Tag: maths]]
- posts - posts
- [[file:posts/posts-intro.org][Posts Introduction]] - [[file:posts/posts-intro.org][Posts Introduction]]
- [[file:posts/posts-list.org][Posts List]] - [[file:posts/posts-list.org][Posts List]]