Compare commits
2 Commits
8b1da56820
...
78bbf04824
| Author | SHA1 | Date | |
|---|---|---|---|
| 78bbf04824 | |||
| 63b2ff2fd0 |
@ -36,14 +36,14 @@
|
|||||||
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
|
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
@ -295,7 +295,7 @@
|
|||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
margin: 0 -16px -16px -16px;
|
margin: 0 -16px 0 -16px;
|
||||||
border-bottom-left-radius: 12px;
|
border-bottom-left-radius: 12px;
|
||||||
border-bottom-right-radius: 12px;
|
border-bottom-right-radius: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -385,7 +385,7 @@
|
|||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin-top: 16px;
|
margin-top: 8px;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -784,44 +784,50 @@
|
|||||||
this.checkDirty();
|
this.checkDirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
MediaState.prototype.toggleSelection = function (id) {
|
MediaState.prototype.toggleSelection = function (id) {
|
||||||
var item = this.items.find(function (i) { return i.id === id; });
|
var item = this.items.find(function (i) { return i.id === id; });
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
var isSelected = this.selectedIds.has(id);
|
var isSelected = this.selectedIds.has(id);
|
||||||
|
var affectedIds = [id];
|
||||||
|
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
this.selectedIds.delete(id);
|
this.selectedIds.delete(id);
|
||||||
} else {
|
} else {
|
||||||
// Enforce one-pair rule: Max one Drive, one Shopify
|
// Enforce one-pair rule: Max one Drive, one Shopify
|
||||||
var isDrive = (item.source === 'drive_only');
|
var isDrive = (item.source === 'drive_only');
|
||||||
var isShopify = (item.source === 'shopify_only');
|
var isShopify = (item.source === 'shopify_only');
|
||||||
|
|
||||||
if (isDrive) {
|
if (isDrive) {
|
||||||
// Clear other Drive selections
|
// Clear other Drive selections
|
||||||
var _this = this;
|
var _this = this;
|
||||||
this.items.forEach(function (i) {
|
this.items.forEach(function (i) {
|
||||||
if (i.source === 'drive_only' && _this.selectedIds.has(i.id)) {
|
if (i.source === 'drive_only' && _this.selectedIds.has(i.id) && i.id !== id) {
|
||||||
_this.selectedIds.delete(i.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);
|
||||||
} else if (isShopify) {
|
}
|
||||||
// Clear other Shopify selections
|
|
||||||
var _this = this;
|
// Targeted updates
|
||||||
this.items.forEach(function (i) {
|
affectedIds.forEach(function (aid) { ui.updateCardState(aid); });
|
||||||
if (i.source === 'shopify_only' && _this.selectedIds.has(i.id)) {
|
};
|
||||||
_this.selectedIds.delete(i.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.selectedIds.add(id);
|
|
||||||
}
|
|
||||||
ui.render(this.items);
|
|
||||||
};
|
|
||||||
|
|
||||||
MediaState.prototype.clearSelection = function () {
|
MediaState.prototype.clearSelection = function () {
|
||||||
|
var affectedIds = Array.from(this.selectedIds);
|
||||||
this.selectedIds.clear();
|
this.selectedIds.clear();
|
||||||
ui.render(this.items);
|
affectedIds.forEach(function (aid) { ui.updateCardState(aid); });
|
||||||
};
|
};
|
||||||
|
|
||||||
MediaState.prototype.addItem = function (item) {
|
MediaState.prototype.addItem = function (item) {
|
||||||
@ -830,14 +836,20 @@
|
|||||||
this.checkDirty();
|
this.checkDirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
MediaState.prototype.deleteItem = function (index) {
|
MediaState.prototype.deleteItem = function (id) {
|
||||||
var item = this.items[index];
|
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') {
|
if (item.source === 'new') {
|
||||||
this.items.splice(index, 1);
|
var index = this.items.indexOf(item);
|
||||||
|
if (index !== -1) this.items.splice(index, 1);
|
||||||
|
ui.render(this.items); // Full render only for actual removal
|
||||||
} else {
|
} else {
|
||||||
item._deleted = !item._deleted;
|
item._deleted = !item._deleted;
|
||||||
|
ui.updateCardState(id); // Targeted update for toggle
|
||||||
}
|
}
|
||||||
ui.render(this.items);
|
|
||||||
this.checkDirty();
|
this.checkDirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1210,12 +1222,12 @@
|
|||||||
// Link selection button
|
// Link selection button
|
||||||
var linkSelectionBtn = '';
|
var linkSelectionBtn = '';
|
||||||
if (!item._deleted && (item.source === 'drive_only' || item.source === 'shopify_only')) {
|
if (!item._deleted && (item.source === 'drive_only' || item.source === 'shopify_only')) {
|
||||||
linkSelectionBtn = '<button class="icon-btn' + (isSelected ? ' active' : '') + '" onclick="event.stopPropagation(); state.toggleSelection(\'' + item.id + '\')" title="Select for linking">🔗</button>';
|
linkSelectionBtn = '<button id="link-btn-' + item.id + '" class="icon-btn' + (isSelected ? ' active' : '') + '" onclick="event.stopPropagation(); state.toggleSelection(\'' + item.id + '\')" title="Select for linking">🔗</button>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var actionBtn = item._deleted
|
var actionBtn = item._deleted
|
||||||
? '<button class="icon-btn" onclick="state.deleteItem(' + index + ')" title="Restore">↩️</button>'
|
? '<button class="icon-btn" onclick="state.deleteItem(\'' + item.id + '\')" title="Restore">↩️</button>'
|
||||||
: '<button class="icon-btn btn-delete" onclick="state.deleteItem(' + index + ')" title="Delete">🗑️</button>';
|
: '<button class="icon-btn btn-delete" onclick="state.deleteItem(\'' + item.id + '\')" title="Delete">🗑️</button>';
|
||||||
|
|
||||||
div.innerHTML +=
|
div.innerHTML +=
|
||||||
badge +
|
badge +
|
||||||
@ -1278,6 +1290,84 @@
|
|||||||
return div;
|
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;
|
||||||
|
|
||||||
|
var isSelected = state.selectedIds.has(item.id);
|
||||||
|
|
||||||
|
// 1. Update Container Class
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Update Overlay Buttons
|
||||||
|
var overlay = el.querySelector('.media-overlay');
|
||||||
|
if (overlay) {
|
||||||
|
// Remove existing link button if it exists
|
||||||
|
var oldLinkBtn = el.querySelector('#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 = '<button id="link-btn-' + item.id + '" class="icon-btn' + (isSelected ? ' active' : '') + '" onclick="event.stopPropagation(); state.toggleSelection(\'' + item.id + '\')" title="Select for linking">🔗</button>';
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
UI.prototype.openPreview = function (id) {
|
||||||
var item = state.items.find(function (i) { return i.id === id; });
|
var item = state.items.find(function (i) { return i.id === id; });
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
@ -1446,11 +1536,12 @@
|
|||||||
if (media) {
|
if (media) {
|
||||||
ui.logStatus('fetch', 'Fetched full media state.', 'success');
|
ui.logStatus('fetch', 'Fetched full media state.', 'success');
|
||||||
const normalized = media.map(function (i) {
|
const normalized = media.map(function (i) {
|
||||||
|
var source = i.source || (i.shopifyId && i.driveId ? 'synced' : (i.shopifyId ? 'shopify_only' : 'drive_only'));
|
||||||
return {
|
return {
|
||||||
...i,
|
...i,
|
||||||
id: i.id || Math.random().toString(36).substr(2, 9),
|
id: i.id || Math.random().toString(36).substr(2, 9),
|
||||||
status: i.source || 'drive_only',
|
status: source,
|
||||||
source: i.source,
|
source: source,
|
||||||
_deleted: false
|
_deleted: false
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -1862,7 +1953,7 @@
|
|||||||
|
|
||||||
startMatching() {
|
startMatching() {
|
||||||
document.getElementById('loading-ui').style.display = 'none';
|
document.getElementById('loading-ui').style.display = 'none';
|
||||||
document.getElementById('main-ui').style.display = 'none';
|
document.getElementById('main-ui').style.display = 'block';
|
||||||
document.getElementById('matching-modal').style.display = 'flex';
|
document.getElementById('matching-modal').style.display = 'flex';
|
||||||
this.renderMatch();
|
this.renderMatch();
|
||||||
},
|
},
|
||||||
@ -1980,8 +2071,12 @@
|
|||||||
|
|
||||||
// All Done
|
// All Done
|
||||||
document.getElementById('matching-modal').style.display = 'none';
|
document.getElementById('matching-modal').style.display = 'none';
|
||||||
ui.logStatus('info', 'Matching complete. Reloading...', 'info');
|
ui.logStatus('info', 'Matching complete. Finalizing gallery...', 'info');
|
||||||
document.getElementById('loading-ui').style.display = 'block';
|
|
||||||
|
// Show main UI immediately if not already showing
|
||||||
|
document.getElementById('main-ui').style.display = 'block';
|
||||||
|
document.getElementById('loading-ui').style.display = 'none';
|
||||||
|
|
||||||
// Reload to get fresh state. Since hasRunMatching is true, it shouldn't trigger again.
|
// Reload to get fresh state. Since hasRunMatching is true, it shouldn't trigger again.
|
||||||
this.loadMedia(true);
|
this.loadMedia(true);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user