feat: add WooCommerce sync dashboard widget
- WooDashboard OWL client action registered as fusion_woocommerce.woo_dashboard - Cards: pending orders (clickable), last sync (relative time), errors 24h (clickable), products mapped % with progress bar - Quick actions: Sync Now, View Conflicts, Open Mapping, View Orders - Instances table showing name, connection state, last sync datetime - Auto-refreshes every 60 s while mounted - All data fetched via standalone rpc() per Odoo 19 rules Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
142
fusion-woo-odoo/fusion_woocommerce/static/src/xml/dashboard.xml
Normal file
142
fusion-woo-odoo/fusion_woocommerce/static/src/xml/dashboard.xml
Normal file
@@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="fusion_woocommerce.Dashboard">
|
||||
<div class="o_action o_client_action woo-dashboard">
|
||||
|
||||
<div class="woo-dashboard-title">WooCommerce Dashboard</div>
|
||||
<div class="woo-dashboard-subtitle">
|
||||
At-a-glance sync status across all WooCommerce instances.
|
||||
</div>
|
||||
|
||||
<!-- Loading -->
|
||||
<t t-if="state.loading">
|
||||
<div class="woo-loading">
|
||||
<div class="woo-spinner"/>
|
||||
Loading dashboard…
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-else="">
|
||||
|
||||
<!-- Stat cards -->
|
||||
<div class="woo-cards">
|
||||
|
||||
<!-- Pending orders -->
|
||||
<div class="woo-card woo-card-pending woo-card-clickable"
|
||||
t-on-click="openOrders">
|
||||
<div class="woo-card-icon">🛒</div>
|
||||
<div class="woo-card-value" t-esc="state.pendingOrders"/>
|
||||
<div class="woo-card-label">Orders Pending Sync</div>
|
||||
<div class="woo-card-sub">Click to view orders</div>
|
||||
</div>
|
||||
|
||||
<!-- Last sync -->
|
||||
<div class="woo-card woo-card-sync">
|
||||
<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>
|
||||
<div class="woo-card-sub">
|
||||
<t t-if="state.instances.length">
|
||||
<t t-esc="state.instances.length"/> instance<t t-if="state.instances.length !== 1">s</t> configured
|
||||
</t>
|
||||
<t t-else="">No instances configured</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Errors -->
|
||||
<div class="woo-card woo-card-errors woo-card-clickable"
|
||||
t-on-click="openSyncLogs">
|
||||
<div class="woo-card-icon">⚠️</div>
|
||||
<div class="woo-card-value" t-esc="state.errors24h"/>
|
||||
<div class="woo-card-label">Errors (Last 24 h)</div>
|
||||
<div class="woo-card-sub">Click to view sync log</div>
|
||||
</div>
|
||||
|
||||
<!-- Products mapped -->
|
||||
<div class="woo-card woo-card-mapped">
|
||||
<div class="woo-card-icon">🔗</div>
|
||||
<div class="woo-card-value">
|
||||
<t t-esc="mappedPercent"/>%
|
||||
</div>
|
||||
<div class="woo-card-label">Products Mapped</div>
|
||||
<div class="woo-progress-wrap">
|
||||
<div class="woo-progress-bar"
|
||||
t-att-style="'width:' + mappedPercent + '%'"/>
|
||||
</div>
|
||||
<div class="woo-card-sub">
|
||||
<t t-esc="state.mappedCount"/> / <t t-esc="state.totalProducts"/> products
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Quick actions -->
|
||||
<div class="woo-section-title">Quick Actions</div>
|
||||
<div class="woo-quick-actions">
|
||||
|
||||
<button class="woo-btn woo-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">
|
||||
<i class="fa fa-exclamation-triangle me-1"/> View Conflicts
|
||||
</button>
|
||||
|
||||
<button class="woo-btn woo-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">
|
||||
<i class="fa fa-shopping-cart me-1"/> View Orders
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Instances table (if any) -->
|
||||
<t t-if="state.instances.length">
|
||||
<div class="woo-section-title mt-4">Instances</div>
|
||||
<div class="woo-table-wrap">
|
||||
<table class="woo-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Instance</th>
|
||||
<th>Status</th>
|
||||
<th>Last Sync</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="state.instances" t-as="inst" t-key="inst.id">
|
||||
<tr>
|
||||
<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>
|
||||
</t>
|
||||
<t t-elif="inst.state === 'error'">
|
||||
<span class="woo-badge woo-badge-error">Error</span>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span class="woo-badge woo-badge-unmapped">Draft</span>
|
||||
</t>
|
||||
</td>
|
||||
<td>
|
||||
<t t-if="inst.last_sync">
|
||||
<t t-esc="inst.last_sync"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span class="text-muted">Never</span>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
Reference in New Issue
Block a user