diff --git a/web/.meteor/packages b/web/.meteor/packages
index 664b93b..d3dac77 100644
--- a/web/.meteor/packages
+++ b/web/.meteor/packages
@@ -7,4 +7,11 @@
meteor-platform
autopublish
insecure
-bootstrap
+twbs:bootstrap
+nimble:restivus
+iron:router
+perak:codemirror
+meteorhacks:npm
+
+
+npm-container
\ No newline at end of file
diff --git a/web/.meteor/versions b/web/.meteor/versions
index c221e1d..52a8eb9 100644
--- a/web/.meteor/versions
+++ b/web/.meteor/versions
@@ -5,9 +5,9 @@ binary-heap@1.0.3
blaze@2.1.2
blaze-tools@1.0.3
boilerplate-generator@1.0.3
-bootstrap@1.0.1
callback-hook@1.0.3
check@1.0.5
+coffeescript@1.0.6
ddp@1.1.0
deps@1.0.7
ejson@1.0.6
@@ -18,6 +18,14 @@ htmljs@1.0.4
http@1.1.0
id-map@1.0.3
insecure@1.0.3
+iron:controller@1.0.7
+iron:core@1.0.7
+iron:dynamic-template@1.0.7
+iron:layout@1.0.7
+iron:location@1.0.7
+iron:middleware-stack@1.0.7
+iron:router@1.0.7
+iron:url@1.0.7
jquery@1.11.3_2
json@1.0.3
launch-screen@1.0.2
@@ -25,12 +33,17 @@ livedata@1.0.13
logging@1.0.7
meteor@1.1.6
meteor-platform@1.2.2
+meteorhacks:async@1.0.0
+meteorhacks:npm@1.3.0
minifiers@1.1.5
minimongo@1.0.8
mobile-status-bar@1.0.3
mongo@1.1.0
+nimble:restivus@0.6.6
+npm-container@1.0.0
observe-sequence@1.0.6
ordered-dict@1.0.3
+perak:codemirror@1.2.3
random@1.0.3
reactive-dict@1.1.0
reactive-var@1.0.5
@@ -42,6 +55,7 @@ spacebars@1.0.6
spacebars-compiler@1.0.6
templating@1.1.1
tracker@1.0.7
+twbs:bootstrap@3.3.4
ui@1.0.6
underscore@1.0.3
url@1.0.4
diff --git a/web/confighub.css b/web/client/confighub.css
similarity index 100%
rename from web/confighub.css
rename to web/client/confighub.css
diff --git a/web/client/confighub.html b/web/client/confighub.html
new file mode 100644
index 0000000..ae70a0d
--- /dev/null
+++ b/web/client/confighub.html
@@ -0,0 +1,8 @@
+
+ confighub
+
+
+
+
+
+
diff --git a/web/client/confighub.js b/web/client/confighub.js
new file mode 100644
index 0000000..fdf387c
--- /dev/null
+++ b/web/client/confighub.js
@@ -0,0 +1,79 @@
+// pages
+// / => home
+// /:machineName => machineDetails
+// .
+
+Machines = new Mongo.Collection("machines");
+Router.route('/', function() {
+ this.render('Home')
+});
+
+Router.route('machine/:machineId', function() {
+ this.render('machinePage', {
+ data: function() {
+ return Machines.findOne({
+ machineId: this.params.machineId
+ });
+ }
+ });
+});
+
+Router.route('/machine/:machineId/config/:configId', function() {
+ this.render('configPage', {
+ data: function() {
+
+ var config = Machines.find({
+ "machineId": this.params.machineId,
+ "configurations._id": this.params.configId
+ }, {
+ 'configurations.$': 1
+ });
+
+ var machine = Machines.findOne({machineId: this.params.machineId});
+ return {
+ machine: machine,
+ config: config
+ };
+ // return config;
+ }
+ });
+});
+
+// this.render('Post', {
+// // we don't really need this since we set the data context for the
+// // the entire layout above. But this demonstrates how you can set
+// // a new data context for each specific region.
+// data: function () { return Posts.findOne({_id: this.params._id})
+// });
+
+
+if (Meteor.isServer) {
+ Meteor.startup(function() {
+ // code to run on server at startup
+ // Global API configuration
+ Restivus.configure({
+ prettyJson: true
+ });
+
+ Restivus.addRoute('machines', {
+ authRequired: false
+ }, {
+ get: function() {
+ var allMaMachines = Machines.find({});
+ return {
+ data: allMaMachines
+ };
+ // var post = Posts.findOne(this.urlParams.id);
+ // if (post) {
+ // return {status: 'success', data: post};
+ // }
+ // return {
+ // statusCode: 404,
+ // body: {status: 'fail', message: 'Post not found'}
+ // };
+ }
+ });
+ });
+
+
+}
diff --git a/web/client/views/configPage/configPage.html b/web/client/views/configPage/configPage.html
new file mode 100644
index 0000000..3ff8174
--- /dev/null
+++ b/web/client/views/configPage/configPage.html
@@ -0,0 +1,22 @@
+
+
+
+
confighub.io
+
+
+ Configuration page for {{ machine.machineId}} {{ config.type }} {{ config.description }}
+
+
+
+
+
+
+
+ {{> CodeMirror id="config-content" name="config-content" options=editorOptions code=editorCode reactiveVar="varName"}}
+
+
+
+
+
+
+
diff --git a/web/client/views/configPage/configPage.js b/web/client/views/configPage/configPage.js
new file mode 100644
index 0000000..b448415
--- /dev/null
+++ b/web/client/views/configPage/configPage.js
@@ -0,0 +1,5 @@
+Template.configPage.events({
+ "click .save-config-details-btn": function(event, template) {
+ console.log('should save config!!!');
+ }
+})
diff --git a/web/client/views/home/home.html b/web/client/views/home/home.html
new file mode 100644
index 0000000..592b870
--- /dev/null
+++ b/web/client/views/home/home.html
@@ -0,0 +1,21 @@
+
+
+
+
confighub.io
+
+
+ Your machines
+
+
+
+ {{> machineList machines=machines}}
+
+ {{#unless newMachineRequested}}
+
+ {{/unless}} {{#if newMachineRequested}} {{> newMachine }} {{/if}}
+
+
diff --git a/web/client/views/home/home.js b/web/client/views/home/home.js
new file mode 100644
index 0000000..b3ebeaa
--- /dev/null
+++ b/web/client/views/home/home.js
@@ -0,0 +1,85 @@
+// var Machines = new Mongo.Collection("machines");
+function guid() {
+ function s4() {
+ return Math.floor((1 + Math.random()) * 0x10000)
+ .toString(16)
+ .substring(1);
+ }
+ return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
+ s4() + '-' + s4() + s4() + s4();
+}
+
+// counter starts at 0
+// Session.setDefault('counter', 0);
+
+Template.home.helpers({
+ machines: function() {
+ return Machines.find({});
+ },
+ newMachineRequested: function() {
+ return Session.get('newMachineRequested');
+ }
+});
+
+Template.home.events({
+ "click .add-new-machine-btn": function() {
+ Session.set('newMachineRequested', true);
+ }
+});
+
+// Template.hello.helpers({
+// counter: function() {
+// return Session.get('counter');
+// }
+// });
+
+// Template.hello.events({
+// 'click button': function() {
+// // increment the counter when button is clicked
+// Session.set('counter', Session.get('counter') + 1);
+// }
+// });
+
+Template.newMachine.helpers({
+ // because the Session variable will most probably
+ // be undefined the first time
+ // return true;
+ newMachineAdded: function() {
+ return Session.get("newMachineJustAdded");
+ }
+});
+
+Template.newMachine.events({
+ "click .close-new-machine-btn": function() {
+ Session.set('newMachineJustAdded', false);
+ Session.set('newMachineRequested', false);
+
+ },
+ "submit .new-machine": function(event) {
+ event.preventDefault();
+ return false;
+ },
+ "click .new-machine-save-btn": function(event, template) {
+ // This function is called when the new task form is submitted
+ // console.log('saving!!!!!!');
+ // event.preventDefault();
+ // return false;
+ //
+ var text = template.find('.machine-name').value; //vent.target.machineName.value;
+ var machineId = guid();
+ Machines.insert({
+ name: text,
+ status: 'init pending',
+ configurations: [],
+ machineId: machineId,
+ createdAt: new Date() // current time
+ });
+
+ // Clear form
+ template.find('.machine-name').value = "";
+
+ Session.set('newMachineJustAdded', machineId);
+ // Prevent default form submit
+ return false;
+ }
+});
diff --git a/web/client/views/machinePage/machinePage.html b/web/client/views/machinePage/machinePage.html
new file mode 100644
index 0000000..bd8bca5
--- /dev/null
+++ b/web/client/views/machinePage/machinePage.html
@@ -0,0 +1,27 @@
+
+
+
+
confighub.io
+
+
+ Machine details: {{ name }}
+
+
+
+
+
+
+ Machine status: {{status}}
+
+
+
+
+
+
+
Configurations
+ {{> configurationList configurations=configurations machineId=machineId}}
+
+
+
+
+
diff --git a/web/client/views/shared/configurationList/configurationList.html b/web/client/views/shared/configurationList/configurationList.html
new file mode 100644
index 0000000..fd2c636
--- /dev/null
+++ b/web/client/views/shared/configurationList/configurationList.html
@@ -0,0 +1,20 @@
+
+
+ {{#each configurations}}
+ {{> configurationListItem}}
+ {{else}}
+ You don't have any configurations for this machine.
+ {{/each}}
+
+ {{#unless newConfigurationRequested}}
+
+
+
+
+
+ {{/unless}}
+
+ {{#if newConfigurationRequested}}
+ {{> newConfigurationDialog machineId=machineId}}
+ {{/if}}
+
diff --git a/web/client/views/shared/configurationList/configurationList.js b/web/client/views/shared/configurationList/configurationList.js
new file mode 100644
index 0000000..10c6528
--- /dev/null
+++ b/web/client/views/shared/configurationList/configurationList.js
@@ -0,0 +1,12 @@
+Template.configurationList.events({
+ "click .add-new-config-btn": function(event, template) {
+ console.log('should add new configuration');
+ Session.set('newConfigurationRequested', true);
+ }
+});
+
+Template.configurationList.helpers({
+ newConfigurationRequested: function() {
+ return Session.get('newConfigurationRequested');
+ }
+});
diff --git a/web/client/views/shared/configurationListItem/configurationListItem.html b/web/client/views/shared/configurationListItem/configurationListItem.html
new file mode 100644
index 0000000..f7a19bd
--- /dev/null
+++ b/web/client/views/shared/configurationListItem/configurationListItem.html
@@ -0,0 +1,13 @@
+
+
+
diff --git a/web/client/views/shared/machineDetails/machineDetails.html b/web/client/views/shared/machineDetails/machineDetails.html
new file mode 100644
index 0000000..9cc16f3
--- /dev/null
+++ b/web/client/views/shared/machineDetails/machineDetails.html
@@ -0,0 +1,15 @@
+
+
+
diff --git a/web/client/views/shared/machineList/machineList.html b/web/client/views/shared/machineList/machineList.html
new file mode 100644
index 0000000..723005b
--- /dev/null
+++ b/web/client/views/shared/machineList/machineList.html
@@ -0,0 +1,5 @@
+
+
+ {{#each machines}} {{> machineDetails}} {{/each}}
+
+
diff --git a/web/client/views/shared/newConfigurationDialog/newConfigurationDialog.html b/web/client/views/shared/newConfigurationDialog/newConfigurationDialog.html
new file mode 100644
index 0000000..3a6660c
--- /dev/null
+++ b/web/client/views/shared/newConfigurationDialog/newConfigurationDialog.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+ Configuration type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/client/views/shared/newConfigurationDialog/newConfigurationDialog.js b/web/client/views/shared/newConfigurationDialog/newConfigurationDialog.js
new file mode 100644
index 0000000..6b5c141
--- /dev/null
+++ b/web/client/views/shared/newConfigurationDialog/newConfigurationDialog.js
@@ -0,0 +1,36 @@
+Template.newConfigurationDialog.events({
+ "click .save-config-btn": function(event, template) {
+ // console.log(template.data.machineId);
+ // var text = template.find('.machine-name').value; //vent.target.machineName.value;
+ var machine = Machines.findOne({
+ machineId: template.data.machineId
+ });
+
+ var configDescription = template.find('.configuration-description').value;
+ var configType = template.find('.config-type').value;
+
+ if (machine) {
+ Machines.update({
+ _id: machine._id
+ }, {
+ $push: {
+ configurations: {
+ machineId: machine.machineId,
+ _id: (new Mongo.ObjectID()).toHexString(),
+ description: configDescription,
+ type: configType
+ }
+ }
+ });
+
+ // db.students.update(
+ // { _id: 1 },
+ // { $push: { scores: 89 } }
+ // )
+ }
+ Session.set('newConfigurationRequested', false);
+ },
+ "click .cancel-save-config-btn": function(event, template) {
+ Session.set('newConfigurationRequested', false);
+ }
+});
diff --git a/web/client/views/shared/newMachineDialog/newMachineDialog.html b/web/client/views/shared/newMachineDialog/newMachineDialog.html
new file mode 100644
index 0000000..cf1e348
--- /dev/null
+++ b/web/client/views/shared/newMachineDialog/newMachineDialog.html
@@ -0,0 +1,16 @@
+
+
+
diff --git a/web/confighub.html b/web/confighub.html
deleted file mode 100644
index 8e52377..0000000
--- a/web/confighub.html
+++ /dev/null
@@ -1,30 +0,0 @@
-
- confighub
-
-
-
-
-
-
Welcome to confighub.io
-
- Here goes list of machines
-
-
-
- {{#each machines}}
- {{> machineDetails}}
- {{/each}}
-
-
-
-
-
-
-
- {{hostname}}
-
-
-
-
- You've pressed the button {{counter}} times.
-
diff --git a/web/confighub.js b/web/confighub.js
deleted file mode 100644
index 1e2fee0..0000000
--- a/web/confighub.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var Machines = new Mongo.Collection("machines");
-
-if (Meteor.isClient) {
- // counter starts at 0
- Session.setDefault('counter', 0);
-
- Template.body.helpers({
- machines: function() {
- return [{hostname: 'machine1'}, {hostname:' machine2'}];
- return Machines.find({});
- }
- });
-
- Template.hello.helpers({
- counter: function () {
- return Session.get('counter');
- }
- });
-
- Template.hello.events({
- 'click button': function () {
- // increment the counter when button is clicked
- Session.set('counter', Session.get('counter') + 1);
- }
- });
-}
-
-if (Meteor.isServer) {
- Meteor.startup(function () {
- // code to run on server at startup
- });
-}
diff --git a/web/packages.json b/web/packages.json
new file mode 100644
index 0000000..077404a
--- /dev/null
+++ b/web/packages.json
@@ -0,0 +1,3 @@
+{
+
+}
\ No newline at end of file
diff --git a/web/packages/npm-container/index.js b/web/packages/npm-container/index.js
new file mode 100644
index 0000000..c3fc862
--- /dev/null
+++ b/web/packages/npm-container/index.js
@@ -0,0 +1,9 @@
+Meteor.npmRequire = function(moduleName) {
+ var module = Npm.require(moduleName);
+ return module;
+};
+
+Meteor.require = function(moduleName) {
+ console.warn('Meteor.require is deprecated. Please use Meteor.npmRequire instead!');
+ return Meteor.npmRequire(moduleName);
+};
\ No newline at end of file
diff --git a/web/packages/npm-container/package.js b/web/packages/npm-container/package.js
new file mode 100644
index 0000000..674de02
--- /dev/null
+++ b/web/packages/npm-container/package.js
@@ -0,0 +1,23 @@
+var path = Npm.require('path');
+var fs = Npm.require('fs');
+
+Package.describe({
+ summary: 'Contains all your npm dependencies',
+ version: '1.0.0',
+ name: 'npm-container'
+});
+
+var packagesJsonFile = path.resolve('./packages.json');
+try {
+ var fileContent = fs.readFileSync(packagesJsonFile);
+ var packages = JSON.parse(fileContent.toString());
+ Npm.depends(packages);
+} catch (ex) {
+ console.error('ERROR: packages.json parsing error [ ' + ex.message + ' ]');
+}
+
+// Adding the app's packages.json as a used file for this package will get
+// Meteor to watch it and reload this package when it changes
+Package.onUse(function(api) {
+ api.add_files(['index.js', '../../packages.json'], 'server');
+});
\ No newline at end of file
diff --git a/web/public/configs/nginx.conf b/web/public/configs/nginx.conf
new file mode 100644
index 0000000..f0ceb89
--- /dev/null
+++ b/web/public/configs/nginx.conf
@@ -0,0 +1,70 @@
+user www www; ## Default: nobody
+worker_processes 5; ## Default: 1
+error_log logs/error.log;
+pid logs/nginx.pid;
+worker_rlimit_nofile 8192;
+
+events {
+ worker_connections 4096; ## Default: 1024
+}
+
+http {
+ include conf/mime.types;
+ include /etc/nginx/proxy.conf;
+ include /etc/nginx/fastcgi.conf;
+ index index.html index.htm index.php;
+
+ default_type application/octet-stream;
+ log_format main '$remote_addr - $remote_user [$time_local] $status '
+ '"$request" $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+ access_log logs/access.log main;
+ sendfile on;
+ tcp_nopush on;
+ server_names_hash_bucket_size 128; # this seems to be required for some vhosts
+
+ server { # php/fastcgi
+ listen 80;
+ server_name domain1.com www.domain1.com;
+ access_log logs/domain1.access.log main;
+ root html;
+
+ location ~ \.php$ {
+ fastcgi_pass 127.0.0.1:1025;
+ }
+ }
+
+ server { # simple reverse-proxy
+ listen 80;
+ server_name domain2.com www.domain2.com;
+ access_log logs/domain2.access.log main;
+
+ # serve static files
+ location ~ ^/(images|javascript|js|css|flash|media|static)/ {
+ root /var/www/virtual/big.server.com/htdocs;
+ expires 30d;
+ }
+
+ # pass requests for dynamic content to rails/turbogears/zope, et al
+ location / {
+ proxy_pass http://127.0.0.1:8080;
+ }
+ }
+
+ upstream big_server_com {
+ server 127.0.0.3:8000 weight=5;
+ server 127.0.0.3:8001 weight=5;
+ server 192.168.0.1:8000;
+ server 192.168.0.1:8001;
+ }
+
+ server { # simple load balancing
+ listen 80;
+ server_name big.server.com;
+ access_log logs/big.server.access.log main;
+
+ location / {
+ proxy_pass http://big_server_com;
+ }
+ }
+}
diff --git a/web/server/confighub.js b/web/server/confighub.js
new file mode 100644
index 0000000..c33fe15
--- /dev/null
+++ b/web/server/confighub.js
@@ -0,0 +1,62 @@
+Machines = new Mongo.Collection("machines");
+
+Meteor.startup(function() {
+ // code to run on server at startup
+
+ // Global API configuration
+ Restivus.configure({
+ prettyJson: true,
+ useAuth: false
+ });
+
+ Restivus.addCollection(Machines);
+Restivus.addRoute('post/:_id', {
+ get: function () {
+ var id = this.urlParams._id; // "5"
+ return {hamo:1}
+ }
+});
+ Restivus.addRoute('/api/templates/:type', {
+
+ },{
+ get: {
+ action: function() {
+ var type = this.urlParams.type;
+ var fs = Meteor.npmRequire('fs');
+
+ var template = Async.runSync(function(done) {
+ // github.gists.getFromUser({user: 'arunoda'}, function(err, data) {
+ // done(null, data);
+ // });
+ fs.readFile('../public/configs/'+type+'.conf', function(err, data) {
+ done(null, data);
+ });
+
+ });
+
+ return template.result;
+ }
+ }
+ })
+ // Restivus.addRoute('/api/machines', {
+ // // authRequired: false
+ // }, {
+ // get: {
+ // action: function() {
+ // var allMaMachines = Machines.find({});
+ // return {
+ // meho:1,
+ // data: allMaMachines
+ // };
+ // }
+ // // var post = Posts.findOne(this.urlParams.id);
+ // // if (post) {
+ // // return {status: 'success', data: post};
+ // // }
+ // // return {
+ // // statusCode: 404,
+ // // body: {status: 'fail', message: 'Post not found'}
+ // // };
+ // }
+ // });
+});