Implemented offline-first fast-paths and hardened API/Layout resilience. Added reactive offline banner, root error page, and ghost site fallbacks to handle server downtime and connection loss without crashing.

This commit is contained in:
Scott Idem
2026-01-16 16:41:32 -05:00
parent 8b611e7875
commit a10accfaaf
14 changed files with 536 additions and 564 deletions

View File

@@ -44,6 +44,16 @@ export async function load_ae_obj_id__event_session({
const params = {};
// Check if we are explicitly offline to avoid long browser timeouts
if (typeof navigator !== 'undefined' && !navigator.onLine) {
if (log_lvl) console.log('Browser is offline. Skipping API and attempting cache load.');
ae_promises.load__event_session_obj = await db_events.session.get(event_session_id);
if (ae_promises.load__event_session_obj) {
return await _handle_nested_loads(ae_promises.load__event_session_obj, { api_cfg, inc_file_li, inc_all_file_li, inc_presentation_li, inc_presenter_li, enabled, hidden, limit, offset, try_cache, log_lvl });
}
return null;
}
try {
ae_promises.load__event_session_obj = await api.get_ae_obj_id_crud({
api_cfg: api_cfg,
@@ -94,11 +104,15 @@ export async function load_ae_obj_id__event_session({
return null;
}
const current_session_id = ae_promises.load__event_session_obj.event_session_id || ae_promises.load__event_session_obj.id;
return await _handle_nested_loads(ae_promises.load__event_session_obj, { api_cfg, inc_file_li, inc_all_file_li, inc_presentation_li, inc_presenter_li, enabled, hidden, limit, offset, try_cache, log_lvl });
}
async function _handle_nested_loads(session_obj: any, { api_cfg, inc_file_li, inc_all_file_li, inc_presentation_li, inc_presenter_li, enabled, hidden, limit, offset, try_cache, log_lvl }: any) {
const current_session_id = session_obj.event_session_id || session_obj.id;
if (inc_file_li) {
// Load the files for the session
ae_promises.load__event_session_obj.event_file_li = await load_ae_obj_li__event_file({
session_obj.event_file_li = await load_ae_obj_li__event_file({
api_cfg: api_cfg,
for_obj_type: 'event_session',
for_obj_id: current_session_id,
@@ -111,7 +125,7 @@ export async function load_ae_obj_id__event_session({
if (inc_presentation_li) {
// Load the presentations for the session
ae_promises.load__event_session_obj.event_presentation_li = await load_ae_obj_li__event_presentation({
session_obj.event_presentation_li = await load_ae_obj_li__event_presentation({
api_cfg: api_cfg,
for_obj_type: 'event_session',
for_obj_id: current_session_id,
@@ -127,7 +141,7 @@ export async function load_ae_obj_id__event_session({
});
}
return ae_promises.load__event_session_obj;
return session_obj;
}
// Updated 2025-05-22
@@ -179,6 +193,21 @@ export async function load_ae_obj_li__event_session({
const params_json: key_val = {};
// Check if offline
if (typeof navigator !== 'undefined' && !navigator.onLine) {
if (log_lvl) console.log('Browser is offline. Skipping API and attempting cache load.');
ae_promises.load__event_session_obj_li = await db_events.session
.where('for_id').equals(for_obj_id)
.toArray();
// Trigger nested loads if requested
if (ae_promises.load__event_session_obj_li) {
for (let i = 0; i < ae_promises.load__event_session_obj_li.length; i++) {
await _handle_nested_loads(ae_promises.load__event_session_obj_li[i], { api_cfg, inc_file_li, inc_all_file_li, inc_presentation_li, inc_presenter_li, enabled, hidden, limit, offset, try_cache, log_lvl });
}
}
return ae_promises.load__event_session_obj_li || [];
}
try {
ae_promises.load__event_session_obj_li = await api
.get_ae_obj_li_for_obj_id_crud_v2({
@@ -234,42 +263,9 @@ export async function load_ae_obj_li__event_session({
}
}
if (inc_file_li && ae_promises.load__event_session_obj_li) {
if (ae_promises.load__event_session_obj_li) {
for (let i = 0; i < ae_promises.load__event_session_obj_li.length; i++) {
const event_session_obj = ae_promises.load__event_session_obj_li[i];
const current_session_id = event_session_obj.event_session_id || event_session_obj.id;
event_session_obj.event_file_li = await load_ae_obj_li__event_file({
api_cfg: api_cfg,
for_obj_type: 'event_session',
for_obj_id: current_session_id,
enabled: enabled,
limit: limit,
try_cache: try_cache,
log_lvl: log_lvl
});
}
}
if (inc_presentation_li && ae_promises.load__event_session_obj_li) {
for (let i = 0; i < ae_promises.load__event_session_obj_li.length; i++) {
const event_session_obj = ae_promises.load__event_session_obj_li[i];
const current_session_id = event_session_obj.event_session_id || event_session_obj.id;
event_session_obj.event_presentation_li = await load_ae_obj_li__event_presentation({
api_cfg: api_cfg,
for_obj_type: 'event_session',
for_obj_id: current_session_id,
inc_file_li: inc_all_file_li,
inc_presenter_li: inc_presenter_li,
enabled: enabled,
hidden: hidden,
limit: limit,
offset: offset,
params: params,
try_cache: try_cache,
log_lvl: log_lvl
});
await _handle_nested_loads(ae_promises.load__event_session_obj_li[i], { api_cfg, inc_file_li, inc_all_file_li, inc_presentation_li, inc_presenter_li, enabled, hidden, limit, offset, try_cache, log_lvl });
}
}