This commit is contained in:
gsinghpal
2026-04-02 03:30:02 -04:00
parent 5b76037988
commit 2a363c6b40
15 changed files with 580 additions and 506 deletions

View File

@@ -23,7 +23,7 @@
<div class="woo-cards">
<!-- Pending orders -->
<div class="woo-card woo-card-pending woo-card-clickable"
<div class="woo-card border-start border-warning border-3 woo-card-clickable"
t-on-click="openOrders">
<div class="woo-card-icon">🛒</div>
<div class="woo-card-value" t-esc="state.pendingOrders"/>
@@ -32,7 +32,7 @@
</div>
<!-- Last sync -->
<div class="woo-card woo-card-sync">
<div class="woo-card border-start border-info border-3">
<div class="woo-card-icon">🔄</div>
<div class="woo-card-value" style="font-size:1.1rem;" t-esc="lastSyncRelative"/>
<div class="woo-card-label">Last Sync</div>
@@ -45,7 +45,7 @@
</div>
<!-- Errors -->
<div class="woo-card woo-card-errors woo-card-clickable"
<div class="woo-card border-start border-danger border-3 woo-card-clickable"
t-on-click="openSyncLogs">
<div class="woo-card-icon">⚠️</div>
<div class="woo-card-value" t-esc="state.errors24h"/>
@@ -54,7 +54,7 @@
</div>
<!-- Products mapped -->
<div class="woo-card woo-card-mapped">
<div class="woo-card border-start border-success border-3">
<div class="woo-card-icon">🔗</div>
<div class="woo-card-value">
<t t-esc="mappedPercent"/>%
@@ -75,19 +75,19 @@
<div class="woo-section-title">Quick Actions</div>
<div class="woo-quick-actions">
<button class="woo-btn woo-btn-primary" t-on-click="syncNow">
<button class="btn btn-primary" t-on-click="syncNow">
<i class="fa fa-refresh me-1"/> Sync Now
</button>
<button class="woo-btn woo-btn-warning" t-on-click="openConflicts">
<button class="btn btn-warning" t-on-click="openConflicts">
<i class="fa fa-exclamation-triangle me-1"/> View Conflicts
</button>
<button class="woo-btn woo-btn-secondary" t-on-click="openMapping">
<button class="btn btn-secondary" t-on-click="openMapping">
<i class="fa fa-th-list me-1"/> Open Product Mapping
</button>
<button class="woo-btn woo-btn-secondary" t-on-click="openOrders">
<button class="btn btn-secondary" t-on-click="openOrders">
<i class="fa fa-shopping-cart me-1"/> View Orders
</button>
@@ -111,13 +111,13 @@
<td><strong><t t-esc="inst.name"/></strong></td>
<td>
<t t-if="inst.state === 'connected'">
<span class="woo-badge woo-badge-mapped">Connected</span>
<span class="badge text-bg-success">Connected</span>
</t>
<t t-elif="inst.state === 'error'">
<span class="woo-badge woo-badge-error">Error</span>
<span class="badge text-bg-danger">Error</span>
</t>
<t t-else="">
<span class="woo-badge woo-badge-unmapped">Draft</span>
<span class="badge text-bg-secondary">Draft</span>
</t>
</td>
<td>
@@ -125,7 +125,7 @@
<t t-esc="inst.last_sync"/>
</t>
<t t-else="">
<span class="woo-text-muted">Never</span>
<span class="text-muted">Never</span>
</t>
</td>
</tr>

View File

