Commit 548e90a6 authored by Thomas Lechauve's avatar Thomas Lechauve

New feature: Can start or stop an instance

You can now change the state of an instance with buttons.
There is also an autorefresh every 30 seconds to update all parameters
in the instance's form.
parent 7f1b6510
(function ($) {
"use strict";
'use strict';
var methods = {
init: function (options) {
var settings = $.extend({
......@@ -38,13 +38,13 @@
/* Cookie storage method */
cStore: function (name, value) {
if (value !== undefined) {
document.cookie = name + "=" + value + ";domain=" + window.location.hostname + ";path=" + window.location.pathname;
document.cookie = name + '=' + value + ';domain=' + window.location.hostname + ';path=' + window.location.pathname;
} else {
var i, x, y, cookies = document.cookie.split(';');
for (i = 0; i < cookies.length; i += 1) {
x = cookies[i].substr(0, cookies[i].indexOf('='));
y = cookies[i].substr(cookies[i].indexOf('=') + 1);
x = x.replace(/^\s+|\s+$/g, "");
x = x.replace(/^\s+|\s+$/g, '');
if (x === name) {
return unescape(y);
}
......@@ -54,15 +54,14 @@
statusDefault: function () {
return {
0: function () { console.error("status error code: 0"); },
404: function () { console.error("status error code: Not Found !"); },
500: function () { console.error("Server error !"); }
0: function () { console.error('status error code: 0'); },
404: function () { console.error('status error code: Not Found !'); },
500: function () { console.error('Server error !'); }
};
},
request: function (type, authentication, args) {
var statusCode;
var data;
var statusCode, data;
if (args.hasOwnProperty('statusCode')) {
statusCode = args.statusCode || methods.statusDefault();
} else {
......@@ -73,7 +72,7 @@
} else {
data = undefined;
}
delete args.data
delete args.data;
$.extend(args, {statusCode: statusCode});
return this.each(function () {
var ajaxOptions = {
......@@ -83,9 +82,11 @@
datatype: 'json',
context: $(this),
beforeSend: function (xhr) {
if ($(this).slapos("access_token") && authentication) {
xhr.setRequestHeader("Authorization", $(this).slapos("store", "token_type") + " " + $(this).slapos("access_token"));
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader('REMOTE_USER', 'test_vifib_customer');
xhr.setRequestHeader('Accept', 'application/json');
if ($(this).slapos('access_token') && authentication) {
//xhr.setRequestHeader('Authorization', $(this).slapos('store', 'token_type') + ' ' + $(this).slapos('access_token'));
//xhr.setRequestHeader('Accept', 'application/json');
}
}
};
......@@ -96,8 +97,9 @@
prepareRequest: function (methodName, args) {
var $this = $(this);
return this.each(function(){
$(this).slapos('discovery', function(access){
args = args || {};
return this.each(function () {
$(this).slapos('discovery', function (access) {
if (access.hasOwnProperty(methodName)) {
var url = args.url || access[methodName].url;
$.extend(args, {'url': url});
......@@ -107,16 +109,16 @@
args);
}
});
})
});
},
discovery: function (callback) {
return this.each(function(){
return this.each(function () {
$.ajax({
url: "http://10.8.2.34:12002/erp5/portal_vifib_rest_api_v1",
dataType: "json",
url: 'http://10.8.2.34:12006/erp5/portal_vifib_rest_api_v1',
dataType: 'json',
beforeSend: function (xhr) {
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader('Accept', 'application/json');
},
success: callback
});
......@@ -134,7 +136,7 @@
},
instanceRequest: function (args) {
return $(this).slapos('prepareRequest', 'request_instance', args)
return $(this).slapos('prepareRequest', 'request_instance', args);
}
};
......
......@@ -74,7 +74,7 @@
<script id="instance" type="text/html">
{{! Service page template }}
<article>
<form class="form-horizontal">
<form class="form-horizontal" id="instance-form">
<fieldset>
<legend>
{{ title }}
......@@ -87,41 +87,36 @@
<div class="control-group">
<label class="control-label">Reference</label>
<div class="controls">
<span class="uneditable-input">{{ title }}</span>
<input name="title" type="text" value="{{ title }}" readOnly></input>
</div>
</div>
<div class="control-group">
<label class="control-label">Software release</label>
<div class="controls">
<span class="uneditable-input">{{ software_release }}</span>
<input type="text" name="software_release" value="{{ software_release }}" readOnly></input>
</div>
</div>
<div class="control-group">
<label class="control-label">Software type</label>
<div class="controls">
<span class="uneditable-input">{{ software_type }}</span>
<input type="text" name="software_type" value="{{ software_type }}"></input>
</div>
</div>
<div class="control-group">
<label class="control-label">Status</label>
<div class="controls">
<div class="btn-group">
<button class="btn" id="stopInstance">Stop</button>
<button class="btn btn-success disabled" id="startInstance">Started</button>
</div>
<div class="controls" id="instanceStatus">
{{{ status }}}
</div>
</div>
</fieldset>
</form>
<table class="table">
<caption>Connection parameters</caption>
{{# connection}}
<tr><td>key</td><td>{{ key }}</td></tr>
<tr><td>{{.}}</td><td>{{ key }}</td></tr>
{{/ connection}}
</table>
<form>
<fieldset>
<legend>
Parameter XML
......@@ -142,6 +137,27 @@
</article>
</script>
<script id="instance.stop_requested" type="text/html">
<div class="btn-group">
<button class="btn btn-danger disabled" disabled="disabled" id="stopInstance">Stopped</button>
<button class="btn" id="startInstance">Start</button>
</div>
</script>
<script id="instance.draft" type="text/html">
<div class="btn-group">
<button class="btn disabled" disabled="disabled">Stop</button>
<button class="btn disabled" disabled="disabled">Start</button>
</div>
</script>
<script id="instance.start_requested" type="text/html">
<div class="btn-group">
<button class="btn" id="stopInstance">Stop</button>
<button class="btn btn-success disabled" disabled="disabled" id="startInstance">Started</button>
</div>
</script>
<script id="simple-form" type="text/html">
<form class="form-inline">
<fieldset>
......@@ -222,6 +238,6 @@
<script type="text/javascript" src="static/js/jquery.slapos.js"></script>
<!--<script type="text/javascript" src="static/js/fake.js"></script>-->
<script type="text/javascript" src="static/js/urlHandler.js"></script>
<script type="text/javascript" src="static/js/form.js"></script>
<script type="text/javascript" src="static/js/core.js"></script>
</body>
</html>
......@@ -28,7 +28,7 @@ var comp1 = {computer_id: "COMP-1",
var inst0 =
{instance_id: "INST-0",
status: "start",
status: "start_requested",
software_release: "http://example.com/example.cfg",
software_type: "type_provided_by_the_software",
slave: "False",
......@@ -49,7 +49,7 @@ var inst0 =
var inst1 =
{instance_id: "INST-1",
status: "start",
status: "stop_requested",
software_release: "http://example.com/example.cfg",
software_type: "type_provided_by_the_software",
slave: "False",
......@@ -71,11 +71,11 @@ var inst1 =
var fakeserver = sinon.fakeServer.create();
// Get instance
fakeserver.respondWith("GET", "/instance/200",[200, {"Content-Type":"application/json; charset=utf-8"}, JSON.stringify(inst0)]);
fakeserver.respondWith("GET", "/instance/201",[200, {"Content-Type":"application/json; charset=utf-8"}, JSON.stringify(inst1)]);
fakeserver.respondWith("GET", "/instance/stop",[200, {"Content-Type":"application/json; charset=utf-8"}, JSON.stringify(inst0)]);
fakeserver.respondWith("GET", "/instance/start",[200, {"Content-Type":"application/json; charset=utf-8"}, JSON.stringify(inst1)]);
// Get instance FAIL
fakeserver.respondWith("GET", "/instance/408",[408, {"Content-Type":"application/json; charset=utf-8"}, "NOT FOUND"]);
fakeserver.respondWith("POST", "/instance",[401, {"Content-Type":"application/json; charset=utf-8"}, "NEED AUTH"]);
fakeserver.respondWith("GET", "/instance/start",[200, {"Content-Type":"application/json; charset=utf-8"}, "NOT FOUND"]);
fakeserver.respondWith("GET", "/instance/stop",[200, {"Content-Type":"application/json; charset=utf-8"}, "NEED AUTH"]);
var tmp = $.ajax;
$.ajax = function(url, options){
......
/**
* NEXEDI
* Author: Thomas Lechauve
* Date: 4/17/12
*/
(function($) {
var routes = {
"/instance" : "requestInstance",
"/instance/:url" : "showInstance",
"/computers" : "listComputers",
"/instances" : "listInstances",
"/invoices" : "listInvoices"
}
var router = function(e, d){
var $this = $(this);
$.each(routes, function(pattern, callback){
pattern = pattern.replace(/:\w+/g, '([^\/]+)');
var regex = new RegExp('^' + pattern + '$');
var result = regex.exec(d);
if (result) {
result.shift();
methods[callback].apply($this, result);
}
});
}
var getDate = function () {
var today = new Date();
return [today.getFullYear(), today.getMonth(), today.getDay()].join('/')
+ ' ' + [today.getHours(), today.getMinutes(), today.getSeconds()].join(':');
};
var substractLists = function(l1, l2){
var newList = [];
$.each(l2, function(){
if ($.inArray(""+this, l1) == -1) {
newList.push(""+this);
}
});
return newList;
};
var redirect = function(){
$(this).vifib('render', 'auth', {
'host':'http://10.8.2.34:12002/erp5/web_site_module/hosting/request-access-token',
'client_id': 'client',
'redirect':escape(window.location.href)
})
};
var payment = function(jqxhr){
var message = $.parseJSON(jqXHR.responseText).error
$(this).vifib('popup', message, "information");
};
var notFound = function(jqxhr){
var message = $.parseJSON(jqXHR.responseText).error
$(this).vifib('popup', message);
};
var serverError = function(jqxhr){
var message = $.parseJSON(jqxhr.responseText).error
$(this).vifib('popup', message);
};
var spinOptions = {color: "#FFF", lines:9, length:3, width:2, radius:6, rotate:0, trail:36, speed:1.0};
var methods = {
init: function() {
// Initialize slapos in this context
$(this).slapos();
var $this = $(this);
// Bind Loading content
$("#loading").ajaxStart(function(){
$(this).spin(spinOptions);
}).ajaxStop(function(){
$(this).spin(false);
});
// Bind to urlChange event
return this.each(function(){
$.subscribe("urlChange", function(e, d){
router.call($this, e, d);
});
$.subscribe("auth", function(e, d){
$(this).vifib("authenticate", d);
});
});
},
genInstanceUrl: function(uri){
return location.href.split('#')[0] + "#/instance/" + encodeURIComponent(uri)
},
extractInstanceURIFromUrl: function () {
return decodeURIComponent($(this).attr('href').split('/').pop())
},
authenticate: function(data) {
for (var d in data) {
if (data.hasOwnProperty(d)) {
$(this).slapos('store', d, data[d]);
}
}
},
refresh: function(method, interval, eventName){
eventName = eventName || 'ajaxStop';
var $this = $(this);
$(this).one(eventName, function(){
var id = setInterval(function(){
method.call($this);
}, interval * 1000);
$.subscribe('urlChange', function(e, d){
clearInterval(id);
})
});
},
showInstance: function (uri) {
var statusCode = {
401: redirect,
402: payment,
404: notFound,
500: serverError
};
$(this).slapos('instanceInfo', uri, {
success: function(infos){
$(this).vifib('render', 'instance', infos);
},
statusCode: statusCode
});
},
getCurrentList: function () {
var list = [];
$.each($(this).find('a'), function () {
list.push($(this).vifib('extractInstanceURIFromUrl'));
});
return list;
},
listComputers: function(){
$(this).vifib('render', 'server.list');
},
refreshRowInstance: function(){
return this.each(function(){
var url = $(this).find('a').vifib('extractInstanceURIFromUrl');
$(this).vifib('fillRowInstance', url);
});
},
fillRowInstance: function(url){
return this.each(function(){
$(this).slapos('instanceInfo', url, {
success: function(instance){
$.extend(instance, {'url': methods.genInstanceUrl(url)});
$(this).vifib('render', 'instance.list.elem', instance);
}
});
});
},
refreshListInstance: function () {
var currentList = $(this).vifib('getCurrentList');
$(this).slapos('instanceList', {
success: function (data) {
var $this = $(this);
var newList = substractLists(currentList, data['list']);
var oldList = substractLists(data['list'], currentList);
$.each(newList, function(){
var url = this+"";
var row = $("<tr></tr>").vifib('fillRowInstance', url);
$this.prepend(row);
});
console.log("newList")
console.log(newList)
console.log("oldList")
console.log(oldList)
},
});
},
listInstances: function(){
var $this = $(this);
var statusCode = {
401: redirect,
402: payment,
404: notFound,
500: serverError,
503: serverError
};
var table = $(this).vifib('render', 'instance.list').find("#instance-table");
table.vifib('refresh', methods.refreshListInstance, 30);
$(this).slapos('instanceList', {
success: function(data){
$.each(data['list'], function(){
var url = this+"";
var row = $("<tr></tr>").vifib('fillRowInstance', url);
row.vifib('refresh', methods.refreshRowInstance, 30);
table.append(row);
});
}, statusCode: statusCode});
},
listInvoices: function(){
$(this).vifib('render', 'invoice.list');
},
instanceInfo: function (url, callback) {
$(this).slapos('instanceInfo', {
success: callback, url: url
});
},
requestInstance: function() {
$(this).vifib('render', 'form.new.instance');
var data = {};
$(this).find("form").submit(function(){
$(this).find('input').serializeArray().map(function(elem){
data[elem["name"]] = elem["value"];
});
$(this).vifib('requestAsking', data);
return false;
});
},
requestAsking: function(data){
var statusCode = {
401: redirect,
402: payment,
404: notFound,
500: serverError
};
var instance = {
software_type: "type_provided_by_the_software",
slave: false,
status: "started",
parameter: {
Custom1: "one string",
Custom2: "one float",
Custom3: ["abc", "def"],
},
sla: {
computer_id: "COMP-0",
}
};
$.extend(instance, data);
var args = {
statusCode: statusCode,
data: instance,
success: function (response) {
console.log(response);
}
};
return this.each(function(){
$(this).slapos('instanceRequest', args);
});
},
popup: function(message, state) {
state = state || 'error';
return this.each(function(){
$(this).prepend(ich['error'](
{'message': message, 'state': state, 'date': getDate()}
, true))
})
},
render: function(template, data){
return this.each(function(){
$(this).html(ich[template](data, true));
});
},
renderAppend: function(template, data){
$(this).append(ich[template](data, true));
},
renderPrepend: function(template, data){
$(this).prepend(ich[template](data, true));
}
};
$.fn.vifib = function(method){
if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.vifib' );
}
};
})(jQuery);
$("#main").vifib();
(function ($) {
"use strict";
'use strict';
var methods = {
init: function (options) {
var settings = $.extend({
......@@ -38,13 +38,13 @@
/* Cookie storage method */
cStore: function (name, value) {
if (value !== undefined) {
document.cookie = name + "=" + value + ";domain=" + window.location.hostname + ";path=" + window.location.pathname;
document.cookie = name + '=' + value + ';domain=' + window.location.hostname + ';path=' + window.location.pathname;
} else {
var i, x, y, cookies = document.cookie.split(';');
for (i = 0; i < cookies.length; i += 1) {
x = cookies[i].substr(0, cookies[i].indexOf('='));
y = cookies[i].substr(cookies[i].indexOf('=') + 1);
x = x.replace(/^\s+|\s+$/g, "");
x = x.replace(/^\s+|\s+$/g, '');
if (x === name) {
return unescape(y);
}
......@@ -54,15 +54,14 @@
statusDefault: function () {
return {
0: function () { console.error("status error code: 0"); },
404: function () { console.error("status error code: Not Found !"); },
500: function () { console.error("Server error !"); }
0: function () { console.error('status error code: 0'); },
404: function () { console.error('status error code: Not Found !'); },
500: function () { console.error('Server error !'); }
};
},
request: function (type, authentication, args) {
var statusCode;
var data;
var statusCode, data;
if (args.hasOwnProperty('statusCode')) {
statusCode = args.statusCode || methods.statusDefault();
} else {
......@@ -73,7 +72,7 @@
} else {
data = undefined;
}
delete args.data
delete args.data;
$.extend(args, {statusCode: statusCode});
return this.each(function () {
var ajaxOptions = {
......@@ -83,9 +82,11 @@
datatype: 'json',
context: $(this),
beforeSend: function (xhr) {
if ($(this).slapos("access_token") && authentication) {
xhr.setRequestHeader("Authorization", $(this).slapos("store", "token_type") + " " + $(this).slapos("access_token"));
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader('REMOTE_USER', 'test_vifib_customer');
xhr.setRequestHeader('Accept', 'application/json');
if ($(this).slapos('access_token') && authentication) {
//xhr.setRequestHeader('Authorization', $(this).slapos('store', 'token_type') + ' ' + $(this).slapos('access_token'));
//xhr.setRequestHeader('Accept', 'application/json');
}
}
};
......@@ -96,8 +97,9 @@
prepareRequest: function (methodName, args) {
var $this = $(this);
return this.each(function(){
$(this).slapos('discovery', function(access){
args = args || {};
return this.each(function () {
$(this).slapos('discovery', function (access) {
if (access.hasOwnProperty(methodName)) {
var url = args.url || access[methodName].url;
$.extend(args, {'url': url});
......@@ -107,16 +109,16 @@
args);
}
});
})
});
},
discovery: function (callback) {
return this.each(function(){
return this.each(function () {
$.ajax({
url: "http://10.8.2.34:12002/erp5/portal_vifib_rest_api_v1",
dataType: "json",
url: 'http://10.8.2.34:12006/erp5/portal_vifib_rest_api_v1',
dataType: 'json',
beforeSend: function (xhr) {
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader('Accept', 'application/json');
},
success: callback
});
......@@ -134,7 +136,7 @@
},
instanceRequest: function (args) {
return $(this).slapos('prepareRequest', 'request_instance', args)
return $(this).slapos('prepareRequest', 'request_instance', args);
}
};
......
......@@ -5,21 +5,24 @@
*/
// Hash parser utility
/**
* @param {String} hashTag hashTag.
* @return {String} a clean hashtag.
*/
$.parseHash = function(hashTag) {
var tokenized = $.extractAuth(hashTag);
if (tokenized) {
$.publish('auth', tokenized);
location.hash = hashTag.split("&")[0]
return location.hash
location.hash = hashTag.split('&')[0];
return location.hash;
}
return hashTag
return hashTag;
};
$.extractAuth = function (hashTag) {
var del = hashTag.indexOf('&');
if (del != -1) {
var splitted = hashTag.substring(del+1).split('&');
var splitted = hashTag.substring(del + 1).split('&');
var result = {};
for (p in splitted) {
var s = splitted[p].split('=');
......@@ -39,6 +42,7 @@ $.genHash = function(url) {
What's happening when we destroy a DOM object subscribed ?
*/
var o = $({});
$.subscribe = function() {
o.on.apply(o, arguments);
};
......@@ -50,8 +54,8 @@ $.publish = function() {
};
// Event Handlers
$.hashHandler = function(){ $.publish("urlChange", $.parseHash(window.location.hash.substr(1))); };
$.redirectHandler = function(event, url){ window.location.hash = $.genHash(url); };
$.hashHandler = function(){ $.publish('urlChange', $.parseHash(window.location.hash.substr(1))); };
$.redirectHandler = function(e, url){ window.location.hash = $.genHash([url]); };
// redirections manager
$.redirect = function(url){ $.publish('redirect', url); };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment