Files
hub/public/sw.js
kelly 2c1f7d093f
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
feat: enterprise accounting UI harmonization for orders/invoices
- Add 3-column header layout (Buyer | Seller | Document Info) to:
  - Order create page (new)
  - Invoice create page (updated)
  - Order show page (updated with units/cases, item comments)
  - Invoice show page (updated with seller info, units/cases)
  - Quote show page (updated with seller info, units/cases)

- Add seller-initiated order creation:
  - New /orders/create route and view
  - Orders track created_by (buyer/seller)
  - New Order button on orders index

- Add ping pong order flow feature:
  - ping_pong_enabled on businesses table
  - is_ping_pong toggle per order
  - Admin toggle in Business > Suite Settings

- Add item comments per line item:
  - item_comment field on order_items, crm_invoice_items, crm_quote_items
  - Inline edit UI on order show page

- UI improvements:
  - Units/cases display (X UNITS / Y CASES)
  - Live totals in document headers
  - Consistent styling across all document types
2025-12-17 19:01:13 -07:00

115 lines
3.4 KiB
JavaScript

// Cannabrands Hub Service Worker
// Uses Workbox for caching strategies and update detection
// LOCALHOST SELF-DESTRUCT: Unregister immediately on localhost to avoid dev issues
if (self.location.hostname === 'localhost' || self.location.hostname === '127.0.0.1') {
self.addEventListener('install', () => self.skipWaiting());
self.addEventListener('activate', () => {
self.registration.unregister().then(() => {
console.log('SW self-destructed on localhost');
});
});
throw new Error('SW disabled on localhost'); // Stop execution here
}
importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.0.0/workbox-sw.js');
// Cache version - update this to trigger a new SW install
const CACHE_VERSION = 'v2';
const OFFLINE_URL = '/offline.html';
if (workbox) {
console.log('Workbox loaded successfully');
// Precache the offline page immediately
workbox.precaching.precacheAndRoute([
{ url: OFFLINE_URL, revision: CACHE_VERSION }
]);
// Cache CSS/JS assets with StaleWhileRevalidate
workbox.routing.registerRoute(
({ request }) => request.destination === 'style' || request.destination === 'script',
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'assets-' + CACHE_VERSION,
})
);
// Cache images with CacheFirst (they don't change often)
workbox.routing.registerRoute(
({ request }) => request.destination === 'image',
new workbox.strategies.CacheFirst({
cacheName: 'images-' + CACHE_VERSION,
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 100,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
}),
],
})
);
// Cache fonts with CacheFirst
workbox.routing.registerRoute(
({ request }) => request.destination === 'font',
new workbox.strategies.CacheFirst({
cacheName: 'fonts-' + CACHE_VERSION,
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 20,
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 year
}),
],
})
);
// Network-first for HTML pages with offline fallback
const networkFirstHandler = new workbox.strategies.NetworkFirst({
cacheName: 'pages-' + CACHE_VERSION,
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 50,
}),
],
});
// Custom handler for navigation requests with offline fallback
workbox.routing.registerRoute(
({ request }) => request.mode === 'navigate',
async ({ event }) => {
try {
return await networkFirstHandler.handle({ event, request: event.request });
} catch (error) {
console.log('Network failed, returning offline page');
return caches.match(OFFLINE_URL);
}
}
);
} else {
console.log('Workbox failed to load');
}
// Handle the "skip waiting" message from the client
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
// Notify clients when a new SW takes over
self.addEventListener('activate', (event) => {
event.waitUntil(
(async () => {
// Clean up old caches
const cacheNames = await caches.keys();
await Promise.all(
cacheNames
.filter((name) => !name.endsWith(CACHE_VERSION) && !name.startsWith('workbox-precache'))
.map((name) => caches.delete(name))
);
// Take control of all clients
await self.clients.claim();
})()
);
});