mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-02-12 08:40:16 +00:00
123 lines
4.4 KiB
JavaScript
123 lines
4.4 KiB
JavaScript
|
|
class ContainerEventsLogClient {
|
||
|
|
overlayElem;
|
||
|
|
overlayLogElem;
|
||
|
|
pollingFrequencySec = 5;
|
||
|
|
pollingIntervalId = null;
|
||
|
|
etag = '';
|
||
|
|
debugLogging = false;
|
||
|
|
|
||
|
|
constructor() {
|
||
|
|
this.overlayElem = document.getElementById('overlay');
|
||
|
|
this.fetchAndShow();
|
||
|
|
this.pollingIntervalId = setInterval(() => this.fetchAndShow(), this.pollingFrequencySec * 1000);
|
||
|
|
}
|
||
|
|
|
||
|
|
#debug(message) {
|
||
|
|
if (this.debugLogging) {
|
||
|
|
console.debug(message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
stopPolling() {
|
||
|
|
if (this.pollingIntervalId) {
|
||
|
|
clearInterval(this.pollingIntervalId);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async storeEtag(response) {
|
||
|
|
const newEtag = response.headers.get('etag');
|
||
|
|
if (newEtag) {
|
||
|
|
this.etag = newEtag;
|
||
|
|
}
|
||
|
|
return response;
|
||
|
|
}
|
||
|
|
|
||
|
|
async getTextFromResponse(response) {
|
||
|
|
if (response.status >= 200 && response.status < 300) {
|
||
|
|
return response.text();
|
||
|
|
} else if (response.status === 304) {
|
||
|
|
this.#debug('Cache hit, nothing to do');
|
||
|
|
return Promise.reject();
|
||
|
|
// Cache hit, nothing to do.
|
||
|
|
} else {
|
||
|
|
console.error(`Got response status ${response.status}, cannot continue`);
|
||
|
|
return Promise.reject();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
showLoggedEventsInOverlay(loggedEvents) {
|
||
|
|
this.overlayLogElem ||= document.getElementById('overlay-log');
|
||
|
|
this.overlayLogElem.classList.add('visible');
|
||
|
|
loggedEvents.forEach((loggedEvent) => {
|
||
|
|
const elem = this.overlayLogElem.querySelector(`.${loggedEvent.id}`);
|
||
|
|
if (elem) {
|
||
|
|
elem.lastElementChild.textContent = loggedEvent.message;
|
||
|
|
} else {
|
||
|
|
const capitalizedContainerName = loggedEvent.id.replace('nextcloud-aio-', '').replace('-', ' ').replace(/(^|\s)[a-z]/gi, (letter) => letter.toUpperCase());
|
||
|
|
const newElem = document.createElement('div');
|
||
|
|
newElem.className = loggedEvent.id;
|
||
|
|
const nameElem = document.createElement('span');
|
||
|
|
nameElem.textContent = `${capitalizedContainerName}:`;
|
||
|
|
const messageElem = document.createElement('span');
|
||
|
|
messageElem.textContent = loggedEvent.message;
|
||
|
|
newElem.append(nameElem, messageElem);
|
||
|
|
this.overlayLogElem.append(newElem);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
showLoggedEventsInContainerList(loggedEvents) {
|
||
|
|
this.containerElems ||= new Map(Array.from(document.getElementsByClassName('container-elem')).map((elem) => [elem.dataset.containerId, elem.querySelector('.events-log')]));
|
||
|
|
loggedEvents.forEach((loggedEvent) => {
|
||
|
|
const textElem = this.containerElems.get(loggedEvent.id);
|
||
|
|
// Check if the element exists, the event list might contain events for containers that are
|
||
|
|
// not contained in our list.
|
||
|
|
if (textElem) {
|
||
|
|
textElem.textContent = loggedEvent.message;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
async showLoggedEvents(text) {
|
||
|
|
const loggedEvents = new Map();
|
||
|
|
this.#debug({ text });
|
||
|
|
// Split text into logged-events and filter out empty lines.
|
||
|
|
const lines = text.split('\n').filter((line) => line);
|
||
|
|
// Reduce the list of events to the last of each container.
|
||
|
|
lines.forEach((line) => {
|
||
|
|
const loggedEvent = JSON.parse(line);
|
||
|
|
loggedEvents.set(loggedEvent.id, loggedEvent);
|
||
|
|
});
|
||
|
|
if (this.overlayElem && this.overlayElem.checkVisibility()) {
|
||
|
|
this.showLoggedEventsInOverlay(loggedEvents);
|
||
|
|
} else {
|
||
|
|
this.showLoggedEventsInContainerList(loggedEvents);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fetchAndShow(args = { forceReloading: false}) {
|
||
|
|
if (args.forceReloading) {
|
||
|
|
this.etag = '';
|
||
|
|
}
|
||
|
|
this.#debug('Fetching logged events from server');
|
||
|
|
fetch('/api/events/containers', {
|
||
|
|
cache: 'no-cache',
|
||
|
|
headers: {
|
||
|
|
'If-None-Match': this.etag,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
.then((response) => this.storeEtag(response))
|
||
|
|
.then((response) => this.getTextFromResponse(response))
|
||
|
|
.then((text) => this.showLoggedEvents(text))
|
||
|
|
.catch((error) => {
|
||
|
|
if (error instanceof Error) {
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
document.addEventListener('DOMContentLoaded', () => {
|
||
|
|
window.containerEventsLogClient = new ContainerEventsLogClient();
|
||
|
|
});
|