feat: Add A-Z filter for clients/suppliers in Telegram bot

- Add A-Z alphabetical filter keyboard for clients and suppliers lists
  (same pattern as company selection, without emoji)
- Increase clients/suppliers list pagination from 10 to 20 items per page
- Remove emoji from company A-Z filter button for consistency
- Add 6 new callback handlers: clients_alpha_menu, clients_alpha:LETTER,
  clients_alpha_page:PAGE:LETTER, and supplier equivalents
- Dashboard service and models updates
- Telegram bot: email handlers, auth, DB operations, internal API improvements
- Frontend: dashboard cards updates (CashFlow, Clienti, Furnizori, Treasury)
- Frontend: SolduriCompactCard and CollapsibleCard improvements
- DashboardView enhancements
- start.sh and run-with-restart.sh script updates
- IIS web.config and service worker updates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-02-21 14:34:15 +00:00
parent 1366dbc11c
commit 30f55cf18b
28 changed files with 1671 additions and 520 deletions

View File

@@ -28,10 +28,24 @@ self.addEventListener('activate', (event) => {
}),
// Take control of all clients immediately
clients.claim()
])
]).then(() => {
// Notify all clients that a new SW version is active
return clients.matchAll({ includeUncontrolled: true }).then(allClients => {
allClients.forEach(client => {
client.postMessage({ type: 'SW_UPDATED' });
});
});
})
);
});
// Message handler - allows pages to trigger SW actions
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
// Fetch event - ALWAYS network first, no caching for HTML/JS/CSS
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
@@ -47,6 +61,19 @@ self.addEventListener('fetch', (event) => {
return;
}
// index.html - bypass HTTP cache entirely to always get fresh app shell
if (
url.pathname.endsWith('index.html') ||
url.pathname === '/roa2web/' ||
url.pathname === '/roa2web'
) {
event.respondWith(
fetch(event.request, { cache: 'no-cache' })
.catch(() => caches.match(event.request))
);
return;
}
// HTML, JS, CSS - always fetch fresh from network
// This ensures PWA always loads latest version
event.respondWith(

View File

@@ -59,25 +59,34 @@
<!-- Outbound rules to set Cache-Control based on request path -->
<outboundRules>
<!-- index.html, sw.js, manifest: NEVER cache - must always be fresh -->
<rule name="No Cache for HTML and SW" preCondition="IsHTMLorSW" stopProcessing="true">
<match serverVariable="RESPONSE_Cache-Control" pattern=".*" />
<action type="Rewrite" value="no-store, no-cache, must-revalidate" />
</rule>
<!-- Hashed assets (Vite output in /assets/): cache 1 year immutable -->
<rule name="Cache Hashed Assets" preCondition="IsHashedAsset" stopProcessing="true">
<match serverVariable="RESPONSE_Cache-Control" pattern=".*" />
<action type="Rewrite" value="public, max-age=31536000, immutable" />
</rule>
<!-- API responses: NO caching (let backend cache handle it) -->
<rule name="No Cache for API" preCondition="IsAPIRequest">
<match serverVariable="RESPONSE_Cache-Control" pattern=".*" />
<action type="Rewrite" value="no-store, no-cache, must-revalidate, proxy-revalidate" />
</rule>
<!-- Static assets: cache for 1 year -->
<rule name="Cache Static Assets" preCondition="IsStaticAsset">
<match serverVariable="RESPONSE_Cache-Control" pattern=".*" />
<action type="Rewrite" value="public, max-age=31536000" />
</rule>
<preConditions>
<preCondition name="IsHTMLorSW">
<add input="{URL}" pattern="(index\.html|sw\.js|manifest\.json|\.webmanifest)$" />
</preCondition>
<preCondition name="IsHashedAsset">
<add input="{URL}" pattern="/assets/" />
</preCondition>
<preCondition name="IsAPIRequest">
<add input="{URL}" pattern="^/api/" />
</preCondition>
<preCondition name="IsStaticAsset">
<add input="{URL}" pattern="\.(js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|ico|webmanifest)$" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>