Files
Odoo-Modules/fusion_portal/static/src/js/technician_push.js
gsinghpal 747c814249 refactor(fusion_portal): rename from fusion_authorizer_portal + modern photo cards on accessibility selector
Rename module fusion_authorizer_portal -> fusion_portal everywhere:
manifest/assets, controllers, models, views, JS (odoo.define + asset URLs),
migration MODULE constants; plus cross-module refs in fusion_schedule,
fusion_repairs, fusion_quotations (depends + inherit_id) and the pdf_filler
import in fusion_claims. Add rename_module.sql for the one-time in-place DB
rename (ir_module_module, ir_model_data, ir_ui_view.key,
ir_module_module_dependency) required on installed envs before -u fusion_portal.
Document the rename gotcha as rule 16 in CLAUDE.md.

Redesign the Accessibility Assessment selector: replace Font Awesome icon tiles
with photo-banner cards using 7 optimized images (1000x750 PNG -> 800x600 JPEG,
~8MB -> 488KB), per-type colour accent bar + centered pill button, hover
lift/zoom. Images ship as module static files so they deploy/sync with the module.

Drop the regenerable graphify-out cache from the module.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 22:38:14 -04:00

97 lines
3.5 KiB
JavaScript

/**
* Fusion Technician Portal - Push Notification Registration
* Registers service worker and subscribes to push notifications.
* Include this script on technician portal pages.
*/
(function() {
'use strict';
// Only run on technician portal pages
if (!document.querySelector('.tech-portal') && !window.location.pathname.startsWith('/my/technician')) {
return;
}
// Get VAPID public key from meta tag or page data
var vapidMeta = document.querySelector('meta[name="vapid-public-key"]');
var vapidPublicKey = vapidMeta ? vapidMeta.content : null;
if (!vapidPublicKey || !('serviceWorker' in navigator) || !('PushManager' in window)) {
return;
}
function urlBase64ToUint8Array(base64String) {
var padding = '='.repeat((4 - base64String.length % 4) % 4);
var base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
var rawData = window.atob(base64);
var outputArray = new Uint8Array(rawData.length);
for (var i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
async function registerPushSubscription() {
try {
// Register service worker
var registration = await navigator.serviceWorker.register(
'/fusion_portal/static/src/js/technician_sw.js',
{scope: '/my/technician/'}
);
// Wait for service worker to be ready
await navigator.serviceWorker.ready;
// Check existing subscription
var subscription = await registration.pushManager.getSubscription();
if (!subscription) {
// Request permission
var permission = await Notification.requestPermission();
if (permission !== 'granted') {
console.log('[TechPush] Notification permission denied');
return;
}
// Subscribe
subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),
});
}
// Send subscription to server
var key = subscription.getKey('p256dh');
var auth = subscription.getKey('auth');
var response = await fetch('/my/technician/push/subscribe', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'call',
params: {
endpoint: subscription.endpoint,
p256dh: btoa(String.fromCharCode.apply(null, new Uint8Array(key))),
auth: btoa(String.fromCharCode.apply(null, new Uint8Array(auth))),
}
}),
});
var data = await response.json();
if (data.result && data.result.success) {
console.log('[TechPush] Push subscription registered successfully');
}
} catch (error) {
console.warn('[TechPush] Push registration failed:', error);
}
}
// Register after page load
if (document.readyState === 'complete') {
registerPushSubscription();
} else {
window.addEventListener('load', registerPushSubscription);
}
})();