Skip to content

Commit

Permalink
add individual detail pages
Browse files Browse the repository at this point in the history
  • Loading branch information
max-mapper committed Mar 21, 2015
1 parent e7f789f commit 4f48715
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 81 deletions.
5 changes: 3 additions & 2 deletions configure.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
<head>
<link rel="stylesheet" href="css/ratchet.css">
<style type="text/css">

/* overrides */
.content .table-view { margin: 0 !important; }
</style>
</head>
<body>
<div class="app"></div>
<div id="container"></div>
<script src="configure.js"></script>
</body>
</html>
82 changes: 61 additions & 21 deletions configure.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
var ipc = require('ipc')
var mustache = require('mustache')
var Ractive = require('ractive')
var page = require('page')
var fs = require('fs')
var $ = require('jquery')

var template = fs.readFileSync('./configure.mustache').toString()
var container = document.querySelector('.app')
Ractive.DEBUG = false

ipc.on('status', function(data) {
data = data.map(function(d) {
var templates = {
configure: fs.readFileSync('./configure.tmpl').toString(),
detail: fs.readFileSync('./detail.tmpl').toString()
}

var state = {}

$(document).on('click', '.processAction', function(e) {
var action = e.currentTarget.attributes['data-action'].value
var procNameAttr = e.currentTarget.attributes['data-name']
var data = {task: action}
if (procNameAttr) data.name = procNameAttr.value
ipc.send('task', data)
})

$(document).on('click', '.btn.quit', function(e) {
ipc.send('terminate')
})

ipc.on('got-all', function gotAll (data) {
data = data.map(function map (d) {
if (d.uptime) {
d.classes = "btn-positive"
d.message = "Running"
Expand All @@ -21,24 +41,44 @@ ipc.on('status', function(data) {
d.message = "Not Running"
return d
})
var output = mustache.render(template, {items: data})
container.innerHTML = output

addEvents()
state.configure.set({items: data})
})

ipc.send('update-me')

function addEvents() {
var startAll = document.querySelector('.start-all')
var stopAll = document.querySelector('.stop-all')
var restartAll = document.querySelector('.restart-all')
var buttons = [startAll, stopAll, restartAll]
ipc.on('got-one', function gotOne (data) {
state.detail.set(data)
})

buttons.forEach(function (button) {
button.addEventListener('mousedown', function(e) {
var action = e.target.attributes['data-action'].value
ipc.send('task', {task: action})
var routes = {
configure: function(ctx, next) {
ctx.template = templates.configure
state.configure = render(ctx, {loading: true})
ipc.send('get-all')
ipc.once('status', function() {
next()
})
},
detail: function(ctx, next) {
ctx.template = templates.detail
state.detail = render(ctx, {loading: true})
ipc.send('get-one', {name: ctx.params.name})
ipc.once('status', function() {
next()
})
}
}

// set up routes
page('/', routes.configure)
page('/detail/:name', routes.detail)

// initialize router
page.start()
page('/')

function render(ctx) {
return new Ractive({
el: "#container",
template: ctx.template,
data: ctx.data
})
}
}
10 changes: 0 additions & 10 deletions configure.mustache

This file was deleted.

35 changes: 35 additions & 0 deletions configure.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<ul class="table-view">
{{#items}}
<li class="table-view-cell media"><a href="/detail/{{name}}" class="navigate-right"><span class="media-object pull-left icon icon-gear"></span> {{name}} <button class="btn {{classes}}">{{message}}</button></a></li>
{{/items}}
<li class="table-view-cell table-view-divider">Actions</li>
<li class="table-view-cell media">
<a rel="external" class="processAction" data-action="startAll">
<span class="media-object pull-left icon icon-play"></span>
<div class="media-body">
Start All
</div>
</a>
</li>
<li class="table-view-cell media">
<a rel="external" class="processAction" data-action="stopAll">
<span class="media-object pull-left icon icon-stop"></span>
<div class="media-body">
Stop All
</div>
</a>
</li>
<li class="table-view-cell media">
<a rel="external" class="processAction" data-action="restartAll">
<span class="media-object pull-left icon icon-refresh"></span>
<div class="media-body">
Restart All
</div>
</a>
</li>
</ul>
<div class="bar bar-standard bar-footer">
<button class="btn pull-right quit">
Quit
</button>
</div>
42 changes: 42 additions & 0 deletions detail.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<header class="bar bar-nav">
<a href="/">
<button class="btn btn-link btn-nav pull-left">
<span class="icon icon-left-nav"></span>
Back
</button>
</a>
<h1 class="title">{{name}}</h1>
</header>
<div class="content">
<ul class="table-view">
{{#uptime}}<li class="table-view-cell">Uptime<p>{{uptime}}</li>{{/uptime}}
{{#pid}}<li class="table-view-cell">PID<p>{{pid}}</li>{{/pid}}
{{#state}}<li class="table-view-cell">State<p>{{state}}</li>{{/state}}
{{#cmd}}<li class="table-view-cell">CMD<p>{{cmd}}</li>{{/cmd}}
<li class="table-view-cell table-view-divider">Actions</li>
<li class="table-view-cell media">
<a rel="external" class="processAction" data-action="start" data-name="{{name}}">
<span class="media-object pull-left icon icon-play"></span>
<div class="media-body">
Start
</div>
</a>
</li>
<li class="table-view-cell media">
<a rel="external" class="processAction" data-action="stop" data-name="{{name}}">
<span class="media-object pull-left icon icon-stop"></span>
<div class="media-body">
Stop
</div>
</a>
</li>
<li class="table-view-cell media">
<a rel="external" class="processAction" data-action="restart" data-name="{{name}}">
<span class="media-object pull-left icon icon-refresh"></span>
<div class="media-body">
Restart
</div>
</a>
</li>
</ul>
</div>
115 changes: 69 additions & 46 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,85 +16,107 @@ var icon, menu, configure, about

app.on('ready', function() {
app.dock.hide()

var atomScreen = require('screen')
var size = atomScreen.getPrimaryDisplay()

var canQuit = false
app.on('will-quit', function(e) {
if (canQuit) return true
configure = undefined
e.preventDefault()
})

// main.js
var template = []

var iconPath = path.join(__dirname, 'images', 'Status.png')
var configFile = './test/config.json'
var conf = require(configFile)
var dir = path.dirname(configFile)

conf.exec = {cwd: path.resolve(dir)}
conf.logs = path.resolve(path.join(dir, conf.logs || 'logs'))
conf.pids = path.resolve(path.join(dir, conf.pids || 'pids'))

mkdir(conf.logs)
mkdir(conf.pids)

conf.mon = path.join(__dirname, 'mon')

// start all once
start([], function started (err) {
if (err) return console.log("error starting processes: " + err.message)
console.log("started all processes")
})

icon = new Tray(iconPath)

icon.on('clicked', function(e) {
if (configure && configure.isVisible()) return hideConfigure()
showConfigure()
})

var menuTemplate = [
{
label: 'Configure...',
click: function() {
showConfigure()
}
},
{
type: 'separator'
},
{
label: 'About',
click: function() {
showAbout()
}
},
{
label: 'Quit',
click: function() {
app.terminate()
}
}
]
ipc.on('terminate', function terminate (ev) {
canQuit = true
app.terminate()
})

showConfigure()
ipc.on('get-all', function getAll (ev, data) {
getStatus()
})

menu = Menu.buildFromTemplate(menuTemplate)
icon.setContextMenu(menu)
ipc.on('get-one', function getOne (ev, data) {
getStatus(null, data.name)
})

ipc.on('update-me', updateStatus)
ipc.on('task', function task (ev, data) {
if (data.task === "startAll") startAll(updateStatus)
if (data.task === "stopAll") stopAll(updateStatus)
if (data.task === "restartAll") restartAll(updateStatus)
if (data.task === "startAll") start([], getStatus)
if (data.task === "stopAll") stop([], getStatus)
if (data.task === "restartAll") restart([], getStatus)
if (data.task === "start") start([data.name], updateSingle)
if (data.task === "stop") stop([data.name], updateSingle)
if (data.task === "restart") restart([data.name], updateSingle)

function updateSingle() {
getStatus(null, data.name)
}
})

function showConfigure() {
if (configure) return configure.show( )
if (configure) {
getStatus()
return configure.show()
}
configure = new BrowserWindow({
width: 400,
height: 400,
show: true
show: true,
frame: false
})
configure.setPosition(size.workArea.width - 500, size.workArea.y)
configure.on('blur', hideConfigure)
configure.loadUrl('file://' + __dirname + '/configure.html')
}

function updateStatus() {
function hideConfigure() {
if (configure) return configure.hide()
}

function getStatus(err, procName) {
if (err) throw err
if (!configure) return
debug('update status...')
debug('get proc status...')
var status = []
var group = new Mongroup(conf)
group.procs.forEach(function(proc) {
var procs = group.procs
if (procName) procs = procs.filter(function filter (proc) {
return proc.name === procName
})
procs.forEach(function(proc) {
var state = proc.state()
var uptime
if (state === 'alive') uptime = ms(Date.now() - proc.mtime(), { long: true })

var item = {
cmd: proc.cmd,
name: proc.name,
state: state,
pid: proc.pid
Expand All @@ -105,28 +127,29 @@ app.on('ready', function() {
status.push(item)
})

configure.webContents.send('status', status)
if (procName) configure.webContents.send('got-one', status[0])
else configure.webContents.send('got-all', status)
}

function restartAll(cb) {
stopAll(function (err1) {
startAll(function (err2) {
function restart(procs, cb) {
stop(procs, function (err1) {
start(procs, function (err2) {
if (cb) cb(err1 || err2)
})
})
}

function startAll(cb) {
function start(procs, cb) {
var group = new Mongroup(conf)
group.start([], function (err) {
group.start(procs, function (err) {
if (err) return cb(err)
cb()
})
}

function stopAll(cb) {
function stop(procs, cb) {
var group = new Mongroup(conf)
group.stop([], 'SIGQUIT', function (err) {
group.stop(procs, 'SIGQUIT', function (err) {
if (cb) return cb(err)
cb()
})
Expand Down
Loading

0 comments on commit 4f48715

Please sign in to comment.