@@ -36,15 +36,15 @@
</select>
<!-- Fetch / Sync buttons -->
<button class="woo-btn woo-btn-secondary" t-on-click="fetchProducts"
<button class="btn btn-secondary" t-on-click="fetchProducts"
t-att-disabled="state.loading">
<i class="fa fa-download me-1"/> Fetch Products
</button>
<button class="woo-btn woo-btn-primary" t-on-click="syncNow"
<button class="btn btn-primary" t-on-click="syncNow"
t-att-disabled="state.loading">
<i class="fa fa-refresh me-1"/> Sync Now
</button>
<button class="woo-btn woo-btn-secondary" t-on-click="refreshPrices"
<button class="btn btn-secondary" t-on-click="refreshPrices"
t-att-disabled="state.loading">
<i class="fa fa-dollar me-1"/> Refresh Prices
</button>
@@ -82,17 +82,17 @@
<button class="woo-tab" t-att-class="state.activeTab === 'mapped' ? 'active' : ''"
t-on-click="() => this.setTab('mapped')">
Mapped Products
<span class="ms-1 woo-badge woo-badge-mapped" t-esc="state.mappedTotal"/>
<span class="ms-1 badge text-bg-success" t-esc="state.mappedTotal"/>
</button>
<button class="woo-tab" t-att-class="state.activeTab === 'unmatched' ? 'active' : ''"
t-on-click="() => this.setTab('unmatched')">
Unmatched Products
<span class="ms-1 woo-badge woo-badge-unmapped" t-esc="state.unmatchedWooTotal"/>
<span class="ms-1 badge text-bg-secondary" t-esc="state.unmatchedWooTotal"/>
</button>
<button class="woo-tab" t-att-class="state.activeTab === 'conflicts' ? 'active' : ''"
t-on-click="() => this.setTab('conflicts')">
Conflicts
<span class="ms-1 woo-badge woo-badge-conflict" t-esc="state.conflictCount"/>
<span class="ms-1 badge text-bg-warning" t-esc="state.conflictCount"/>
</button>
</div>
@@ -105,26 +105,26 @@
endpoint="'/woo/search/mapped'"
t-props="{ instanceId: state.instanceId, onResults: onMappedResults.bind(this), placeholder: 'Search mapped products…' }"
/>
<button class="woo-btn woo-btn-danger woo-btn-sm"
<button class="btn btn-outline-danger btn-sm"
t-on-click="unmapSelected"
t-att-disabled="!state.selectedMapped.length">
<i class="fa fa-unlink me-1"/> Unmap Selected
</button>
<button class="woo-btn woo-btn-success woo-btn-sm"
<button class="btn btn-success btn-sm"
t-on-click="syncSelected"
t-att-disabled="!state.selectedMapped.length">
<i class="fa fa-refresh me-1"/> Sync Selected
</button>
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="bulkPriceOdooToWC">
<button class="btn btn-secondary btn-sm" t-on-click="bulkPriceOdooToWC">
<i class="fa fa-arrow-right me-1"/> All Prices Odoo → WC
</button>
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="bulkPriceWCToOdoo">
<button class="btn btn-secondary btn-sm" t-on-click="bulkPriceWCToOdoo">
<i class="fa fa-arrow-left me-1"/> All Prices WC → Odoo
</button>
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="bulkSkuOdooToWC">
<button class="btn btn-secondary btn-sm" t-on-click="bulkSkuOdooToWC">
<i class="fa fa-arrow-right me-1"/> All SKUs Odoo → WC
</button>
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="bulkSkuWCToOdoo">
<button class="btn btn-secondary btn-sm" t-on-click="bulkSkuWCToOdoo">
<i class="fa fa-arrow-left me-1"/> All SKUs WC → Odoo
</button>
</div>
@@ -211,8 +211,8 @@
<td>
<t t-esc="p.odoo_product_name"/>
<t t-if="p.odoo_variant_count > 1 and !p.is_variation">
<button class="woo-btn woo-btn-sm ms-2"
t-att-class="p.needs_variant_push ? 'woo-btn woo-btn-primary woo-btn-sm ms-2' : 'woo-btn woo-btn-secondary woo-btn-sm ms-2'"
<button class="btn btn-sm ms-2"
t-att-class="p.needs_variant_push ? 'btn btn-primary btn-sm ms-2' : 'btn btn-secondary btn-sm ms-2'"
t-on-click.stop="() => this.pushVariantsToWC(p.id)"
title="Manage variants — create new or update existing">
<i class="fa fa-sitemap me-1"/>
@@ -242,9 +242,9 @@
</t>
<t t-else="">
<t t-if="p.woo_sale_price">
<span class="woo-sale-price" t-esc="this.formatPrice(p.woo_sale_price)"/>
<span class="text-success fw-bold" t-esc="this.formatPrice(p.woo_sale_price)"/>
</t>
<t t-else=""><span class="woo-text-muted"></span></t>
<t t-else=""><span class="text-muted"></span></t>
</t>
</td>
<td class="text-center woo-price-sync-col">
@@ -279,7 +279,7 @@
</t>
<t t-else="" t-esc="this.formatPrice(p.odoo_cost)"/>
</td>
<td class="text-end woo-editable-cell woo-margin-cell" t-on-click.stop="() => this.startEdit(p.id, 'margin', this.calcMargin(p.odoo_cost, p.odoo_price))">
<td class="text-end woo-editable-cell text-success fw-bold" t-on-click.stop="() => this.startEdit(p.id, 'margin', this.calcMargin(p.odoo_cost, p.odoo_price))">
<t t-if="this.isEditing(p.id, 'margin')">
<input type="number" step="1" min="0" max="99" class="woo-edit-input"
t-att-value="state.editValue"
@@ -307,7 +307,7 @@
</table>
</div>
<div class="woo-pagination">
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="mappedPrevPage"
<button class="btn btn-secondary btn-sm" t-on-click="mappedPrevPage"
t-att-disabled="state.mappedPage &lt;= 1">
<i class="fa fa-chevron-left"/> Prev
</button>
@@ -315,7 +315,7 @@
Page <t t-esc="state.mappedPage"/> of <t t-esc="mappedTotalPages"/>
(<t t-esc="state.mappedTotal"/> total)
</span>
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="mappedNextPage"
<button class="btn btn-secondary btn-sm" t-on-click="mappedNextPage"
t-att-disabled="state.mappedPage &gt;= mappedTotalPages">
Next <i class="fa fa-chevron-right"/>
</button>
@@ -329,13 +329,13 @@
<t t-if="state.activeTab === 'unmatched'">
<!-- Map action bar -->
<div class="woo-map-actions">
<button class="woo-btn woo-btn-primary"
<button class="btn btn-primary"
t-on-click="mapSelected"
t-att-disabled="!canMap">
<i class="fa fa-link me-1"/> Map Selected
</button>
<t t-if="!canMap">
<small class="woo-text-muted align-self-center">
<small class="text-muted align-self-center">
Select one Odoo product and one WooCommerce product to map them.
</small>
</t>
@@ -347,7 +347,7 @@
<div class="woo-split-panel-header" style="flex-wrap: wrap; gap: 6px;">
<span>Odoo Products</span>
<div class="d-flex gap-2 align-items-center">
<button class="woo-btn woo-btn-secondary woo-btn-sm"
<button class="btn btn-secondary btn-sm"
t-on-click="openCategoryFilter"
title="Manage hidden categories">
<i class="fa fa-filter me-1"/>
@@ -357,7 +357,7 @@
</t>
</button>
<t t-if="state.excludedCategoryCount">
<button t-att-class="'woo-btn woo-btn-sm ' + (state.categoryFilterActive ? 'woo-btn-primary' : 'woo-btn-secondary')"
<button t-att-class="'btn btn-sm ' + (state.categoryFilterActive ? 'btn-primary' : 'btn-secondary')"
t-on-click="toggleCategoryFilter"
t-att-title="state.categoryFilterActive ? 'Filter active — click to show all' : 'Filter off — click to hide categories'">
<i t-att-class="'fa ' + (state.categoryFilterActive ? 'fa-eye-slash' : 'fa-eye')"/>
@@ -382,7 +382,7 @@
<div class="woo-split-item-name">
<t t-esc="op.name"/>
<t t-if="op.has_variants">
<span class="woo-badge woo-badge-unmapped ms-2">
<span class="badge text-bg-secondary ms-2">
<t t-esc="op.variant_count"/> variants
</span>
</t>
@@ -396,7 +396,7 @@
</t>
</div>
<div class="woo-pagination">
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="unmatchedOdooPrevPage"
<button class="btn btn-secondary btn-sm" t-on-click="unmatchedOdooPrevPage"
t-att-disabled="state.unmatchedOdooPage &lt;= 1">
<i class="fa fa-chevron-left"/> Prev
</button>
@@ -404,7 +404,7 @@
Page <t t-esc="state.unmatchedOdooPage"/> of <t t-esc="unmatchedOdooTotalPages"/>
(<t t-esc="state.unmatchedOdooTotal"/> total)
</span>
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="unmatchedOdooNextPage"
<button class="btn btn-secondary btn-sm" t-on-click="unmatchedOdooNextPage"
t-att-disabled="state.unmatchedOdooPage &gt;= unmatchedOdooTotalPages">
Next <i class="fa fa-chevron-right"/>
</button>
@@ -413,7 +413,7 @@
<!-- Divider -->
<div class="woo-split-divider">
<i class="fa fa-exchange woo-text-muted"/>
<i class="fa fa-exchange text-muted"/>
</div>
<!-- WooCommerce products panel -->
@@ -439,14 +439,15 @@
<div class="woo-split-item-sub">
<t t-if="wp.woo_sku">SKU: <t t-esc="wp.woo_sku"/> · </t>
<t t-esc="wp.woo_product_type"/>
<t t-if="wp.woo_category_name"> · <t t-esc="wp.woo_category_name"/></t>
</div>
<!-- Per-item actions -->
<div class="mt-1 d-flex gap-1">
<button class="woo-btn woo-btn-secondary woo-btn-sm"
<button class="btn btn-secondary btn-sm"
t-on-click.stop="() => this.createInOdoo(wp.id)">
Create in Odoo
<i class="fa fa-plus me-1"/>Create &amp; Edit in Odoo
</button>
<button class="woo-btn woo-btn-danger woo-btn-sm"
<button class="btn btn-outline-danger btn-sm"
t-on-click.stop="() => this.ignoreWoo(wp.id)">
Ignore
</button>
@@ -455,7 +456,7 @@
</t>
</div>
<div class="woo-pagination">
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="unmatchedWooPrevPage"
<button class="btn btn-secondary btn-sm" t-on-click="unmatchedWooPrevPage"
t-att-disabled="state.unmatchedWooPage &lt;= 1">
<i class="fa fa-chevron-left"/> Prev
</button>
@@ -463,7 +464,7 @@
Page <t t-esc="state.unmatchedWooPage"/> of <t t-esc="unmatchedWooTotalPages"/>
(<t t-esc="state.unmatchedWooTotal"/> total)
</span>
<button class="woo-btn woo-btn-secondary woo-btn-sm" t-on-click="unmatchedWooNextPage"
<button class="btn btn-secondary btn-sm" t-on-click="unmatchedWooNextPage"
t-att-disabled="state.unmatchedWooPage &gt;= unmatchedWooTotalPages">
Next <i class="fa fa-chevron-right"/>
</button>
@@ -474,7 +475,7 @@
<!-- Odoo-only actions (create in WC) shown below list -->
<t t-if="state.selectedOdooId">
<div class="mt-2">
<button class="woo-btn woo-btn-secondary woo-btn-sm"
<button class="btn btn-secondary btn-sm"
t-on-click="() => this.createInWC(state.selectedOdooId)">
<i class="fa fa-cloud-upload me-1"/> Create Selected in WooCommerce
</button>
@@ -494,11 +495,11 @@
</t>
<t t-else="">
<div class="woo-map-actions">
<button class="woo-btn woo-btn-secondary woo-btn-sm"
<button class="btn btn-secondary btn-sm"
t-on-click="() => this.resolveAllConflicts('use_odoo')">
Use Odoo for All
</button>
<button class="woo-btn woo-btn-secondary woo-btn-sm"
<button class="btn btn-secondary btn-sm"
t-on-click="() => this.resolveAllConflicts('use_woo')">
Use WooCommerce for All
</button>
@@ -519,7 +520,7 @@
<t t-foreach="state.conflicts" t-as="c" t-key="c.id">
<tr>
<td>
<span class="woo-badge woo-badge-conflict">
<span class="badge text-bg-warning">
<t t-esc="c.conflict_type"/>
</span>
</td>
@@ -528,11 +529,11 @@
<td><t t-esc="c.woo_value"/></td>
<td>
<div class="d-flex gap-1">
<button class="woo-btn woo-btn-secondary woo-btn-sm"
<button class="btn btn-secondary btn-sm"
t-on-click="() => this.resolveConflict(c.id, 'use_odoo')">
Use Odoo
</button>
<button class="woo-btn woo-btn-secondary woo-btn-sm"
<button class="btn btn-secondary btn-sm"
t-on-click="() => this.resolveConflict(c.id, 'use_woo')">
Use WooCommerce
</button>