mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-04-27 15:07:43 +00:00
feat: Better URL rendering
This commit is contained in:
parent
273763dd58
commit
2882017876
3 changed files with 41 additions and 21 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* viz/app/linker_page.js */
|
||||||
import { esc, renderThumbHtml } from "./dom.js";
|
import { esc, renderThumbHtml } from "./dom.js";
|
||||||
import {
|
import {
|
||||||
tokenizeQuery,
|
tokenizeQuery,
|
||||||
|
|
@ -110,14 +111,6 @@ function buildMappedSkuSet(links) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
function openLinkHtml(url) {
|
|
||||||
const u = String(url || "").trim();
|
|
||||||
if (!u) return "";
|
|
||||||
return `<a class="badge" href="${esc(
|
|
||||||
u
|
|
||||||
)}" target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()">open</a>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isBCStoreLabel(label) {
|
function isBCStoreLabel(label) {
|
||||||
const s = String(label || "").toLowerCase();
|
const s = String(label || "").toLowerCase();
|
||||||
return s.includes("bcl") || s.includes("strath");
|
return s.includes("bcl") || s.includes("strath");
|
||||||
|
|
@ -381,7 +374,17 @@ export async function renderSkuLinker($app) {
|
||||||
const plus = storeCount > 1 ? ` +${storeCount - 1}` : "";
|
const plus = storeCount > 1 ? ` +${storeCount - 1}` : "";
|
||||||
const price = it.cheapestPriceStr ? it.cheapestPriceStr : "(no price)";
|
const price = it.cheapestPriceStr ? it.cheapestPriceStr : "(no price)";
|
||||||
const store = it.cheapestStoreLabel || ([...it.stores][0] || "Store");
|
const store = it.cheapestStoreLabel || ([...it.stores][0] || "Store");
|
||||||
const open = openLinkHtml(it.sampleUrl || "");
|
|
||||||
|
// NEW: store badge is the link (use first store url)
|
||||||
|
const href = String(it.sampleUrl || "").trim();
|
||||||
|
const storeBadge = href
|
||||||
|
? `<a class="badge" href="${esc(
|
||||||
|
href
|
||||||
|
)}" target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()">${esc(
|
||||||
|
store
|
||||||
|
)}${esc(plus)}</a>`
|
||||||
|
: `<span class="badge">${esc(store)}${esc(plus)}</span>`;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="item ${pinned ? "pinnedItem" : ""}" data-sku="${esc(it.sku)}">
|
<div class="item ${pinned ? "pinnedItem" : ""}" data-sku="${esc(it.sku)}">
|
||||||
<div class="itemRow">
|
<div class="itemRow">
|
||||||
|
|
@ -393,10 +396,8 @@ export async function renderSkuLinker($app) {
|
||||||
</div>
|
</div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<span class="mono">${esc(price)}</span>
|
<span class="mono">${esc(price)}</span>
|
||||||
<span class="badge">${esc(store)}${esc(plus)}</span>
|
${storeBadge}
|
||||||
${open}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="meta"><span class="mono">${esc(it.sampleUrl || "")}</span></div>
|
|
||||||
${pinned ? `<div class="small">Pinned (click again to unpin)</div>` : ``}
|
${pinned ? `<div class="small">Pinned (click again to unpin)</div>` : ``}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -639,7 +640,7 @@ export async function renderSkuLinker($app) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isIgnoredPair(a, b)) {
|
if (isIgnoredPair(a, b)) {
|
||||||
$status.textContent = "This pair is already ignored.";
|
$status.textContent = "Not allowed: unknown SKUs cannot be ignored.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* viz/app/search_page.js */
|
||||||
import { esc, renderThumbHtml, prettyTs } from "./dom.js";
|
import { esc, renderThumbHtml, prettyTs } from "./dom.js";
|
||||||
import { tokenizeQuery, matchesAllTokens, displaySku } from "./sku.js";
|
import { tokenizeQuery, matchesAllTokens, displaySku } from "./sku.js";
|
||||||
import { loadIndex, loadRecent, loadSavedQuery, saveQuery } from "./state.js";
|
import { loadIndex, loadRecent, loadSavedQuery, saveQuery } from "./state.js";
|
||||||
|
|
@ -45,6 +46,16 @@ export function renderSearch($app) {
|
||||||
const price = it.cheapestPriceStr ? it.cheapestPriceStr : "(no price)";
|
const price = it.cheapestPriceStr ? it.cheapestPriceStr : "(no price)";
|
||||||
const store = it.cheapestStoreLabel || ([...it.stores][0] || "Store");
|
const store = it.cheapestStoreLabel || ([...it.stores][0] || "Store");
|
||||||
|
|
||||||
|
// NEW: store badge is the link (use first store url)
|
||||||
|
const href = String(it.sampleUrl || "").trim();
|
||||||
|
const storeBadge = href
|
||||||
|
? `<a class="badge" href="${esc(
|
||||||
|
href
|
||||||
|
)}" target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()">${esc(
|
||||||
|
store
|
||||||
|
)}${esc(plus)}</a>`
|
||||||
|
: `<span class="badge">${esc(store)}${esc(plus)}</span>`;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="item" data-sku="${esc(it.sku)}">
|
<div class="item" data-sku="${esc(it.sku)}">
|
||||||
<div class="itemRow">
|
<div class="itemRow">
|
||||||
|
|
@ -58,10 +69,7 @@ export function renderSearch($app) {
|
||||||
</div>
|
</div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<span class="mono">${esc(price)}</span>
|
<span class="mono">${esc(price)}</span>
|
||||||
<span class="badge">${esc(store)}${esc(plus)}</span>
|
${storeBadge}
|
||||||
</div>
|
|
||||||
<div class="meta">
|
|
||||||
<span class="mono">${esc(it.sampleUrl || "")}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -123,6 +131,16 @@ export function renderSearch($app) {
|
||||||
|
|
||||||
const img = aggBySku.get(sku)?.img || "";
|
const img = aggBySku.get(sku)?.img || "";
|
||||||
|
|
||||||
|
// NEW: store badge links to this row's url
|
||||||
|
const href = String(r.url || "").trim();
|
||||||
|
const storeBadge = href
|
||||||
|
? `<a class="badge" href="${esc(
|
||||||
|
href
|
||||||
|
)}" target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()">${esc(
|
||||||
|
r.storeLabel || ""
|
||||||
|
)}</a>`
|
||||||
|
: `<span class="badge">${esc(r.storeLabel || "")}</span>`;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="item" data-sku="${esc(sku)}">
|
<div class="item" data-sku="${esc(sku)}">
|
||||||
<div class="itemRow">
|
<div class="itemRow">
|
||||||
|
|
@ -136,15 +154,12 @@ export function renderSearch($app) {
|
||||||
</div>
|
</div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<span class="badge">${esc(kind)}</span>
|
<span class="badge">${esc(kind)}</span>
|
||||||
<span class="badge">${esc(r.storeLabel || "")}</span>
|
${storeBadge}
|
||||||
<span class="mono">${esc(priceLine)}</span>
|
<span class="mono">${esc(priceLine)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<span class="mono">${esc(when)}</span>
|
<span class="mono">${esc(when)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="meta">
|
|
||||||
<span class="mono">${esc(r.url || "")}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* viz/style.css */
|
||||||
:root {
|
:root {
|
||||||
--bg: #0b0d10;
|
--bg: #0b0d10;
|
||||||
--panel: #12161b;
|
--panel: #12161b;
|
||||||
|
|
@ -18,6 +19,9 @@ body {
|
||||||
a { color: var(--accent); text-decoration: none; }
|
a { color: var(--accent); text-decoration: none; }
|
||||||
a:hover { text-decoration: underline; }
|
a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
|
/* NEW: don't underline badge-links on hover */
|
||||||
|
a.badge:hover { text-decoration: none; }
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
max-width: 980px;
|
max-width: 980px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue