Snapshot of the working tree exactly as it stood, no edits. This is the predecessor
PRICEGOD was rewritten from ("kept intact, untouched" per pricegod/README.md), and it
is still the only place the DYMO scale is actually implemented —
rfid-daemon/index.js:1068-1265: HID discovery, parseScaleReport, one-shot read, and a
streaming /weight + /scale/start|stop session whose JSON shape PRICEGOD's daemon.js
already speaks.
Preserved verbatim on purpose (hence -og), including the known bug: DYMO_PIDS at
index.js:1082 is [0x8003, 0x8004], so it cannot see the bench M25 (0x8009). Fix that
in whatever daemon inherits the scale, not here.
node_modules stays ignored (22M of the 24M tree). No credentials in the import: the
two PEM markers in utils.js/sheets.js only strip headers off a key read from settings,
and mrpadmin / johnking are an SSH and a Postgres username, both key/trust auth.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1149 lines
69 KiB
HTML
1149 lines
69 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Discogentag</title>
|
||
<link rel="stylesheet" href="label.css">
|
||
<link rel="stylesheet" href="large.css">
|
||
<link rel="stylesheet" href="small.css">
|
||
<link rel="stylesheet" href="textlabel.css">
|
||
|
||
<style>
|
||
@font-face {
|
||
font-family: 'Code128';
|
||
src: url('code128.ttf') format('truetype');
|
||
font-weight: normal;
|
||
font-style: normal;
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<div id="stylePageContainer" style="display: none; padding: 20px; text-align: center;">
|
||
<h2>Style Page Data</h2>
|
||
<button id="saveStyleData" class="action-button">SAVE JSON</button>
|
||
<div id="styleDataStatus" style="margin-top: 10px; font-weight: bold;"></div>
|
||
</div>
|
||
|
||
<!-- Tab Navigation -->
|
||
<div class="tab-container">
|
||
<div class="tab-nav">
|
||
<button class="tab-button active" data-tab="discogs">Discogs</button>
|
||
<button class="tab-button" data-tab="youtube">YouTube</button>
|
||
<button class="tab-button" data-tab="textlabel">Text Label</button>
|
||
<button class="tab-button" data-tab="qrcode">QR Code</button>
|
||
<button class="tab-button" data-tab="settings">Settings</button>
|
||
<button class="tab-button" data-tab="mapping">Mapping</button>
|
||
<button class="tab-button" data-tab="research">Prompt</button>
|
||
<button class="tab-button" data-tab="rfid">RFID</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Discogs Tab Content -->
|
||
<div id="discogs-tab" class="tab-content active">
|
||
<div class="container">
|
||
<div class="left-column">
|
||
<!-- All action buttons in single row -->
|
||
<div class="primary-buttons">
|
||
<div class="primary-buttons-large">
|
||
<button id="bothActions" class="action-button all-button">ALL</button>
|
||
<button id="printLabel" class="action-button btn-vis-label">LABEL</button>
|
||
<button id="printLabel203" class="action-button btn-vis-label203" style="display:none">LABEL 203</button>
|
||
<button id="rfidQuickWrite" class="action-button rfid-quick-button btn-vis-rfid">RFID</button>
|
||
<button id="rfidQuickRead" class="action-button btn-vis-rfid" title="Read what's currently on the tag (no write)" style="background:#546e7a;color:#fff;">🔍 SCAN</button>
|
||
</div>
|
||
<div class="primary-buttons-small" id="buttons-small-row">
|
||
<button id="updateSheet" class="action-button action-button-small btn-vis-sheet">SHEET</button>
|
||
<button id="writeJSON" class="action-button action-button-small btn-vis-json" title="Download JSON (shift+click to upload)">JSON ↓↑</button>
|
||
<button id="importWordPress" class="action-button action-button-small" title="Sync SKUs/Price from Website VPS">INV</button>
|
||
</div>
|
||
</div>
|
||
<!-- Collection copy selector — shown when item is in collection multiple times -->
|
||
<div id="collection-box-selector" style="display:none; align-items:center; gap:5px; margin-bottom:4px; flex-wrap:wrap;">
|
||
<span style="font-size:11px; color:#666; flex-shrink:0;">Copy:</span>
|
||
<div id="collection-box-buttons" style="display:flex; gap:3px; flex-wrap:wrap;"></div>
|
||
</div>
|
||
|
||
<div id="sku-mode-indicator" style="font-size:11px; color:#888; margin-bottom:4px; display:none;">
|
||
SKU mode: <strong id="sku-mode-status">OFF</strong>
|
||
</div>
|
||
<div id="monster-sync-indicator" style="font-size:11px; margin-bottom:4px; display:none; transition:opacity 1.5s;"></div>
|
||
<div id="gemini-sync-indicator" style="font-size:11px; margin-bottom:4px; display:none; transition:opacity 1.5s;"></div>
|
||
<!-- Inventory SKU auto-fill: status line + mismatch picker -->
|
||
<div id="inventory-sku-panel" style="display:none; margin-bottom:6px;">
|
||
<div id="inventory-sku-status" style="font-size:11px; color:#555; margin-bottom:4px;"></div>
|
||
<div id="inventory-sku-picker" style="display:none;">
|
||
<div id="inventory-sku-cards" style="display:flex; flex-direction:column; gap:4px; margin-bottom:6px;"></div>
|
||
<div style="font-size:11px; color:#666; margin-bottom:3px;">Write selected SKU to box:</div>
|
||
<div id="inventory-sku-box-buttons" style="display:flex; gap:4px; flex-wrap:wrap;"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status messages -->
|
||
<div class="status-messages">
|
||
<span id="rfidStatus" class="status-text" style="display:block;"></span>
|
||
<span id="allStatus" class="status-text"></span>
|
||
<span id="sheetStatus" class="status-text"></span>
|
||
</div>
|
||
|
||
<!-- Live scale readout (hidden unless scale online + setting enabled) -->
|
||
<div id="scale-pill" style="display:none; font-family:monospace; font-size:12px; padding:3px 8px; border-radius:10px; background:#eef; color:#225; margin-bottom:4px; width:fit-content;" title="DYMO M10 live reading"></div>
|
||
|
||
<div class="input-group">
|
||
<label class="price-input-label">Price: </label>
|
||
<input type="number" id="price" min="0" step="0.01">
|
||
|
||
<div class="price-options">
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="5">
|
||
<span class="price-label">$5</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="8">
|
||
<span class="price-label">$8</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="10">
|
||
<span class="price-label">$10</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="12">
|
||
<span class="price-label">$12</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="15">
|
||
<span class="price-label">$15</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="20">
|
||
<span class="price-label">$20</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="25">
|
||
<span class="price-label">$25</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="30">
|
||
<span class="price-label">$30</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="35">
|
||
<span class="price-label">$35</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="40">
|
||
<span class="price-label">$40</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="45">
|
||
<span class="price-label">$45</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="50">
|
||
<span class="price-label">$50</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="60">
|
||
<span class="price-label">$60</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="70">
|
||
<span class="price-label">$70</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="80">
|
||
<span class="price-label">$80</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="90">
|
||
<span class="price-label">$90</span>
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" class="price-checkbox" value="100">
|
||
<span class="price-label">$100</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="release-info">
|
||
<h3>Release Information</h3>
|
||
<div id="releaseDetails">
|
||
<div class="info-field" data-field="artist"><strong>Artist:</strong> <span class="value"
|
||
contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="title"><strong>Title:</strong> <span class="value"
|
||
contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="genre"><strong>Genre:</strong> <span class="value"
|
||
contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="style"><strong>Style:</strong> <span class="value"
|
||
contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="label"><strong>Label:</strong> <span class="value"
|
||
contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="year"><strong>Year:</strong> <span class="value"
|
||
contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="country"><strong>Country:</strong> <span class="value"
|
||
contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="format"><strong>Format:</strong> <span class="value"
|
||
contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="catno"><strong>Cat#:</strong> <span class="value"
|
||
contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="releaseId"><strong>Release ID:</strong> <span
|
||
class="value"></span></div>
|
||
<div class="info-field" data-field="comment"><strong>Comment:</strong> <span id="commentInput"
|
||
class="value" contenteditable="true"></span></div>
|
||
<div class="info-field" data-field="appleId"><strong>Apple ID:</strong> <span
|
||
class="value"></span></div>
|
||
<div class="info-field" data-field="collectionSku"><strong>SKU:</strong> <span
|
||
class="value"></span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="input-group">
|
||
<label>Media Condition:</label>
|
||
<select id="mediaCondition">
|
||
<option value=""></option>
|
||
<option value="Mint (M)">Mint (M)</option>
|
||
<option value="Near Mint (NM)">Near Mint (NM)</option>
|
||
<option value="Near Mint Minus (NM-)">Near Mint Minus (NM-)</option>
|
||
<option value="Very Good Plus (VG+)" selected>Very Good Plus (VG+)</option>
|
||
<option value="Very Good (VG)">Very Good (VG)</option>
|
||
<option value="Very Good Minus (VG-)">Very Good Minus (VG-)</option>
|
||
<option value="Good Plus Plus (G++)">Good Plus Plus (G++)</option>
|
||
<option value="Good Plus (G+)">Good Plus (G+)</option>
|
||
<option value="Good (G)">Good (G)</option>
|
||
<option value="Fair (F)">Fair (F)</option>
|
||
<option value="Poor (P)">Poor (P)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="input-group">
|
||
<label>Sleeve Condition:</label>
|
||
<select id="sleeveCondition">
|
||
<option value=""></option>
|
||
<option value="Generic (GEN)">Generic (GEN)</option>
|
||
<option value="Mint (M)">Mint (M)</option>
|
||
<option value="Near Mint (NM)">Near Mint (NM)</option>
|
||
<option value="Near Mint Minus (NM-)">Near Mint Minus (NM-)</option>
|
||
<option value="Very Good Plus (VG+)" selected>Very Good Plus (VG+)</option>
|
||
<option value="Very Good (VG)">Very Good (VG)</option>
|
||
<option value="Very Good Minus (VG-)">Very Good Minus (VG-)</option>
|
||
<option value="Company Sleeve (C.SL)">Company Sleeve (C.SL)</option>
|
||
<option value="Good Plus Plus (G++)">Good Plus Plus (G++)</option>
|
||
<option value="Good Plus (G+)">Good Plus (G+)</option>
|
||
<option value="Good (G)">Good (G)</option>
|
||
<option value="Fair (F)">Fair (F)</option>
|
||
<option value="Poor (P)">Poor (P)</option>
|
||
</select>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
<div class="right-column-combined">
|
||
<!-- Label preview at top of right column -->
|
||
<div class="label-preview" style="display: none;">
|
||
<div class="label-field print-artist"></div>
|
||
<div class="label-field print-title"></div>
|
||
<div class="label-field print-genre"></div>
|
||
<div class="label-field print-style"></div>
|
||
<div class="label-field print-description"></div>
|
||
<div class="label-field print-comment"></div>
|
||
<div class="label-field print-notes"></div>
|
||
<div class="label-field print-bottom-info">
|
||
<span class="year"></span><span class="country"></span><span class="label"></span>
|
||
</div>
|
||
<div class="label-field print-condition">
|
||
<span class="print-media"></span> | <span class="print-sleeve"></span>
|
||
</div>
|
||
<div class="label-field print-barcode"></div>
|
||
<div class="label-field print-price"></div>
|
||
<img src="logo.svg" class="print-logo" alt="Logo">
|
||
</div>
|
||
|
||
<div class="label-preview-large">
|
||
<div class="label-field print-artist-large"></div>
|
||
<div class="label-field print-title-large"></div>
|
||
<div class="label-field print-genre-large"></div>
|
||
<div class="label-field print-style-large"></div>
|
||
<div class="label-field print-description-large"></div>
|
||
<div class="label-field print-comment-large"></div>
|
||
<div class="label-field print-notes-large"></div>
|
||
<div class="label-field print-bottom-info-large">
|
||
<span class="year"></span><span class="country"></span><span class="label"></span>
|
||
</div>
|
||
<div class="label-field print-condition-large">
|
||
<span class="print-media-large"></span> | <span class="print-sleeve-large"></span>
|
||
</div>
|
||
<div class="label-field print-barcode-large"></div>
|
||
<div class="label-field print-price-large"></div>
|
||
<img src="logo.svg" class="print-logo-large" alt="Logo">
|
||
</div>
|
||
|
||
<div class="label-preview-xlarge" style="display:none;">
|
||
<div class="label-field print-artist-xlarge"></div>
|
||
<div class="label-field print-title-xlarge"></div>
|
||
<div class="label-field print-genre-xlarge"></div>
|
||
<div class="label-field print-style-xlarge"></div>
|
||
<div class="label-field print-description-xlarge"></div>
|
||
<div class="label-field print-comment-xlarge"></div>
|
||
<div class="label-field print-notes-xlarge"></div>
|
||
<div class="label-field print-bottom-info-xlarge">
|
||
<span class="year"></span><span class="country"></span><span class="label"></span>
|
||
</div>
|
||
<div class="label-field print-condition-xlarge">
|
||
<span class="print-media-xlarge"></span> | <span class="print-sleeve-xlarge"></span>
|
||
</div>
|
||
<div class="label-field print-barcode-xlarge"></div>
|
||
<div class="label-field print-price-xlarge"></div>
|
||
<img src="logo.svg" class="print-logo-xlarge" alt="Logo">
|
||
</div>
|
||
|
||
<div class="market-info">
|
||
<h3>Market Information</h3>
|
||
<div id="marketDetails"></div>
|
||
</div>
|
||
<div class="release-info">
|
||
<div id="releaseDetails"></div>
|
||
</div>
|
||
<div class="tracklist">
|
||
<h3>Tracklist</h3>
|
||
<div id="trackList"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- YouTube Tab Content -->
|
||
<div id="youtube-tab" class="tab-content">
|
||
<div class="youtube-cookie-container">
|
||
<h3>YouTube Cookie Extractor</h3>
|
||
<div style="margin-bottom: 15px;">
|
||
<label class="switch">
|
||
<input type="checkbox" id="autoUpdate">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label">Auto-update cookies</span>
|
||
</div>
|
||
<div style="margin-bottom: 15px;">
|
||
<label class="switch">
|
||
<input type="checkbox" id="blagginateBridge" checked>
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label">BLAGGINATE Bridge</span>
|
||
</div>
|
||
<button id="getCookies" class="youtube-extract-btn">Extract Cookies</button>
|
||
<button id="getCookiesJd2" class="youtube-extract-btn" style="margin-top:6px;background:#2196F3;">Copy for JDownloader 2 (JSON)</button>
|
||
<textarea id="cookieOutput" readonly placeholder="YouTube cookies will appear here..."></textarea>
|
||
<div class="status-message"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Settings Tab Content -->
|
||
<div id="settings-tab" class="tab-content">
|
||
<div class="settings-tab-container">
|
||
|
||
<!-- ALL Button config -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:12px 15px; border-radius:8px; margin-bottom:8px;">
|
||
<div class="settings-section-label">ALL Button</div>
|
||
<div class="settings-check-grid">
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="allDoesLabel" checked> Label
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="allDoesSheet" checked> Sheet
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="allDoesRfid" checked> RFID
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="allDoesJson" checked> JSON
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="allDoesPrice" checked> Discogs Price
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="qrUseSku"> Timestamp SKU
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Scale options -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:12px 15px; border-radius:8px; margin-bottom:8px;">
|
||
<div class="settings-section-label">Scale (DYMO M10)</div>
|
||
<div class="settings-check-grid">
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="scaleShowOnDiscogs" checked> Show live weight pill on Discogs tab
|
||
</label>
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="scaleSaveToSheet"> Include weight when saving to Sheets
|
||
</label>
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="scaleRequireStable" checked> Only save when scale is stable
|
||
</label>
|
||
</div>
|
||
<div style="font-size:11px; color:#888; margin-top:6px;">DB updates happen via the ⚖→DB button on each inventory row (per-SKU).</div>
|
||
</div>
|
||
|
||
<!-- RFID options -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:12px 15px; border-radius:8px; margin-bottom:8px;">
|
||
<div class="settings-section-label">RFID</div>
|
||
<div class="settings-check-grid">
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="rfidAppendR"> Append -R to SKU after successful write <span style="color:#888;font-size:10px;">marks chipped items in Discogs collection</span>
|
||
</label>
|
||
<div style="grid-column:1/-1; color:#888; font-size:11px; padding:4px 0;">Release ID is always included in the tag now (was previously a toggle).</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Visible buttons -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:12px 15px; border-radius:8px; margin-bottom:8px;">
|
||
<div class="settings-section-label">Visible Buttons</div>
|
||
<div class="settings-check-grid">
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="btnShowLabel" checked> LABEL
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="btnShowRfid" checked> RFID
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="btnShowSheet" checked> SHEET
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="btnShowJson" checked> JSON
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="btnShowInventory" checked> INV
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="btnShowLabel203"> LABEL 203
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- General -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:12px 15px; border-radius:8px; margin-bottom:8px;">
|
||
<div class="settings-section-label">General</div>
|
||
<div class="settings-check-grid">
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="enableJsonDownload" checked> JSON includes reviews & ratings
|
||
</label>
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="stripSkuSuffix"> Strip <code>-A</code> suffix from SKU for QR & RFID <span style="color:#888;font-size:10px;">e.g. 20260321001001-A → 20260321001001</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Label settings -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:12px 15px; border-radius:8px; margin-bottom:8px;">
|
||
<div class="settings-section-label">Label</div>
|
||
<div style="display:flex; align-items:center; gap:8px; margin-bottom:7px;">
|
||
<label style="font-size:12px; color:#555; min-width:44px; flex-shrink:0;">Size</label>
|
||
<select id="labelSize" style="flex:1; font-size:12px; padding:2px 4px;">
|
||
<option value="small">Small (19mm × 51mm)</option>
|
||
<option value="large" selected>Large (25mm × 54mm)</option>
|
||
<option value="xlarge">XL (34mm × 64mm)</option>
|
||
</select>
|
||
</div>
|
||
<div style="display:flex; align-items:center; gap:8px; margin-bottom:7px;">
|
||
<label style="font-size:12px; color:#555; min-width:44px; flex-shrink:0;">Font</label>
|
||
<select id="label-font-select" style="flex:1; font-size:12px; padding:2px 4px;">
|
||
<option value="Arial" selected>Arial</option>
|
||
<option value="'MS Gothic','Hiragino Kaku Gothic Pro',Arial">MS Gothic</option>
|
||
<option value="'Helvetica Neue',Helvetica,Arial">Helvetica Neue</option>
|
||
<option value="Verdana,Arial">Verdana</option>
|
||
<option value="'Times New Roman',serif">Times New Roman</option>
|
||
<option value="Georgia,serif">Georgia</option>
|
||
<option value="Futura,'Trebuchet MS',Arial">Futura</option>
|
||
<option value="'Courier New',monospace">Courier New</option>
|
||
</select>
|
||
</div>
|
||
<div class="settings-check-grid">
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="label-bold-toggle"> Bold
|
||
</label>
|
||
<label class="settings-check-item">
|
||
<input type="checkbox" id="label-italic-toggle"> Italic
|
||
</label>
|
||
</div>
|
||
<!-- Per-field style overrides -->
|
||
<div class="lfs-grid">
|
||
<div class="lfs-header"><span></span><span title="Bold">B</span><span title="Italic">I</span><span title="Ellipsis instead of shrink">…</span></div>
|
||
<div class="lfs-row"><span>Artist</span> <input type="checkbox" id="lfs-artist-b"> <input type="checkbox" id="lfs-artist-i"> <input type="checkbox" id="lfs-artist-e"></div>
|
||
<div class="lfs-row"><span>Title</span> <input type="checkbox" id="lfs-title-b"> <input type="checkbox" id="lfs-title-i"> <input type="checkbox" id="lfs-title-e"></div>
|
||
<div class="lfs-row"><span>Genre</span> <input type="checkbox" id="lfs-genre-b"> <input type="checkbox" id="lfs-genre-i"> <input type="checkbox" id="lfs-genre-e"></div>
|
||
<div class="lfs-row"><span>Style</span> <input type="checkbox" id="lfs-style-b"> <input type="checkbox" id="lfs-style-i"> <input type="checkbox" id="lfs-style-e"></div>
|
||
<div class="lfs-row"><span>Format</span> <input type="checkbox" id="lfs-format-b"> <input type="checkbox" id="lfs-format-i"> <input type="checkbox" id="lfs-format-e"></div>
|
||
<div class="lfs-row"><span>Yr/Co/Lbl</span><input type="checkbox" id="lfs-info-b"> <input type="checkbox" id="lfs-info-i"> <input type="checkbox" id="lfs-info-e"></div>
|
||
<div class="lfs-row"><span>Price</span> <input type="checkbox" id="lfs-price-b"> <input type="checkbox" id="lfs-price-i"> <input type="checkbox" id="lfs-price-e"></div>
|
||
<div class="lfs-row"><span>Condition</span><input type="checkbox" id="lfs-condition-b"><input type="checkbox" id="lfs-condition-i"><input type="checkbox" id="lfs-condition-e"></div>
|
||
<div class="lfs-row"><span>Comment</span> <input type="checkbox" id="lfs-comment-b"> <input type="checkbox" id="lfs-comment-i"> <input type="checkbox" id="lfs-comment-e"></div>
|
||
<div class="lfs-row"><span>Notes</span> <input type="checkbox" id="lfs-notes-b"> <input type="checkbox" id="lfs-notes-i"> <input type="checkbox" id="lfs-notes-e"></div>
|
||
</div>
|
||
</div>
|
||
<div class="settings-container">
|
||
<button id="settings-toggle-connect">Connect</button>
|
||
<div id="settings-content-connect" style="display: none;">
|
||
<div class="input-group">
|
||
<label>Extension ID:</label>
|
||
<div class="extension-id-row"
|
||
style="display:flex; align-items:center; gap:8px; flex-wrap:wrap;">
|
||
<div id="extension-id-display" style="font-weight: bold; word-break: break-all;"></div>
|
||
<button id="copy-extension-id" title="Copy Extension ID" aria-label="Copy Extension ID"
|
||
style="padding:2px 6px; font-size:11px; line-height:1;">Copy</button>
|
||
<span id="copy-extension-id-status"
|
||
style="display:none; font-size:12px; color:green;">Copied!</span>
|
||
</div>
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="discogs-token">Discogs Token:</label>
|
||
<input type="text" id="discogs-token">
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="spreadsheet-id">Spreadsheet ID:</label>
|
||
<input type="text" id="spreadsheet-id">
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="google-service-account-json">Service Account JSON:</label>
|
||
<textarea id="google-service-account-json" rows="5"></textarea>
|
||
</div>
|
||
<!-- Inventory SKU Lookup settings -->
|
||
<div style="border-top:1px solid #ddd; margin-top:10px; padding-top:10px;">
|
||
<div style="font-size:12px; font-weight:600; color:#444; margin-bottom:6px;">Inventory SKU Lookup</div>
|
||
<label class="settings-check-item" style="display:flex; align-items:center; gap:6px; margin-bottom:6px;">
|
||
<input type="checkbox" id="inventorySkuEnabled">
|
||
<span style="font-size:12px;">Auto-fill SKU on popup open</span>
|
||
</label>
|
||
<div class="input-group">
|
||
<label for="inventory-db-host">DB Host:</label>
|
||
<input type="text" id="inventory-db-host" placeholder="100.123.123.64">
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="inventory-db-name">DB Name:</label>
|
||
<input type="text" id="inventory-db-name" placeholder="wp_rmp_disc_">
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="inventory-db-user">DB User:</label>
|
||
<input type="text" id="inventory-db-user" autocomplete="off">
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="inventory-db-pass">DB Password:</label>
|
||
<input type="password" id="inventory-db-pass" autocomplete="off">
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="inventory-ssh-key">SSH Key Path:</label>
|
||
<input type="text" id="inventory-ssh-key" placeholder="~/.ssh/id_rsa">
|
||
</div>
|
||
</div>
|
||
<button id="save-connect-settings">Save Connect Settings</button>
|
||
</div>
|
||
</div>
|
||
<div class="settings-container">
|
||
<div style="display:flex; align-items:center; gap:10px;">
|
||
<button id="settings-toggle-beatport">BEATPORT</button>
|
||
<span id="beatport-status-dot" style="
|
||
display: inline-block;
|
||
width: 10px; height: 10px;
|
||
border-radius: 50%;
|
||
background: #ccc;
|
||
flex-shrink: 0;
|
||
title: 'No token saved';
|
||
"></span>
|
||
<span id="beatport-status-label" style="font-size:12px; color:#666;"></span>
|
||
</div>
|
||
<div id="settings-content-beatport" style="display: none; margin-top: 10px;">
|
||
<div id="beatport-token-info" style="font-size:12px; color:#555; margin-bottom:8px;"></div>
|
||
<div style="display:flex; gap:8px; flex-wrap:wrap;">
|
||
<button id="beatport-fetch-token">Fetch Token</button>
|
||
<button id="beatport-copy-json" style="background:#2196F3; color:#fff; border:none; border-radius:4px; padding:4px 10px; cursor:pointer;">Copy JSON</button>
|
||
<button id="beatport-clear-token" style="background:#f44336; color:#fff; border:none; border-radius:4px; padding:4px 10px; cursor:pointer;">Clear</button>
|
||
</div>
|
||
<div id="beatport-fetch-status" style="margin-top:8px; font-size:12px;"></div>
|
||
</div>
|
||
</div>
|
||
<div class="settings-container">
|
||
<button id="settings-toggle-monster">MONSTERWIKI</button>
|
||
<div id="settings-content-monster" style="display:none; margin-top:10px;">
|
||
<div class="settings-check-grid" style="margin-bottom:10px;">
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="monster-enabled">
|
||
Sync to MONSTERWIKI Postgres on popup open
|
||
</label>
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="monster-autocapture">
|
||
Auto-capture while browsing <span style="color:#888;font-size:10px;">silently harvests every release page you open — no popup needed</span>
|
||
</label>
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="monster-prefer-localhost">
|
||
Prefer localhost server when available
|
||
</label>
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="monster-server-url">Server URL (Tailscale host:port):</label>
|
||
<input type="text" id="monster-server-url" placeholder="http://100.91.239.7:5002">
|
||
</div>
|
||
<div style="display:flex; gap:8px; align-items:center; margin-top:8px;">
|
||
<button id="save-monster-settings">Save</button>
|
||
<button id="test-monster-connection">Test</button>
|
||
<span id="monster-status" style="font-size:11px; color:#666;"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="settings-container">
|
||
<button id="settings-toggle-gemini">GEMINI PROMPT</button>
|
||
<div id="settings-content-gemini" style="display:none; margin-top:10px;">
|
||
<div class="settings-check-grid" style="margin-bottom:10px;">
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="gemini-close-tab" checked>
|
||
Close Gemini tab after successful save
|
||
</label>
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<input type="checkbox" id="gemini-auto-run">
|
||
Auto-run AI in background on popup open
|
||
</label>
|
||
<label class="settings-check-item" style="grid-column:1/-1;">
|
||
<span style="min-width:72px;">Provider</span>
|
||
<select id="ai-provider" style="flex:1; font-size:12px; padding:2px 4px;">
|
||
<option value="gemini">Gemini</option>
|
||
<option value="deepseek">DeepSeek</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="gemini-prompt-template">Prompt template:</label>
|
||
<textarea id="gemini-prompt-template" rows="10" placeholder="Use {{INPUT_JSON}} where the release JSON should be inserted."></textarea>
|
||
</div>
|
||
<div style="display:flex; gap:8px; align-items:center; margin-top:8px;">
|
||
<button id="save-gemini-prompt">Save</button>
|
||
<button id="reset-gemini-prompt">Reset</button>
|
||
<span id="gemini-prompt-status" style="font-size:11px; color:#666;"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="settings-container">
|
||
<button id="settings-toggle-wowplatter">WOWPLATTER</button>
|
||
<div id="settings-content-wowplatter" style="display: none;">
|
||
<div class="input-group">
|
||
<label for="wp-endpoint">Endpoint URL:</label>
|
||
<input type="text" id="wp-endpoint" placeholder="https://your-site.com/wp-json/your/endpoint">
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="wp-key">API Key:</label>
|
||
<input type="text" id="wp-key">
|
||
</div>
|
||
<div class="input-group">
|
||
<label for="wp-secret">API Secret:</label>
|
||
<input type="password" id="wp-secret">
|
||
</div>
|
||
<button id="save-wp-settings">Save Settings</button>
|
||
<button id="test-wp-connection" style="margin-left: 10px;">Test Connection</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Text Label Tab Content -->
|
||
<div id="textlabel-tab" class="tab-content">
|
||
<div class="textlabel-container">
|
||
<div class="textlabel-header">
|
||
<h3>Simple Text Label</h3>
|
||
<p>Create a custom text label with basic formatting. Uses label size: <strong
|
||
id="current-label-size">Large (25mm x 54mm)</strong></p>
|
||
</div>
|
||
|
||
<div class="formatting-toolbar">
|
||
<div class="toolbar-row">
|
||
<div class="toolbar-group">
|
||
<label for="text-font-family">Font:</label>
|
||
<select id="text-font-family">
|
||
<option value="Arial">Arial</option>
|
||
<option value="'MS Gothic', 'Hiragino Kaku Gothic Pro', Arial">Asian Characters (MS Gothic)
|
||
</option>
|
||
<option value="'Times New Roman'">Times New Roman</option>
|
||
<option value="'Courier New'">Courier New</option>
|
||
<option value="Helvetica">Helvetica</option>
|
||
<option value="Verdana">Verdana</option>
|
||
<option value="Georgia">Georgia</option>
|
||
<option value="'SF Pro'">SF Pro</option>
|
||
<option value="'SF Mono'">SF Mono</option>
|
||
<option value="Menlo">Menlo</option>
|
||
<option value="Monaco">Monaco</option>
|
||
<option value="'American Typewriter'">American Typewriter</option>
|
||
<option value="Baskerville">Baskerville</option>
|
||
<option value="'Brush Script MT'">Brush Script MT</option>
|
||
<option value="Chalkboard">Chalkboard</option>
|
||
<option value="'Comic Sans MS'">Comic Sans MS</option>
|
||
<option value="Copperplate">Copperplate</option>
|
||
<option value="Didot">Didot</option>
|
||
<option value="Futura">Futura</option>
|
||
<option value="'Gill Sans'">Gill Sans</option>
|
||
<option value="'Helvetica Neue'">Helvetica Neue</option>
|
||
<option value="'Hoefler Text'">Hoefler Text</option>
|
||
<option value="Impact">Impact</option>
|
||
<option value="'Lucida Grande'">Lucida Grande</option>
|
||
<option value="Optima">Optima</option>
|
||
<option value="Palatino">Palatino</option>
|
||
<option value="Papyrus">Papyrus</option>
|
||
<option value="Phosphate">Phosphate</option>
|
||
<option value="Rockwell">Rockwell</option>
|
||
<option value="'Snell Roundhand'">Snell Roundhand</option>
|
||
<option value="Tahoma">Tahoma</option>
|
||
<option value="'Trebuchet MS'">Trebuchet MS</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="toolbar-group">
|
||
<label for="text-font-size">Size:</label>
|
||
<input type="number" id="text-font-size" min="6" max="72" value="12" step="1">
|
||
<span>pt</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toolbar-row">
|
||
<div class="toolbar-group">
|
||
<button id="text-bold" class="format-button" title="Bold">
|
||
<strong>B</strong>
|
||
</button>
|
||
<button id="text-underline" class="format-button" title="Underline">
|
||
<u>U</u>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="toolbar-group">
|
||
<label>
|
||
<input type="checkbox" id="text-wrap" checked>
|
||
Word Wrap
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toolbar-row">
|
||
<div class="toolbar-group">
|
||
<label style="margin-right: 4px;">Align:</label>
|
||
<button id="align-left" class="format-button active" title="Align Left">
|
||
L
|
||
</button>
|
||
<button id="align-center" class="format-button" title="Align Center">
|
||
C
|
||
</button>
|
||
<button id="align-right" class="format-button" title="Align Right">
|
||
R
|
||
</button>
|
||
</div>
|
||
|
||
<div class="toolbar-group">
|
||
<label style="margin-right: 4px;">Vertical:</label>
|
||
<button id="align-top" class="format-button active" title="Align Top">
|
||
T
|
||
</button>
|
||
<button id="align-middle" class="format-button" title="Align Middle">
|
||
M
|
||
</button>
|
||
<button id="align-bottom" class="format-button" title="Align Bottom">
|
||
B
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="textlabel-workspace">
|
||
<div class="input-section">
|
||
<label for="text-input-area">Text Input:</label>
|
||
<textarea id="text-input-area" placeholder="Type your text here..."></textarea>
|
||
</div>
|
||
|
||
<div class="preview-section">
|
||
<label>Label Preview:</label>
|
||
<div class="label-preview-box" id="label-preview-box">
|
||
<div class="label-preview-content" id="label-preview-content"></div>
|
||
</div>
|
||
<p class="preview-note">Preview shows actual label size. Text that doesn't fit will be cut off when
|
||
printed.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="textlabel-actions">
|
||
<button id="print-text-label" class="action-button">Print Text Label</button>
|
||
<button id="clear-text-label" class="action-button" style="background: #f44336;">Clear</button>
|
||
</div>
|
||
|
||
<div id="text-label-status" class="status-text"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- QR Code Tab Content -->
|
||
<div id="qrcode-tab" class="tab-content">
|
||
<div class="qrcode-container">
|
||
<div class="qrcode-header">
|
||
<h3>QR Code Label</h3>
|
||
<p>Print a QR code from an integer. Uses label size: <strong>Large (25mm x 54mm)</strong></p>
|
||
</div>
|
||
|
||
<div class="qrcode-options" style="margin-bottom: 12px; display: flex; align-items: center; gap: 10px;">
|
||
<label class="switch">
|
||
<input type="checkbox" id="qr-use-sku">
|
||
<span class="slider"></span>
|
||
</label>
|
||
<span class="toggle-label">Use Timestamp SKU for QR (instead of Release ID)</span>
|
||
</div>
|
||
<div id="qr-sku-display" style="display: none; margin-bottom: 10px; font-size: 12px; color: #555;">
|
||
Last SKU: <strong id="qr-sku-value"></strong>
|
||
</div>
|
||
|
||
<div class="qrcode-input-section">
|
||
<label for="qrcode-integer-input">Enter Integer:</label>
|
||
<input type="number" id="qrcode-integer-input" placeholder="e.g., 12345" min="0">
|
||
</div>
|
||
|
||
<div class="qrcode-preview-section">
|
||
<label>Label Preview:</label>
|
||
<div class="qrcode-preview-box" id="qrcode-preview-box">
|
||
<img id="qrcode-preview-img" src="" alt="QR Code Preview" style="display: none;">
|
||
</div>
|
||
<p class="preview-note">QR code will be centered on the label</p>
|
||
</div>
|
||
|
||
<div class="qrcode-actions">
|
||
<button id="print-qrcode-label" class="action-button">Print QR Code</button>
|
||
<button id="clear-qrcode" class="action-button" style="background: #f44336;">Clear</button>
|
||
</div>
|
||
|
||
<div id="qrcode-status" class="status-text"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Mapping Tab Content -->
|
||
<div id="mapping-tab" class="tab-content">
|
||
<div class="mapping-tab-container">
|
||
<div class="mapping-header">
|
||
<h3>Column Mapping Configuration</h3>
|
||
<p>Configure which data fields map to which Google Sheets columns. Leave blank to skip a field.</p>
|
||
<div class="mapping-actions">
|
||
<button id="detect-sheet">Detect Sheet Structure</button>
|
||
<button id="auto-map">Auto-Map Headers</button>
|
||
<button id="save-mappings">Save</button>
|
||
<button id="reset-mappings">Reset</button>
|
||
<button id="load-mappings">Load</button>
|
||
</div>
|
||
<div id="mappingStatus" class="status-text"></div>
|
||
|
||
<div class="sheet-info">
|
||
<div class="info-row">
|
||
<label>Sheet Name:</label>
|
||
<span id="detected-sheet-name">Not detected</span>
|
||
</div>
|
||
<div class="info-row">
|
||
<label>Column Range:</label>
|
||
<span id="detected-column-range">Not detected</span>
|
||
<input type="text" id="manual-range" placeholder="e.g., A:AL" style="display:none;">
|
||
<button id="toggle-manual-range">Manual</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mapping-grid">
|
||
<!-- Grid items will be dynamically generated by JavaScript -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Research Tab Content -->
|
||
<div id="research-tab" class="tab-content">
|
||
<div class="research-container">
|
||
|
||
<div class="research-header">
|
||
<h3>LLM Research Export</h3>
|
||
<p class="research-desc" id="research-desc">Navigate to a Discogs release page and open the popup to load release data.</p>
|
||
</div>
|
||
|
||
<!-- Release identity card -->
|
||
<div id="research-release-card" class="research-release-card" style="display:none;">
|
||
<div class="research-cover-wrap">
|
||
<img id="research-img" src="" alt="Cover" class="research-cover">
|
||
<div class="research-cover-placeholder" id="research-cover-placeholder">♪</div>
|
||
</div>
|
||
<div class="research-release-meta">
|
||
<div class="research-artist" id="research-artist"></div>
|
||
<div class="research-title" id="research-title"></div>
|
||
<div class="research-meta-row">
|
||
<span id="research-label"></span>
|
||
<span class="research-sep" id="research-catno-sep">·</span>
|
||
<span id="research-catno"></span>
|
||
<span class="research-sep">·</span>
|
||
<span id="research-year"></span>
|
||
<span class="research-sep">·</span>
|
||
<span id="research-country"></span>
|
||
</div>
|
||
<div class="research-meta-row research-format-row" id="research-format"></div>
|
||
<div class="research-tags" id="research-tags"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Market snapshot grid -->
|
||
<div id="research-market" class="research-market" style="display:none;">
|
||
<div class="research-stat">
|
||
<span class="rstat-label">Have</span>
|
||
<span class="rstat-value" id="rs-have">—</span>
|
||
</div>
|
||
<div class="research-stat">
|
||
<span class="rstat-label">Want</span>
|
||
<span class="rstat-value rstat-accent" id="rs-want">—</span>
|
||
</div>
|
||
<div class="research-stat">
|
||
<span class="rstat-label">W/H</span>
|
||
<span class="rstat-value" id="rs-ratio">—</span>
|
||
<span class="rstat-sub" id="rs-ratio-signal"></span>
|
||
</div>
|
||
<div class="research-stat">
|
||
<span class="rstat-label">For Sale</span>
|
||
<span class="rstat-value" id="rs-forsale">—</span>
|
||
</div>
|
||
<div class="research-stat">
|
||
<span class="rstat-label">Low</span>
|
||
<span class="rstat-value" id="rs-low">—</span>
|
||
</div>
|
||
<div class="research-stat">
|
||
<span class="rstat-label">Median</span>
|
||
<span class="rstat-value rstat-median" id="rs-med">—</span>
|
||
</div>
|
||
<div class="research-stat">
|
||
<span class="rstat-label">High</span>
|
||
<span class="rstat-value" id="rs-high">—</span>
|
||
</div>
|
||
<div class="research-stat">
|
||
<span class="rstat-label">Reviews</span>
|
||
<span class="rstat-value" id="rs-reviews">—</span>
|
||
</div>
|
||
<div class="research-stat">
|
||
<span class="rstat-label">Tracks</span>
|
||
<span class="rstat-value" id="rs-tracks">—</span>
|
||
</div>
|
||
<div class="research-stat">
|
||
<span class="rstat-label">Last Sold</span>
|
||
<span class="rstat-value rstat-small" id="rs-lastsold">—</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tracklist preview -->
|
||
<div id="research-tracklist-wrap" class="research-tracklist-wrap" style="display:none;">
|
||
<div class="research-section-label">Tracklist</div>
|
||
<div id="research-tracklist" class="research-tracklist"></div>
|
||
</div>
|
||
|
||
<!-- Export actions -->
|
||
<div id="research-actions" class="research-actions" style="display:none;">
|
||
<button id="research-download" class="research-btn research-btn-download">
|
||
<span class="research-btn-icon">↓</span> Download
|
||
</button>
|
||
<button id="research-copy" class="research-btn research-btn-copy">
|
||
<span class="research-btn-icon">⎘</span> Copy
|
||
</button>
|
||
<button id="research-gemini" class="research-btn research-btn-gemini">
|
||
<span class="research-btn-icon">◆</span> Gemini
|
||
</button>
|
||
<button id="research-drive" class="research-btn research-btn-drive" style="display:none;">
|
||
<span class="research-btn-icon">▲</span> Drive
|
||
</button>
|
||
</div>
|
||
|
||
<div id="research-status" class="research-status"></div>
|
||
|
||
<!-- JSON preview (collapsible) -->
|
||
<div id="research-preview-wrap" class="research-preview-wrap" style="display:none;">
|
||
<button id="research-toggle-preview" class="research-preview-toggle">
|
||
<span id="research-toggle-icon">▶</span> Preview JSON
|
||
</button>
|
||
<pre id="research-preview" class="research-preview" style="display:none;"></pre>
|
||
|
||
<button id="gemini-toggle-input" class="research-preview-toggle" style="margin-top:6px;">
|
||
<span id="gemini-input-toggle-icon">▶</span> Preview/Edit Gemini Input
|
||
</button>
|
||
<textarea id="gemini-input-editor" class="research-preview" style="display:none;"></textarea>
|
||
|
||
<button id="gemini-toggle-prompt" class="research-preview-toggle" style="margin-top:6px;">
|
||
<span id="gemini-prompt-toggle-icon">▶</span> Preview Gemini Prompt
|
||
</button>
|
||
<pre id="gemini-prompt-preview" class="research-preview" style="display:none;"></pre>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- RFID Tab Content -->
|
||
<div id="rfid-tab" class="tab-content">
|
||
<div class="settings-tab-container">
|
||
|
||
<!-- Connection status -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:15px; border-radius:8px; margin-bottom:10px;">
|
||
<div style="display:flex; align-items:center; gap:8px; margin-bottom:6px;">
|
||
<span id="rfid-status-dot" style="
|
||
display:inline-block; width:12px; height:12px;
|
||
border-radius:50%; background:#ccc; flex-shrink:0;"></span>
|
||
<span id="rfid-status-label" style="font-size:13px; color:#555;">Not checked</span>
|
||
<button id="rfid-check-btn" style="margin-left:auto; padding:3px 8px; font-size:12px;">Check</button>
|
||
<button id="rfid-stop-btn" style="padding:3px 8px; font-size:12px; background:#e53935; color:#fff; border:none; border-radius:4px; cursor:pointer; display:none;">Stop</button>
|
||
</div>
|
||
<div id="rfid-status-port" style="font-size:11px; color:#888; margin-bottom:6px;"></div>
|
||
<!-- shown when daemon is online -->
|
||
<!-- shown when daemon is offline -->
|
||
<div id="rfid-start-cmd" style="display:none; align-items:center; gap:6px;">
|
||
<code id="rfid-start-cmd-text" style="font-size:11px; background:#eee; padding:3px 6px; border-radius:3px; flex:1;">node rfid-daemon/index.js -q</code>
|
||
<button id="rfid-copy-cmd-btn" style="padding:3px 8px; font-size:12px; cursor:pointer;">Copy</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tag data (to write) + Tag on reader — side by side -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:10px 12px; border-radius:8px; margin-bottom:8px;">
|
||
<div style="display:flex; gap:10px;">
|
||
<!-- Left: to write -->
|
||
<div style="flex:1; min-width:0;">
|
||
<div style="font-size:11px; color:#666; font-weight:600; text-transform:uppercase; letter-spacing:.5px; margin-bottom:5px;">To Write</div>
|
||
<div style="display:flex; gap:4px; margin-bottom:3px;">
|
||
<span style="font-size:11px; color:#888; width:56px; flex-shrink:0;">SKU</span>
|
||
<span id="rfid-sku-display" style="font-size:11px; font-weight:600; font-family:monospace; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">—</span>
|
||
</div>
|
||
<div style="display:flex; gap:4px;">
|
||
<span style="font-size:11px; color:#888; width:56px; flex-shrink:0;">Rel ID</span>
|
||
<span id="rfid-releaseid-display" style="font-size:11px; font-weight:600; font-family:monospace;">—</span>
|
||
</div>
|
||
</div>
|
||
<!-- Divider -->
|
||
<div style="width:1px; background:#ddd; flex-shrink:0;"></div>
|
||
<!-- Right: on reader -->
|
||
<div style="flex:1; min-width:0;">
|
||
<div style="display:flex; align-items:center; margin-bottom:5px; gap:5px;">
|
||
<span style="font-size:11px; color:#666; font-weight:600; text-transform:uppercase; letter-spacing:.5px;">On Reader</span>
|
||
<span id="rfid-tag-scanning" style="font-size:10px; color:#ffc107; display:none;">scanning…</span>
|
||
</div>
|
||
<div style="display:flex; gap:4px; margin-bottom:3px;">
|
||
<span style="font-size:11px; color:#888; width:56px; flex-shrink:0;">SKU</span>
|
||
<span id="rfid-tag-sku" style="font-size:11px; font-weight:600; font-family:monospace; color:#555; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">—</span>
|
||
</div>
|
||
<div style="display:flex; gap:4px; margin-bottom:3px;">
|
||
<span style="font-size:11px; color:#888; width:56px; flex-shrink:0;">Rel ID</span>
|
||
<span id="rfid-tag-releaseid" style="font-size:11px; font-weight:600; font-family:monospace; color:#555;">—</span>
|
||
</div>
|
||
<div style="display:flex; gap:4px;">
|
||
<span style="font-size:11px; color:#888; width:56px; flex-shrink:0;">RSSI</span>
|
||
<span id="rfid-tag-rssi" style="font-size:11px; font-family:monospace; color:#555;">—</span>
|
||
<span id="rfid-tag-antenna" style="font-size:11px; font-family:monospace; color:#aaa; margin-left:4px;">—</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Write + recovery buttons -->
|
||
<div class="settings-container" style="padding:10px 12px; border-radius:8px; margin-bottom:8px;">
|
||
<div style="display:flex; gap:6px; margin-bottom:6px;">
|
||
<button id="rfid-write-btn" style="
|
||
flex:2; padding:7px 10px; font-size:13px; font-weight:700;
|
||
background:#1976d2; color:#fff; border:none; border-radius:5px; cursor:pointer;">
|
||
Write SKU to Tag
|
||
</button>
|
||
<button id="rfid-rescan-btn" style="
|
||
flex:1; padding:7px 10px; font-size:12px; font-weight:600;
|
||
background:#546e7a; color:#fff; border:none; border-radius:5px; cursor:pointer;">
|
||
Rescan
|
||
</button>
|
||
</div>
|
||
<div style="display:flex; gap:6px;">
|
||
<button id="rfid-clear-mask-btn2" style="
|
||
flex:1; padding:5px 8px; font-size:11px; font-weight:600;
|
||
background:#ff8f00; color:#fff; border:none; border-radius:4px; cursor:pointer;"
|
||
title="Clear SELECTMASK — fixes 'reader can not see tag' after a failed write.">
|
||
Clear Mask
|
||
</button>
|
||
<button id="rfid-recover-btn" style="
|
||
flex:1; padding:5px 8px; font-size:11px; font-weight:600;
|
||
background:#c62828; color:#fff; border:none; border-radius:4px; cursor:pointer;"
|
||
title="Force-stop the reader and reset to answer mode. Use when reader is stuck, streaming, or not responding.">
|
||
Recover Reader
|
||
</button>
|
||
</div>
|
||
<div style="display:flex; gap:6px; margin-top:6px;">
|
||
<button id="rfid-recover-mode-btn" style="
|
||
flex:1; padding:5px 8px; font-size:11px; font-weight:600;
|
||
background:#6a1b9a; color:#fff; border:none; border-radius:4px; cursor:pointer;"
|
||
title="Closes serial, scans baud rates, and sends SET_RFID_MODE to switch the H102 back from barcode/QR mode to RFID mode. Use when the gun has accidentally changed modes.">
|
||
Restore RFID Mode
|
||
</button>
|
||
</div>
|
||
<div id="rfid-write-status" style="margin-top:8px; font-size:12px; min-height:16px;"></div>
|
||
</div>
|
||
|
||
<!-- Device Info & Battery -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:15px; border-radius:8px; margin-bottom:10px;">
|
||
<div style="font-size:12px; color:#666; margin-bottom:8px; font-weight:600; text-transform:uppercase; letter-spacing:.5px;">Device</div>
|
||
<div style="display:flex; gap:6px; margin-bottom:8px;">
|
||
<button id="rfid-device-info-btn" style="padding:4px 10px; font-size:12px; cursor:pointer; border-radius:4px; border:1px solid #ccc;">Device Info</button>
|
||
<button id="rfid-battery-btn" style="padding:4px 10px; font-size:12px; cursor:pointer; border-radius:4px; border:1px solid #ccc;">Battery</button>
|
||
</div>
|
||
<div id="rfid-device-info-display" style="font-size:11px; color:#555; font-family:monospace; white-space:pre-wrap;"></div>
|
||
</div>
|
||
|
||
<!-- Reader Config -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:15px; border-radius:8px; margin-bottom:10px;">
|
||
<div style="display:flex; align-items:center; margin-bottom:8px; gap:6px;">
|
||
<span style="font-size:12px; color:#666; font-weight:600; text-transform:uppercase; letter-spacing:.5px;">Reader Config</span>
|
||
<button id="rfid-get-config-btn" style="margin-left:auto; padding:3px 8px; font-size:12px; cursor:pointer; border-radius:4px; border:1px solid #ccc;">Get</button>
|
||
</div>
|
||
<div id="rfid-config-display" style="font-size:11px; color:#555; font-family:monospace; white-space:pre-wrap; margin-bottom:8px;"></div>
|
||
<div style="display:grid; grid-template-columns:1fr 1fr; gap:6px; margin-bottom:8px;">
|
||
<label style="font-size:11px; color:#666; display:block;">Q Value (0-15)
|
||
<input id="rfid-cfg-qvalue" type="number" min="0" max="15" placeholder="—" style="width:100%; margin-top:2px; padding:2px 4px; font-size:11px; box-sizing:border-box;">
|
||
</label>
|
||
<label style="font-size:11px; color:#666; display:block;">Session (0-3)
|
||
<input id="rfid-cfg-session" type="number" min="0" max="3" placeholder="—" style="width:100%; margin-top:2px; padding:2px 4px; font-size:11px; box-sizing:border-box;">
|
||
</label>
|
||
<label style="font-size:11px; color:#666; display:block;">Filter Time (0-255s)
|
||
<input id="rfid-cfg-filtertime" type="number" min="0" max="255" placeholder="—" style="width:100%; margin-top:2px; padding:2px 4px; font-size:11px; box-sizing:border-box;">
|
||
</label>
|
||
<label style="font-size:11px; color:#666; display:block;">Buzzer (0-255 × 10ms)
|
||
<input id="rfid-cfg-buzzertime" type="number" min="0" max="255" placeholder="—" style="width:100%; margin-top:2px; padding:2px 4px; font-size:11px; box-sizing:border-box;">
|
||
</label>
|
||
<label style="font-size:11px; color:#666; display:block;">RF Power (0-33 dBm)
|
||
<input id="rfid-cfg-rfpower" type="number" min="0" max="33" step="0.1" placeholder="—" style="width:100%; margin-top:2px; padding:2px 4px; font-size:11px; box-sizing:border-box;">
|
||
</label>
|
||
<label style="font-size:11px; color:#666; display:block;">Poll Interval (0-255 × 10ms)
|
||
<input id="rfid-cfg-polling" type="number" min="0" max="255" placeholder="—" style="width:100%; margin-top:2px; padding:2px 4px; font-size:11px; box-sizing:border-box;">
|
||
</label>
|
||
</div>
|
||
<button id="rfid-set-config-btn" style="padding:5px 14px; font-size:12px; font-weight:600; background:#43a047; color:#fff; border:none; border-radius:4px; cursor:pointer;">Apply Config</button>
|
||
<div id="rfid-config-status" style="font-size:11px; margin-top:6px; min-height:14px;"></div>
|
||
</div>
|
||
|
||
<!-- Inventory Scan -->
|
||
<div class="settings-container" style="background:#f8f9fa; padding:15px; border-radius:8px; margin-bottom:10px;">
|
||
<div style="font-size:12px; color:#666; margin-bottom:8px; font-weight:600; text-transform:uppercase; letter-spacing:.5px;">Inventory Scan</div>
|
||
<div style="display:flex; gap:8px; align-items:flex-end; margin-bottom:6px; flex-wrap:wrap;">
|
||
<label style="font-size:11px; color:#666; display:block;">Type
|
||
<select id="rfid-inv-type" style="margin-left:4px; font-size:11px; padding:2px 4px; border-radius:3px; border:1px solid #ccc;">
|
||
<option value="time">Time-based (seconds)</option>
|
||
<option value="count">Count-based (cycles)</option>
|
||
</select>
|
||
</label>
|
||
<label style="font-size:11px; color:#666; display:block;">Param
|
||
<input id="rfid-inv-param" type="number" min="1" max="255" value="1" style="width:48px; margin-left:4px; padding:2px 4px; font-size:11px; border-radius:3px; border:1px solid #ccc;">
|
||
</label>
|
||
<button id="rfid-scan-btn" style="padding:5px 14px; font-size:12px; font-weight:600; background:#546e7a; color:#fff; border:none; border-radius:4px; cursor:pointer;">Scan</button>
|
||
</div>
|
||
<div id="rfid-scan-result" style="font-size:11px; color:#555; font-family:monospace; min-height:14px;"></div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<script src="constants.js"></script>
|
||
<script src="monster_capture.js"></script>
|
||
<script src="utils.js"></script>
|
||
<script src="sheets.js"></script>
|
||
<script src="wp.js"></script>
|
||
<script src="ui.js"></script>
|
||
<script src="popup.js"></script>
|
||
</body>
|
||
|
||
</html>
|