aktueller stand
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
FROM node:18-alpine
|
FROM node:22-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
|
|
||||||
RUN npm install --production
|
RUN apk add --no-cache python3 make g++ \
|
||||||
|
&& npm install --production
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const { v4: uuidv4 } = require('uuid');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
const os = require('os');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
@@ -6000,6 +6001,22 @@ app.get('/health', (req, res) => {
|
|||||||
|
|
||||||
startAutomationWorker();
|
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', () => {
|
app.listen(PORT, '0.0.0.0', () => {
|
||||||
|
logRuntimeInfo();
|
||||||
console.log(`Server running on port ${PORT}`);
|
console.log(`Server running on port ${PORT}`);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -86,6 +86,7 @@
|
|||||||
let sortState = { key: 'next', dir: 'asc' };
|
let sortState = { key: 'next', dir: 'asc' };
|
||||||
let listInstance = null;
|
let listInstance = null;
|
||||||
let sse = null;
|
let sse = null;
|
||||||
|
let relativeTimer = null;
|
||||||
|
|
||||||
function toDateTimeLocal(value) {
|
function toDateTimeLocal(value) {
|
||||||
if (!value) return '';
|
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() {
|
function renderRequests() {
|
||||||
if (!requestTableBody) return;
|
if (!requestTableBody) return;
|
||||||
requestTableBody.innerHTML = '';
|
requestTableBody.innerHTML = '';
|
||||||
@@ -946,10 +961,7 @@
|
|||||||
function initListInstance() {
|
function initListInstance() {
|
||||||
const container = document.getElementById('automationTable');
|
const container = document.getElementById('automationTable');
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
if (listInstance) {
|
|
||||||
listInstance.remove();
|
|
||||||
listInstance = null;
|
listInstance = null;
|
||||||
}
|
|
||||||
const options = {
|
const options = {
|
||||||
listClass: 'list',
|
listClass: 'list',
|
||||||
valueNames: [
|
valueNames: [
|
||||||
@@ -968,7 +980,6 @@
|
|||||||
applyFilters();
|
applyFilters();
|
||||||
listInstance.sort(sortState.key, { order: sortState.dir === 'desc' ? 'desc' : 'asc' });
|
listInstance.sort(sortState.key, { order: sortState.dir === 'desc' ? 'desc' : 'asc' });
|
||||||
updateSortIndicators();
|
updateSortIndicators();
|
||||||
listInstance.on('updated', updateSortIndicators);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyFilters() {
|
function applyFilters() {
|
||||||
@@ -996,6 +1007,7 @@
|
|||||||
|
|
||||||
return matchName && matchNext && matchLast && matchStatus && matchRuns;
|
return matchName && matchNext && matchLast && matchStatus && matchRuns;
|
||||||
});
|
});
|
||||||
|
updateSortIndicators();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSelectedRequest() {
|
function getSelectedRequest() {
|
||||||
@@ -1135,6 +1147,15 @@
|
|||||||
applyPresetDisabling();
|
applyPresetDisabling();
|
||||||
resetForm();
|
resetForm();
|
||||||
loadRequests();
|
loadRequests();
|
||||||
|
if (!relativeTimer) {
|
||||||
|
updateRelativeTimes();
|
||||||
|
relativeTimer = setInterval(updateRelativeTimes, 60000);
|
||||||
|
document.addEventListener('visibilitychange', () => {
|
||||||
|
if (!document.hidden) {
|
||||||
|
updateRelativeTimes();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
form.addEventListener('submit', handleSubmit);
|
form.addEventListener('submit', handleSubmit);
|
||||||
intervalPreset.addEventListener('change', applyPresetDisabling);
|
intervalPreset.addEventListener('change', applyPresetDisabling);
|
||||||
|
|||||||
Reference in New Issue
Block a user