← Commit history

adom-stock: sign-in aware (lookups are attributed per person), carries the reader's cap on refresh

Colby Knox ·1f7438755a ·28d ago ·parent 18e15c0
1 file changed +9−4
widgets/stock-widget.js+9−4
@@ -24,8 +24,8 @@ tr+tr td{border-top:1px solid var(--border)}td.num{font-variant-numeric:tabular-       if (inline) { try { data = JSON.parse(inline.textContent); } catch (e) { err = 'bad inline data'; } }       const src = this.getAttribute('src');       if (!data && src) ({ data, err } = await this.load(src, false));-      // Nothing cached yet: this reader asked, so spend the lookup now.-      if (!err && data && src && data.refresh === 'declined' && !Object.values(data.vendors || {}).some(Boolean)) ({ data, err } = await this.load(src, true));+      // Nothing cached yet and the reader is signed in: they asked, so spend the lookup now.+      if (!err && data && src && data.refresh === 'declined' && data.signed_in !== false && !Object.values(data.vendors || {}).some(Boolean)) ({ data, err } = await this.load(src, true));       this.render(data, err);       this.shadowRoot.addEventListener('click', async (e) => {         const a = e.target.closest && e.target.closest('a.refresh'); if (!a || !src) return;@@ -34,7 +34,10 @@ tr+tr td{border-top:1px solid var(--border)}td.num{font-variant-numeric:tabular-     }     // fresh=false reads the wiki's cache only; fresh=true lets the wiki spend a vendor lookup (counted against the daily budget).     async load(src, fresh) {-      try { const r = await fetch(src, { credentials: 'include', headers: fresh ? { 'X-Adom-Widget': 'stock' } : {} }); const data = await r.json(); return { data, err: r.ok ? null : (data && data.error ? data.error : `stock route answered ${r.status}`) }; }+      // The frame is opaque-origin (no session); the src carries the user cap the wiki minted for a signed-in reader.+      let cap = ''; try { cap = new URL(src, 'https://wiki.adom.inc').searchParams.get('cap') || ''; } catch (e) {}+      const headers = fresh ? { 'X-Adom-Widget': 'stock', ...(cap ? { 'X-Adom-Cap': cap } : {}) } : {};+      try { const r = await fetch(src, { credentials: 'include', headers }); const data = await r.json(); return { data, err: r.ok ? null : (data && data.error ? data.error : `stock route answered ${r.status}`) }; }       catch (e) { return { data: null, err: 'could not load stock' }; }     }     render(d, err) {@@ -42,6 +45,8 @@ tr+tr td{border-top:1px solid var(--border)}td.num{font-variant-numeric:tabular-       const body = wrap.querySelector('.note') || wrap.querySelector('table');       if (err || !d) { when.textContent = ''; body.outerHTML = `<div class="note">${esc(err || 'no data')}</div>`; return; }       if (d.unavailable || d.skipped) { when.textContent = ''; body.outerHTML = `<div class="note">${esc(d.unavailable || d.skipped)}</div>`; return; }+      const anyRow = Object.values(d.vendors || {}).some(Boolean);+      if (!anyRow && (d.login_required || d.signed_in === false)) { when.textContent = ''; body.outerHTML = `<div class="note">Sign in to check live stock and price (lookups are counted per person).</div>`; return; }       const budget = Object.values(d.vendors || {}).some(r => r && r.error && /budget/.test(r.error));       const rows = VENDORS.filter(v => d.vendors && d.vendors[v] !== undefined).map(v => {         const r = d.vendors[v]; const label = r && r.label || v;@@ -51,7 +56,7 @@ tr+tr td{border-top:1px solid var(--border)}td.num{font-variant-numeric:tabular-         const link = r.product_url ? `<a href="${esc(r.product_url)}" target="_blank" rel="noopener">open</a>` : '';         return `<tr><td>${esc(label)}<br><span class="pn">${esc(r.part || r.mpn || '')}</span></td><td class="num ${r.stock > 0 ? 'in' : 'out'}">${r.stock > 0 ? num(r.stock) + ' in stock' : 'out of stock'}</td><td class="num">${esc(r.unit_price || '')}</td><td class="num">${esc(r.price_100 || '')}</td><td>${link}</td></tr>`;       });-      when.innerHTML = esc(ago(d.checked_at)) + (d.checked_at ? ' <a class="refresh" href="#" title="Ask the distributors again (counts against the daily lookup budget)">refresh</a>' : '');+      when.innerHTML = esc(ago(d.checked_at)) + (d.checked_at && d.signed_in !== false && !d.login_required ? ' <a class="refresh" href="#" title="Ask the distributors again (counts against the daily lookup budget)">refresh</a>' : d.login_required ? ' (sign in to refresh)' : '');       body.outerHTML = `<table><thead><tr><th>Distributor</th><th class="num">Stock</th><th class="num">Unit</th><th class="num">At 100</th><th></th></tr></thead><tbody>${rows.join('')}</tbody></table>`;     }   }