diff --git a/src/MediaManager.html b/src/MediaManager.html index 76e17fb..6841576 100644 --- a/src/MediaManager.html +++ b/src/MediaManager.html @@ -525,46 +525,54 @@ /* Combined Card Styles */ .combined-item { - display: flex; - flex-direction: column; - background: #f0f9ff; /* Light blue tint */ - border: 2px solid var(--primary); + display: flex; + flex-direction: column; + background: #f0f9ff; + /* Light blue tint */ + border: 2px solid var(--primary); } + .combined-images { - display: flex; - flex: 1; - overflow: hidden; - border-bottom: 1px solid var(--border); + display: flex; + flex: 1; + overflow: hidden; + border-bottom: 1px solid var(--border); } + .combined-part { - flex: 1; - position: relative; - border-right: 1px solid var(--border); + flex: 1; + position: relative; + border-right: 1px solid var(--border); } + .combined-part:last-child { - border-right: none; + border-right: none; } + .combined-part .media-content { - aspect-ratio: auto; /* Allow filling height */ - height: 100px; + aspect-ratio: auto; + /* Allow filling height */ + height: 100px; } + .unlink-btn { - width: 100%; - background: white; - border: none; - padding: 6px; - color: var(--danger); - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - gap: 6px; - font-size: 11px; - font-weight: 500; - transition: background 0.1s; + width: 100%; + background: white; + border: none; + padding: 6px; + color: var(--danger); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + font-size: 11px; + font-weight: 500; + transition: background 0.1s; } + .unlink-btn:hover { - background: #fee2e2; + background: #fee2e2; } @@ -830,54 +838,54 @@ this.checkDirty(); }; - MediaState.prototype.toggleSelection = function (id) { - var item = this.items.find(function (i) { return i.id === id; }); - if (!item) return; + MediaState.prototype.toggleSelection = function (id) { + var item = this.items.find(function (i) { return i.id === id; }); + if (!item) return; - var isSelected = this.selectedIds.has(id); - var affectedIds = [id]; + var isSelected = this.selectedIds.has(id); + var affectedIds = [id]; - if (isSelected) { - this.selectedIds.delete(id); - } else { - // Enforce one-pair rule: Max one Drive, one Shopify - var isDrive = (item.source === 'drive_only'); - var isShopify = (item.source === 'shopify_only'); + if (isSelected) { + this.selectedIds.delete(id); + } else { + // Enforce one-pair rule: Max one Drive, one Shopify + var isDrive = (item.source === 'drive_only'); + var isShopify = (item.source === 'shopify_only'); - if (isDrive) { - // Clear other Drive selections - var _this = this; - this.items.forEach(function (i) { - // Simplified clearing logic - if (i.source === 'drive_only' && _this.selectedIds.has(i.id) && i.id !== id) { - _this.selectedIds.delete(i.id); - affectedIds.push(i.id); - } - }); - } else if (isShopify) { - // Clear other Shopify selections - var _this = this; - this.items.forEach(function (i) { - if (i.source === 'shopify_only' && _this.selectedIds.has(i.id) && i.id !== id) { - _this.selectedIds.delete(i.id); - affectedIds.push(i.id); - } - }); - } - this.selectedIds.add(id); - } + if (isDrive) { + // Clear other Drive selections + var _this = this; + this.items.forEach(function (i) { + // Simplified clearing logic + if (i.source === 'drive_only' && _this.selectedIds.has(i.id) && i.id !== id) { + _this.selectedIds.delete(i.id); + affectedIds.push(i.id); + } + }); + } else if (isShopify) { + // Clear other Shopify selections + var _this = this; + this.items.forEach(function (i) { + if (i.source === 'shopify_only' && _this.selectedIds.has(i.id) && i.id !== id) { + _this.selectedIds.delete(i.id); + affectedIds.push(i.id); + } + }); + } + this.selectedIds.add(id); + } - // Targeted updates - affectedIds.forEach(function (aid) { ui.updateCardState(aid); }); - ui.updateLinkButtonState(); - }; + // Targeted updates + affectedIds.forEach(function (aid) { ui.updateCardState(aid); }); + ui.updateLinkButtonState(); + }; - MediaState.prototype.clearSelection = function () { - var affectedIds = Array.from(this.selectedIds); - this.selectedIds.clear(); - affectedIds.forEach(function (aid) { ui.updateCardState(aid); }); - ui.updateLinkButtonState(); - }; + MediaState.prototype.clearSelection = function () { + var affectedIds = Array.from(this.selectedIds); + this.selectedIds.clear(); + affectedIds.forEach(function (aid) { ui.updateCardState(aid); }); + ui.updateLinkButtonState(); + }; MediaState.prototype.addItem = function (item) { this.items.push(item); @@ -885,12 +893,12 @@ this.checkDirty(); }; - MediaState.prototype.deleteItem = function (id) { - var item = this.items.find(function (i) { return i.id === id; }); - if (!item) { - console.warn("[MediaState] Item not found for deletion:", id); - return; - } + MediaState.prototype.deleteItem = function (id) { + var item = this.items.find(function (i) { return i.id === id; }); + if (!item) { + console.warn("[MediaState] Item not found for deletion:", id); + return; + } if (item.source === 'new') { var index = this.items.indexOf(item); if (index !== -1) this.items.splice(index, 1); @@ -906,13 +914,13 @@ // Handled by Sortable }; - MediaState.prototype.unlinkMedia = function (driveId, shopifyId) { - this.tentativeLinks = this.tentativeLinks.filter(function (l) { - return !(l.driveId === driveId && l.shopifyId === shopifyId); - }); - ui.render(this.items); - this.checkDirty(); - }; + MediaState.prototype.unlinkMedia = function (driveId, shopifyId) { + this.tentativeLinks = this.tentativeLinks.filter(function (l) { + return !(l.driveId === driveId && l.shopifyId === shopifyId); + }); + ui.render(this.items); + this.checkDirty(); + }; MediaState.prototype.checkDirty = function () { var plan = this.calculateDiff(); @@ -1010,8 +1018,8 @@ }; var state = new MediaState(); - state.sku = "!= initialSku ?>"; - state.title = "!= initialTitle ?>"; + state.sku = "!= initialSku ?>"; + state.title = "!= initialTitle ?>"; window.state = state; // --- ES5 Refactor: UI --- @@ -1131,21 +1139,21 @@ btn.disabled = false; }; - UI.prototype.updateLinkButtonState = function () { - var btnLink = document.getElementById('btn-link-selected'); - if (btnLink) { - var items = state.items || []; - var selectedItems = items.filter(function (i) { return state.selectedIds.has(i.id); }); - var hasDrive = selectedItems.some(function (i) { return i.source === 'drive_only'; }); - var hasShopify = selectedItems.some(function (i) { return i.source === 'shopify_only'; }); + UI.prototype.updateLinkButtonState = function () { + var btnLink = document.getElementById('btn-link-selected'); + if (btnLink) { + var items = state.items || []; + var selectedItems = items.filter(function (i) { return state.selectedIds.has(i.id); }); + var hasDrive = selectedItems.some(function (i) { return i.source === 'drive_only'; }); + var hasShopify = selectedItems.some(function (i) { return i.source === 'shopify_only'; }); - if (hasDrive && hasShopify) { - btnLink.style.display = 'block'; - } else { - btnLink.style.display = 'none'; - } + if (hasDrive && hasShopify) { + btnLink.style.display = 'block'; + } else { + btnLink.style.display = 'none'; } - }; + } + }; UI.prototype.render = function (items) { this.grid.innerHTML = ''; @@ -1297,23 +1305,23 @@ } }; - UI.prototype.setSavingState = function (isSaving) { - if (isSaving) { - this.grid.classList.add('grid-disabled'); - if (this.sortable) this.sortable.option('disabled', true); + UI.prototype.setSavingState = function (isSaving) { + if (isSaving) { + this.grid.classList.add('grid-disabled'); + if (this.sortable) this.sortable.option('disabled', true); - // Disable action buttons explicitly if needed (pointer-events handles most, but keyboard nav?) - var btns = this.grid.querySelectorAll('button'); - btns.forEach(function (b) { b.disabled = true; }); + // Disable action buttons explicitly if needed (pointer-events handles most, but keyboard nav?) + var btns = this.grid.querySelectorAll('button'); + btns.forEach(function (b) { b.disabled = true; }); - } else { - this.grid.classList.remove('grid-disabled'); - if (this.sortable) this.sortable.option('disabled', false); + } else { + this.grid.classList.remove('grid-disabled'); + if (this.sortable) this.sortable.option('disabled', false); - var btns = this.grid.querySelectorAll('button'); - btns.forEach(function (b) { b.disabled = false; }); - } - }; + var btns = this.grid.querySelectorAll('button'); + btns.forEach(function (b) { b.disabled = false; }); + } + }; UI.prototype.logStatus = function (step, message, type) { if (!type) type = 'info'; @@ -1422,7 +1430,7 @@ centerIcon + '
'; @@ -1477,84 +1485,84 @@ return div; }; - UI.prototype.updateCardState = function (id) { - var item = state.items.find(function (i) { return i.id === id; }); - var el = this.grid.querySelector('[data-id="' + id + '"]'); - if (!item || !el) return; + UI.prototype.updateCardState = function (id) { + var item = state.items.find(function (i) { return i.id === id; }); + var el = this.grid.querySelector('[data-id="' + id + '"]'); + if (!item || !el) return; - var isSelected = state.selectedIds.has(item.id); + var isSelected = state.selectedIds.has(item.id); - // 1. Update Container Class - // Combined Items don't use this update path (they are re-rendered if unlinked) - el.className = 'media-item ' + (item._deleted ? 'deleted-item' : '') + (isSelected ? ' selected' : ''); - if (item.isProcessing) el.className += ' processing-card'; + // 1. Update Container Class + // Combined Items don't use this update path (they are re-rendered if unlinked) + el.className = 'media-item ' + (item._deleted ? 'deleted-item' : '') + (isSelected ? ' selected' : ''); + if (item.isProcessing) el.className += ' processing-card'; - // 2. Update Badge - var badgeEl = el.querySelector('.badge'); - if (badgeEl) { - if (!item._deleted) { - if (item.source === 'synced') { - badgeEl.innerText = 'Synced'; - badgeEl.title = 'Synced'; - badgeEl.style.background = '#dcfce7'; - badgeEl.style.color = '#166534'; - } else if (item.source === 'drive_only') { - badgeEl.innerText = 'Drive'; - badgeEl.title = 'Drive Only'; - badgeEl.style.background = '#dbeafe'; - badgeEl.style.color = '#1e40af'; - } else if (item.source === 'shopify_only') { - badgeEl.innerText = 'Shopify'; - badgeEl.title = 'Shopify Only'; - badgeEl.style.background = '#fce7f3'; - badgeEl.style.color = '#9d174d'; - } - } else { - badgeEl.innerText = 'Deleted'; - badgeEl.title = ''; - badgeEl.style.background = '#fee2e2'; - badgeEl.style.color = '#991b1b'; - } - } + // 2. Update Badge + var badgeEl = el.querySelector('.badge'); + if (badgeEl) { + if (!item._deleted) { + if (item.source === 'synced') { + badgeEl.innerText = 'Synced'; + badgeEl.title = 'Synced'; + badgeEl.style.background = '#dcfce7'; + badgeEl.style.color = '#166534'; + } else if (item.source === 'drive_only') { + badgeEl.innerText = 'Drive'; + badgeEl.title = 'Drive Only'; + badgeEl.style.background = '#dbeafe'; + badgeEl.style.color = '#1e40af'; + } else if (item.source === 'shopify_only') { + badgeEl.innerText = 'Shopify'; + badgeEl.title = 'Shopify Only'; + badgeEl.style.background = '#fce7f3'; + badgeEl.style.color = '#9d174d'; + } + } else { + badgeEl.innerText = 'Deleted'; + badgeEl.title = ''; + badgeEl.style.background = '#fee2e2'; + badgeEl.style.color = '#991b1b'; + } + } - // 3. Update Overlay Buttons - var overlay = el.querySelector('.media-overlay'); - if (overlay) { - // Remove existing link button if it exists - var oldLinkBtn = el.querySelector('[id="link-btn-' + id + '"]'); - if (oldLinkBtn) oldLinkBtn.remove(); + // 3. Update Overlay Buttons + var overlay = el.querySelector('.media-overlay'); + if (overlay) { + // Remove existing link button if it exists + var oldLinkBtn = el.querySelector('[id="link-btn-' + id + '"]'); + if (oldLinkBtn) oldLinkBtn.remove(); - // Add link button back if NOT deleted - if (!item._deleted && (item.source === 'drive_only' || item.source === 'shopify_only')) { - var linkHtml = ''; - var viewBtn = overlay.querySelector('.btn-view'); - if (viewBtn) { - viewBtn.insertAdjacentHTML('afterend', linkHtml); - } else { - overlay.insertAdjacentHTML('afterbegin', linkHtml); - } - } + // Add link button back if NOT deleted + if (!item._deleted && (item.source === 'drive_only' || item.source === 'shopify_only')) { + var linkHtml = ''; + var viewBtn = overlay.querySelector('.btn-view'); + if (viewBtn) { + viewBtn.insertAdjacentHTML('afterend', linkHtml); + } else { + overlay.insertAdjacentHTML('afterbegin', linkHtml); + } + } - // Update Delete/Restore button - var actionBtn = overlay.querySelector('.btn-delete') || overlay.querySelector('[title="Restore"]'); - if (actionBtn) { - if (item._deleted) { - actionBtn.className = 'icon-btn'; - actionBtn.innerHTML = 'âŠī¸'; - actionBtn.title = 'Restore'; - } else { - actionBtn.className = 'icon-btn btn-delete'; - actionBtn.innerHTML = 'đī¸'; - actionBtn.title = 'Delete'; - } - } - } + // Update Delete/Restore button + var actionBtn = overlay.querySelector('.btn-delete') || overlay.querySelector('[title="Restore"]'); + if (actionBtn) { + if (item._deleted) { + actionBtn.className = 'icon-btn'; + actionBtn.innerHTML = 'âŠī¸'; + actionBtn.title = 'Restore'; + } else { + actionBtn.className = 'icon-btn btn-delete'; + actionBtn.innerHTML = 'đī¸'; + actionBtn.title = 'Delete'; + } + } + } - // 4. Update global item count - var activeCount = state.items.filter(function (i) { return !i._deleted; }).length; - var countEl = document.getElementById('item-count'); - if (countEl) countEl.innerText = '(' + activeCount + ')'; - }; + // 4. Update global item count + var activeCount = state.items.filter(function (i) { return !i._deleted; }).length; + var countEl = document.getElementById('item-count'); + if (countEl) countEl.innerText = '(' + activeCount + ')'; + }; UI.prototype.openPreview = function (id) { var item = state.items.find(function (i) { return i.id === id; }); @@ -1790,15 +1798,15 @@ if (manualMatches.length > 0) { this.matches = manualMatches; this.currentMatchIndex = 0; - this.postMatchAction = 'save'; + this.postMatchAction = 'save'; - ui.logStatus('info', 'Processing ' + manualMatches.length + ' pending links before saving...', 'info'); + ui.logStatus('info', 'Processing ' + manualMatches.length + ' pending links before saving...', 'info'); - // Update Modal Text - document.getElementById('match-modal-title').innerText = "Confirm Manual Links"; - document.getElementById('match-modal-text').innerText = "Please confirm the links you selected."; + // Update Modal Text + document.getElementById('match-modal-title').innerText = "Confirm Manual Links"; + document.getElementById('match-modal-text').innerText = "Please confirm the links you selected."; - this.startMatching(); + this.startMatching(); return; } } @@ -2199,8 +2207,20 @@ dImg.src = blank; sImg.src = blank; - document.getElementById('match-drive-name').innerText = match.drive.filename; - document.getElementById('match-shopify-name').innerText = match.shopify.filename; + // Link to Drive Preview + var driveLink = "https://drive.google.com/file/d/" + match.drive.id + "/view"; + document.getElementById('match-drive-name').innerHTML = '' + match.drive.filename + ''; + + // Link to Shopify Admin Media + var shopifyLink = match.shopify.contentUrl || "#"; + if (ui.shopifyUrl) { + // Pattern: .../admin/content/files/{id}?selectedView=all + // We derive the base admin URL from the product URL + var adminBase = ui.shopifyUrl.split('/products/')[0]; + var mediaId = match.shopify.id.split('/').pop(); + shopifyLink = adminBase + "/content/files/" + mediaId + "?selectedView=all"; + } + document.getElementById('match-shopify-name').innerHTML = '' + match.shopify.filename + ''; document.getElementById('match-index').innerText = this.currentMatchIndex + 1; document.getElementById('match-total').innerText = this.matches.length;