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>
97 lines
3.5 KiB
JavaScript
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);
|
|
}
|
|
})();
|