mirror of
https://github.com/HackPlan/NodeMonitor.git
synced 2026-01-12 15:04:53 +08:00
frontend
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
node_modules
|
||||
static/bower_components
|
||||
49
README.md
49
README.md
@@ -1,43 +1,22 @@
|
||||
# NodeMonitor
|
||||
|
||||
服务器上的状态监视器,支持查看:
|
||||
Status Monitor on the server, supports viewing:
|
||||
|
||||
* 服务器操作系统
|
||||
* 服务器当前时间
|
||||
* 服务器已运行时间
|
||||
* CPU型号
|
||||
* CPU使用状况
|
||||
* 硬盘使用状况
|
||||
* 内存使用状况(包括物理内存/Cache/真实内存/SWAP分区)
|
||||
* 系统平均负载
|
||||
* 用户进程状况
|
||||
* 所有用户进程状况
|
||||
* OS
|
||||
* Server time
|
||||
* Uptime
|
||||
* CPU model
|
||||
* CPU usage
|
||||
* Hard disk usage
|
||||
* Memory usage (including physical memory / Cache / real memory / SWAP partition)
|
||||
* System load average
|
||||
* User process
|
||||
* All user process
|
||||
|
||||
## 效果图
|
||||
## Screenshoot
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## Licence
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 faceair
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
The MIT License (MIT)
|
||||
@@ -25,14 +25,15 @@ setInterval sendData, 5000
|
||||
|
||||
exports.runWebServer = ->
|
||||
app = http.createServer (req, res) ->
|
||||
reqfile = url.parse(req.url).pathname.slice(1).match(/[a-zA-Z0-9_ -.]+/) ? 'index.html'
|
||||
reqfile = url.parse(req.url).pathname.slice(1).match(/[a-zA-Z0-9_ -.\/]+/) ? 'index.html'
|
||||
fs.readFile __dirname + '/static/' + reqfile, (err, data) ->
|
||||
if err
|
||||
res.writeHead 500
|
||||
return res.end('Error loading ' + reqfile)
|
||||
res.writeHead 200
|
||||
res.end data
|
||||
app.listen 2957
|
||||
app.listen 2957, ->
|
||||
console.log "NodeMonitor is listening on: 2957"
|
||||
return app
|
||||
|
||||
exports.runWebSocket = (app) ->
|
||||
|
||||
25
static/bower.json
Normal file
25
static/bower.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "NodeMonitor",
|
||||
"version": "0.1.0",
|
||||
"homepage": "https://github.com/faceair/NodeMonitor",
|
||||
"authors": [
|
||||
"unstop <unstop01@gmail.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"angular-sanitize": "~1.2.21",
|
||||
"at-table": "~1.0.1",
|
||||
"lodash": "~2.4.1",
|
||||
"jquery": "~2.1.1",
|
||||
"socket.io": "0.9.17",
|
||||
"socket.io-client": "~1.0.6"
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
socket = io.connect("http://you.site/")
|
||||
socket.on "data", (data) ->
|
||||
$('#hostname').html(data.os.hostname)
|
||||
$('#system').html(data.os.type + " " + data.os.release)
|
||||
$('#cpus').html('<abbr title="' + data.os.cpus + '">' + data.os.cpus + '</abbr>')
|
||||
startTime(data.os.servertime)
|
||||
$('#uptime').html(data.os.uptime)
|
||||
$('#loadavg').html(data.os.loadavg)
|
||||
|
||||
$('#totalMem').html(data.mem.totalMem)
|
||||
$('#realMem').html(data.mem.realMem)
|
||||
$('#cachedMem').html(data.mem.cachedMem)
|
||||
$('#realMemPer').attr("style","width: " + data.mem.realMemPer + "%;")
|
||||
$('#realMemPer').text("real " + data.mem.realMemPer + " %")
|
||||
$('#cachedMemPer').attr("style","width: " + data.mem.cachedMemPer + "%;")
|
||||
$('#cachedMemPer').text("cached " + data.mem.cachedMemPer + " %")
|
||||
$('#freeMemPer').attr("style","width: " + data.mem.freeMemPer + "%;")
|
||||
$('#freeMemPer').text("free " + data.mem.freeMemPer + " %")
|
||||
$('#swaptotalMem').html(data.mem.swaptotalMem)
|
||||
$('#swapUsedMem').html(data.mem.swapUsedMem)
|
||||
$('#swapUsedMemPer').attr("style","width: " + data.mem.swapUsedMemPer + "%;")
|
||||
$('#swapUsedMemPer').text("swapUsed " + data.mem.swapUsedMemPer + " %")
|
||||
$('#swapFreeMem').html(data.mem.swapFreeMem)
|
||||
$('#swapFreeMemPer').attr("style","width: " + data.mem.swapFreeMemPer + "%;")
|
||||
$('#swapFreeMemPer').text("swapFree " + data.mem.swapFreeMemPer + " %")
|
||||
|
||||
$('#diskAll').html(data.disk.diskAll)
|
||||
$('#diskUsed').html(data.disk.diskUsed)
|
||||
$('#diskUsedPer').attr("style","width: " + data.disk.diskUsedPer + "%;")
|
||||
$('#diskUsedPer').text("diskUsed " + data.disk.diskUsedPer + " %")
|
||||
$('#diskFreePer').attr("style","width: " + data.disk.diskFreePer + "%;")
|
||||
$('#diskFreePer').text("diskFree " + data.disk.diskFreePer + " %")
|
||||
|
||||
psuser = psall = ""
|
||||
for user of data.ps["user"]
|
||||
psuser += ("<tr><td>"+user+"</td><td>"+data.ps["user"][user].procNum+"</td><td>"+data.ps["user"][user].cpuPer.toFixed(1)+"%</td><td>"+(data.ps["user"][user].realMem/1024).toFixed(1)+" MB ("+data.ps["user"][user].memPer.toFixed(1)+"%)</td><td>"+(data.ps["user"][user].swapMem/1024).toFixed(1)+" MB</td></tr>")
|
||||
$("#psuser").html(psuser)
|
||||
for i of data.ps["all"]
|
||||
psall += ("<tr><td>"+data.ps["all"][i][0]+"</td><td>"+data.ps["all"][i][1]+"</td><td>"+data.ps["all"][i][2]+"</td><td>"+data.ps["all"][i][3]+"</td><td>"+data.ps["all"][i][4]+"</td><td>"+data.ps["all"][i][5]+"</td><td>"+data.ps["all"][i][6]+"</td><td>"+data.ps["all"][i][7]+"</td><td>"+data.ps["all"][i][8]+"</td><td>"+data.ps["all"][i][9]+'</td><td><abbr title="' + data.ps["all"][i][10] + '">' + data.ps["all"][i][10] + "</abbr></td></tr>")
|
||||
$("#psall").html(psall)
|
||||
|
||||
startTime = (servertime)->
|
||||
setTime new Date servertime
|
||||
setTimeout ->
|
||||
time = new Date servertime
|
||||
time.setSeconds time.getSeconds() + 1
|
||||
setTime time
|
||||
, 1000
|
||||
setTimeout ->
|
||||
time = new Date servertime
|
||||
time.setSeconds time.getSeconds() + 2
|
||||
setTime time
|
||||
, 2000
|
||||
setTimeout ->
|
||||
time = new Date servertime
|
||||
time.setSeconds time.getSeconds() + 3
|
||||
setTime time
|
||||
, 3000
|
||||
setTimeout ->
|
||||
time = new Date servertime
|
||||
time.setSeconds time.getSeconds() + 4
|
||||
setTime time
|
||||
, 4000
|
||||
|
||||
setTime = (time)->
|
||||
hours = checkTime time.getHours()
|
||||
minutes = checkTime time.getMinutes()
|
||||
seconds = checkTime time.getSeconds()
|
||||
$('#servertime').html(time.getFullYear() + "-" + (time.getMonth() + 1) + "-" + time.getDate() + " " + hours + ":" + minutes + ":" + seconds)
|
||||
|
||||
checkTime = (i) ->
|
||||
return "0" + i if i < 10
|
||||
return i
|
||||
1
static/index.html
Normal file
1
static/index.html
Normal file
File diff suppressed because one or more lines are too long
@@ -1,149 +1,140 @@
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
title NodeMonitor
|
||||
link(href='http://cdn.staticfile.org/twitter-bootstrap/3.0.2/css/bootstrap.min.css', rel='stylesheet', type='text/css')
|
||||
link(href='/style.css', rel='stylesheet', type='text/css')
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
title NodeMonitor
|
||||
link(href='http://cdn.staticfile.org/twitter-bootstrap/3.0.2/css/bootstrap.min.css', rel='stylesheet', type='text/css')
|
||||
link(href='/spinner.css', rel='stylesheet', type='text/css')
|
||||
link(href='/style.css', rel='stylesheet', type='text/css')
|
||||
|
||||
body
|
||||
#navbar-wrapper
|
||||
#navigation.navbar.navbar-default.navbar-fixed-top
|
||||
.container
|
||||
.navbar-header
|
||||
a.navbar-brand(href='/') NodeMonitor
|
||||
.navbar-collapse.collapse
|
||||
ul.nav.navbar-nav
|
||||
li.active
|
||||
a(href='/#') Top
|
||||
li
|
||||
a(href='/#System') System
|
||||
li
|
||||
a(href='/#MemoryDisk') Memory & Disk
|
||||
li
|
||||
a(href='/#User') User
|
||||
li
|
||||
a(href='/#Process') Process
|
||||
body(ng-app="main", ng-controller="MainCtrl")
|
||||
|
||||
#navbar-wrapper
|
||||
#navigation.navbar.navbar-default.navbar-fixed-top
|
||||
.container
|
||||
.navbar-header
|
||||
a.navbar-brand(href='#') NodeMonitor
|
||||
.navbar-collapse.collapse
|
||||
ul.nav.navbar-nav
|
||||
li
|
||||
a(href='/#System') System
|
||||
li
|
||||
a(href='/#MemoryDisk') Memory & Disk
|
||||
li
|
||||
a(href='/#User') User
|
||||
li
|
||||
a(href='/#Process') Process
|
||||
.container(ng-show="loading")
|
||||
.spinner
|
||||
.rect1
|
||||
.rect2
|
||||
.rect3
|
||||
.rect4
|
||||
.rect5
|
||||
.container.ng-hide(ng-hide="loading")
|
||||
.row
|
||||
.col-md-4
|
||||
#System.panel.panel-default
|
||||
.panel-heading System
|
||||
table.table
|
||||
tbody
|
||||
tr
|
||||
td HostName
|
||||
td
|
||||
span#hostname {{system.hostname}}
|
||||
tr
|
||||
td System
|
||||
td
|
||||
span#system {{system.type}} {{system.release}}
|
||||
tr
|
||||
td Cpus
|
||||
td
|
||||
span#cpus(title="{{system.cpus}}") {{system.cpus}}
|
||||
tr
|
||||
td ServerTime
|
||||
td
|
||||
span#servertime {{system.servertime}}
|
||||
tr
|
||||
td UpTime
|
||||
td
|
||||
span#uptime {{system.uptime}}
|
||||
tr
|
||||
td Loadavg
|
||||
td
|
||||
span#loadavg {{system.loadavg}}
|
||||
|
||||
.container
|
||||
.row
|
||||
.col-md-4
|
||||
#System.panel.panel-default
|
||||
.panel-heading
|
||||
h3.panel-title System
|
||||
table.table
|
||||
tbody
|
||||
tr
|
||||
td HostName
|
||||
td
|
||||
span#hostname loading...
|
||||
tr
|
||||
td System
|
||||
td
|
||||
span#system loading...
|
||||
tr
|
||||
td Cpus
|
||||
td
|
||||
span#cpus loading...
|
||||
tr
|
||||
td ServerTime
|
||||
td
|
||||
span#servertime loading...
|
||||
tr
|
||||
td UpTime
|
||||
td
|
||||
span#uptime loading...
|
||||
tr
|
||||
td Loadavg
|
||||
td
|
||||
span#loadavg.label.label-info loading...
|
||||
.col-md-8
|
||||
#MemoryDisk.panel.panel-default
|
||||
.panel-heading Memory & Disk
|
||||
.panel-body
|
||||
p Total memory
|
||||
span#totalMem.label.label-primary {{mem.totalMem}}
|
||||
span , Real memory usage
|
||||
span#realMem.label.label-danger {{mem.realMem}}
|
||||
span , Cache memory
|
||||
span#cachedMem.label.label-warning {{mem.cachedMem}}
|
||||
progress.progress
|
||||
bar(value='mem.realMemPer', type='danger')
|
||||
span {{mem.realMemPer}} %
|
||||
bar(value='mem.cachedMemPer', type='warning')
|
||||
span {{mem.cachedMemPer}} %
|
||||
bar(value='mem.freeMemPer', type='success')
|
||||
span {{mem.freeMemPer}} %
|
||||
p SWAP total
|
||||
span#swaptotalMem.label.label-primary {{mem.swaptotalMem}}
|
||||
span , has been used
|
||||
span#swapUsedMem.label.label-warning {{mem.swapUsedMem}}
|
||||
progress.progress
|
||||
bar(value='mem.swapUsedMemPer', type='warning')
|
||||
span {{mem.swapUsedMemPer}} %
|
||||
bar(value='mem.swapFreeMemPer', type='success')
|
||||
span {{mem.swapFreeMemPer}} %
|
||||
p Disk total
|
||||
span#diskAll.label.label-primary {{disk.diskAll}}
|
||||
span , has been used
|
||||
span#diskUsed.label.label-danger {{disk.diskUsed}}
|
||||
progress.progress
|
||||
bar(value='disk.diskUsedPer', type='danger')
|
||||
span {{disk.diskUsedPer}} %
|
||||
bar(value='disk.diskFreePer', type='success')
|
||||
span {{disk.diskFreePer}} %
|
||||
#User.panel.panel-default
|
||||
table.table.table-striped(at-table, at-list='psUser')
|
||||
thead
|
||||
tbody
|
||||
tr
|
||||
td(at-implicit, at-sortable, at-attribute='USER')
|
||||
td(at-implicit, at-sortable, at-attribute='PS')
|
||||
td(at-sortable, at-attribute='CPU') {{item.CPU | fixToOne}} %
|
||||
td(at-sortable, at-attribute='MEM') {{item.MEM | fixToOne}} %
|
||||
td(at-sortable, at-attribute='SWAP') {{item.SWAP | mb}} MB
|
||||
|
||||
.col-md-8
|
||||
#MemoryDisk.panel.panel-default
|
||||
.panel-heading
|
||||
h3.panel-title Memory & Disk
|
||||
.panel-body
|
||||
p Total memory
|
||||
span#totalMem.label.label-primary loading...
|
||||
span , Real memory usage
|
||||
span#realMem.label.label-danger loading...
|
||||
span , Cache memory
|
||||
span#cachedMem.label.label-warning loading...
|
||||
.progress
|
||||
#realMemPer.progress-bar.progress-bar-danger(role='progressbar', style='width: 33%;')
|
||||
| loading...
|
||||
#cachedMemPer.progress-bar.progress-bar-warning(role='progressbar', style='width: 34%;')
|
||||
| loading...
|
||||
#freeMemPer.progress-bar.progress-bar-success(role='progressbar', style='width: 33%;')
|
||||
| loading...
|
||||
p SWAP total
|
||||
span#swaptotalMem.label.label-primary loading...
|
||||
span , has been used
|
||||
span#swapUsedMem.label.label-warning loading...
|
||||
.progress
|
||||
#swapUsedMemPer.progress-bar.progress-bar-warning(role='progressbar', style='width: 50%;')
|
||||
| loading...
|
||||
#swapFreeMemPer.progress-bar.progress-bar-success(role='progressbar', style='width: 50%;')
|
||||
| loading...
|
||||
p Disk total
|
||||
span#diskAll.label.label-primary loading...
|
||||
span , has been used
|
||||
span#diskUsed.label.label-danger loading...
|
||||
.progress
|
||||
#diskUsedPer.progress-bar.progress-bar-danger(role='progressbar', style='width: 50%;')
|
||||
| loading...
|
||||
#diskFreePer.progress-bar.progress-bar-success(role='progressbar', style='width: 50%;')
|
||||
| loading...
|
||||
#User.panel.panel-default
|
||||
table.table.table-striped
|
||||
thead
|
||||
tr
|
||||
th USER
|
||||
th PS
|
||||
th %CPU
|
||||
th %MEM
|
||||
th %CACHE
|
||||
tbody#psuser
|
||||
tr
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
#Process.panel.panel-default
|
||||
table.table.table-striped(at-table, at-list='psAll')
|
||||
thead
|
||||
tbody
|
||||
tr
|
||||
td(at-implicit, at-sortable, at-attribute='USER')
|
||||
td(at-implicit, at-sortable, at-attribute='PID')
|
||||
td(at-sortable, at-attribute='CPU') {{item['CPU']}} %
|
||||
td(at-sortable, at-attribute='MEM') {{item['MEM']}} %
|
||||
td(at-sortable, at-attribute='RES') {{item.RES | mb}} MB
|
||||
td(at-sortable, at-attribute='VSZ') {{item.VSZ | mb}} MB
|
||||
td(at-implicit, at-sortable, at-attribute='TTY')
|
||||
td(at-implicit, at-sortable, at-attribute='STAT')
|
||||
td(at-implicit, at-sortable, at-attribute='TIME')
|
||||
td(at-attribute='COMMAND', title="{{item.COMMAND | nbsp}}", ng-bind-html="trustAsHtml(item.COMMAND)", width="100")
|
||||
footer
|
||||
.container
|
||||
.pull-left
|
||||
| Powered by
|
||||
a.text-muted(href='https://github.com/faceair/NodeMonitor', target='_blank') NodeMonitor
|
||||
| .
|
||||
|
||||
#Process.panel.panel-default
|
||||
table.table.table-hover.table-condensed
|
||||
thead
|
||||
tr
|
||||
th USER
|
||||
th PID
|
||||
th %CPU
|
||||
th %MEM
|
||||
th VSZ
|
||||
th RES
|
||||
th TTY
|
||||
th STAT
|
||||
th START
|
||||
th TIME
|
||||
th COMMAND
|
||||
tbody#psall
|
||||
tr
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
td loading...
|
||||
footer
|
||||
.container
|
||||
.pull-left
|
||||
| Powered by
|
||||
a.text-muted(href='https://github.com/faceair/NodeMonitor', target='_blank') NodeMonitor
|
||||
| .
|
||||
script(type='text/javascript', src='http://cdn.staticfile.org/jquery/2.0.3/jquery.min.js')
|
||||
script(type='text/javascript', src='http://cdn.staticfile.org/socket.io/0.9.16/socket.io.min.js')
|
||||
script(type='text/javascript', src='/change.js')
|
||||
script(type='text/javascript', src='/vendor/socket.io.min.js')
|
||||
script(type='text/javascript', src='/bower_components/jquery/dist/jquery.min.js')
|
||||
script(type='text/javascript', src='/bower_components/lodash/dist/lodash.min.js')
|
||||
script(type='text/javascript', src='/bower_components/angular/angular.min.js')
|
||||
script(type='text/javascript', src='/vendor/ui.bootstrap.progressbar.js')
|
||||
script(type='text/javascript', src='/bower_components/angular-sanitize/angular-sanitize.min.js')
|
||||
script(type='text/javascript', src='/bower_components/at-table/dist/angular-table.min.js')
|
||||
script(type='text/javascript', src='/main.js')
|
||||
54
static/main.coffee
Normal file
54
static/main.coffee
Normal file
@@ -0,0 +1,54 @@
|
||||
app = angular.module("main", ["angular-table", "ngSanitize", "ui.bootstrap"])
|
||||
|
||||
.controller("MainCtrl", ["$scope", "$sce", ($scope, $sce) ->
|
||||
|
||||
$scope.trustAsHtml = (d) ->
|
||||
$sce.trustAsHtml d
|
||||
|
||||
$scope.loading = true
|
||||
|
||||
socket = io.connect(":2957")
|
||||
socket.on "data", (d) ->
|
||||
# System
|
||||
$scope.system = d.os
|
||||
# User
|
||||
psUser = []
|
||||
for name, userData of d.ps["user"]
|
||||
oneUser =
|
||||
USER: name
|
||||
PS: userData["procNum"]
|
||||
CPU: userData["cpuPer"]
|
||||
MEM: userData["memPer"]
|
||||
SWAP: userData["swapMem"]
|
||||
psUser.push oneUser
|
||||
$scope.psUser = psUser
|
||||
# Process
|
||||
psAll = []
|
||||
for index, processData of d.ps["all"]
|
||||
oneProcess = _.zipObject ["USER", "PID", "CPU", "MEM", "VSZ", "RES", "TTY", "STAT", "START", "TIME", "COMMAND"], processData
|
||||
for k in ["VSZ", "MEM", "CPU", "PID", "RES"]
|
||||
oneProcess[k] = parseFloat oneProcess[k]
|
||||
psAll.push oneProcess
|
||||
$scope.psAll = psAll
|
||||
# Memory and Disk
|
||||
$scope.mem = d.mem
|
||||
$scope.disk = d.disk
|
||||
|
||||
$scope.$apply()
|
||||
$scope.loading = false
|
||||
])
|
||||
|
||||
.filter('fixToOne', ->
|
||||
(d) ->
|
||||
d.toFixed(1)
|
||||
)
|
||||
|
||||
.filter('mb', ->
|
||||
(d) ->
|
||||
(d/1024).toFixed(1)
|
||||
)
|
||||
|
||||
.filter('nbsp', ->
|
||||
(d) ->
|
||||
d.replace(/ /g, ' ')
|
||||
)
|
||||
59
static/main.js
Normal file
59
static/main.js
Normal file
@@ -0,0 +1,59 @@
|
||||
var app;
|
||||
|
||||
app = angular.module("main", ["angular-table", "ngSanitize", "ui.bootstrap"]).controller("MainCtrl", [
|
||||
"$scope", "$sce", function($scope, $sce) {
|
||||
var socket;
|
||||
$scope.trustAsHtml = function(d) {
|
||||
return $sce.trustAsHtml(d);
|
||||
};
|
||||
$scope.loading = true;
|
||||
socket = io.connect(":2957");
|
||||
return socket.on("data", function(d) {
|
||||
var index, k, name, oneProcess, oneUser, processData, psAll, psUser, userData, _i, _len, _ref, _ref1, _ref2;
|
||||
$scope.system = d.os;
|
||||
psUser = [];
|
||||
_ref = d.ps["user"];
|
||||
for (name in _ref) {
|
||||
userData = _ref[name];
|
||||
oneUser = {
|
||||
USER: name,
|
||||
PS: userData["procNum"],
|
||||
CPU: userData["cpuPer"],
|
||||
MEM: userData["memPer"],
|
||||
SWAP: userData["swapMem"]
|
||||
};
|
||||
psUser.push(oneUser);
|
||||
}
|
||||
$scope.psUser = psUser;
|
||||
psAll = [];
|
||||
_ref1 = d.ps["all"];
|
||||
for (index in _ref1) {
|
||||
processData = _ref1[index];
|
||||
oneProcess = _.zipObject(["USER", "PID", "CPU", "MEM", "VSZ", "RES", "TTY", "STAT", "START", "TIME", "COMMAND"], processData);
|
||||
_ref2 = ["VSZ", "MEM", "CPU", "PID", "RES"];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
k = _ref2[_i];
|
||||
oneProcess[k] = parseFloat(oneProcess[k]);
|
||||
}
|
||||
psAll.push(oneProcess);
|
||||
}
|
||||
$scope.psAll = psAll;
|
||||
$scope.mem = d.mem;
|
||||
$scope.disk = d.disk;
|
||||
$scope.$apply();
|
||||
return $scope.loading = false;
|
||||
});
|
||||
}
|
||||
]).filter('fixToOne', function() {
|
||||
return function(d) {
|
||||
return d.toFixed(1);
|
||||
};
|
||||
}).filter('mb', function() {
|
||||
return function(d) {
|
||||
return (d / 1024).toFixed(1);
|
||||
};
|
||||
}).filter('nbsp', function() {
|
||||
return function(d) {
|
||||
return d.replace(/ /g, ' ');
|
||||
};
|
||||
});
|
||||
53
static/spinner.css
Normal file
53
static/spinner.css
Normal file
@@ -0,0 +1,53 @@
|
||||
.spinner {
|
||||
margin: 200px auto;
|
||||
width: 50px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.spinner > div {
|
||||
background-color: #999;
|
||||
height: 100%;
|
||||
width: 6px;
|
||||
margin: 2px;
|
||||
display: inline-block;
|
||||
|
||||
-webkit-animation: stretchdelay 1.2s infinite ease-in-out;
|
||||
animation: stretchdelay 1.2s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.spinner .rect2 {
|
||||
-webkit-animation-delay: -1.1s;
|
||||
animation-delay: -1.1s;
|
||||
}
|
||||
|
||||
.spinner .rect3 {
|
||||
-webkit-animation-delay: -1.0s;
|
||||
animation-delay: -1.0s;
|
||||
}
|
||||
|
||||
.spinner .rect4 {
|
||||
-webkit-animation-delay: -0.9s;
|
||||
animation-delay: -0.9s;
|
||||
}
|
||||
|
||||
.spinner .rect5 {
|
||||
-webkit-animation-delay: -0.8s;
|
||||
animation-delay: -0.8s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes stretchdelay {
|
||||
0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
|
||||
20% { -webkit-transform: scaleY(1.0) }
|
||||
}
|
||||
|
||||
@keyframes stretchdelay {
|
||||
0%, 40%, 100% {
|
||||
transform: scaleY(0.4);
|
||||
-webkit-transform: scaleY(0.4);
|
||||
} 20% {
|
||||
transform: scaleY(1.0);
|
||||
-webkit-transform: scaleY(1.0);
|
||||
}
|
||||
}
|
||||
35
static/style.css
Executable file → Normal file
35
static/style.css
Executable file → Normal file
@@ -1,34 +1 @@
|
||||
body {
|
||||
padding-top: 70px;
|
||||
background: #E0E0E0;
|
||||
font-family: "Monaco", "Menlo", "Consolas";
|
||||
}
|
||||
a:hover, a:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
.container {
|
||||
max-width: 95%;
|
||||
margin-left: auto;
|
||||
margin-right: auto
|
||||
}
|
||||
abbr[title], abbr[data-original-title] {
|
||||
cursor: wait;
|
||||
border-bottom: 0;
|
||||
}
|
||||
table {
|
||||
font-size: 14px;
|
||||
}
|
||||
td{
|
||||
white-space:nowrap;
|
||||
}
|
||||
#System, #Process {
|
||||
overflow:hidden;
|
||||
}
|
||||
footer {
|
||||
line-height: 150%;
|
||||
padding: 10px;
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
background: #fff;
|
||||
border-top: 1px solid #CCC
|
||||
}
|
||||
body{padding-top:70px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}a:hover,a:focus{text-decoration:none}.container{max-width:95%;margin-left:auto;margin-right:auto}abbr[title],abbr[data-original-title]{cursor:wait;border-bottom:0}table{font-size:14px}table thead th{border-bottom-width:1px !important}table td{border-top:0 !important;white-space:nowrap}.panel-heading{border-color:#DDD;padding:8px;font-weight:bold;font-size:14px !important;background:none !important}.label{padding:0.15em 0.4em 0.15em;font-size:88%;font-weight:normal}#navigation{background-image:linear-gradient(#f9f9f9, #f3f3f3);text-shadow:0 1px 0 #FFF;border-bottom:1px solid #E5E5E5}#navigation a{color:#333}#System,#Process{overflow:hidden}.progress{margin:11px 0}table .glyphicon{display:inline}.glyphicon-minus{display:none !important}footer{line-height:150%;padding:10px;color:#999999;font-size:12px;background:#fff;border-top:1px solid #ccc}
|
||||
71
static/style.less
Executable file
71
static/style.less
Executable file
@@ -0,0 +1,71 @@
|
||||
body {
|
||||
padding-top: 70px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
a:hover, a:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
.container {
|
||||
max-width: 95%;
|
||||
margin-left: auto;
|
||||
margin-right: auto
|
||||
}
|
||||
abbr[title], abbr[data-original-title] {
|
||||
cursor: wait;
|
||||
border-bottom: 0;
|
||||
}
|
||||
table {
|
||||
font-size: 14px;
|
||||
thead th{
|
||||
border-bottom-width: 1px !important;
|
||||
}
|
||||
td{
|
||||
border-top: 0 !important;
|
||||
white-space:nowrap;
|
||||
}
|
||||
}
|
||||
.panel-heading{
|
||||
border-color: #DDD;
|
||||
padding: 8px;
|
||||
font-weight: bold;
|
||||
font-size: 14px !important;
|
||||
background: none !important;
|
||||
}
|
||||
.label{
|
||||
padding: 0.15em 0.4em 0.15em;
|
||||
font-size: 88%;
|
||||
font-weight: normal;
|
||||
}
|
||||
#navigation{
|
||||
background-image: linear-gradient(#F9F9F9, #F3F3F3);
|
||||
text-shadow: 0 1px 0 #FFF;
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
a{
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
#System, #Process {
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin: 11px 0;
|
||||
}
|
||||
|
||||
table .glyphicon{
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.glyphicon-minus{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
footer {
|
||||
line-height: 150%;
|
||||
padding: 10px;
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
background: #fff;
|
||||
border-top: 1px solid #CCC
|
||||
}
|
||||
2
static/vendor/socket.io.min.js
generated
vendored
Normal file
2
static/vendor/socket.io.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
206
static/vendor/ui.bootstrap.progressbar.js
vendored
Normal file
206
static/vendor/ui.bootstrap.progressbar.js
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* angular-ui-bootstrap
|
||||
* http://angular-ui.github.io/bootstrap/
|
||||
|
||||
* Version: 0.10.0 - 2014-01-14
|
||||
* License: MIT
|
||||
*/
|
||||
angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.transition","ui.bootstrap.progressbar"]);
|
||||
angular.module("ui.bootstrap.tpls", ["template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html"]);
|
||||
angular.module('ui.bootstrap.transition', [])
|
||||
|
||||
/**
|
||||
* $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.
|
||||
* @param {DOMElement} element The DOMElement that will be animated.
|
||||
* @param {string|object|function} trigger The thing that will cause the transition to start:
|
||||
* - As a string, it represents the css class to be added to the element.
|
||||
* - As an object, it represents a hash of style attributes to be applied to the element.
|
||||
* - As a function, it represents a function to be called that will cause the transition to occur.
|
||||
* @return {Promise} A promise that is resolved when the transition finishes.
|
||||
*/
|
||||
.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {
|
||||
|
||||
var $transition = function(element, trigger, options) {
|
||||
options = options || {};
|
||||
var deferred = $q.defer();
|
||||
var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];
|
||||
|
||||
var transitionEndHandler = function(event) {
|
||||
$rootScope.$apply(function() {
|
||||
element.unbind(endEventName, transitionEndHandler);
|
||||
deferred.resolve(element);
|
||||
});
|
||||
};
|
||||
|
||||
if (endEventName) {
|
||||
element.bind(endEventName, transitionEndHandler);
|
||||
}
|
||||
|
||||
// Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
|
||||
$timeout(function() {
|
||||
if ( angular.isString(trigger) ) {
|
||||
element.addClass(trigger);
|
||||
} else if ( angular.isFunction(trigger) ) {
|
||||
trigger(element);
|
||||
} else if ( angular.isObject(trigger) ) {
|
||||
element.css(trigger);
|
||||
}
|
||||
//If browser does not support transitions, instantly resolve
|
||||
if ( !endEventName ) {
|
||||
deferred.resolve(element);
|
||||
}
|
||||
});
|
||||
|
||||
// Add our custom cancel function to the promise that is returned
|
||||
// We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
|
||||
// i.e. it will therefore never raise a transitionEnd event for that transition
|
||||
deferred.promise.cancel = function() {
|
||||
if ( endEventName ) {
|
||||
element.unbind(endEventName, transitionEndHandler);
|
||||
}
|
||||
deferred.reject('Transition cancelled');
|
||||
};
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
// Work out the name of the transitionEnd event
|
||||
var transElement = document.createElement('trans');
|
||||
var transitionEndEventNames = {
|
||||
'WebkitTransition': 'webkitTransitionEnd',
|
||||
'MozTransition': 'transitionend',
|
||||
'OTransition': 'oTransitionEnd',
|
||||
'transition': 'transitionend'
|
||||
};
|
||||
var animationEndEventNames = {
|
||||
'WebkitTransition': 'webkitAnimationEnd',
|
||||
'MozTransition': 'animationend',
|
||||
'OTransition': 'oAnimationEnd',
|
||||
'transition': 'animationend'
|
||||
};
|
||||
function findEndEventName(endEventNames) {
|
||||
for (var name in endEventNames){
|
||||
if (transElement.style[name] !== undefined) {
|
||||
return endEventNames[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
$transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
|
||||
$transition.animationEndEventName = findEndEventName(animationEndEventNames);
|
||||
return $transition;
|
||||
}]);
|
||||
|
||||
angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition'])
|
||||
|
||||
.constant('progressConfig', {
|
||||
animate: true,
|
||||
max: 100
|
||||
})
|
||||
|
||||
.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', '$transition', function($scope, $attrs, progressConfig, $transition) {
|
||||
var self = this,
|
||||
bars = [],
|
||||
max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max,
|
||||
animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;
|
||||
|
||||
this.addBar = function(bar, element) {
|
||||
var oldValue = 0, index = bar.$parent.$index;
|
||||
if ( angular.isDefined(index) && bars[index] ) {
|
||||
oldValue = bars[index].value;
|
||||
}
|
||||
bars.push(bar);
|
||||
|
||||
this.update(element, bar.value, oldValue);
|
||||
|
||||
bar.$watch('value', function(value, oldValue) {
|
||||
if (value !== oldValue) {
|
||||
self.update(element, value, oldValue);
|
||||
}
|
||||
});
|
||||
|
||||
bar.$on('$destroy', function() {
|
||||
self.removeBar(bar);
|
||||
});
|
||||
};
|
||||
|
||||
// Update bar element width
|
||||
this.update = function(element, newValue, oldValue) {
|
||||
var percent = this.getPercentage(newValue);
|
||||
|
||||
if (animate) {
|
||||
element.css('width', this.getPercentage(oldValue) + '%');
|
||||
$transition(element, {width: percent + '%'});
|
||||
} else {
|
||||
element.css({'transition': 'none', 'width': percent + '%'});
|
||||
}
|
||||
};
|
||||
|
||||
this.removeBar = function(bar) {
|
||||
bars.splice(bars.indexOf(bar), 1);
|
||||
};
|
||||
|
||||
this.getPercentage = function(value) {
|
||||
return Math.round(100 * value / max);
|
||||
};
|
||||
}])
|
||||
|
||||
.directive('progress', function() {
|
||||
return {
|
||||
restrict: 'EA',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
controller: 'ProgressController',
|
||||
require: 'progress',
|
||||
scope: {},
|
||||
template: '<div class="progress" ng-transclude></div>'
|
||||
//templateUrl: 'template/progressbar/progress.html' // Works in AngularJS 1.2
|
||||
};
|
||||
})
|
||||
|
||||
.directive('bar', function() {
|
||||
return {
|
||||
restrict: 'EA',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
require: '^progress',
|
||||
scope: {
|
||||
value: '=',
|
||||
type: '@'
|
||||
},
|
||||
templateUrl: 'template/progressbar/bar.html',
|
||||
link: function(scope, element, attrs, progressCtrl) {
|
||||
progressCtrl.addBar(scope, element);
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
.directive('progressbar', function() {
|
||||
return {
|
||||
restrict: 'EA',
|
||||
replace: true,
|
||||
transclude: true,
|
||||
controller: 'ProgressController',
|
||||
scope: {
|
||||
value: '=',
|
||||
type: '@'
|
||||
},
|
||||
templateUrl: 'template/progressbar/progressbar.html',
|
||||
link: function(scope, element, attrs, progressCtrl) {
|
||||
progressCtrl.addBar(scope, angular.element(element.children()[0]));
|
||||
}
|
||||
};
|
||||
});
|
||||
angular.module("template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("template/progressbar/bar.html",
|
||||
"<div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" ng-transclude></div>");
|
||||
}]);
|
||||
|
||||
angular.module("template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("template/progressbar/progress.html",
|
||||
"<div class=\"progress\" ng-transclude></div>");
|
||||
}]);
|
||||
|
||||
angular.module("template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) {
|
||||
$templateCache.put("template/progressbar/progressbar.html",
|
||||
"<div class=\"progress\"><div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" ng-transclude></div></div>");
|
||||
}]);
|
||||
Reference in New Issue
Block a user