Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
willerce committed Nov 29, 2013
1 parent 74fd9a2 commit 29d5c7f
Show file tree
Hide file tree
Showing 27 changed files with 1,065 additions and 0 deletions.
39 changes: 39 additions & 0 deletions app/app.html

Large diffs are not rendered by default.

478 changes: 478 additions & 0 deletions app/assets/css/style.css

Large diffs are not rendered by default.

Binary file added app/assets/img/icon-close.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-close_hover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-minimizi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-minimizi_hover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-remove.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-remove_hover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-run.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-run_hover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-stop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-stop_hover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-terminal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/icon-terminal_hover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/img/sidebar-shadow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
149 changes: 149 additions & 0 deletions app/scripts/Main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
//node modules
var fs = require('fs');
var spawn = require("child_process").spawn;
var exec = require("child_process").exec;
var path = require("path");
var md5 = require("MD5");
var ansi2html = require('ansi2html');
var clc = require('cli-color');
var gui = require('nw.gui');
var winMain = gui.Window.get();

$(document).ready(function () {

//spock app
window.spock = {};
window.spock.templates = {};
window.spock.temp = {};
window.spock.util = new Util();
window.spock.storageService = new StorageService();
window.spock.projectManager = new ProjectManager();
window.spock.terminalManager = new TerminalManager();
window.spock.app = new TmTSpock();

var $body = $('body');

//标题栏
$('.JS-TitleBar').click(function (event) {

var aciton = $(this).attr('data-action');
switch (aciton) {
case 'close':
winMain.close();
break;
case 'minimizi':
winMain.minimize();
break;
}

return false;
});

//项目切换
$body.on('click', '.JS-Sidebar-Item', function () {
spock.app.switchProject($(this).attr('data-id'));
return false;
});

//移除项目
$body.on('click', '.JS-Project-Remove', function () {
spock.app.removeProject($(this).attr('data-id'));
return false;
});

//任务运行
$body.on('click', '.JS-Task-Run', function () {
var project_id = $(this).attr('data-project-id');
var task_name = $(this).attr('data-task-name');
spock.app.runTask(project_id, task_name);
return false;
});

$body.on('click', '.JS-Task-Terminal', function () {
var project_id = $(this).attr('data-project-id');
var task_name = $(this).attr('data-task-name');
$('#console_' + project_id + "_" + task_name).fadeIn();

//scroll to bottom
spock.app.terminalScrollToBottom(project_id, task_name);

spock.temp.showConsoleId = '#console_' + project_id + "_" + task_name;

return false;
});


$body.on('click', '.JS-Task-Stop', function () {
var project_id = $(this).attr('data-project-id');
var task_name = $(this).attr('data-task-name');
spock.app.stopTask(project_id, task_name);
return false;
});

//监听文件、文件夹拖入事件
document.body.addEventListener('dragenter', handleDragEnter, false);
document.body.addEventListener('dragover', handleDragOver, false);
document.body.addEventListener('drop', handleDrop, false);
document.body.addEventListener('dragleave', handleDragLeave, false);

// node-webkit 开发者工具
window.addEventListener('keydown', function (e) {
if (e.keyIdentifier === 'F12') {
winMain.showDevTools();
} else if (e.keyIdentifier === 'F5') {
location.reload();
} else if (e.keyIdentifier === 'U+001B') {
if (spock.temp.showConsoleId) {
$(spock.temp.showConsoleId).fadeOut();
spock.temp.showConsoleId = "";
}
}
});

function handleDragEnter(event) {
console.log("handleDragEnter");
}

function handleDragOver(event) {
event.stopPropagation();
event.preventDefault();
console.log("handleDragOver");
}

function handleDrop(event) {
event.stopPropagation();
event.preventDefault();
console.log("handleDrop");

//获取拖入的文件
var files = event.dataTransfer.files;

//遍历文件、文件夹
_.each(files, function (file) {

var stats = fs.statSync(file.path);

if (stats.isDirectory() && path.dirname(file.path) !== file.path) {
//文件夹
spock.app.addProject(file.path);
} else if (stats.isFile() && path.dirname(path.dirname(file.path)) !== path.dirname(file.path)) {
//文件
spock.app.addProject(path.dirname(file.path));
}
});
return false;
}

function handleDragLeave() {
console.log("handleDragLeave");
}

//node-webkit 的相关事件监听

winMain.on('close', function () {
spock.terminalManager.killWorkers();
gui.App.closeAllWindows();
gui.App.quit();
});

});
69 changes: 69 additions & 0 deletions app/scripts/ProjectManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
var ProjectManager = (function () {
function ProjectManager() {
this.projects = spock.storageService.getProjects();
}

ProjectManager.prototype.add = function (dir, cb) {

//判断是否已经存在该项目
var exist = false;
_.each(this.projects, function (project) {
if (!path.relative(project.path, dir)) {
exist = true;
}
});

if (!exist) {

var project_name = path.basename(dir);
var project_id = spock.util.uid(project_name);

var grunt = require(dir + "/node_modules/grunt/");

var GruntinitConfigFnPath = grunt.file.findup('Gruntfile.{js,coffee}', {cwd: dir, nocase: true});
require(GruntinitConfigFnPath)(grunt);

var tasks = [];
_.each(grunt.task._tasks, function (task) {
tasks.push(task.name);
});

var project = {
id: project_id,
name: project_name,
path: dir,
tasks: tasks,
config: {
}
};

this.projects.push(project);
spock.storageService.setProjects(this.projects);

cb(project);
}
};


ProjectManager.prototype.remove = function (id) {

var projects = _.reject(self.projects, function (project) {
return project.id === id;
});

//更新 projects
spock.storageService.setProjects(projects);

//杀死项目的进程
spock.terminalManager.killProjectWorkers(id);

};

ProjectManager.prototype.getById = function (id) {
return _.find(spock.projectManager.projects, function (project) {
return project.id == id;
});
};

return ProjectManager;
})();
20 changes: 20 additions & 0 deletions app/scripts/StorageService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
var StorageService = (function () {
function StorageService() {
}

StorageService.prototype.setProjects = function (projects) {
localStorage.SpockData = JSON.stringify(projects);
};

StorageService.prototype.getProjects = function () {
try {
var projects = JSON.parse(localStorage.SpockData || '[]');
} catch (e) {
window.alert('Error Reading Spock ! Reverting to defaults.');
}

return projects || [];
};

return StorageService;
})();
97 changes: 97 additions & 0 deletions app/scripts/TerminalManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
var TerminalManager = (function () {

var TerminalManager = function () {
this.command = (process.platform === 'win32') ? 'grunt.cmd' : 'grunt';
this.process_list = {};
};

TerminalManager.prototype.killWorkers = function () {
var self = this;
_.forEach(self.process_list, function (project, project_id) {
self.killProjectWorkers(project_id);
});
};


TerminalManager.prototype.killProjectWorkers = function (project_id) {
var self = this;

var project = this.process_list[project_id];

if (!project) {
return;
}

_.forEach(project, function (task, task_name) {
if (task.status == "running") {
self.killTask(project_id, task_name);
}
});
};


TerminalManager.prototype.runTask = function (project_id, task_name, startCb, endCb, errorCb) {

var project = spock.projectManager.getById(project_id);

startCb();

var terminal = spawn(this.command, [task_name], {cwd: project.path});

//如果这个
if (_.isUndefined(this.process_list[project_id])) {
this.process_list[project_id] = {};
}

this.process_list[project_id][task_name] = {
name: task_name,
terminal: terminal,
status: 'running'
};

terminal.stdout.setEncoding('utf8');
terminal.stdout.on('data', function (data) {
//console.log('=> ' + data);
//控制台输出
spock.app.putCliLog(data, project_id, task_name);
});

terminal.stderr.on('data', function (data) {
//console.log('ERROR: => ' + data);
spock.app.putCliLog(data, project_id, task_name);
errorCb();
});

terminal.on('close', function (code) {
endCb();
//console.log('child process exited with code ', code);
terminal.status = "stop";
});

};

//停止一个任务
TerminalManager.prototype.stopTask = function (project_id, task_name) {
if (!_.isUndefined(this.process_list[project_id])) {
try {
this.killTask(project_id, task_name);
var pid = this.process_list[project_id][task_name].status = "stop"
} catch (e) {
alert("process end error!")
}
}
};

//残忍地杀死一个进程,连同其子进程一起杀了
TerminalManager.prototype.killTask = function (project_id, task_name) {
if (process.platform === 'win32') {
var pid = this.process_list[project_id][task_name].terminal.pid;
exec('taskkill /pid ' + pid + ' /T /F');
} else {
this.process_list[project_id][task_name].terminal.kill();
}
};

return TerminalManager;

})();
Loading

0 comments on commit 29d5c7f

Please sign in to comment.