# wt-security/2.3.14/htdocs/js/wtsec_Chart.js

WebTotem Security, version 2.3.14. 572 lines.

- Page: https://pluginprobe.com/plugins/wt-security/2.3.14/code/htdocs/js/wtsec_Chart.js
- Raw: https://pluginprobe.com/plugins/wt-security/2.3.14/raw/htdocs/js/wtsec_Chart.js
- Modified: 2021-02-24T11:10:52+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/wt-security/2.3.14/code/htdocs/js/wtsec_Chart.js#L10-L20`.

```javascript
async function drawLineChart(dataset) {
    var diagram = document.getElementById('wtotem_chart_diagram');
    var days = diagram.dataset.days;

    const attacksAccessor = (d) => d.attacks;
    const blockedAccessor = (d) => d.blocked;
    const biggerAccessor = (d) =>
        d.attacks > d.blocked ? d.attacks : d.blocked;
    const dateParser = (days <= 1) ? d3.timeParse("%Y-%m-%d %H:%m:%M"): d3.timeParse("%Y-%m-%d");
    const xAccessor = (d) => dateParser(d.date);


    const chartWrapper = document.getElementById('line-chart')
    let dimensions = {
        width: chartWrapper.offsetWidth,
        height: 251,
        margin: {
            top: 15,
            right: 15,
            bottom: 40,
            left: 60,
        },
    };
    dimensions.boundedWidth =
        dimensions.width - dimensions.margin.left - dimensions.margin.right;
    dimensions.boundedHeight =
        dimensions.height - dimensions.margin.top - dimensions.margin.bottom;

    const wrapper = d3
        .select("#line-chart")
        .append("svg")
        .attr("width", dimensions.width)
        .attr("height", dimensions.height);

    const bounds = wrapper
        .append("g")
        .style(
            "transform",
            `translate(${dimensions.margin.left - 10}px, ${
                dimensions.margin.top
            }px)`
        );

    const yScale = d3
        .scaleLinear()
        .domain(d3.extent(dataset, biggerAccessor))
        .range([dimensions.boundedHeight, 0]);
    const xScale = d3
        .scaleTime()
        .domain(d3.extent(dataset, xAccessor))
        .range([0, dimensions.boundedWidth]);

    function make_y_gridlines() {
        return d3.axisLeft(yScale).ticks(5);
    }

    bounds
        .append("g")
        .attr("class", "grid")
        .call(
            make_y_gridlines().tickSize(-dimensions.boundedWidth).tickFormat("")
        );

    const area1 = d3
        .area()
        .x((d) => xScale(xAccessor(d)))
        .y0(dimensions.height)
        .y1((d) => yScale(attacksAccessor(d)));

    const area2 = d3
        .area()
        .x((d) => xScale(xAccessor(d)))
        .y0(dimensions.height)
        .y1((d) => yScale(blockedAccessor(d)));

    bounds
        .append("linearGradient")
        .attr("id", "area-gradient1")
        .attr("gradientUnits", "userSpaceOnUse")
        .attr("x1", 0)
        .attr("y1", yScale(0))
        .attr("x2", 0)
        .attr("y2", yScale(100))
        .selectAll("stop")
        .data([
            { offset: "0%", color: "#d46c6a", opacity: 0.04 },
            { offset: "100%", color: "#d46c6a", opacity: 1 },
        ])
        .enter()
        .append("stop")
        .attr("offset", function (d) {
            return d.offset;
        })
        .attr("stop-color", function (d) {
            return d.color;
        })
        .attr("stop-opacity", function (d) {
            return d.opacity;
        });

    bounds
        .append("linearGradient")
        .attr("id", "area-gradient2")
        .attr("gradientUnits", "userSpaceOnUse")
        .attr("x1", 0)
        .attr("y1", yScale(0))
        .attr("x2", 0)
        .attr("y2", yScale(100))
        .selectAll("stop")
        .data([
            { offset: "0%", color: "#bace3d", opacity: 0.02 },
            { offset: "100%", color: "#bace3d", opacity: 1 },
        ])
        .enter()
        .append("stop")
        .attr("offset", function (d) {
            return d.offset;
        })
        .attr("stop-color", function (d) {
            return d.color;
        })
        .attr("stop-opacity", function (d) {
            return d.opacity;
        });

    const lineGenerator1 = d3
        .line()
        .x((d) => xScale(xAccessor(d)))
        .y((d) => yScale(attacksAccessor(d)));
    const lineGenerator2 = d3
        .line()
        .x((d) => xScale(xAccessor(d)))
        .y((d) => yScale(attacksAccessor(d)));

    const line1 = bounds
        .append("path")
        .datum(dataset)
        .attr("d", lineGenerator1(dataset))
        .attr("class", "area")
        .attr("d", area1)
        .style("fill", "url(#area-gradient1)");

    const line2 = bounds
        .append("path")
        .datum(dataset)
        .attr("d", lineGenerator2(dataset))
        .attr("class", "area")
        .attr("d", area2)
        .style("fill", "url(#area-gradient2)");

    const yAxisGenerator = d3.axisLeft().scale(yScale);
    // const xAxisGenerator = d3.axisBottom().scale(xScale);

    let dateFormat = (days <= 1) ? d3.timeFormat("%H:%M") : (days > 31) ? d3.timeFormat("%b %Y")  : d3.timeFormat("%b %d");
    const xAxisGenerator = (days <= 1) ? d3.axisBottom().scale(xScale).ticks(d3.timeHour.every(2)).tickFormat(dateFormat) :
                           (days > 31) ? d3.axisBottom().scale(xScale).ticks(d3.timeMonth.every(1)).tickFormat(dateFormat) :
                           (days <= 7) ? d3.axisBottom().scale(xScale).ticks(d3.timeDay.every(1)).tickFormat(dateFormat) :
                               d3.axisBottom().scale(xScale).ticks(9).tickFormat(dateFormat);
    //const xAxisGenerator = d3.axisBottom().scale(xScale).ticks(ticks).tickFormat(dateFormat);

    const yAxis = bounds.append("g").attr("class", "axis").call(yAxisGenerator);
    const xAxis = bounds
        .append("g")
        .call(xAxisGenerator)
        .attr("class", "axis chart-date")
        .style("transform", `translateY(${dimensions.boundedHeight}px)`);

    const listeningRect = bounds
        .append("rect")
        .attr("class", "listening-rect")
        .attr("width", dimensions.boundedWidth)
        .attr("height", dimensions.boundedHeight)
        .on("mousemove", onMouseMove)
        .on("mouseleave", onMouseLeave);

    const tooltipAttacks = d3.select("#tooltipAttacks");
    const tooltipBlocked = d3.select("#tooltipBlocked");
    const tooltipCircle1 = bounds
        .append("circle")
        .attr("class", "tooltip-circle")
        .attr("r", 4)
        .attr("stroke", "#F3F5F6")
        .attr("fill", "#1D293F")
        .attr("stroke-width", 2)
        .style("opacity", 0);
    const tooltipCircle2 = bounds
        .append("circle")
        .attr("class", "tooltip-circle")
        .attr("r", 4)
        .attr("stroke", "#F3F5F6")
        .attr("fill", "#1D293F")
        .attr("stroke-width", 2)
        .style("opacity", 0);
    function onMouseMove() {
        const mousePosition = d3.mouse(this);
        const hoveredDate = xScale.invert(mousePosition[0]);

        const getDistanceFromHoveredDate = (d) =>
            Math.abs(xAccessor(d) - hoveredDate);
        const closestIndex = d3.scan(
            dataset,
            (a, b) =>
                getDistanceFromHoveredDate(a) - getDistanceFromHoveredDate(b)
        );
        const closestDataPoint = dataset[closestIndex];

        const closestXValue = xAccessor(closestDataPoint);
        const closestAttacksValue = attacksAccessor(closestDataPoint);
        const closestBlockedValue = blockedAccessor(closestDataPoint);

        const x = xScale(closestXValue) + dimensions.margin.left + 8;
        const yAttacks =
            yScale(closestAttacksValue) + dimensions.margin.top + 10;
        const yBlocked =
            yScale(closestBlockedValue) + dimensions.margin.top + 10;

        tooltipAttacks.style(
            "transform",
            `translate(` +
                `calc( -50% + ${x}px),` +
                `calc(-100% + ${yAttacks}px)` +
                `)`
        );
        tooltipBlocked.style(
            "transform",
            `translate(` +
                `calc( -50% + ${x}px),` +
                `calc(-100% + ${yBlocked}px)` +
                `)`
        );

        tooltipAttacks.style("opacity", 1);
        tooltipBlocked.style("opacity", 1);

        tooltipAttacks.select("#countAttacks").html(closestAttacksValue);
        tooltipBlocked.select("#countBlocked").html(closestBlockedValue);
        tooltipCircle1
            .attr("cx", xScale(closestXValue))
            .attr("cy", yScale(closestAttacksValue))
            .style("opacity", 1);
        tooltipCircle2
            .attr("cx", xScale(closestXValue))
            .attr("cy", yScale(closestBlockedValue))
            .style("opacity", 1);
    }

    function onMouseLeave() {
        tooltipAttacks.style("opacity", 0);
        tooltipBlocked.style("opacity", 0);

        tooltipCircle1.style("opacity", 0);
        tooltipCircle2.style("opacity", 0);
    }
}

const drawWafChart = (data) => {
    drawLineChart(data);
};

if(typeof waf_chart == "object"){
    drawWafChart(waf_chart);
}

var resizeTimerFirewallChart;
window.onresize = function (event) {
    clearTimeout(resizeTimerFirewallChart);
    resizeTimerFirewallChart = setTimeout(function () {
        var s = d3.select("#line-chart").selectAll("svg")
        s = s.remove();
        drawLineChart(waf_chart);
    }, 10);
};

// server-status
async function drawServerStatusChart(id, elementSelector, tooltipSelector, tooltipValueSelector, color, dataset) {
    const dataAccessor = (d) => d.value;

    let diagram  = document.querySelector(elementSelector);
    let days = diagram.dataset.days;

    const dateParser = (days <= 1) ? d3.timeParse("%Y-%m-%d %H:%m:%M"): d3.timeParse("%Y-%m-%d");

    const xAccessor = (d) => dateParser(d.date);

    const chartWrapper = document.querySelector(elementSelector);
    let dimensions = {
        width: chartWrapper.offsetWidth,
        height: 251,
        margin: {
            top: 15,
            right: 15,
            bottom: 40,
            left: 60,
        },
    };
    dimensions.boundedWidth =
        dimensions.width - dimensions.margin.left - dimensions.margin.right;
    dimensions.boundedHeight =
        dimensions.height - dimensions.margin.top - dimensions.margin.bottom;

    const wrapper = d3
        .select(elementSelector)
        .append("svg")
        .attr("width", dimensions.width)
        .attr("height", dimensions.height);

    const bounds = wrapper
        .append("g")
        .style(
            "transform",
            `translate(${dimensions.margin.left - 10}px, ${
                dimensions.margin.top
                }px)`
        );

    const yScale = d3
        .scaleLinear()
        .domain(d3.extent(dataset, dataAccessor))
        .range([dimensions.boundedHeight, 0]);
    const xScale = d3
        .scaleTime()
        .domain(d3.extent(dataset, xAccessor))
        .range([0, dimensions.boundedWidth]);

    function make_y_gridlines() {
        return d3.axisLeft(yScale).ticks(5);
    }

    bounds
        .append("g")
        .attr("class", "grid")
        .call(
            make_y_gridlines().tickSize(-dimensions.boundedWidth).tickFormat("")
        );

    const area1 = d3
        .area()
        .x((d) => xScale(xAccessor(d)))
        .y0(dimensions.height)
        .y1((d) => yScale(dataAccessor(d)));

    const gradientAreaId = "area-gradient-" + id;

    bounds
        .append("linearGradient")
        .attr("id", gradientAreaId)
        .attr("gradientUnits", "userSpaceOnUse")
        .attr("x1", 0)
        .attr("y1", yScale(0))
        .attr("x2", 0)
        .attr("y2", yScale(100))
        .selectAll("stop")
        .data([
            { offset: "0%", color: color, opacity: 0 },
            { offset: "100%", color: color, opacity: 0.6 },
        ])
        .enter()
        .append("stop")
        .attr("offset", function (d) {
            return d.offset;
        })
        .attr("stop-color", function (d) {
            return d.color;
        })
        .attr("stop-opacity", function (d) {
            return d.opacity;
        });

    const lineGenerator1 = d3
        .line()
        .x((d) => xScale(xAccessor(d)))
        .y((d) => yScale(dataAccessor(d)));

    const line1 = bounds
        .append("path")
        .datum(dataset)
        .attr("d", lineGenerator1(dataset))
        .attr("class", "area")
        .attr("d", area1)
        .style("fill", "url(#"+gradientAreaId+")");

    const yAxisGenerator = d3.axisLeft().scale(yScale);
    // const xAxisGenerator = d3.axisBottom().scale(xScale);
    let dateFormat = (days <= 1) ? d3.timeFormat("%H:%M") : (days > 31) ? d3.timeFormat("%b %Y")  : d3.timeFormat("%b %d");
    const xAxisGenerator = (days <= 1) ? d3.axisBottom().scale(xScale).ticks(d3.timeHour.every(2)).tickFormat(dateFormat) :
                           (days > 31) ? d3.axisBottom().scale(xScale).ticks(d3.timeMonth.every(1)).tickFormat(dateFormat) :
                           (days <= 7) ? d3.axisBottom().scale(xScale).ticks(d3.timeDay.every(1)).tickFormat(dateFormat) :
                               d3.axisBottom().scale(xScale).ticks(9).tickFormat(dateFormat);

    const yAxis = bounds.append("g").attr("class", "axis").call(yAxisGenerator);
    const xAxis = bounds
        .append("g")
        .call(xAxisGenerator)
        .attr("class", "axis")
        .style("transform", `translateY(${dimensions.boundedHeight}px)`);

    const listeningRect = bounds
        .append("rect")
        .attr("class", "listening-rect")
        .attr("width", dimensions.boundedWidth)
        .attr("height", dimensions.boundedHeight)
        .on("mousemove", onMouseMove)
        .on("mouseleave", onMouseLeave);

    const tooltipData = d3.select(tooltipSelector);
    const tooltipCircle1 = bounds
        .append("circle")
        .attr("class", "tooltip-circle")
        .attr("r", 4)
        .attr("stroke", "#F3F5F6")
        .attr("fill", "#1D293F")
        .attr("stroke-width", 2)
        .style("opacity", 0);

    function onMouseMove() {
        const mousePosition = d3.mouse(this);
        const hoveredDate = xScale.invert(mousePosition[0]);

        const getDistanceFromHoveredDate = (d) =>
            Math.abs(xAccessor(d) - hoveredDate);
        const closestIndex = d3.scan(
            dataset,
            (a, b) =>
                getDistanceFromHoveredDate(a) - getDistanceFromHoveredDate(b)
        );
        const closestDataPoint = dataset[closestIndex];

        const closestXValue = xAccessor(closestDataPoint);
        const closestValue = dataAccessor(closestDataPoint);

        const x = xScale(closestXValue) + dimensions.margin.left + 8;
        const yAttacks =
            yScale(closestValue) + dimensions.margin.top + 10;

        tooltipData.style(
            "transform",
            `translate(` +
            `calc( -50% + ${x}px),` +
            `calc(-100% + ${yAttacks}px)` +
            `)`
        );

        tooltipData.style("opacity", 1);

        tooltipData.select(tooltipValueSelector).html(closestValue);
        tooltipCircle1
            .attr("cx", xScale(closestXValue))
            .attr("cy", yScale(closestValue))
            .style("opacity", 1);
    }

    function onMouseLeave() {
        tooltipData.style("opacity", 0);
        tooltipCircle1.style("opacity", 0);
    }
}

const ramChartSelector = "#ram-chart";
const drawRamChart = (data) => {
    const ramTooltipSelector = "#tooltipRam";
    const ramTooltipValueSelector = "#countRam";
    const ramChartColor = "#3d50df";
    drawServerStatusChart("ram", ramChartSelector, ramTooltipSelector, ramTooltipValueSelector, ramChartColor, data);
}


if(typeof serverStatusRam == "object"){
    drawRamChart(serverStatusRam);
}


const cpuChartSelector = "#cpu-chart";
const drawCpuChart = (data) => {
    const cpuTooltipSelector = "#tooltipCpu";
    const cpuTooltipValueSelector = "#countCpu";
    const cpuChartColor = "#6d3594";
    drawServerStatusChart("cpu", cpuChartSelector, cpuTooltipSelector, cpuTooltipValueSelector, cpuChartColor, data);
}

if(typeof serverStatusCpu == "object") {
    drawCpuChart(serverStatusCpu);
}


var resizeTimerRamChart;
var resizeTimerCpuChart;

window.onresize = function (event) {

    if (document.querySelector("#ram-chart") !== null) {
        clearTimeout(resizeTimerRamChart);
        resizeTimerRamChart = setTimeout(function () {
            var s1 = d3.select("#ram-chart").selectAll("svg")
            s1 = s1.remove();
            drawRamChart(serverStatusRam);
        }, 10);
    };

    if (document.querySelector("#cpu-chart") !== null) {
        clearTimeout(resizeTimerCpuChart);
        resizeTimerCpuChart = setTimeout(function () {
            var s2 = d3.select("#cpu-chart").selectAll("svg")
            s2 = s2.remove();
            drawCpuChart(serverStatusCpu);
        }, 10);
    };
}



    // disk-chart

async function drawDiskChart_(elementSelector, data) {
// set the dimensions and margins of the graph
    var width = 150
    height = 150
    margin = 1

// The radius of the pieplot is half the width or half the height (smallest one). I subtract a bit of margin.
    var radius = Math.min(width, height) / 2 - margin

// append the svg object to the div called 'my_dataviz'
    var svg = d3.select(elementSelector)
        .append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

// Create dummy data
// var data = {a: 9, b: 20, c:30, d:8, e:12}

// set the color scale
    var color = d3.scaleOrdinal()
        .domain(data)
        .range(["#5E6977", "#3D50DF"])

// Compute the position of each group on the pie:
    var pie = d3.pie()
        .value(function(d) {return d.value; })
    var data_ready = pie(d3.entries(data))

// Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
    svg
        .selectAll('whatever')
        .data(data_ready)
        .enter()
        .append('path')
        .attr('d', d3.arc()
            .innerRadius(30)         // This is the size of the donut hole
            .outerRadius(radius)
        )
        .attr('fill', function(d){ return(color(d.data.key)) })
        .attr("stroke", "white")
        .style("stroke-width", "15px")
        .style("opacity", 1)

}


const drawDiskChart = (data) => {
    const diskData = {use: data['use'], free: data['free']};
    const discChartSelector = "#disk-chart";
    drawDiskChart_(discChartSelector, diskData);
};

if(typeof serverStatusDiscUsage == "object") {
    drawDiskChart(serverStatusDiscUsage);
}



```
