summaryrefslogblamecommitdiffstats
path: root/dmt/script.js
blob: bc9554cc4395bd7bdc2199348f9e665356187c8d (plain) (tree)





















































































                                                                       
                                                                
















                                                               
                                           





                                                             
                                                                 









































                                                                
const ICON_VIEW  = "⬇";
const ICON_MAINT = "↻";
const ICON_EVENT = "ϟ";
const ICON_PASS  = "✔";
const ICON_FAIL  = "✖";

let version = null;
let latest_job = -1;

async function api(x) {
    let r = await fetch(x);
    return r.json();
}

function icon_progress() {
    // Use random braille glyphs to create a moving progress effect.
    let i = Math.floor(Math.random() * (0x28ff - 0x2801)) + 0x2801;
    return `&#${i};`;
}

function set_progress(element, x) {
    if (x !== null || element.className == "") {
        element.className = (x === null ? "progress" : "");
        element.innerHTML = (x === null ? icon_progress() : x);
    }
}

function set_time(element) {
    let timestamp = element.dataset.timestamp;
    let seconds = Math.floor((Date.now() / 1000) - timestamp);
    let minutes = Math.floor(seconds / 60);
    let hours = Math.floor(minutes / 60);
    let days = Math.floor(hours / 24);

    if (seconds < 120) {
        element.innerText = `${seconds} seconds ago`;
    } else if (minutes < 120) {
        element.innerText = `${minutes} minutes ago`;
    } else if (hours < 48) {
        element.innerText = `${hours} hours ago`;
    } else {
        element.innerText = `${days} days ago`;
    }
}

function touch_job(list, job) {
    // New job, new <div>
    if (document.getElementById(`${job.job}`) === null) {
        let abv_hash = job.hash.substring(0, 16);
        let reason = (job.reason == "event" ? ICON_EVENT : ICON_MAINT);

        let element = document.createElement("div");
        list.insertBefore(element, list.childNodes[0]);

        element.innerHTML = `
        <div class="box" id="${job.job}">
            <div class="box-title">
                <a href="/api/log/${job.job}/%($CYCHE_LOG_FILENAME%)">
                    <span class="button">${ICON_VIEW}</span>
                </a>
                #${job.job}
                ${job.service}
                <small><i>${abv_hash}</i></small>

                <span class="right">
                    <span class="time" id="${job.job}_time"
                            data-timestamp="${job.time}"></span>
                    <span id="${job.job}_result"></span>
                    ${reason}
                </span>
            </div>

            <div class="box-text">
                <pre id="${job.job}_log"></pre>
            </div>
        </div>`;

        let time = document.getElementById(`${job.job}_time`);
        set_time(time);
    }

    // Update existing
    let box = document.getElementById(`${job.job}`);
    let result = document.getElementById(`${job.job}_result`);
    let log = document.getElementById(`${job.job}_log`);

    let cn = (job.reason == "remove" ? "standout" : job.result);
    box.className = `box ${cn}`;

    switch (job.result) {
        case "active": set_progress(result, null);      break;
        case "fail":   set_progress(result, ICON_FAIL); break;
        case "pass":   set_progress(result, ICON_PASS); break;
    }

    log.innerText = job.log;
}

async function update_jobs() {
    let nav_progress = document.getElementById("nav_progress");
    let no_server = document.getElementById("no_server");
    let no_jobs = document.getElementById("no_jobs");
    let list = document.getElementById("list");

    let timeout = %($CYCHE_ACTIVE_UPDATE%);

    try {
        let status = await api("/api/status");

        if (version === null) { version = status.version; }
        if (version != status.version) { location.reload(); }
        if (!status.active) { timeout = %($CYCHE_IDLE_UPDATE%); }
        set_progress(nav_progress, (status.active ? null : ""));

        for (let i = status.oldest; i <= status.newest; i++) {
            if (i >= latest_job) {
                let job = await api(`/api/job/${i}`);
                touch_job(list, job);
                latest_job = i;
            }
        }

        if (list.childElementCount > 0) {
            list.classList.remove("hidden");
            no_jobs.classList.add("hidden");
        }

        no_server.classList.add("hidden");
    } catch (ex) {
        no_server.classList.remove("hidden");
        console.log(ex);
    }

    setTimeout(update_jobs, timeout);
}

function update_times() {
    let elements = document.getElementsByClassName("time");
    for (let e of elements) {
        set_time(e);
    }
}

function update_progress() {
    let elements = document.getElementsByClassName("progress");
    for (let e of elements) {
        e.innerHTML = icon_progress();
    }
}

update_jobs();
update_progress();
setInterval(update_times, 1000);
setInterval(update_progress, %($CYCHE_PROGRESS_ANIM_SPEED%));