aktueller stand
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
FROM node:18-alpine
|
||||
FROM node:22-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
|
||||
RUN npm install --production
|
||||
RUN apk add --no-cache python3 make g++ \
|
||||
&& npm install --production
|
||||
|
||||
COPY . .
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ const { v4: uuidv4 } = require('uuid');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const crypto = require('crypto');
|
||||
const os = require('os');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
@@ -6000,6 +6001,22 @@ app.get('/health', (req, res) => {
|
||||
|
||||
startAutomationWorker();
|
||||
|
||||
function logRuntimeInfo() {
|
||||
let osPretty = '';
|
||||
try {
|
||||
const raw = fs.readFileSync('/etc/os-release', 'utf8');
|
||||
const match = raw.match(/^PRETTY_NAME="?(.*?)"?$/m);
|
||||
if (match && match[1]) {
|
||||
osPretty = match[1];
|
||||
}
|
||||
} catch (error) {
|
||||
// ignore
|
||||
}
|
||||
const osInfo = osPretty || `${os.platform()} ${os.release()}`;
|
||||
console.log(`Runtime: Node ${process.version}, OS ${osInfo}`);
|
||||
}
|
||||
|
||||
app.listen(PORT, '0.0.0.0', () => {
|
||||
logRuntimeInfo();
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
});
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
let sortState = { key: 'next', dir: 'asc' };
|
||||
let listInstance = null;
|
||||
let sse = null;
|
||||
let relativeTimer = null;
|
||||
|
||||
function toDateTimeLocal(value) {
|
||||
if (!value) return '';
|
||||
@@ -509,6 +510,20 @@
|
||||
`;
|
||||
}
|
||||
|
||||
function updateRelativeTimes() {
|
||||
renderHero();
|
||||
if (!requestTableBody || !state.requests.length) return;
|
||||
const byId = new Map(state.requests.map((req) => [String(req.id), req]));
|
||||
requestTableBody.querySelectorAll('tr[data-id]').forEach((row) => {
|
||||
const req = byId.get(row.dataset.id);
|
||||
if (!req) return;
|
||||
const nextEl = row.querySelector('.next');
|
||||
if (nextEl) nextEl.textContent = formatRelative(req.next_run_at);
|
||||
const lastEl = row.querySelector('.last');
|
||||
if (lastEl) lastEl.textContent = formatRelative(req.last_run_at);
|
||||
});
|
||||
}
|
||||
|
||||
function renderRequests() {
|
||||
if (!requestTableBody) return;
|
||||
requestTableBody.innerHTML = '';
|
||||
@@ -946,10 +961,7 @@
|
||||
function initListInstance() {
|
||||
const container = document.getElementById('automationTable');
|
||||
if (!container) return;
|
||||
if (listInstance) {
|
||||
listInstance.remove();
|
||||
listInstance = null;
|
||||
}
|
||||
const options = {
|
||||
listClass: 'list',
|
||||
valueNames: [
|
||||
@@ -968,7 +980,6 @@
|
||||
applyFilters();
|
||||
listInstance.sort(sortState.key, { order: sortState.dir === 'desc' ? 'desc' : 'asc' });
|
||||
updateSortIndicators();
|
||||
listInstance.on('updated', updateSortIndicators);
|
||||
}
|
||||
|
||||
function applyFilters() {
|
||||
@@ -996,6 +1007,7 @@
|
||||
|
||||
return matchName && matchNext && matchLast && matchStatus && matchRuns;
|
||||
});
|
||||
updateSortIndicators();
|
||||
}
|
||||
|
||||
function getSelectedRequest() {
|
||||
@@ -1135,6 +1147,15 @@
|
||||
applyPresetDisabling();
|
||||
resetForm();
|
||||
loadRequests();
|
||||
if (!relativeTimer) {
|
||||
updateRelativeTimes();
|
||||
relativeTimer = setInterval(updateRelativeTimes, 60000);
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if (!document.hidden) {
|
||||
updateRelativeTimes();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
form.addEventListener('submit', handleSubmit);
|
||||
intervalPreset.addEventListener('change', applyPresetDisabling);
|
||||
|
||||
Reference in New Issue
Block a user