parent
d4a3c36b60
commit
f48d4decfd
@ -0,0 +1,81 @@
|
|||||||
|
<div id="dialog" class="input-dialog border-round">
|
||||||
|
<input id="server_name" type="text" placeholder="Node/Computer name"/>
|
||||||
|
<div class="cols">
|
||||||
|
<div class="menu border-right" style="margin-right:4px">
|
||||||
|
<div class="border-round"><i class="fa fa-bars"></i> Setup</div>
|
||||||
|
<div id="menu-items" class="items" >
|
||||||
|
<div class="item active" onclick="jx.dom.hide('folder_input'); jx.dom.show('app_input'); jx.dom.set.focus('apps') ">
|
||||||
|
<i class="fa fa-cog"></i>
|
||||||
|
Apps</div>
|
||||||
|
<div class="item active" onclick="jx.dom.hide('app_input'); jx.dom.show('folder_input'); jx.dom.set.focus('folders') ">
|
||||||
|
<i class="fa fa-folder-open"></i> Folders
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div id="app_input">
|
||||||
|
<div class="caption" style="display:grid; grid-template-columns: 32px auto">
|
||||||
|
<i class="fa fa-cog"></i>
|
||||||
|
Apps to Monitor</div>
|
||||||
|
<input id="apps" type="text" placeholder="app_1, app_2"/>
|
||||||
|
|
||||||
|
<div class="option">
|
||||||
|
<input type="checkbox" id="reboot" style="display:none"/>
|
||||||
|
<label for="reboot" class="active">
|
||||||
|
<div class="" align="center">
|
||||||
|
<i id="check_reboot" class="fa fa-times" onclick="$('#reboot').prop('checked',false)"></i>
|
||||||
|
<i class="fa fa-check" onclick="$('#reboot').prop('checked',true)"></i>
|
||||||
|
</div>
|
||||||
|
<div>Reboot Apps on this node/computer</div>
|
||||||
|
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="folder_input" style="display:grid; grid-template-columns: 32px auto; display:none;">
|
||||||
|
<div class="caption" >
|
||||||
|
<i class="fa fa-folder-open"></i> Folders to Monitor</div>
|
||||||
|
<input id="folders" type="text" placeholder="path_1, path_2"/>
|
||||||
|
|
||||||
|
<div class="option">
|
||||||
|
<input type="checkbox" id="archive" style="display:none"/>
|
||||||
|
<label for="archive" class="active">
|
||||||
|
<div class="" align="center">
|
||||||
|
<i id="check_archive" class="fa fa-times" onclick="$('#archive').prop('checked',false)"></i>
|
||||||
|
<i class="fa fa-check" onclick="$('#archive').prop('checked',true)"></i>
|
||||||
|
</div>
|
||||||
|
<div>Archive to the cloud</div>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<div style="display:grid; grid-template-columns: auto 105px 105px 105px; grid-gap:2px;">
|
||||||
|
|
||||||
|
<div></div>
|
||||||
|
<div >
|
||||||
|
<div id="download_config" class="button border-round border" onclick="downloadConfig()">
|
||||||
|
|
||||||
|
<div><i class="fa fa-download"></i></div>
|
||||||
|
<div>Config</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="button border-round border" onclick="jx.modal.close('dialog')">
|
||||||
|
<div><i class="fa fa-times"></i></div>
|
||||||
|
<div>Cancel</div>
|
||||||
|
</div>
|
||||||
|
<div class="border-round border button" onclick="save()">
|
||||||
|
<div><i class="fa fa-check"></i></div>
|
||||||
|
<div align="center">Save</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
</div>
|
@ -0,0 +1,69 @@
|
|||||||
|
body {
|
||||||
|
/* margin-left:1%; */
|
||||||
|
/* margin-right:1%; */
|
||||||
|
font-family:sans-serif;
|
||||||
|
font-weight: lighter;
|
||||||
|
font-size:14px;
|
||||||
|
}
|
||||||
|
.small {font-size:12px;}
|
||||||
|
.bold {font-weight:bold}
|
||||||
|
.no-border{border:1px solid transparent}
|
||||||
|
.border {border: 1px solid #CAD5E0}
|
||||||
|
.border-top {border-top: 1px solid #CAD5E0}
|
||||||
|
.border-right {border-right: 1px solid #CAD5E0}
|
||||||
|
.border-left {border-left: 1px solid #CAD5E0}
|
||||||
|
.border-bottom {border-bottom: 1px solid #CAD5E0}
|
||||||
|
.left {float:left}
|
||||||
|
.right{float:right}
|
||||||
|
.no-float{float:none}
|
||||||
|
|
||||||
|
.title-bar {padding:4px; margin:4px}
|
||||||
|
.title-bar .title {font-size:18px;}
|
||||||
|
.jsgrid-edit-row > .jsgrid-cell {
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active { border:2px solid transparent; cursor:pointer; margin:4px;}
|
||||||
|
.active:hover {border-bottom:2px solid #4682b4}
|
||||||
|
.edit-grid input[type=text]{
|
||||||
|
font-family:sans-serif;
|
||||||
|
font-weight:lighter;
|
||||||
|
border:0px;
|
||||||
|
border-left:2px solid transparent;
|
||||||
|
background-color:#f3f3f3;
|
||||||
|
font-size:14px;
|
||||||
|
margin:0px;
|
||||||
|
padding:4px;
|
||||||
|
outline:0px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.edit-grid input[type=text]:focus {
|
||||||
|
outline:0px;
|
||||||
|
border-left:2px solid #4682b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-times {color:maroon}
|
||||||
|
.fa-check {color:green}
|
||||||
|
.search-box{}
|
||||||
|
.search-box input[type=text] {font-size:13px;
|
||||||
|
padding-left:4px;
|
||||||
|
font-weight: lighter;
|
||||||
|
background-color:#f3f3f3;
|
||||||
|
border:4px solid transparent;
|
||||||
|
|
||||||
|
outline:none}
|
||||||
|
.search-box input[type=text]:focus{
|
||||||
|
outline:none;
|
||||||
|
border-left:4px solid #4682b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
padding:4px;
|
||||||
|
cursor:pointer;
|
||||||
|
|
||||||
|
font-family:arial;
|
||||||
|
}
|
||||||
|
.button:hover{
|
||||||
|
background-color:#4682B4 ;
|
||||||
|
color:#ffffff;
|
||||||
|
}
|
After Width: | Height: | Size: 772 B |
After Width: | Height: | Size: 1.9 KiB |
@ -0,0 +1 @@
|
|||||||
|
!function(r){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=r();else if("function"==typeof define&&define.amd)define([],r);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.uuidv5=r()}}(function(){return function r(e,n,t){function o(f,i){if(!n[f]){if(!e[f]){var u="function"==typeof require&&require;if(!i&&u)return u(f,!0);if(a)return a(f,!0);var c=new Error("Cannot find module '"+f+"'");throw c.code="MODULE_NOT_FOUND",c}var s=n[f]={exports:{}};e[f][0].call(s.exports,function(r){var n=e[f][1][r];return o(n?n:r)},s,s.exports,r,e,n,t)}return n[f].exports}for(var a="function"==typeof require&&require,f=0;f<t.length;f++)o(t[f]);return o}({1:[function(r,e,n){function t(r,e){var n=e||0,t=o;return[t[r[n++]],t[r[n++]],t[r[n++]],t[r[n++]],"-",t[r[n++]],t[r[n++]],"-",t[r[n++]],t[r[n++]],"-",t[r[n++]],t[r[n++]],"-",t[r[n++]],t[r[n++]],t[r[n++]],t[r[n++]],t[r[n++]],t[r[n++]]].join("")}for(var o=[],a=0;a<256;++a)o[a]=(a+256).toString(16).substr(1);e.exports=t},{}],2:[function(r,e,n){"use strict";function t(r,e,n,t){switch(r){case 0:return e&n^~e&t;case 1:return e^n^t;case 2:return e&n^e&t^n&t;case 3:return e^n^t}}function o(r,e){return r<<e|r>>>32-e}function a(r){var e=[1518500249,1859775393,2400959708,3395469782],n=[1732584193,4023233417,2562383102,271733878,3285377520];if("string"==typeof r){var a=unescape(encodeURIComponent(r));r=new Array(a.length);for(var f=0;f<a.length;f++)r[f]=a.charCodeAt(f)}r.push(128);for(var i=r.length/4+2,u=Math.ceil(i/16),c=new Array(u),f=0;f<u;f++){c[f]=new Array(16);for(var s=0;s<16;s++)c[f][s]=r[64*f+4*s]<<24|r[64*f+4*s+1]<<16|r[64*f+4*s+2]<<8|r[64*f+4*s+3]}c[u-1][14]=8*(r.length-1)/Math.pow(2,32),c[u-1][14]=Math.floor(c[u-1][14]),c[u-1][15]=8*(r.length-1)&4294967295;for(var f=0;f<u;f++){for(var d=new Array(80),p=0;p<16;p++)d[p]=c[f][p];for(var p=16;p<80;p++)d[p]=o(d[p-3]^d[p-8]^d[p-14]^d[p-16],1);for(var l=n[0],v=n[1],y=n[2],h=n[3],b=n[4],p=0;p<80;p++){var g=Math.floor(p/20),w=o(l,5)+t(g,v,y,h)+b+e[g]+d[p]>>>0;b=h,h=y,y=o(v,30)>>>0,v=l,l=w}n[0]=n[0]+l>>>0,n[1]=n[1]+v>>>0,n[2]=n[2]+y>>>0,n[3]=n[3]+h>>>0,n[4]=n[4]+b>>>0}return[n[0]>>24&255,n[0]>>16&255,n[0]>>8&255,255&n[0],n[1]>>24&255,n[1]>>16&255,n[1]>>8&255,255&n[1],n[2]>>24&255,n[2]>>16&255,n[2]>>8&255,255&n[2],n[3]>>24&255,n[3]>>16&255,n[3]>>8&255,255&n[3],n[4]>>24&255,n[4]>>16&255,n[4]>>8&255,255&n[4]]}e.exports=a},{}],3:[function(r,e,n){function t(r){var e=[];return r.replace(/[a-fA-F0-9]{2}/g,function(r){e.push(parseInt(r,16))}),e}function o(r){r=unescape(encodeURIComponent(r));for(var e=new Array(r.length),n=0;n<r.length;n++)e[n]=r.charCodeAt(n);return e}var a=r("./bytesToUuid");e.exports=function(r,e,n){var f=function(r,f,i,u){var c=i&&u||0;if("string"==typeof r&&(r=o(r)),"string"==typeof f&&(f=t(f)),!Array.isArray(r))throw TypeError("value must be an array of bytes");if(!Array.isArray(f)||16!==f.length)throw TypeError("namespace must be uuid string or an Array of 16 byte values");var s=n(f.concat(r));if(s[6]=15&s[6]|e,s[8]=63&s[8]|128,i)for(var d=0;d<16;++d)i[c+d]=s[d];return i||a(s)};try{f.name=r}catch(r){}return f.DNS="6ba7b810-9dad-11d1-80b4-00c04fd430c8",f.URL="6ba7b811-9dad-11d1-80b4-00c04fd430c8",f}},{"./bytesToUuid":1}],4:[function(r,e,n){var t=r("./lib/v35.js"),o=r("./lib/sha1");e.exports=t("v5",80,o)},{"./lib/sha1":2,"./lib/v35.js":3}]},{},[4])(4)});
|
@ -0,0 +1,44 @@
|
|||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1">
|
||||||
|
|
||||||
|
<link href="{{context}}static/css/fa/css/font-awesome.css" type="text/css" rel="stylesheet">
|
||||||
|
<link href="{{context}}static/css/fa/animation.css" rel="stylesheet" type="text/css">
|
||||||
|
<script src="{{context}}/static/js/jquery/jquery.min.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/dom.js"></script>
|
||||||
|
<link href="{{context}}/static/js/jsgrid/jsgrid.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="{{context}}/static/js/jsgrid/jsgrid-theme.css" rel="stylesheet" type="text/css">
|
||||||
|
<script src="{{context}}/static/js/jsgrid/jsgrid.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/dom.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/rpc.js"></script>
|
||||||
|
<link href="{{context}}/static/css/default.css" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var DATA_GRID={{grid|tojson}}
|
||||||
|
var STATUS_ICONS = {
|
||||||
|
"S":"fa ellipsis-h",
|
||||||
|
"T":"fa fa-times",
|
||||||
|
"Z":"fa fa-exclamation-triangle",
|
||||||
|
"R":"fa fa-check"
|
||||||
|
}
|
||||||
|
DATA_GRID.width = '100%'
|
||||||
|
DATA_GRID.rowClass = function(item,index){
|
||||||
|
return "small"
|
||||||
|
}
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#grid").jsGrid(DATA_GRID)
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<body>
|
||||||
|
<div class="title-bar">
|
||||||
|
<span class="title">Application/Processes</span>
|
||||||
|
</div>
|
||||||
|
<div class="search-box border" style="padding:2px; margin-bottom:4px; display:grid; grid-template-columns: auto 64px">
|
||||||
|
<input type="text" id="search" placeholder="[Enter Application Name]" onkeyup="on_keyup(event)"/>
|
||||||
|
<div class="default" style="display:grid; grid-template-columns: 50% 50%; grid-gap:2px">
|
||||||
|
<div class="active" align="center" onclick="save_emails()"><i class="fa fa-check"></i></div>
|
||||||
|
<div class="active" align="center" onclick="clear_emails()"><i class="fa fa-times"></i></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="grid"></div>
|
||||||
|
</body>
|
@ -0,0 +1,231 @@
|
|||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1">
|
||||||
|
<!--
|
||||||
|
This file is designed to provide a summary view of a given node
|
||||||
|
-->
|
||||||
|
<link href="{{context}}/static/css/default.css" type="text/css" rel="stylesheet">
|
||||||
|
<link href="{{context}}/static/css/fa/css/font-awesome.css" type="text/css" rel="stylesheet">
|
||||||
|
<link href="{{context}}/static/css/fa/animation.css" rel="stylesheet" type="text/css">
|
||||||
|
<script src="{{context}}/static/js/jquery/jquery.min.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/dom.js"></script>
|
||||||
|
<link href="{{context}}/static/js/jsgrid/jsgrid.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="{{context}}/static/js/jsgrid/jsgrid-theme.css" rel="stylesheet" type="text/css">
|
||||||
|
<script src="{{context}}/static/js/jsgrid/jsgrid.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/dom.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/rpc.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/utils.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/ext/math.js"></script>
|
||||||
|
<link href="{{context}}/static/css/default.css" rel="stylesheet" type="text/css">
|
||||||
|
<style>
|
||||||
|
.board {
|
||||||
|
display:grid ;
|
||||||
|
grid-template-rows: 32px auto;
|
||||||
|
grid-gap:10px;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.border-round {
|
||||||
|
|
||||||
|
border-radius:6px;
|
||||||
|
-webkit-border-radius:6px;
|
||||||
|
-moz-border-radius:6px;
|
||||||
|
padding:6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget {
|
||||||
|
width:100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
.widget .title {
|
||||||
|
font-size:22px;
|
||||||
|
align-items: center;
|
||||||
|
display:grid;
|
||||||
|
grid-template-columns: auto 95px;
|
||||||
|
grid-gap:2px;
|
||||||
|
}
|
||||||
|
.widget .chart {
|
||||||
|
|
||||||
|
display:grid;
|
||||||
|
grid-template-columns: 35% 35% 30%;
|
||||||
|
grid-gap:1px;
|
||||||
|
width:100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
.widget .chart iframe {width:100%; height:200px; overflow:hidden}
|
||||||
|
|
||||||
|
input[type=text] {
|
||||||
|
border:0px;
|
||||||
|
background:#f3f3f3;
|
||||||
|
padding:8px;
|
||||||
|
border-radius:6px;
|
||||||
|
margin:2px;
|
||||||
|
width:100%;
|
||||||
|
|
||||||
|
font-size:13px;
|
||||||
|
}
|
||||||
|
.search {display:grid;
|
||||||
|
grid-template-columns:auto 32px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.search i {font-size:22px; margin:4px;}
|
||||||
|
/* .search div {align-items: center;} */
|
||||||
|
/* .search div span {font-size:18px; padding:4px; margin:4px;} */
|
||||||
|
.stat-board {
|
||||||
|
display:grid;
|
||||||
|
grid-template-columns: repeat(2, [col] 1fr);
|
||||||
|
grid-gap:1px;
|
||||||
|
margin:4px;
|
||||||
|
}
|
||||||
|
.stat-board .number {
|
||||||
|
margin:1px;
|
||||||
|
background-color:#f3f3f3;
|
||||||
|
padding:4px;
|
||||||
|
}
|
||||||
|
.stat-board .number .value {
|
||||||
|
font-size:22px;
|
||||||
|
font-family:verdana;
|
||||||
|
text-align:right;
|
||||||
|
margin:4px;
|
||||||
|
}
|
||||||
|
.stat-board .number .unit {
|
||||||
|
text-align:right;
|
||||||
|
padding:4px;
|
||||||
|
border-top:1px solid #FFFFFF;
|
||||||
|
}
|
||||||
|
.fa-check {color:green}
|
||||||
|
.fa-ellipsis-h {color:orange}
|
||||||
|
.fa-times {color:maroon}
|
||||||
|
.fa-folder-open {color:#FF7F24;}
|
||||||
|
.fa-cog {color:#d3d3d3}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
// var nodes = jx.utils.keys(LOGS.apps)
|
||||||
|
// nodes = jx.math.sets.union(nodes,jx.utils.keys(LOGS.folders))
|
||||||
|
// nodes = jx.math.sets.unique(nodes)
|
||||||
|
// console.log(nodes)
|
||||||
|
|
||||||
|
// var config = {width:'100%',fields:[{'name':'name'},{'name':'mem'},{'name':'cpu'},{'name':'args'}]}
|
||||||
|
|
||||||
|
// config.rowClass = 'small'
|
||||||
|
// $(document).ready(function(){
|
||||||
|
// config.data = apps
|
||||||
|
// $('#grid').jsGrid(config)
|
||||||
|
// })
|
||||||
|
var render_grid = function(name){
|
||||||
|
var logs = {{app_logs|tojson}}
|
||||||
|
var config = {{ app_grid|tojson}}
|
||||||
|
config.data = logs[name]
|
||||||
|
config.fields[config.fields.length-1].itemTemplate = function(value,item){
|
||||||
|
var p = {"X":"fa fa-times","S":"fa fa-ellipsis-h","S+":"fa fa-ellipsis-h","R":"fa fa-check"}
|
||||||
|
var i = jx.dom.get.instance('I')
|
||||||
|
i.className = p[value]
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
var id = '#app_grid_'+name
|
||||||
|
$(id).jsGrid(config)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param id identifier to be hidden
|
||||||
|
* @param aid idetifiers to be shown
|
||||||
|
*/
|
||||||
|
var show_hide = function(xo,xi){
|
||||||
|
jx.utils.patterns.visitor(xi,jx.dom.hide)
|
||||||
|
jx.utils.patterns.visitor(xo,jx.dom.show)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<div class="board">
|
||||||
|
<div class="search">
|
||||||
|
<input type="text" placeholder="[Node/Data Collector]">
|
||||||
|
<div align="left" style="align-items: center">
|
||||||
|
<span class="active"><i class="fa fa-times"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class=" border-round">
|
||||||
|
{% for name in nodes %}
|
||||||
|
<div class="widget">
|
||||||
|
<div class="title border-bottom" align='center'>
|
||||||
|
<h3>{{name}}</h3>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<span class="active"><i class="fa fa-file-pdf-o"></i></span>
|
||||||
|
<span id="{{name}}_o" class="active" onclick="show_hide(['{{name}}_data','{{name}}_i'],['{{name}}','{{name}}_o'])" ><i class="fa fa-th" style="color:darkgray"></i></span>
|
||||||
|
<span id="{{name}}_i" class="active" onclick="show_hide(['{{name}}','{{name}}_o'],['{{name}}_i','{{name}}_data'])" style="display:none"><i class="fa fa-pie-chart" style=" color:orangered"></i></span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="{{name}}" class="chart">
|
||||||
|
<div class="no-border border-right">
|
||||||
|
<div align="center">
|
||||||
|
<h3>Crash Analysis</h3>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<iframe class="no-border" src="{{context}}/1/plot/html/pie/apps.status?index={{loop.index -1}}&no=title" style=""></iframe>
|
||||||
|
<div align="center" class="bold">
|
||||||
|
Status Counts
|
||||||
|
</div>
|
||||||
|
<div class="stat-board">
|
||||||
|
<div class="number border">
|
||||||
|
<div class="value">{{ app_summary[loop.index-1].crash}}</div>
|
||||||
|
<div class="small unit"> Crash</div>
|
||||||
|
</div>
|
||||||
|
<div class="number border">
|
||||||
|
<div class="value">{{ app_summary[loop.index-1].crash+app_summary[loop.index-1].idle+app_summary[loop.index-1].running}}</div>
|
||||||
|
<div class="small unit"> Total</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div align="center">
|
||||||
|
<h3>Resource Usage</h3>
|
||||||
|
</div>
|
||||||
|
<iframe class="no-border" src="{{context}}/1/plot/html/bar/apps.resource?index={{loop.index -1}}" style=""></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="border-left">
|
||||||
|
<div align="center">
|
||||||
|
<h3>Folder Analysis</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{%for row in folders_summary %}
|
||||||
|
|
||||||
|
{%if row.node == name %}
|
||||||
|
<div class="stat-board ">
|
||||||
|
<div class="number border">
|
||||||
|
<div class="value">{{ row.folders}}</div>
|
||||||
|
<div class="unit small">Folders</div>
|
||||||
|
</div>
|
||||||
|
<div class="number border">
|
||||||
|
<div class="value">{{ row.age}}</div>
|
||||||
|
<div class="unit small">Days</div>
|
||||||
|
</div>
|
||||||
|
<div class="number border">
|
||||||
|
<div class="value">{{ row.size}}</div>
|
||||||
|
<div class="unit small">MB Used</div>
|
||||||
|
</div>
|
||||||
|
<div class="number border">
|
||||||
|
<div class="value">{{ row.max_size}}</div>
|
||||||
|
<div class="small unit">MB Threshold</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="{{name}}_data"class="grid no-border" style="display:none;">
|
||||||
|
<div id="app_grid_{{name}}" style="margin-top:10px;"></div>
|
||||||
|
<script>
|
||||||
|
render_grid('{{name}}')
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,334 @@
|
|||||||
|
<!--
|
||||||
|
generating client keys
|
||||||
|
-->
|
||||||
|
<script src="{{context}}/static/js/uuid5.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jquery/jquery.min.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/dom.js"></script>
|
||||||
|
|
||||||
|
<link href="{{context}}/static/css/fa/css/font-awesome.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="{{context}}/static/css/fa/font-awesome-animation.css" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<link href="{{context}}/static/js/jsgrid/jsgrid.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="{{context}}/static/js/jsgrid/jsgrid-theme.css" rel="stylesheet" type="text/css">
|
||||||
|
<script src="{{context}}/static/js/jsgrid/jsgrid.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/dom.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/rpc.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/utils.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/ext/modal.js"></script>
|
||||||
|
<link href="{{context}}/static/css/default.css" rel="stylesheet" type="text/css">
|
||||||
|
<script>
|
||||||
|
var GRID={{grid|tojson}}
|
||||||
|
GRID.width = '90%'
|
||||||
|
GRID.editing = false
|
||||||
|
GRID.fields.push(
|
||||||
|
{"name":"edit","title":"","align":"center","width":"28px",
|
||||||
|
itemTemplate:function(value,item){
|
||||||
|
var size = $('#grid').jsGrid("option","data").length
|
||||||
|
|
||||||
|
if (value == null){
|
||||||
|
var i = jx.dom.get.instance('I')
|
||||||
|
i.className = 'fa fa-pencil active'
|
||||||
|
i.index = size -1
|
||||||
|
i.onclick = function(){
|
||||||
|
|
||||||
|
show_dialog(item)
|
||||||
|
setTimeout(function(){
|
||||||
|
jx.dom.set.value('server_name',item.node)
|
||||||
|
if(! item.apps){
|
||||||
|
jx.dom.set.value('apps','')
|
||||||
|
}else{
|
||||||
|
jx.dom.set.value('apps',item.apps.join(','))
|
||||||
|
}
|
||||||
|
if (! item.folders){
|
||||||
|
jx.dom.set.value('folders','')
|
||||||
|
}else{
|
||||||
|
jx.dom.set.value('folders',item.folders.join(','))
|
||||||
|
}
|
||||||
|
jx.dom.set.attribute('server_name','disabled',true)
|
||||||
|
jx.dom.set.attribute('server_name','item',item)
|
||||||
|
jx.dom.set.attribute('server_name','index',(size-1))
|
||||||
|
if (item.archive){
|
||||||
|
if (item.archive == true){
|
||||||
|
$('#check_archive').click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.reboot){
|
||||||
|
if(item.reboot == true){
|
||||||
|
$('#check_reboot').click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},200)
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
GRID.fields.push({
|
||||||
|
"name":"delete","title":"","align":"center","width":"28px",
|
||||||
|
itemTemplate:function(value,item){
|
||||||
|
var i = jx.dom.get.instance('I')
|
||||||
|
i.className='fa fa-times active'
|
||||||
|
i.onclick = function(){
|
||||||
|
|
||||||
|
|
||||||
|
$('#grid').jsGrid('deleteItem',item)
|
||||||
|
$('#grid').jsGrid('option','refresh')
|
||||||
|
var data = $('#grid').jsGrid('option','data')
|
||||||
|
post(data)
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
});
|
||||||
|
GRID.fields.push({
|
||||||
|
"name":"download","title":"","align":"center","width":"28px",
|
||||||
|
itemTemplate:function(value,item){
|
||||||
|
if (item.key != null){
|
||||||
|
var i = jx.dom.get.instance('I')
|
||||||
|
i.className = 'fa fa-download active'
|
||||||
|
i.title = 'Download Configuration for '+item.node
|
||||||
|
i.data_value = item
|
||||||
|
i.onclick = function(){
|
||||||
|
$('#grid').jsGrid('cancelEdit')
|
||||||
|
$('#grid').jsGrid('option','refresh')
|
||||||
|
var item = this.data_value
|
||||||
|
downloadConfig(item)
|
||||||
|
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
//return '<i class="fa fa-download active" title="Download Configuration" onclick="getConfig()"></i>'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
FEATURES = {{features|tojson}}
|
||||||
|
var add = function(){
|
||||||
|
var data = $('#grid').jsGrid('option','data')
|
||||||
|
if (data.length < FEATURES.clients){
|
||||||
|
show_dialog({node:'server_name'})
|
||||||
|
setTimeout(function(){
|
||||||
|
jx.dom.set.attribute('server_name','item',{})
|
||||||
|
jx.dom.set.attribute('server_name','index',-1)
|
||||||
|
jx.dom.hide('download_config')
|
||||||
|
jx.dom.set.focus('server_name')
|
||||||
|
},200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var save = function(){
|
||||||
|
var _item = jx.dom.get.attribute('server_name','item')
|
||||||
|
var index = jx.dom.get.attribute('server_name','index')
|
||||||
|
archive = jx.dom.get.attribute('archive','checked')
|
||||||
|
reboot = jx.dom.get.attribute('reboot','checked')
|
||||||
|
var apps = jx.utils.patterns.visitor(jx.dom.get.value('apps').split(','),function(name){
|
||||||
|
if(name.trim()!="")
|
||||||
|
return name.trim()
|
||||||
|
})
|
||||||
|
var folders = jx.utils.patterns.visitor(jx.dom.get.value('folders').split(','),function(name){
|
||||||
|
if(name.trim() != "")
|
||||||
|
return name.trim()
|
||||||
|
})
|
||||||
|
|
||||||
|
var item = {node:jx.dom.get.value('server_name'),key:_item.key,apps:apps,folders:folders}
|
||||||
|
item.archive = archive
|
||||||
|
item.reboot = reboot
|
||||||
|
|
||||||
|
// var index = $('#grid').jsGrid('rowByItem',_item)
|
||||||
|
data = $('#grid').jsGrid("option","data")
|
||||||
|
data[index] = item
|
||||||
|
|
||||||
|
|
||||||
|
// $('#grid').jsGrid("option","data",data)
|
||||||
|
$('#grid').jsGrid("updateItem",_item,item)
|
||||||
|
$('#grid').jsGrid("option","refresh")
|
||||||
|
post(data)
|
||||||
|
jx.modal.close()
|
||||||
|
}
|
||||||
|
var show_dialog = function(item){
|
||||||
|
var httpclient = HttpClient.instance()
|
||||||
|
var url = "{{context|safe}}/static/client-dialog.html"
|
||||||
|
httpclient.get(url,function(x){
|
||||||
|
var html = x.responseText
|
||||||
|
jx.modal.show({html:html,id:'dialog'})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
var onUpdated = function(args){
|
||||||
|
|
||||||
|
var hash = "{{hash|safe}}"
|
||||||
|
var data = $('#grid').jsGrid('option','data')
|
||||||
|
|
||||||
|
var key = uuidv5(args.item.node,"{{hash|safe}}")
|
||||||
|
if (args.itemIndex < FEATURES.clients ){
|
||||||
|
// console.log(args.itemIndex)
|
||||||
|
args.item.key = key
|
||||||
|
if (args.itemIndex < 0){
|
||||||
|
//
|
||||||
|
// let's make sure the key doesn't exist
|
||||||
|
var found = false
|
||||||
|
jx.utils.patterns.visitor(data,function(row){
|
||||||
|
if (row.key == args.item.key){
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (found == false){
|
||||||
|
data.push(args.item)
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
data[args.index] = args.item
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// post the data
|
||||||
|
post(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
var post = function(data){
|
||||||
|
// $('#grid').jsGrid("option","refresh")
|
||||||
|
$('#grid').jsGrid('option','data',data)
|
||||||
|
$('#grid').jsGrid("option","refresh")
|
||||||
|
var url = "{{context}}/1/clients"
|
||||||
|
http = HttpClient.instance()
|
||||||
|
http.setData(JSON.stringify(data))
|
||||||
|
http.setHeader("Content-Type","application/json")
|
||||||
|
http.post(url,function(x){
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
var downloadConfig = function(item){
|
||||||
|
item = (item == null)? {id:jx.dom.get.value('server_name'),key:jx.dom.get.attribute('server_name','key')}: item
|
||||||
|
var p = {id:item.node,key:item.key}
|
||||||
|
var a = jx.dom.get.instance('a')
|
||||||
|
a.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(p) ))
|
||||||
|
a.setAttribute('download','config.json');
|
||||||
|
a.style.display = 'none'
|
||||||
|
document.body.appendChild(a)
|
||||||
|
a.click()
|
||||||
|
document.body.removeChild(a);
|
||||||
|
}
|
||||||
|
GRID.onItemUpdated = onUpdated
|
||||||
|
$(document).ready(function(){
|
||||||
|
$("#grid").jsGrid(GRID)
|
||||||
|
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.caption {font-size:20px; margin:4px; font-family:arial; font-weight:lighter;}
|
||||||
|
.data-frame {
|
||||||
|
display:grid;
|
||||||
|
margin:4px;
|
||||||
|
padding:4px;
|
||||||
|
grid-template-rows: 80% 20%;
|
||||||
|
grid-gap:2px;
|
||||||
|
height:85%;
|
||||||
|
|
||||||
|
overflow:hidden;
|
||||||
|
|
||||||
|
}
|
||||||
|
.data-frame .comment {
|
||||||
|
grid-row: 2;
|
||||||
|
padding:4px;
|
||||||
|
|
||||||
|
font-size:12px;
|
||||||
|
color:gray;
|
||||||
|
font-weight: lighter;
|
||||||
|
font-family: verdana;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.fa-pencil {color:#000000;}
|
||||||
|
.data-frame .grid {
|
||||||
|
grid-row:1;
|
||||||
|
width:100%;
|
||||||
|
padding:4px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
padding:4px;
|
||||||
|
margin:4px;
|
||||||
|
font-size:11px;
|
||||||
|
border-top:1px solid #CAD5E0;
|
||||||
|
display:none;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.border-round { padding:6px; border-radius:8px;}
|
||||||
|
.input-dialog {width:500px}
|
||||||
|
.input-dialog .cols {
|
||||||
|
display:grid;
|
||||||
|
grid-template-columns: 105px auto;
|
||||||
|
}
|
||||||
|
.input-dialog .cols .menu {
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-dialog input[type=text]{
|
||||||
|
padding:6px;
|
||||||
|
width:99%;
|
||||||
|
font-size:14px;
|
||||||
|
border:1px solid #cad5e0;
|
||||||
|
margin:4px;
|
||||||
|
}
|
||||||
|
.input-dialog input[type=text]:focus {
|
||||||
|
outline:none
|
||||||
|
}
|
||||||
|
.input-dialog .option i { font-size:22px; cursor:pointer}
|
||||||
|
.input-dialog .option label {
|
||||||
|
display:grid;
|
||||||
|
grid-template-columns: 28px auto;
|
||||||
|
grid-gap:1px;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.input-dialog .option label div { display:flex; align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
padding:4px;
|
||||||
|
|
||||||
|
color:gray;
|
||||||
|
|
||||||
|
}
|
||||||
|
.input-dialog .fa-folder-open {color:orange}
|
||||||
|
.input-dialog .fa-cog {color:gray}
|
||||||
|
.input-dialog input[type=checkbox] +label .fa-check {display:none}
|
||||||
|
.input-dialog input[type=checkbox]:checked +label .fa-check {display:block;}
|
||||||
|
.input-dialog input[type=checkbox]:checked +label .fa-times {display:none;}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display:grid;
|
||||||
|
grid-template-columns: 22px auto;
|
||||||
|
}
|
||||||
|
.button i {font-size:20px;}
|
||||||
|
</style>
|
||||||
|
<div class="title-bar border-bottom">
|
||||||
|
<span class="title">Register Clients</span>
|
||||||
|
<div class="right">
|
||||||
|
<span class="active"><i class="fa fa-refresh title"></i></span>
|
||||||
|
<span class="active"><i class="fa fa-plus title" onclick="add()"></i></span>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="data-frame">
|
||||||
|
<div class="comment border-top">
|
||||||
|
|
||||||
|
|
||||||
|
<div style="width:100%">
|
||||||
|
Add clients and download the configuration template that will be used on the data-collector
|
||||||
|
<ul>
|
||||||
|
<li type="square">This account is entitled to <b>{{features.clients|tojson}}</b> data-collect(s)</li>
|
||||||
|
<li type="square">Keys are unique to data-collectors installed on systems (servers)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="grid" class="grid " ></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer small" align="center">{{uid}}</div>
|
@ -0,0 +1,9 @@
|
|||||||
|
<!-- <link rel="shortcut icon" href="{{context}}/static/img/logo-small.png" type="image/x-icon"> -->
|
||||||
|
<link rel="icon" href="{{context}}/static/img/logo-small.png" type="image/x-icon">
|
||||||
|
|
||||||
|
<link href="{{context}}/static/chartist/chartist.css" type="text/css" rel="stylesheet">
|
||||||
|
<script src="{{context}}/static/js/chart.js/chart.bundle.js"></script>
|
||||||
|
|
||||||
|
<script src="{{context}}/static/js/jquery/jquery.min.js"></script>
|
||||||
|
|
||||||
|
{% block content %} {% endblock%}
|
@ -0,0 +1,53 @@
|
|||||||
|
{% extends 'dashboard/graphs/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
// Chart.plugins.register({
|
||||||
|
// afterDatasetsDraw: function(chart) {
|
||||||
|
|
||||||
|
// var ctx = chart.chart.ctx;
|
||||||
|
// chart.data.datasets.forEach(function(dataset, i) {
|
||||||
|
// var meta = chart.getDatasetMeta(i);
|
||||||
|
// if (!meta.hidden) {
|
||||||
|
// meta.data.forEach(function(element, index) {
|
||||||
|
// // Draw the text in black, with the specified font
|
||||||
|
// ctx.fillStyle = 'rgb(0, 0, 0)';
|
||||||
|
// var fontSize = 16;
|
||||||
|
// var fontStyle = 'normal';
|
||||||
|
// var fontFamily = 'Helvetica Neue';
|
||||||
|
// ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
|
||||||
|
// // Just naively convert to string for now
|
||||||
|
// var dataString = dataset.datalabels[index].toString();
|
||||||
|
// // Make sure alignment settings are correct
|
||||||
|
// ctx.textAlign = 'center';
|
||||||
|
// ctx.textBaseline = 'middle';
|
||||||
|
// ctx.fillStyle = 'white'
|
||||||
|
// var padding = 5;
|
||||||
|
// var position = element.tooltipPosition();
|
||||||
|
|
||||||
|
// ctx.fillText(dataString, position.x -40 , position.y - (fontSize / 2) - padding);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
var context = document.getElementById('{{chart_id|safe}}').getContext('2d')
|
||||||
|
var args = {{config|tojson}}
|
||||||
|
// args.options.plugins.datalabels = {backgroundColor:'rgba(242,242,242,0.7)',
|
||||||
|
// display:function(context){
|
||||||
|
// var labels = context.dataset.datalabels
|
||||||
|
// var index = context.dataIndex
|
||||||
|
// return labels[index]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
new Chart(context, args)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<div>
|
||||||
|
<canvas id="{{chart_id|safe}}"></canvas>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,133 @@
|
|||||||
|
<!--
|
||||||
|
Managing user emails that will be notified or receive emails from the user
|
||||||
|
-->
|
||||||
|
<script src="{{context}}/static/js/jquery/jquery.min.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/dom.js"></script>
|
||||||
|
|
||||||
|
<link href="{{context}}/static/css/fa/css/font-awesome.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="{{context}}/static/css/fa/font-awesome-animation.css" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<link href="{{context}}/static/js/jsgrid/jsgrid.css" rel="stylesheet" type="text/css">
|
||||||
|
<link href="{{context}}/static/js/jsgrid/jsgrid-theme.css" rel="stylesheet" type="text/css">
|
||||||
|
<script src="{{context}}/static/js/jsgrid/jsgrid.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/dom.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/utils.js"></script>
|
||||||
|
<script src="{{context}}/static/js/jx/rpc.js"></script>
|
||||||
|
<link href="{{context}}/static/css/default.css" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var on_keyup=function(event){
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.keyCode == 13){
|
||||||
|
save_emails()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var save_emails = function(){
|
||||||
|
uid = jx.dom.get.value('search')
|
||||||
|
if(uid.match(/^.+@.+..[a-z]{2,3}$/i)){
|
||||||
|
// var data = jx.dom.get.attribute('data','data')
|
||||||
|
var emails = $('#emails').jsGrid('option','data')
|
||||||
|
emails.push({"email":uid})
|
||||||
|
$('#emails').jsGrid("option","data",emails)
|
||||||
|
$("#emails").jsGrid("refresh")
|
||||||
|
|
||||||
|
|
||||||
|
clear_emails()
|
||||||
|
post_changes(emails)
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var post_changes = function(emails){
|
||||||
|
|
||||||
|
var http = HttpClient.instance()
|
||||||
|
var url = "{{context|safe}}/1/emails"
|
||||||
|
var data = jx.utils.patterns.visitor(emails,function(item){ return item.email})
|
||||||
|
http.setData(JSON.stringify(data))
|
||||||
|
http.setHeader("Content-Type","application/json")
|
||||||
|
http.post(url,function(x){
|
||||||
|
console.log([x.responseText,x.status])
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
var clear_emails = function(){
|
||||||
|
jx.dom.set.value('search','')
|
||||||
|
jx.dom.set.focus('search')
|
||||||
|
|
||||||
|
}
|
||||||
|
var render_emails = function(emails){
|
||||||
|
|
||||||
|
var options = {width:'100%',editing:false,paging:true,
|
||||||
|
pageSize:4,
|
||||||
|
pageIndex:1,
|
||||||
|
pagerContainer: $('#email_pager'),
|
||||||
|
pagerFormat: "{prev} Page {pageIndex} of {pageCount} {next}",
|
||||||
|
pagePrevText: "<i class='fa fa-chevron-left left'> </i>",
|
||||||
|
pageNextText: "<i class='fa fa-chevron-right right' > </i>"
|
||||||
|
|
||||||
|
}
|
||||||
|
options.fields = [{name:'email',css:'small',cssheader:'small bold',title:'Email',width:'90%'},
|
||||||
|
{type:'action',align:'center',cssheader:'small bold',width:'10%',
|
||||||
|
itemTemplate:function(value,item){
|
||||||
|
// if(value != null){
|
||||||
|
var uid = jx.dom.get.value('uid').trim()
|
||||||
|
if(uid != item.email.trim()){
|
||||||
|
var i = jx.dom.get.instance('I')
|
||||||
|
i.className = 'fa fa-times'
|
||||||
|
i.onclick = function(){
|
||||||
|
var emails = $('#emails').jsGrid('option','data')
|
||||||
|
var mails = jx.utils.patterns.visitor(emails,function(node){
|
||||||
|
if(node.email.trim() != item.email.trim()){
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
})
|
||||||
|
emails = mails
|
||||||
|
// console.log(jx.utils.patterns.visitor(emails,function(item){return item.email}))
|
||||||
|
$('#emails').jsGrid('option','data',emails)
|
||||||
|
$('emails').jsGrid('refresh')
|
||||||
|
|
||||||
|
post_changes(emails)
|
||||||
|
clear_emails()
|
||||||
|
|
||||||
|
|
||||||
|
// jx.dom.set.attribute('data','data',data)
|
||||||
|
|
||||||
|
// render_emails(mails)
|
||||||
|
//
|
||||||
|
// We can now save the data
|
||||||
|
// monitor.data.submit.emails()
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// }
|
||||||
|
}]
|
||||||
|
options.data = emails
|
||||||
|
|
||||||
|
jx.dom.set.value('emails','')
|
||||||
|
$("#emails").jsGrid(options)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
var EMAILS = {{emails|tojson}}
|
||||||
|
render_emails(EMAILS)
|
||||||
|
}) ;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="uid" style="display:none">{{uid|safe}}</div>
|
||||||
|
<div class="search-box border" style="padding:2px; margin-bottom:4px; display:grid; grid-template-columns: auto 64px">
|
||||||
|
<input type="text" id="search" placeholder="[Enter Email Address]" onkeyup="on_keyup(event)"/>
|
||||||
|
<div class="default" style="display:grid; grid-template-columns: 50% 50%; grid-gap:2px">
|
||||||
|
<div class="active" align="center" onclick="save_emails()"><i class="fa fa-check"></i></div>
|
||||||
|
<div class="active" align="center" onclick="clear_emails()"><i class="fa fa-times"></i></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div id="emails"></div>
|
||||||
|
<div id="email_pager"></div>
|
||||||
|
|
||||||
|
</div>
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,5 @@
|
|||||||
|
"""
|
||||||
|
Machine learning and analytics module. This module will have :
|
||||||
|
- Basic descriptive statistics
|
||||||
|
- Machine learning models
|
||||||
|
"""
|
@ -0,0 +1,181 @@
|
|||||||
|
"""
|
||||||
|
Smart Top Analytics
|
||||||
|
Steve L. Nyemba<steve@the-phi.com>
|
||||||
|
|
||||||
|
"""
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from utils.transport import DataSourceFactory as Factory
|
||||||
|
import json
|
||||||
|
class analytics :
|
||||||
|
"""
|
||||||
|
This class generates basic statistics and some generic navigation of analytics
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self,**args) :
|
||||||
|
factory = Factory()
|
||||||
|
self.handler = factory.instance(**args['config'])
|
||||||
|
|
||||||
|
self.cache = {}
|
||||||
|
self.cache['key'] = args['key']
|
||||||
|
self.cache['name'] = self.__class__.__name__
|
||||||
|
self.init()
|
||||||
|
def init(self):
|
||||||
|
"""
|
||||||
|
Store logs as is per node i.e this enables to see the latest pull
|
||||||
|
The function will summarize
|
||||||
|
"""
|
||||||
|
key = self.cache['key']
|
||||||
|
r = self.handler.view('clients/latest_logs',key=key)
|
||||||
|
id = self.get('name')
|
||||||
|
if id in r :
|
||||||
|
nodes = r[id].keys()
|
||||||
|
self.set('nodes',nodes)
|
||||||
|
logs = {}
|
||||||
|
for name in nodes :
|
||||||
|
logs[name] = r[id][name]['log']
|
||||||
|
|
||||||
|
self.set('logs',logs)
|
||||||
|
self.set('summary',self.summary(r[id]))
|
||||||
|
self.format(self.summary(r[id]))
|
||||||
|
|
||||||
|
def summary(self,logs) :
|
||||||
|
raise Exception("needs to be implemented")
|
||||||
|
def get(self,key):
|
||||||
|
"""
|
||||||
|
This function will return a particular attribute from the cache
|
||||||
|
"""
|
||||||
|
id = self.cache['name']+'.'+key
|
||||||
|
if key not in self.cache :
|
||||||
|
return self.cache[id] if id in self.cache else None
|
||||||
|
else:
|
||||||
|
return self.cache[key] if key in self.cache else None
|
||||||
|
|
||||||
|
def set(self,key,value):
|
||||||
|
id = self.cache['name']+'.'+key
|
||||||
|
self.cache[id] = value
|
||||||
|
def from_json(self,stream) :
|
||||||
|
self.cache = json.loads(stream)
|
||||||
|
def to_json(self) :
|
||||||
|
return self.cache
|
||||||
|
class apps(analytics) :
|
||||||
|
"""
|
||||||
|
This class will handle analytics associated with applications
|
||||||
|
- latest logs
|
||||||
|
- nodes
|
||||||
|
- other summaries
|
||||||
|
"""
|
||||||
|
def __init__(self,**args):
|
||||||
|
analytics.__init__(self,**args)
|
||||||
|
logs = self.get('logs')
|
||||||
|
def init(self):
|
||||||
|
"""
|
||||||
|
This function will handle initialization of critical variables
|
||||||
|
In addition to basic known variables!
|
||||||
|
"""
|
||||||
|
analytics.init(self)
|
||||||
|
grid = {"width":"100%","editing":False,"rowClass":"small"}
|
||||||
|
grid['fields'] = [{"name":"name","title":"Process","headercss":"small"},{"name":"cpu","title":"CPU Usage","headercss":"small","type":"number"},{"name":"mem","title":"RAM Usage","headercss":"small","type":"number"},{"name":"status","title":"Status","headercss":"small","align":"center"}]
|
||||||
|
self.set('grid',grid)
|
||||||
|
|
||||||
|
def summary(self,logs):
|
||||||
|
"""
|
||||||
|
The
|
||||||
|
Status count and load assessment
|
||||||
|
"""
|
||||||
|
# logs = pd.DataFrame(self.get('logs'))
|
||||||
|
r = []
|
||||||
|
for id in logs :
|
||||||
|
row = pd.DataFrame(logs[id]['log'])
|
||||||
|
|
||||||
|
crash = np.sum(row.status == 'X')
|
||||||
|
idle = np.sum(row.status == 'S') + np.sum(row.status == 'S+')
|
||||||
|
cpu = row.cpu.sum()
|
||||||
|
mem = row.mem.sum() #{"sum":row.mem.sum(),"mean":row.mem.mean(),"sd":np.sqrt(row.mem.var())}
|
||||||
|
running = row.shape[0] - crash - idle
|
||||||
|
|
||||||
|
r.append({"node":id,"date":logs[id]['date']['long'],"running":running,"idle":idle,"crash":crash,"mem":mem,"cpu":cpu})
|
||||||
|
return r
|
||||||
|
# self.set("summary",)
|
||||||
|
def format(self,slogs) :
|
||||||
|
|
||||||
|
r = []
|
||||||
|
q = []
|
||||||
|
for row in slogs :
|
||||||
|
|
||||||
|
r.append( {"x":[row['running'],row['idle'],row['crash']],"labels":['Crash','Idle','Running'],"title":row['node'],"date":row['date']})
|
||||||
|
# q.append({"x":[[row['cpu'],row['mem']]],"labels":["CPU","RAM"],"title":"Resources","date":row['date'],"title":row['node'],"series":[ 'CPU','RAM' ]})
|
||||||
|
|
||||||
|
q.append({"x":[[row['cpu'],0],[0,row['mem']]],"labels":["",""],"title":"Resources","date":row['date'],"title":row['node'],"series":[ 'CPU','RAM' ],"ylabel":"% Resource Used"})
|
||||||
|
|
||||||
|
self.set('status',r)
|
||||||
|
self.set('resource',q)
|
||||||
|
|
||||||
|
|
||||||
|
class folders(analytics):
|
||||||
|
def __init__(self,**args):
|
||||||
|
analytics.__init__(self,**args)
|
||||||
|
def format(self,slogs):
|
||||||
|
pass
|
||||||
|
def init(self):
|
||||||
|
"""
|
||||||
|
This function will initialize the folder analysis
|
||||||
|
"""
|
||||||
|
analytics.init(self)
|
||||||
|
grid = {"width":"100%","editing":False}
|
||||||
|
grid['fields'] = [{"name":"name","name":"Process"},{"name":"size","title":"Size (MB)"},{"name":"mem","title":"RAM Usage"}]
|
||||||
|
self.set('grid',grid)
|
||||||
|
|
||||||
|
def summary(self,logs):
|
||||||
|
r = []
|
||||||
|
features = self.handler.view('clients/features',key=self.get('key'))
|
||||||
|
|
||||||
|
if features :
|
||||||
|
max_size = features['features']['folder_size']
|
||||||
|
if max_size.endswith('MB') :
|
||||||
|
max_size = int(max_size.replace('MB','').strip())
|
||||||
|
else :
|
||||||
|
max_size = int(max_size.replace('GB','').strip()) * 1000
|
||||||
|
|
||||||
|
else:
|
||||||
|
max_size = 0
|
||||||
|
for id in logs :
|
||||||
|
|
||||||
|
row = pd.DataFrame(logs[id]['log'])
|
||||||
|
size = row.size_in_kb.mean() * .001
|
||||||
|
N = row.shape[0]
|
||||||
|
age = np.round(row.age_in_days.mean(),2)
|
||||||
|
files=row.files.mean()
|
||||||
|
r.append({"node":id,"size":size,"max_size":max_size,"age":age,"folders":N,"files":files})
|
||||||
|
return r
|
||||||
|
class protocol(analytics):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class didact():
|
||||||
|
"""
|
||||||
|
This class is designed to handle data and the front-end like a didact (Halo reference)
|
||||||
|
In order to discharge its role the class serves as a wrapper around apps,folders, protocols
|
||||||
|
"""
|
||||||
|
def __init__(self,**args) :
|
||||||
|
"""
|
||||||
|
Initializing all the data classes (apps,folders,protocols) into a collection and will be
|
||||||
|
@param config data-store configuration
|
||||||
|
@param key customer key provided by calling code
|
||||||
|
"""
|
||||||
|
config = args['config']
|
||||||
|
key = args['key']
|
||||||
|
collection = [apps(config=config,key=key),folders(config=config,key=key)]
|
||||||
|
self.cache = {}
|
||||||
|
for item in collection :
|
||||||
|
self.cache = dict(self.cache,**item.cache)
|
||||||
|
|
||||||
|
r = []
|
||||||
|
for item in collection:
|
||||||
|
id = item.get('name')+'.nodes'
|
||||||
|
r += item.get(id)
|
||||||
|
self.cache['nodes'] = list(set(r) - set([None]))
|
||||||
|
def get(self,id):
|
||||||
|
return self.cache[id] if id in self.cache else None
|
||||||
|
|
||||||
|
config = {"args":{"uid":"cus_D2x3ItYNfWjSY3", "dbname":"smart-top","uri":"http://admin:@dm1n@dev.the-phi.com:5985"},"type":"CouchdbReader"}
|
||||||
|
p = folders(config = config,key="cus_D2x3ItYNfWjSY3")
|
Loading…
Reference in new issue