Commit daa69dc0 authored by Cédric de Saint Martin's avatar Cédric de Saint Martin

Merge branch 'slaprunner'

Conflicts:
	CHANGES.txt
parents f209a4f8 a17c7c92
......@@ -5,6 +5,7 @@ import logging.handlers
import os
import sys
import subprocess
import hashlib
class Parser(OptionParser):
"""
......@@ -121,5 +122,11 @@ def serve(config):
)
if not os.path.exists(workdir):
os.mkdir(workdir)
if not os.path.exists(os.path.join(config.runner_workdir, '.users')):
#set default user and password
salt = "runner81" #to be changed
pwd = hashlib.md5( salt + "insecure" ).hexdigest()
user = "root;"+pwd+";;Slaprunner Administrator"
open(os.path.join(config.runner_workdir, '.users'), 'w').write(user)
app.run(host=config.runner_host, port=int(config.runner_port),
debug=config.debug, threaded=True)
# -*- coding: utf-8 -*-
import slapos.slap
import time
import subprocess
......@@ -21,6 +23,15 @@ class Popen(subprocess.Popen):
self.stdin = None
def cloneRepo(data):
"""Clonne a repository
Args:
data: a dictionnary of parameters to use:
data['path'] is the path of the new project
data['repo'] is the url of the repository to be cloned
data['email'] is the user email
data['user'] is the name of the user
Returns:
a jsonify data"""
workDir = data['path']
if not workDir:
return jsonify(code=0,
......@@ -34,7 +45,7 @@ def cloneRepo(data):
config_writer = repo.config_writer()
config_writer.add_section("user")
if data["user"] != "":
config_writer.set_value("user", "name", data["user"])
config_writer.set_value("user", "name", data["user"].encode("utf-8"))
if data["email"] != "":
config_writer.set_value("user", "email", data["email"])
code = 1
......@@ -45,6 +56,11 @@ def cloneRepo(data):
return jsonify(code=code, result=json)
def gitStatus(project):
"""Run git status and return status of specified project folder
Args:
project: path of the projet ti get status
Returns:
a parsed string that contains the result of git status"""
code = 0
json = ""
try:
......@@ -59,6 +75,12 @@ def gitStatus(project):
return jsonify(code=code, result=json, branch=branch, dirty=isdirty)
def switchBranch(project, name):
"""Switch a git branch
Args:
project: directory of the local git repository
name: switch from current branch to `name` branch
Returns:
a jsonify data"""
code = 0
json = ""
try:
......@@ -76,6 +98,13 @@ def switchBranch(project, name):
return jsonify(code=code, result=json)
def addBranch(project, name, onlyCheckout=False):
"""Add new git branch to the repository
Args:
project: directory of the local git repository
name: name of the new branch
onlyCheckout: if True then the branch `name` is created before checkout
Returns:
a jsonify data"""
code = 0
json = ""
try:
......@@ -91,6 +120,7 @@ def addBranch(project, name, onlyCheckout=False):
return jsonify(code=code, result=json)
def getDiff(project):
"""Get git diff for the specified project directory"""
result = ""
try:
repo = Repo(project)
......@@ -102,6 +132,10 @@ def getDiff(project):
return result
def gitPush(project, msg):
"""Commit and Push changes for the specified repository
Args:
project: directory of the local repository
msg: commit message"""
code = 0
json = ""
undo_commit = False
......@@ -143,5 +177,6 @@ def gitPull(project):
return jsonify(code=code, result=result)
def safeResult(result):
"""Parse string and remove credential of the user"""
regex=re.compile("(https:\/\/)([\w\d\._-]+:[\w\d\._-]+)\@([\S]+\s)", re.VERBOSE)
return regex.sub(r'\1\3', result)
\ No newline at end of file
......@@ -10,6 +10,9 @@
#tabContaier textarea {
width:702px;
}
#tabContaier textarea.slap{white-space: pre-wrap;word-wrap: break-word;overflow: hidden;color: #6F6F6F;width:430px; max-height:120px;
resize: none; height:18px;padding:3px;min-height:18px;font-size: 13px;}
#tabContaier textarea.mb_style{width:560px;}
#tabContaier > ul{
overflow:hidden;
height:34px;
......
......@@ -4,7 +4,6 @@ blockquote, q {quotes: none;}
blockquote:before, blockquote:after, q:before, q:after {content: none;}
:focus {outline: 0 none;}
img{border:0}
a{
text-decoration: none;
color: #19485C;
......@@ -15,11 +14,12 @@ a:hover {
}
table {
margin: 0;
margin: 0;padding:0;
border-right: none;
border-bottom: none;
font-size: 14px;
background: #fff;
border-spacing:0;
}
td{
padding: 4px;
......@@ -36,16 +36,19 @@ th{
font-weight: normal;
font-size: 18px;
}
table.small th{padding: 4px;font-size: 16px;}
textarea {
width:762px;
font-family: 'Helvetica Neue',Tahoma,Helvetica,Arial,sans-serif;
}
body {
background: url("../images/1307251316-background-stripes.gif") repeat #9C9C9C;
font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
background: #2281C1;/*url("../images/1307251316-background-stripes.gif") repeat #9C9C9C;*/
font-family: 'Helvetica Neue',Tahoma,Helvetica,Arial,sans-serif;
color: #000000;
font-size: 13px;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
#page
......@@ -67,7 +70,7 @@ body {
.block_header{
text-align: left;
padding-left: 25px;
padding-left: 20px;
height: 30px;
}
......@@ -81,7 +84,7 @@ body {
font-weight: normal;
padding-top: 3px;
float: left;
width: 690px;
width: 656px;
height: 22px;
text-align: center;
color: #4c6172;
......@@ -257,11 +260,8 @@ body {
box-shadow: 1px 1px 1px #888888;
}
.button:active {
background-position: 0 top;
position: relative;
top: 1px;
padding: 6px 10px 4px;
box-shadow: 1px 1px 1px #888888;
background: #eee;
color: #000;
}
.focusField{
......@@ -314,7 +314,7 @@ input[type="radio"], input[type="checkbox"]{
#home_box{
background: none;
border: 1px solid #678dad;
border: 2px solid #87B0D4;
padding: 0;
color: #4c6172;
margin: 15px 59px 15px 59px;
......@@ -333,7 +333,7 @@ input[type="radio"], input[type="checkbox"]{
#home_box h2{
font-weight: normal;
font-size: 23px;
color: #4c6172;
color: #475F73;
}
#home_box p{
......@@ -351,7 +351,6 @@ input[type="radio"], input[type="checkbox"]{
.inner_box{
background: none;
margin: 0;
border: 1px solid #CAD4DC;
display: block;
padding: 30px 0 30px 0;
}
......@@ -371,23 +370,24 @@ input[type="radio"], input[type="checkbox"]{
margin: 10px 45px 10px 45px;
padding: 10px;
padding-bottom:15px;
border: #678dad;
width: 530px;
border: 1px solid #678dad;
}
.lmenu:hover, .smenu:hover, .sright_menu:hover{
.smaller{margin-left:10px; width: 350px; float:right}
.smaller p{width: 280px;}
.umenu{display: block;margin: 10px 0 10px 45px; width: 147px; float:left;border: 1px solid #678dad;
padding: 10px;height: 80px;padding-bottom:15px;}
.umenu p{font-size: 13px;float: left;width: 77px;cursor:default;}
.lmenu:hover, .smenu:hover, .sright_menu:hover, .smaller:hover, .umenu:hover{
background: #96b9d7;
}
.smenu{
display: block;
height: 80px;
margin: 0 10px 0 45px;
padding: 10px;
padding-bottom:15px;
border: #678dad;
width: 250px;
border: 1px solid #678dad;
float: left;
......@@ -541,7 +541,6 @@ h2.hight:hover{
overflow: auto;
height: 95px;
padding: 5px;
width: 604px;
background:#fff;
margin-bottom: 10px;
color: #3A494F;
......@@ -583,6 +582,7 @@ a.lshare{
color: #4DA0C6;
text-align:center;
font-weight:bold;
cursor:pointer;
}
a.lshare:hover{
background:#D9D9D9;
......@@ -593,7 +593,9 @@ a.lshare:hover{
a.lshare:focus{
border:solid 1px #73A6FF;
}
a.no-right-border{border-right:none}
a.no-right-border:hover{border-right:none}
a.no-right-border:focus{border-right:none}
a.lshare img{
margin: 5px;
}
......@@ -635,19 +637,28 @@ a.lshare img{
width: 36px;
height: 26px;
}
#error td.close{
#error td.b_close{
width: 30px;
height:22px;
}
#error p{white-space: pre-wrap; word-wrap: break-word; width: 430px; padding-bottom: 5px;}
.noscroll {
overflow: hidden;
}
.form{padding:10px; padding-left:20px;}
.form label{display:block; float:left; width:150px; padding-top:10px;}
.form input[type=text] ,.form input[type=password] {float:left; width:190px;margin:5px;}
.hiddendiv {display: none;white-space: pre-wrap;min-height: 18px;font-size: 13px;
padding:3px;word-wrap: break-word;width:430px; max-height:120px;font-family: 'Helvetica Neue',Tahoma,Helvetica,Arial,sans-serif;}
.list{background: url(../images/menu_dropdown.png) left center no-repeat; padding-left:10px;}
.slidebox{padding:10px; }
.alert_message{ background: url(../images/alert.png) center no-repeat; height: 26px;}
.error_message{ background: url(../images/exit.png) center no-repeat; height: 26px;}
.confirm_message{ background: url(../images/confirm.png) center no-repeat; height: 26px;}
.info_message{ background: url(../images/info.png) center no-repeat; height: 26px;}
#error p{ font-size: 13px; color: #4A131F;}
#pClose{background:url(../images/close.png) no-repeat 0px 0px; display:block; width:22px; height:22px; cursor:pointer}
#pClose:hover{background:url(../images/close_hover.png) no-repeat 0px 0px;}
#pClose, .close{background:url(../images/close.png) no-repeat 0px 0px; display:block; width:22px; height:22px; cursor:pointer}
#pClose:hover, .close:hover{background:url(../images/close_hover.png) no-repeat 0px 0px;}
.md5sum {margin:10px; font-size:15px;}
.title{background: #e4e4e4; width: 100%; height: 25px; padding-top:2px; text-indent: 5px; color: #737373; text-shadow: 0px 1px #FFF;}
.menu-box-left{float:left; width: 120px; font-size:14px; background: #e4e4e4; padding:5px 0 5px 5px; margin-top:10px;
......@@ -656,6 +667,7 @@ a.lshare img{
margin-top:10px; box-shadow: 1px 1px 1px #888888;}
.menu-box-left ul{margin:0px; list-style:none;}
.menu-box-left li{padding: 2px; padding-left:10px; padding-right:10px; text-shadow: 0px 1px #fff;border-bottom:1px solid #fff;}
.menu-box-left li label, .menu-box-left li input[type=radio] { cursor:pointer}
.menu-box-left li:hover{background:#F0F2F2;}
.menu-box-left li.checked{background:#fff;}
.menu-box-right h2{text-align:center}
......@@ -679,7 +691,8 @@ a.lshare img{
.popup li{border-bottom: 1px dashed #666666; padding:5px; padding-top:5px;}
.popup-value{display:none;}
textarea.parameter {border: solid 1px #678dad; color: #666666; height:110px;}
.link{color:#fff; font-weight:bold; text-decoration:none}
.link:hover{color: #19485C;}
input[type=radio] {
}
......@@ -689,3 +702,12 @@ input[type=radio]:checked {
input[type=radio]:hover {
box-shadow: 0px 1px 3px #F0F1F2;
}
/* Login Css region *******/
#login-page{width:429px; height:236px; margin:130px auto 0px; background:url(../images/loginBox.png) no-repeat;
padding:10px; font-size:14px; color:#03406A}
#login-page h2{color:#fff; font-size:26px; font-weight:normal; text-indent:50px;}
.login-content{margin:10px; margin-top:40px; margin-bottom:0; height:90px;}
.login-button{width:140px; margin:0 auto;}
.login-element{float:left; min-width:120px;}
.login-label{padding:5px; font-size:16px;}
.login-input{width:220px;}
\ No newline at end of file
$(document).ready(function(){
$(".tabContents").hide(); // Hide all tab content divs by default
var hashes = window.location.href.split('#');
if (hashes.length == 2){
var fromheight = 0;
var previoustab = null;
if (hashes.length == 2 && hashes[1] != ""){
$("#tabContaier>ul li").each(function() {
var $tab = $(this).find("a");
if($tab.hasClass("active")) $tab.removeClass("active");
if($tab.hasClass("active")){
$tab.removeClass("active");
}
if ($tab.attr("href") == "#"+hashes[1]){
$tab.addClass("active");
$("#"+hashes[1]).show();
previoustab = "#"+hashes[1];
}
//alert($(this).attr("href"));
});
}
else{$(".tabContents:first").show();} // Show the first div of tab content by default
else{$(".tabContents:first").show(); previoustab = ".tabContents:first";} // Show the first div of tab content by default
$("#tabContaier ul li a").click(function(){ //Fire the click event
if($(this).hasClass('active')){
return;
}
fromheight = $(previoustab).height();
var activeTab = $(this).attr("href"); // Catch the click link
$("#tabContaier .tabDetails").css("height", $("#tabContaier .tabDetails").height());
$("#tabContaier ul li a").removeClass("active"); // Remove pre-highlighted link
$(this).addClass("active"); // set clicked link to highlight state
$(".tabContents").hide(); // hide currently visible tab content div
$(activeTab).fadeIn(); // show the target tab content div by matching clicked link.
var diff = fromheight - $(activeTab).height();
if (diff > 0){$("#tabContaier .tabDetails").animate({height: '-=' + diff + 'px'}, 850, 'swing', function() {
$("#tabContaier .tabDetails").css("height", "");
});}
else{diff = -1*diff; $("#tabContaier .tabDetails").animate({height: '+=' + diff + 'px'}, 850, 'swing', function() {
$("#tabContaier .tabDetails").css("height", "");
});}
previoustab = activeTab;
$("#tabContaier .tabDetails").css("height", $("#tabContaier .tabDetails").height());
});
});
\ No newline at end of file
......@@ -3,45 +3,65 @@
//
(function ($, document, window) {
var isShow = null;
var showDelayTimer = null;
$.extend($.fn, {
Popup: function(msg, option) {
var h;
if (option.type == undefined) option.type = "info";
if (option.closebtn == undefined) option.closebtn = false;
if (option.duration == undefined) option.duration = 0;
if (option.load == undefined) option.load = false;
$box = $(this);
if(showDelayTimer){clearTimeout(showDelayTimer);}
if(isShow){
$box.fadeOut('normal', function() {
setupBox();
});
}
else{setupBox();}
function setupBox(){
$box.empty();
$box.css('top','-1000px');
$box.show();
$box.append('<div><table id="bcontent"><tr>' +
'<td valign="middle" class="logo ' + option.type + '_message"></td>' +
'<td valign="middle"><p>' + msg + '</p></td>' +
'<td valign="middle" class="close"><span id="pClose"></span></td></tr></table></div>');
'<td valign="middle" class="b_close"><span id="pClose"></span></td></tr></table></div>');
$(window).scroll(function(){
$box.animate({top:$(window).scrollTop()+"px" },{queue: false, duration: 350});
});
var h = $("#bcontent").height()+5;
h = $("#bcontent").height()+5;
$("#pClose").bind("click", function() {
close();
});
showBox();
if(option.duration != 0){
showDelayTimer = setTimeout(function(){
showDelayTimer = null;
close();
}, option.duration);
}
}
function showBox(){
if(option.load){
$(window).load(function(){
$box.css('top', + ($(window).scrollTop() - h) +'px');
$box.animate({ top:"+=" + h + "px" }, "slow");
isShow = true;
});
}
else{
$box.css('top', + ($(window).scrollTop() - h) +'px');
$box.animate({ top:"+=" + h + "px" }, "slow");
isShow = true;
}
if(option.duration != 0){
setTimeout(function(){
close();
}, option.duration);
}
function close(){
$box.animate({ top:"-=" + h + "px" }, "slow", function(){
$box.fadeOut("normal");
$box.fadeOut("normal", function() {
isShow = false;
});
});
}
}
......
$(document).ready( function() {
var send = false;
$("#update").click(function(){
var haspwd = false;
if($("input#username").val() === "" || !$("input#username").val().match(/^[\w\d\._-]+$/)){
$("#error").Popup("Invalid user name. Please check it!", {type:'alert', duration:3000});
return false;
}
if($("input#name").val() === ""){
$("#error").Popup("Please enter your name and surname!", {type:'alert', duration:3000});
return false;
}
if(!$("input#email").val().match(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/)){
$("#error").Popup("Please enter a valid email adress!", {type:'alert', duration:3000});
return false;
}
if($("input#password").val() !== ""){
if($("input#password").val() === "" || !$("input#password").val().match(/^[\w\d\._-]+$/)){
$("#error").Popup("Please enter your new password!", {type:'alert', duration:3000});
return false;
}
if($("input#password").val() !== $("input#cpassword").val()){
$("#error").Popup("your password does not match!", {type:'alert', duration:3000});
return false;
}
haspwd = true;
}
if(send) return false;
send = true;
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/updateAccount',
data: {name: $("input#name").val(), username:$("input#username").val(), email:$("input#email").val(),
password:((haspwd) ? $("input#password").val():"")},
success: function(data){
if(data.code ==1){
$("#error").Popup("Your account informations has been saved!", {type:'confirm', duration:3000});
}
else{
$("#error").Popup(data.result, {type:'error', duration:5000});
}
send = false;
},
error:function(){send = false;}
});
return false;
});
});
\ No newline at end of file
/*Common javascript function*/
String.prototype.toHtmlChar = function(){
c = {'<':'&lt;', '>':'&gt;', '&':'&amp;', '"':'&quot;', "'":'&#039;',
var c = {'<':'&lt;', '>':'&gt;', '&':'&amp;', '"':'&quot;', "'":'&#039;',
'#':'&#035;' };
return this.replace( /[<&>'"#]/g, function(s) { return c[s]; } );
}
......@@ -8,11 +8,12 @@ String.prototype.trim = function () {
return this.replace(/^\s*/, "").replace(/\s*$/, "");
}
/**************************/
$(document).ready(function() {
$('input[type="text"]').addClass("idleField");
$('input[type="text"]').focus(function() {
/****************************************/
function setInput($elt) {
if(!$elt){var $elt = $('input[type="text"], input[type="password"]');}
$elt.addClass("idleField");
$elt.focus(function() {
$(this).removeClass("idleField").addClass("focusField");
if (this.value == this.defaultValue){
this.value = '';
......@@ -21,10 +22,36 @@ $(document).ready(function() {
this.select();
}
});
$('input[type="text"]').blur(function() {
$elt.blur(function() {
$(this).removeClass("focusField").addClass("idleField");
if ($.trim(this.value) == ''){
this.value = (this.defaultValue ? this.defaultValue : '');
}
});
});
\ No newline at end of file
}
/**************************/
(function ($, document, window) {
$.extend($.fn, {
slideBox: function(state) {
if (!state) state = "hide";
var header = $("#"+$(this).attr('id')+">h2");
var box = $("#"+$(this).attr('id')+">div");
header.addClass(state);
if(state=="hide"){box.css('display', 'none');}
header.click(function(){
var state = box.css("display");
if (state == "none"){
box.slideDown("normal");
header.removeClass("hide");
header.addClass("show");
}
else{
box.slideUp("normal");
header.removeClass("show");
header.addClass("hide");
}
});
}
});
}(jQuery, document, this));
\ No newline at end of file
......@@ -35,7 +35,7 @@ $(document).ready( function() {
$("#error").Popup("Invalid project name", {type:'alert', duration:3000});
return false;
}
if($("input#user").val() != "" && $("input#user").val() != "Enter your name..."){
if($("input#user").val() !== ""){
name = $("input#user").val();
}
if($("input#email").val() != "" && $("input#email").val() != "Enter your email adress..."){
......@@ -97,6 +97,12 @@ $(document).ready( function() {
$("#clone").empty();
$("#clone").append("Clone");
send = false;
},
error: function(request,error) {
$("#error").Popup("unable to clone your project, please check your internet connection", {type:'error', duration:3000});
$("#imgwaitting").hide();
$("#clone").empty();
$("#clone").append("Clone");
}
});
return false;
......
......@@ -4,19 +4,121 @@ $(document).ready( function() {
$($("#slappart li")[0]).find("input:radio").attr('checked', true);
$(".menu-box-right>div").css('min-height', $("#slappart li").length*26 + 20 + "px");
configRadio();
var send = false;
var lastli = null;
var partitionAmount = $("imput#partitionAmount").val();
var partitionAmount = $("input#partitionAmount").val();
$("#slappart li").each(function(){
lastli = $(this);
$(this).find("input:radio").change(function(){
configRadio();
});
});
lastli.css("border-bottom", "none");
if(lastli){lastli.css("border-bottom", "none");}
function setupFileTree(){
$("#parameterkw").slideBox("show");
setupSlappart();
$("#softwareType").slideBox();
$("#reloadfiles").click(function(){
setupFileTree();
});
$("#refresh").click(function(){
if (send) return;
$("#imgwaitting").fadeIn();
$.ajax({
type: "GET",
url: $SCRIPT_ROOT + '/supervisordStatus',
data: "",
success: function(data){
if(data.code == 1){
$("#supervisordcontent").empty();
$("#supervisordcontent").append(data.result);
}
$("#imgwaitting").fadeOut();
}
});
return false;
});
$("#add_attribute").click(function(){
var size = Number($("#partitionParameter > tbody > tr").last().attr('id').split('_')[1]) + 1;
var row="<tr id='row_"+size+"'><td class='first'><input type='text' name='txt_"+size+"' id='txt_"+size+"'></td>"+
"<td style='padding:6px'><textarea class='slap' id='value_"+size+"'></textarea>"+
"</td><td valign='middle'><span style='margin-left: 10px;' id='btn_"+size+"' class='close'></span></td></tr>";
$("#partitionParameter").append(row);
setInput($("input#txt_"+size));
setupTextarea($("textarea#value_"+size));
$("#btn_"+size).click(function(){
var index = $(this).attr('id').split('_')[1];
$("tr#row_"+index).remove();
});
return false;
});
$("#updateParameters").click(function(){
updateParameter();
return false;
});
$("#xmlview").click(function(){
var content = '<h2 style="color: #4c6172; font: 18px \'Helvetica Neue\', Helvetica, Arial, sans-serif;">' +
'INSTANCE PARAMETERS: Load XML file</h2><p id="xmllog" class="message"><br/></p>';
content += '<div class="main_content" style="height:230px"><pre id="editor"></pre></div>'+
'<input type=submit value="Load" id="loadxml" class="button">';
$.ajax({
type: "GET",
url: $SCRIPT_ROOT + '/getParameterXml/xml',
success: function(data){
if(data.code == 1){
$("#inline_content").html(content);
setupEditor(true);
$(".inline").colorbox({inline:true, width: "600px", height: "410px", onComplete:function(){
editor.getSession().setValue(data.result);
}});
$(".inline").click();
$("#loadxml").click(function(){
//Parse XML file
try{
var xmlDoc = $.parseXML(editor.getSession().getValue()), $xml = $( xmlDoc );
if($xml.find("parsererror").length !== 0){$("p#xmllog").html("Error: Invalid XML document!<br/>");return false;}
} catch(err) {
$("p#xmllog").html("Error: Invalid XML document!<br/>");return false;
}
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/saveParameterXml',
data: {software_type:"", parameter:editor.getSession().getValue()},
success: function(data){
if(data.code == 1){
location.href = $SCRIPT_ROOT + '/inspectInstance#tab3';
location.reload();
}
else{$("p#xmllog").html(data.result);}
}
});
return false;
});
}
else{
$("#error").Popup(data.result, {type:'error', duration:5000});
}
}
});
});
//Load previous instance parameters
loadParameter();
$("a#parameterTab").click(function(){
var size = $("#partitionParameter > tbody > tr").length;
for(var i=2; i<=size; i++){
$("textarea#value_"+i).keyup();
}
});
function setupFileTree(path){
var root = $("input#root").val();
if (root == "") return;
if (path){
root += "/" + path;
$("#tab4>h2").html("File content for <strong>" + path + "</strong>");
}
else{$("#tab4>h2").html("File content for all your partitions");}
$('#fileTree').empty();
$('#fileTree').fileTree({ root: root, script: $SCRIPT_ROOT + "/readFolder", folderEvent: 'click', expandSpeed: 750,
collapseSpeed: 750, multiFolder: false, selectFolder: false }, function(file) {
......@@ -91,6 +193,70 @@ $(document).ready( function() {
}
});
}
function updateParameter(){
var xml = '<?xml version="1.0" encoding="utf-8"?>\n', software_type="";
if($("input#software_type").val() != "" && $("input#software_type").val() != "Software Type here..."){
software_type = +$("input#software_type").val();
}
xml +='<instance>\n';
var size = $("#partitionParameter > tbody > tr").length;
if(size > 1){
for(var i=2; i<=size; i++){
if($("input#txt_"+i).val() != ""){
xml +='<parameter id="'+$("input#txt_"+i).val()+'">'+$("textarea#value_"+i).val()+'</parameter>\n';
}
}
}
xml +='</instance>\n';
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/saveParameterXml',
data: {software_type:software_type, parameter:xml},
success: function(data){
if(data.code == 1){
$("#error").Popup("Instance parameters has been updated, please run your instance now!", {type:'confirm', duration:5000});
}
else{
$("#error").Popup(data.result, {type:'error', duration:5000});
}
}
});
}
function setupTextarea($txt){
var size = Number($txt.attr('id').split('_')[1]);
var hiddenDiv = $(document.createElement('div')),
content = null;
hiddenDiv.attr('id', 'div_'+size);
hiddenDiv.addClass('hiddendiv');
$('div#parameterkw').append(hiddenDiv);
$txt.keyup(function() {
content = $txt.val().replace(/\n/g, '<br>');
hiddenDiv.html(content);
if(hiddenDiv.height() > $txt.height() && hiddenDiv.height() > 120){return}
$txt.css('height', hiddenDiv.height()+"px");
});
}
function loadParameter(){
$.ajax({
type: "GET",
url: $SCRIPT_ROOT + '/getParameterXml/dict',
success: function(data){
if(data.code == 1){
var dict=data.result['instance'];
for (propertie in dict){
$("#add_attribute").click();
var size = Number($("#partitionParameter > tbody > tr").last().attr('id').split('_')[1]);
$("input#txt_"+size).val(propertie);
$("textarea#value_"+size).val(dict[propertie]);
$("textarea#value_"+size).keyup();
}
}
else{
$("#error").Popup(data.result, {type:'error', duration:5000});
}
}
});
}
function configRadio(){
$("#slappart li").each(function() {
var $radio = $(this).find("input:radio");
......@@ -107,7 +273,20 @@ $(document).ready( function() {
}
});
}
function setupEditor(){
function setupBox(){
var state = $("#softwareType").css("display");
if (state == "none"){
$("#softwareType").slideDown("normal");
$("#softwareTypeHead").removeClass("hide");
$("#softwareTypeHead").addClass("show");
}
else{
$("#softwareType").slideUp("normal");
$("#softwareTypeHead").removeClass("show");
$("#softwareTypeHead").addClass("hide");
}
}
function setupEditor(editable){
editor = ace.edit("editor");
editor.setTheme("ace/theme/crimson_editor");
......@@ -116,13 +295,18 @@ $(document).ready( function() {
editor.getSession().setTabSize(2);
editor.getSession().setUseSoftTabs(true);
editor.renderer.setHScrollBarAlwaysVisible(false);
editor.setReadOnly(true);
if(!editable){editor.setReadOnly(true);}
}
function setupSlappart(){
for(var i=0; i<partitionAmount; i++){
var elt = $("#slappart"+i+"Parameter");
if(elt != undefined) elt.click(function(){
alert(elt.attr('id'));
var fileId = $("#slappart"+i+"Files");
if(elt && elt != undefined) elt.click(function(){
alert($(this).html());
});
if(fileId && fileId != undefined) fileId.click(function(){
$("#instancetabfiles").click();
setupFileTree($(this).attr("rel"));
});
}
}
......
......@@ -20,16 +20,22 @@ $(document).ready( function() {
function fillContent(){
var folder = $("#softwarelist").val();
var elt = $("option:selected", $("#softwarelist"));
if(elt.val() !== "No Software Release found"){
$('#fileTree').fileTree({ root: runnerDir + "/" + folder, script: $SCRIPT_ROOT + '/readFolder',
folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false, selectFolder: true }, function(file) {
selectFile(file);
}, function(file){ viewFile(file)});
$("#softcontent").empty();
$("#softcontent").append("File content: " + elt.attr('title'));
}
}
$("#open").click(function(){
var elt = $("option:selected", $("#softwarelist"));
if(elt.val() === "No Software Release found"){
$("#error").Popup("Please select your Software Release", {type:'alert', duration:5000});
return false;
}
$.ajax({
type: "POST",
url: $SCRIPT_ROOT + '/setCurrentProject',
......@@ -39,7 +45,7 @@ $(document).ready( function() {
location.href = $SCRIPT_ROOT + '/editSoftwareProfile'
}
else{
$("#error").Popup(data.result, {type:'error'});
$("#error").Popup(data.result, {type:'error', duration:5000});
}
}
});
......@@ -47,6 +53,10 @@ $(document).ready( function() {
});
$("#delete").click(function(){
if($("#softwarelist").val() === "No Software Release found"){
$("#error").Popup("Please select your Software Release", {type:'alert', duration:5000});
return false;
}
if(send) return;
send = false;
$.ajax({
......@@ -56,11 +66,6 @@ $(document).ready( function() {
success: function(data){
if(data.code == 1){
var folder = $("#softwarelist").val();
$('#fileTree').fileTree({ root: runnerDir + "/" + folder, script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750,
collapseSpeed: 750, multiFolder: false, selectFolder: true }, function(file) {
selectFile(file);
setupFileTree(runnerDir);
}, function(file){ viewFile(file)});
$("input#file").val("");
$("#info").empty();
$("#info").append("Please select your file or folder into the box...");
......@@ -70,6 +75,17 @@ $(document).ready( function() {
'" title="' + data.result[i]["title"] +'" rel="' +
data.result[i]["path"] +'">' + data.result[i]["title"] + '</option>');
}
if(data.result.length < 1){
$("#softwarelist").append('<option>No Software Release found</option>');
$('#fileTree').empty();
}
else{
folder = $("#softwarelist").val();
$('#fileTree').fileTree({ root: runnerDir + "/" + folder, script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750,
collapseSpeed: 750, multiFolder: false, selectFolder: true }, function(file) {
selectFile(file);
}, function(file){ viewFile(file)});
}
$("#error").Popup("Operation complete, Selected Software Release has been delete!", {type:'confirm', duration:5000});
}
else{
......
$(document).ready( function() {
var send = false;
//change background
$("body").css("background", "#9C9C9C");
$("#login").click(function(){
if (send) return false;
if($("input#clogin").val() === "" || !$("input#clogin").val().match(/^[\w\d\.-]+$/)){
$("#error").Popup("Please enter a valid user name", {type:'alert', duration:3000});
return false;
}
if($("input#cpwd").val() === "" || $("input#cpwd").val() ==="******"){
$("#error").Popup("Please enter your password", {type:'alert', duration:3000});
return false;
}
send = true;
var param = {clogin:$("input#clogin").val(), cpwd:$("input#cpwd").val()};
var url = $SCRIPT_ROOT + "/doLogin";
$.post(url, param, function(data) {
if (data.code==1){
location.href = $SCRIPT_ROOT + '/';
}
else{
$("#error").Popup(data.result, {type:'alert', duration:3000});
}
})
.error(function() {$("#error").Popup("Cannot send your account identifier please try again!!",
{type:'alert', duration:3000});})
.complete(function() {
send = false;
});
return false;
});
});
\ No newline at end of file
......@@ -106,7 +106,7 @@ function setRunningState(data){
$current.css("color", "#000");
$current = undefined;
currentState = false;
$("#error").Popup("Successfully run " + processType + " Profile", {type:'info', duration:3000});
$("#error").Popup("Slapgrid completely finish running your " + processType + " Profile", {type:'info', duration:3000});
}
}
currentState = data.result;
......
{% extends "layout.html" %}
{% block title %}Update your account{% endblock %}
{% block head %}
{{ super() }}
<script src="{{ url_for('static', filename='js/scripts/account.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}
{% block body %}
<h2 class='title'>Your personal informations</h2><br/>
<form>
<div class='form'>
<label for="name">Your name: </label>
<input type='text' name='name' id='name' value='{{name}}'/>
<div class='clear'></div>
<label for="email">Your email adress: </label>
<input type='text' name='email' id='email' value='{{email}}'/>
<div class='clear'></div>
<label for="username">User name: </label>
<input type='text' name='username' id='username' value='{{username}}'/>
<div class='clear'></div>
<label for="password">Password: </label>
<input type='password' name='password' id='password' value=''/>
<div class='clear'></div>
<label for="cpassword">Confirm Password: </label>
<input type='password' name='cpassword' id='cpassword' value=''/>
<div class='clear'></div>
<br/>
<label></label>
<input type="submit" name="update" id ="update" value="Update" class="button"/>
<div class='clear'></div>
<br/><br/><br/>
</div>
<div id="file_info" class="file_info">leave passwords blank to preserve your current password...</div>
<br/>
</form>
{% endblock %}
......@@ -3,28 +3,37 @@
{% block head %}
{{ super() }}
<link href="{{ url_for('static', filename='css/jqueryFileTree.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<link href="{{ url_for('static', filename='css/jqueryTabs.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='js/jquery/jqueryFileTree.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/scripts/folder.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/jqueryTabs.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}
{% block body %}
<h2 class='title'>Clone your repository into the workspace</h2><br/>
<div id="repository" style="margin-left:40px;">
<label for='name'>Project name*: </label>
<input type="text" name="name" id="name" size='20' value="Enter the project name..." />
<label for='repo'>&nbsp;url*: &nbsp;&nbsp;</label>
<input type="text" name="repo" id="repo" size='25' value="Enter the url of your repository..." /><br/>
<label for='user'>Your name: &nbsp;&nbsp;&nbsp;&nbsp;</label>
<input type="text" name="user" id="user" size='20' value="Enter your name..." />
<label for='email'>Email: </label>
<input type="text" name="email" id="email" size='25' value="Enter your email adress..." />
<input type="hidden" name="workdir" id="workdir" value="{{workDir}}" />
<button class="button" id="clone">clone</button>
<img class="waitting" id="imgwaitting" src="{{ url_for('static', filename='images/waiting.gif') }}" alt="" />
<br/><br/>
</div>
<h2>Set your Security Mode</h2>
<div class="menu-box-right">
<h2>Clone a repository into your workspace</h2><br/>
<div id="tabContaier">
<ul>
<li><a href="#tab1" class="active">Clone your repository</a></li>
<li><a href="#tab2">Manage your project folder</a></li>
</ul><!-- //Tab buttons -->
<div class="tabDetails">
<div id="tab1" class="tabContents">
<div id="repository" style="margin-left:40px;">
<label for='name'>Project name*: </label>
<input type="text" name="name" id="name" size='20' value="Enter the project name..." />
<label for='repo'>&nbsp;url*: &nbsp;&nbsp;</label>
<input type="text" name="repo" id="repo" size='25' value="Enter the url of your repository..." /><br/>
<label for='user'>Your name: &nbsp;&nbsp;&nbsp;&nbsp;</label>
<input type="text" name="user" id="user" size='20' value="{{name}}" />
<label for='email'>Email: </label>
<input type="text" name="email" id="email" size='25' value="{% if not email %}Enter your email adress...{% else %}{{email}}{%endif%}" />
<input type="hidden" name="workdir" id="workdir" value="{{workDir}}" />
<button class="button" id="clone">clone</button>
<img class="waitting" id="imgwaitting" src="{{ url_for('static', filename='images/waiting.gif') }}" alt="" />
<br/><br/>
</div>
<br/>
<h2>Set your Security Mode</h2>
<div class="menu-box-right" style="width: 592px;">
<div style="background:#fff; padding:10px; min-height:100px; font-size:14px;">
<div id="box0">
<h2>Clone Repository without using HTTPS and SSH</h2><br/>
......@@ -35,7 +44,7 @@
</div>
<div id="box1" style="display:none">
<h2>You can use this public key to setup your repository</h2><br/>
<textarea class="public_key" readonly>
<textarea class="mb_style public_key" readonly>
{{public_key}}
</textarea>
</div>
......@@ -50,17 +59,21 @@
<p></p>
</div>
</div>
</div>
<div class="menu-box-left">
</div>
<div class="menu-box-left" style="width: 115px;">
<ul id="modelist">
<li class="checked"><input type="radio" name="security" id="nothing" value="nothing" /><label for="nothing">ReadOnly</label></li>
<li><input type="radio" name="security" id="ssh" value="SSH" checked /><label for="ssh">SSH Mode</label></li>
<li style="border-bottom:none"><input type="radio" name="security" id="https" value="HTTPS" /><label for="https">Https Mode</label></li>
</ul>
</div>
<div class="clear"></div><br/>
<div id="file_navigation">
<h2 class='title'>Your project folder</h2><br/>
<div id="fileTree" class="file_tree"></div>
</div>
<div class="clear"></div><br/>
<!--Fin tab1-->
</div>
<div id="tab2" class="tabContents">
<h2>Content of your cloned project</h2><br/>
<div id="fileTree" class="file_tree_tabs"></div>
</div>
</div>
</div>
{% endblock %}
{% extends "layout.html" %}
{% block title %}SlapOs buildout web based runner {% endblock %}
{% block title %}SlapOS buildout web based runner {% endblock %}
{% block body %}
<div id="home_box">
<div class="inner_box">
......@@ -23,14 +23,20 @@
<img src="{{ url_for('static', filename='images/manage_repo.png') }}" />
</div>
<div class="clear"></div>
<div class="lmenu">
<h2><a href="{{ url_for('openProject', method='new')}}">Create your new Software Release</a></h2>
<p>To create a new Software Release, choose the project directory in which you want to create your software. You will then be able to edit and
run the new software release.
<div class="lmenu smaller">
<h2><a href="{{ url_for('openProject', method='new')}}">Create your Software Release</a></h2>
<p>To create a new Software Release, choose the project directory in which you want to create your software.<!-- You will then be able to edit and
run the new software release.-->
</p>
<img src="{{ url_for('static', filename='images/folder_blue.png') }}" />
<div class="clear"></div>
</div>
<div class="umenu">
<h2><a href="{{ url_for('myAccount')}}">Your Account</a></h2>
<p>Update your account informations</p>
<img src="{{ url_for('static', filename='images/user_card.png') }}" />
</div>
<div class="clear"></div>
</div>
</div>
{% endblock %}
......@@ -19,14 +19,15 @@
<div id="tabContaier">
<ul>
<li><a href="#tab1" class="active">Slapgrid Supervisor</a></li>
<li><a href="#tab2">SLAP Response & Parameters</a></li>
<li><a href="#tab3">Partitions Content</a></li>
<li><a href="#tab2">SLAP Response</a></li>
<li><a href="#tab3" id="parameterTab">Parameters</a></li>
<li><a href="#tab4" id="instancetabfiles">Partitions Content</a></li>
</ul><!-- //Tab buttons -->
<div class="tabDetails">
<div id="tab1" class="tabContents">
<p>This tab show all process generated by slapgrid for your application. You can click on the process name to display log.</p>
{% if supervisor %}
<table cellpadding="0" cellspacing="0" width="100%">
<table cellpadding="0" cellspacing="0" width="100%" id="supervisordcontent">
<tr>
<th>Partition and Process name</th><th>Status</th><th>Process PID </th><th> UpTime</th><th></th>
</tr>
......@@ -39,7 +40,10 @@
</tr>
{% endfor %}
</table><br/>
<a href="{{ url_for('stopAllPartition') }}" class="lshare simple">Stop all process</a>
<a href="#" id="refresh" class="lshare simple no-right-border" style="float:left">Refresh Status</a>
<a href="{{ url_for('stopAllPartition') }}" class="lshare simple" style="float:left">Stop all process</a>
<img class="waitting" id="imgwaitting" src="{{ url_for('static', filename='images/waiting.gif') }}" alt="" />
<div class="clear"></div><br/>
{% else %}
<h2>No process to display, please run your instance</h2>
{%endif%}
......@@ -52,10 +56,10 @@
{% for item in slap_status %}
<div id="box{{item[0]}}" style="display:none;">
{% if item[1] %}
<!--<h2><span style="float:left; margin-left:10px;" id="{{item[0]}}title">Slap Response for {{item[0]}}</span>
<a href="#" id="{{item[0]}}Parameter" rel="{{item[0]}}" class="lshare simple" style="float:right">SLAP Parameters</a>
</h2>-->
<h2>Slap Response for {{item[0]}}</h2>
<h2><span style="float:left; margin-left:10px;" id="{{item[0]}}title">Slap Response for {{item[0]}}</span>
<a href="#" id="{{item[0]}}Parameter" rel="{{item[0]}}" class="lshare simple" style="float:right" title='Restart all partition process'>Restart</a>
<a href="#" id="{{item[0]}}Files" rel="{{item[0]}}" class="lshare simple no-right-border" style="float:right">Files</a>
</h2>
<div class="clear"></div><br/>
<div id="bcontent{{item[0]}}">
<table cellpadding="0" cellspacing="0" width="100%">
......@@ -92,8 +96,39 @@
{%endif%}
</div><!-- end tab2 -->
<div id="tab3" class="tabContents">
<div id="fileTree" class="file_tree_tabs"></div>
<div id="softwareType">
<h2 class='hight'>Software Type parameter</h2>
<div class="slidebox">
<label for="software_type">Software Type </label>
<input type="text" name="software_type" id="software_type" size="35" value="Software Type here..." />
</div>
</div>
<br/>
<div id="parameterkw">
<h2 class='hight'>Partitions Parameter</h2>
<div class="slidebox">
<table class="small" cellpadding="0" cellspacing="0" width="100%" id="partitionParameter">
<tr id="row_1">
<th width="150">Parameter Name</th><th>Parameter Value</th><th width="49">
<a href="#" class="link" id="add_attribute">[new]</a>
</th>
</tr>
</table>
</div>
</div>
<br/>
<div>
<a id="updateParameters" class="lshare simple no-right-border" style="float:left">Update Values</a>
<a href="#" id="xmlview" class="lshare simple" style="float:left">Load XML</a>
</div>
<div class="clear"></div>
</div><!-- end tab3 -->
<div id="tab4" class="tabContents">
<h2>File content for all your partitions</h2>
<div id="fileTree" class="file_tree_tabs" title="Double click to open file"></div>
<br/>
<a href="#" id="reloadfiles" class="lshare simple">Reload Files</a>
</div><!-- end tab4 -->
</div>
</div>
<!-- This contains the hidden content for inline calls -->
......@@ -103,4 +138,5 @@
</div>
</div>
{{instance}}
{% endblock %}
......@@ -19,9 +19,15 @@
<script type=text/javascript>
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script>
<script src="{{ url_for('static', filename='js/scripts/process.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/scripts/cookies.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/scripts/common.js') }}" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
$(document).ready(function() {
setInput();
});
</script>
{% if request.path != '/login' %}
<script src="{{ url_for('static', filename='js/scripts/process.js') }}" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
$(document).ready(function() {
if($("input#fmsg").val() != ""){
......@@ -33,20 +39,22 @@
}
});
</script>
{%endif%}
{% endblock %}
</head>
<body>
<div id="error"></div>
<div id="page">
<div {% if request.path != '/login' %}id="page"{%else%}id="login-page"{%endif%}>
<input type="hidden" name="fmsg" value="{{ get_flashed_messages()[0] }}" id="fmsg" />
<!--<div id="logo">-->
<!--<a href="{{ url_for('home') }}"><img src="{{ url_for('static', filename='images/logo.png') }}" alt="" /></a>-->
<!--</div>-->
{% if request.path != '/login' %}
<div id="header">
<div class="block_header">
<a href="{{ url_for('home') }}" style="float:left;" id="home" {% if request.path != '/' %}rel="tooltip"{% endif %} title="Home"><img alt="" src="{{ url_for('static', filename='images/home.png') }}" /></a>
<div class="line"></div>
<a href="{{ url_for('editCurrentProject') }}" style="float:left" title="Edit your current project"><img alt="" src="{{ url_for('static', filename='images/project.png') }}" /></a>
<div class="line"></div>
<a href="{{ url_for('logout') }}" style="float:left" title="Close your session"><img alt="" src="{{ url_for('static', filename='images/logout.png') }}" /></a>
<div class="line"></div>
<h2 class="info">{% block title %}{% endblock %} - {{session.title}}</h2>
<div class="run"><span id="running" style="display:none"><img alt="" src="{{ url_for('static', filename='images/ajax_roller.gif') }}"
......@@ -71,24 +79,27 @@
</div>
<div class="clear"></div>
</div>
<div id="main">
<div {% if request.path == '/' %} class="home_content" {%else%} id="content" {% endif %}>
{% if request.path != '/' %}
{% endif %}
<div {% if request.path != '/login' %}id="main"{% endif %}>
<div {% if request.path == '/' %} class="home_content" {%elif request.path == '/login'%} {%else%} id="content" {% endif %}>
{% if request.path != '/' and request.path != '/login'%}
<div class="main_head">
</div>
<div class="content">
{% endif %}
{% block body %}{% endblock %}
{% if request.path != '/' %}
{% if request.path != '/' and request.path != '/login'%}
</div>
<div class="main_foot">
</div>
{% endif %}
</div>
</div>
{% if request.path != '/login' %}
<div id="footer">
SlapOs web runner &copy; Vifib SARL 2011 - All right reserved - Creative Commons Shared Alike Non Commercial
</div>
{%endif%}
</div>
<div class="popup">
<table id="dpop" cellpadding="0" border="0">
......@@ -112,7 +123,7 @@
<div style="margin-top:3px;border-bottom: 1px dashed #666666; heigth:1px"></div>
<ul>
<li><a href="{{ url_for('manageProject')}}">Manage Repositories</a></li>
<li><a href="{{ url_for('configRepo')}}" >Clone your Repository</a></li>
<li><a href="{{ url_for('configRepo')}}" >Clone your repository</a></li>
<li><a href="{{ url_for('openProject', method='open')}}">Open Software Release</a></li>
<li><a href="{{ url_for('openProject', method='new')}}">Create Software Release</a></li>
</ul>
......
{% extends "layout.html" %}
{% block head %}
{{ super() }}
<script src="{{ url_for('static', filename='js/scripts/login.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}
{% block body %}
<form method="POST" action="">
<h2>Login to Slapos Web Runner</h2>
<div class="login-content">
<div class="login-element login-label"><label for="clogin">Your login&nbsp; : </label></div>
<div class="login-element"><input type="text" class="login-input" name="clogin" id="clogin" value="Enter login..." /></div><br/><br/>
<div class="clear"></div>
<div class="login-element login-label"><label for="cpwd">Password : </label></div>
<div class="login-element"><input type="password" class="idleField login-input" name="cpwd" id="cpwd" value="******" /></div>
<div class="clear"></div>
</div>
<div style="text-align:center">
<input type="reset" class="button" value="reset" />
<input type="submit" class="button" id="login" value="login" />
</div>
</form>
{% endblock %}
\ No newline at end of file
......@@ -14,7 +14,7 @@
<input type="hidden" name="method" id="method" value="{{method}}" />
{% if method == "new" %}
<div id="addsoftware">
<h2>Create your software release</h2>
<h2 class="title">Create your software release</h2><br/>
<label for='software'>Name: </label>
<input type="text" name="software" id="software" size='30' value="Enter software name..." />
<br/><br/>
......@@ -28,7 +28,7 @@
</div>
{% elif method == "open" %}
<div id="openSoftware">
<h2>Select the folder of your software release into the box</h2>
<h2 class="title">Select the folder of your software release into the box</h2><br/>
<div id="fileTree" class="file_tree"></div>
<div id="file_info" class="file_info">
<img src="{{ url_for('static', filename='images/check.png') }}" class="check" id="check" alt=""/>
......
......@@ -16,6 +16,7 @@
<input type="hidden" name="runnerdir" id="runnerdir" value="{{softwareRoot}}" />
<label for='softwarelist'>Select software: </label>
<select name="softwarelist" id="softwarelist">
{%if not softwares %}<option >No Software Release found</option>{% endif %}
{%for soft in softwares %}
<option value="{{soft['md5']}}" title="{{soft['title']}}" rel="{{soft['path']}}">{{soft['title']}}</option>
{%endfor%}
......@@ -23,8 +24,8 @@
&nbsp;&nbsp;<button id ="delete" class="button" title="Remove this software">Remove</button>
&nbsp;&nbsp;<button id ="open" class="button" title="Set this software as current software release">Open</button>
<br/><br/>
<h2 id="softcontent">No content to displays</h2>
<div id="fileTree" class="file_tree" style='height:200px;'></div>
<h2 id="softcontent">No file or folder to display</h2>
<div id="fileTree" class="file_tree" style='height:200px;' title="Double click to open file"></div>
<div id="file_info" class="file_info">
<span id="info">Please select your file or folder into the box...</span></div>
<!-- This contains the hidden content for inline calls -->
......
This diff is collapsed.
# -*- coding: utf-8 -*-
from flask import Flask, request, redirect, url_for, \
render_template, flash, jsonify, session
from utils import *
......@@ -9,21 +11,51 @@ from gittools import cloneRepo, gitStatus, switchBranch, addBranch, getDiff, \
app = Flask(__name__)
#Access Control: Only static files and login pages are allowed to guest
@app.before_request
def before_request():
if (not session.has_key('account') or not session['account']) \
and request.path != '/login' \
and request.path != '/doLogin' and not request.path.startswith('/static'):
return redirect(url_for('login'))
if session.has_key('account') and session['account']:
session['title'] = getProjectTitle(app.config)
session['account'] = getSession(app.config)
# general views
@app.route('/')
def home():
if not os.path.exists(app.config['workspace']) or len(os.listdir(app.config['workspace'])) == 0:
return redirect(url_for('configRepo'))
return render_template('index.html')
@app.route("/login")
def login():
return render_template('login.html')
@app.route("/myAccount")
def myAccount():
return render_template('account.html', username=session['account'][0],
email=session['account'][2], name=session['account'][3].decode('utf-8'))
@app.route("/logout")
def logout():
session['account'] = None
return redirect(url_for('login'))
@app.route('/configRepo')
def configRepo():
public_key = open(app.config['public_key'], 'r').read()
return render_template('cloneRepository.html', workDir='workspace', public_key=public_key)
return render_template('cloneRepository.html', workDir='workspace',
public_key=public_key, name=session['account'][3].decode('utf-8'),
email=session['account'][2])
@app.route("/doLogin", methods=['POST'])
def doLogin():
check_user = checkLogin(app.config, request.form['clogin'], request.form['cpwd'])
if not check_user:
return jsonify(code=0, result="Login or password is incorrect, please check it!")
else:
session['account'] = check_user
return jsonify(code=1, result=check_user)
# software views
@app.route('/editSoftwareProfile')
......@@ -43,6 +75,7 @@ def inspectSoftware():
return render_template('runResult.html', softwareRoot='software_root',
softwares=loadSoftwareData(app.config['runner_workdir']))
#remove content of compiled software release
@app.route('/removeSoftware')
def removeSoftware():
file_config = os.path.join(app.config['runner_workdir'], ".softdata")
......@@ -80,6 +113,7 @@ def editInstanceProfile():
return render_template('updateInstanceProfile.html', workDir='workspace',
profile=profile, projectList=getProjectList(app.config['workspace']))
# get status of all computer partitions and process state
@app.route('/inspectInstance', methods=['GET'])
def inspectInstance():
file_content = ''
......@@ -93,12 +127,34 @@ def inspectInstance():
file_path=file_content, supervisor=result, slap_status=getSlapStatus(app.config),
supervisore=result, partition_amount=app.config['partition_amount'])
#Reload instance process ans returns new value to ajax
@app.route('/supervisordStatus', methods=['GET'])
def supervisordStatus():
result = getSvcStatus(app.config)
if not (result):
return jsonify(code=0, result="")
html = "<tr><th>Partition and Process name</th><th>Status</th><th>Process PID </th><th> UpTime</th><th></th></tr>"
for item in result:
html += "<tr>"
html +="<td class='first'><b><a href='" + url_for('tailProcess', process=item[0])+"'>"+item[0]+"</a></b></td>"
html +="<td align='center'><a href='"+url_for('startStopProccess', process=item[0], action=item[1])+"'>"+item[1]+"</a></td>"
html +="<td align='center'>"+item[3]+"</td><td>"+item[5]+"</td>"
html +="<td align='center'><a href='"+url_for('startStopProccess', process=item[0], action='RESTART')+"'>Restart</a></td>"
html +="</tr>"
return jsonify(code=1, result=html)
@app.route('/removeInstance')
def removeInstance():
if isInstanceRunning(app.config):
flash('Instantiation in progress, cannot remove')
else:
stopProxy(app.config)
removeProxyDb(app.config)
startProxy(app.config)
removeInstanceRoot(app.config)
param_path = os.path.join(app.config['runner_workdir'], ".parameter.xml")
if os.path.exists(param_path):
os.remove(param_path)
flash('Instance removed')
return redirect(url_for('inspectInstance'))
......@@ -201,6 +257,7 @@ def getProjectStatus():
else:
return jsonify(code=0, result="Can not read folder: Permission Denied")
#view for current software release files
@app.route("/editCurrentProject")
def editCurrentProject():
project = os.path.join(app.config['runner_workdir'], ".project")
......@@ -210,6 +267,7 @@ def editCurrentProject():
projectList=getProjectList(app.config['workspace']))
return redirect(url_for('configRepo'))
#create file or directory
@app.route("/createFile", methods=['POST'])
def createFile():
path = realpath(app.config, request.form['file'], False)
......@@ -225,6 +283,7 @@ def createFile():
except Exception, e:
return jsonify(code=0, result=str(e))
#remove file or directory
@app.route("/removeFile", methods=['POST'])
def removeFile():
try:
......@@ -238,8 +297,13 @@ def removeFile():
@app.route("/removeSoftwareDir", methods=['POST'])
def removeSoftwareDir():
return removeSoftwareByName(app.config, request.form['name'])
try:
data = removeSoftwareByName(app.config, request.form['name'])
return jsonify(code=1, result=data)
except Exception, e:
return jsonify(code=0, result=str(e))
#read file and return content to ajax
@app.route("/getFileContent", methods=['POST'])
def getFileContent():
file_path = realpath(app.config, request.form['file'])
......@@ -256,7 +320,7 @@ def getFileContent():
def saveFileContent():
file_path = realpath(app.config, request.form['file'])
if file_path:
open(file_path, 'w').write(request.form['content'])
open(file_path, 'w').write(request.form['content'].encode("utf-8"))
return jsonify(code=1, result="")
else:
return jsonify(code=0, result="Error: No such file!")
......@@ -323,6 +387,7 @@ def getmd5sum():
else:
return jsonify(code=0, result="Can not get md5sum for this file!")
#return informations about state of slapgrid process
@app.route("/slapgridResult", methods=['POST'])
def slapgridResult():
software_state = isSoftwareRunning(app.config)
......@@ -359,31 +424,61 @@ def getPath():
else:
return jsonify(code=1, result=realfile)
#update instance parameter into a local xml file
@app.route("/saveParameterXml", methods=['POST'])
def redParameterXml():
def saveParameterXml():
project = os.path.join(app.config['runner_workdir'], ".project")
if not os.path.exists(project):
return jsonify(code=0, result="Please first open a Software Release")
content = request.form['parameter']
content = request.form['parameter'].encode("utf-8")
param_path = os.path.join(app.config['runner_workdir'], ".parameter.xml")
try:
f = open(param_path, 'w')
f.write(content)
f.close()
result = readParameters(param_path)
except Exception, e:
result = str(e)
software_type = None
if(request.form['software_type']):
software_type = request.form['software_type']
if type(result) == type(''):
return jsonify(code=0, result="XML Error: " + result)
return jsonify(code=0, result=result)
else:
try:
updateProxy(app.config)
except Exeption:
return jsonify(code=0, result="An error occurred while applying your settings!")
updateInstanceParameter(app.config, software_type)
except Exception, e:
return jsonify(code=0, result="An error occurred while applying your settings!<br/>" + str(e))
return jsonify(code=1, result="")
@app.route("/getParameterXml", methods=['GET'])
def getParameterXml():
#read instance parameters into the local xml file and return a dict
@app.route("/getParameterXml/<request>", methods=['GET'])
def getParameterXml(request):
param_path = os.path.join(app.config['runner_workdir'], ".parameter.xml")
if os.path.exists(param_path):
content = open(param_path, 'r').read()
return html_escape(content)
if not os.path.exists(param_path):
default = '<?xml version="1.0" encoding="utf-8"?>\n'
default += '<instance>\n</instance>'
return jsonify(code=1, result=default)
if request == "xml":
parameters = open(param_path, 'r').read()
else:
parameters = readParameters(param_path)
if type(parameters) == type('') and request != "xml":
return jsonify(code=0, result=parameters)
else:
return "&lt;?xml version='1.0' encoding='utf-8'?&gt;"
\ No newline at end of file
return jsonify(code=1, result=parameters)
#update user account data
@app.route("/updateAccount", methods=['POST'])
def updateAccount():
account = []
user = os.path.join(app.config['runner_workdir'], '.users')
account.append(request.form['username'].strip())
account.append(request.form['password'].strip())
account.append(request.form['email'].strip())
account.append(request.form['name'].strip())
result = saveSession(app.config, session, account)
if type(result) == type(""):
return jsonify(code=0, result=result)
else:
return jsonify(code=1, result="")
\ No newline at end of file
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