TenantAtlas/apps/platform/public/js/tenantpilot/ops-ux-progress-widget-poller.js
Ahmed Darrazi a7df5c9adb
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 8m56s
chore: commit all changes (automated)
2026-05-04 14:09:40 +02:00

249 lines
7.2 KiB
JavaScript

(() => {
if (typeof window === 'undefined') {
return;
}
if (typeof window.opsUxProgressWidgetPoller === 'function') {
return;
}
window.opsUxProgressWidgetPoller = function opsUxProgressWidgetPoller() {
return {
timer: null,
activeSinceMs: null,
fastUntilMs: null,
teardownObserver: null,
isCollapsed: false,
init() {
this.onVisibilityChange = this.onVisibilityChange.bind(this);
window.addEventListener('visibilitychange', this.onVisibilityChange);
this.onNavigated = this.onNavigated.bind(this);
window.addEventListener('livewire:navigated', this.onNavigated);
this.onRunEnqueued = this.onRunEnqueued.bind(this);
window.addEventListener('ops-ux:run-enqueued', this.onRunEnqueued);
this.teardownObserver = new MutationObserver(() => {
if (!this.$el || this.$el.isConnected !== true) {
this.destroy();
}
});
this.teardownObserver.observe(document.body, { childList: true, subtree: true });
this.syncCollapsedState();
this.schedule(0);
},
destroy() {
this.stop();
window.removeEventListener('visibilitychange', this.onVisibilityChange);
window.removeEventListener('livewire:navigated', this.onNavigated);
window.removeEventListener('ops-ux:run-enqueued', this.onRunEnqueued);
if (this.teardownObserver) {
this.teardownObserver.disconnect();
this.teardownObserver = null;
}
},
currentTenantId() {
const tenantId = Number(this.$el?.dataset?.tenantId ?? this.$wire?.tenantId ?? 0);
return Number.isFinite(tenantId) ? tenantId : 0;
},
collapseStorageKey() {
return `tenantpilot:ops-ux-activity-feedback:${this.currentTenantId() || 'global'}:collapsed`;
},
readCollapsedState() {
try {
return window.sessionStorage?.getItem(this.collapseStorageKey()) === '1';
} catch {
return false;
}
},
writeCollapsedState(value) {
try {
if (!window.sessionStorage) {
return;
}
const key = this.collapseStorageKey();
if (value) {
window.sessionStorage.setItem(key, '1');
return;
}
window.sessionStorage.removeItem(key);
} catch {
}
},
syncCollapsedState() {
this.isCollapsed = this.readCollapsedState();
},
collapse() {
this.isCollapsed = true;
this.writeCollapsedState(true);
},
expand() {
this.isCollapsed = false;
this.writeCollapsedState(false);
},
stop() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
},
isModalOpen() {
return document.querySelector('[role="dialog"][aria-modal="true"]') !== null;
},
isPaused() {
if (document.hidden === true) {
return true;
}
if (this.isModalOpen()) {
return true;
}
if (!this.$el || this.$el.isConnected !== true) {
return true;
}
return false;
},
onVisibilityChange() {
if (!this.isPaused()) {
this.schedule(0);
}
},
onNavigated() {
this.syncCollapsedState();
if (!this.isPaused()) {
this.schedule(0);
}
},
onRunEnqueued(event) {
const eventTenantId = Number(event?.detail?.tenantId ?? 0);
const currentTenantId = this.currentTenantId();
if (eventTenantId > 0 && currentTenantId > 0 && eventTenantId !== currentTenantId) {
return;
}
this.fastUntilMs = Date.now() + 10_000;
this.expand();
if (!this.isPaused()) {
this.schedule(0);
}
},
activeAgeSeconds() {
if (this.activeSinceMs === null) {
return 0;
}
return Math.floor((Date.now() - this.activeSinceMs) / 1000);
},
nextIntervalMs() {
if (this.$wire?.disabled === true) {
return null;
}
if (this.$wire?.hasVisibleRuns !== true) {
this.activeSinceMs = null;
return 30_000;
}
if (this.$wire?.hasActiveRuns !== true) {
this.activeSinceMs = null;
return 5_000;
}
if (this.activeSinceMs === null) {
this.activeSinceMs = Date.now();
}
const now = Date.now();
if (this.fastUntilMs && now < this.fastUntilMs) {
return 1_000;
}
const age = this.activeAgeSeconds();
if (age < 10) {
return 1_000;
}
if (age < 60) {
return 5_000;
}
return 10_000;
},
async tick() {
if (this.isPaused()) {
this.schedule(2_000);
return;
}
try {
await this.$wire.refreshRuns();
} catch (error) {
const isCancellation = Boolean(
error &&
typeof error === 'object' &&
error.status === null &&
error.body === null &&
error.json === null &&
error.errors === null,
);
if (!isCancellation) {
console.warn('Ops UX widget refreshRuns failed', error);
}
}
const next = this.nextIntervalMs();
if (next === null) {
this.stop();
return;
}
this.schedule(next);
},
schedule(delayMs) {
this.stop();
const delay = Math.max(0, Number(delayMs ?? 0));
this.timer = setTimeout(() => {
this.tick().catch(() => {});
}, delay);
},
};
};
})();