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;
......@@ -39,9 +42,9 @@
}
#tabContaier > ul > li a.active{
background:#fbfbfb;
border:1px solid #fff;
border:1px solid #fff;
border-top:0;
border-right:0;
border-right:0;
color:#333;
}
#tabContaier > ul > li:first-child a{border-left:0}
......@@ -55,4 +58,4 @@
}
.tabContents p{
padding:0 0 10px;
}
}
......@@ -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;
......@@ -580,9 +579,10 @@ a.lshare{
height: 18px;
font-size: 15px;
border: solid 1px #678dad;
color: #4DA0C6;
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){
$(".tabContents").hide(); // Hide all tab content divs by default
var hashes = window.location.href.split('#');
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,47 +3,67 @@
//
(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);
$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>');
$(window).scroll(function(){
$box.animate({top:$(window).scrollTop()+"px" },{queue: false, duration: 350});
});
var h = $("#bcontent").height()+5;
$("#pClose").bind("click", function() {
close();
});
if(option.load){
$(window).load(function(){
$box.css('top', + ($(window).scrollTop() - h) +'px');
$box.animate({ top:"+=" + h + "px" }, "slow");
});
$box = $(this);
if(showDelayTimer){clearTimeout(showDelayTimer);}
if(isShow){
$box.fadeOut('normal', function() {
setupBox();
});
}
else{
$box.css('top', + ($(window).scrollTop() - h) +'px');
$box.animate({ top:"+=" + h + "px" }, "slow");
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="b_close"><span id="pClose"></span></td></tr></table></div>');
$(window).scroll(function(){
$box.animate({top:$(window).scrollTop()+"px" },{queue: false, duration: 350});
});
h = $("#bcontent").height()+5;
$("#pClose").bind("click", function() {
close();
});
showBox();
if(option.duration != 0){
showDelayTimer = setTimeout(function(){
showDelayTimer = null;
close();
}, option.duration);
}
}
if(option.duration != 0){
setTimeout(function(){
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;
}
}
function close(){
$box.animate({ top:"-=" + h + "px" }, "slow", function(){
$box.fadeOut("normal");
});
$box.animate({ top:"-=" + h + "px" }, "slow", function(){
$box.fadeOut("normal", function() {
isShow = false;
});
});
}
}
});
});
}(jQuery, document, this));
\ No newline at end of file
$(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,23 +8,50 @@ String.prototype.trim = function () {
return this.replace(/^\s*/, "").replace(/\s*$/, "");
}
/**************************/
$(document).ready(function() {
$('input[type="text"]').addClass("idleField");
$('input[type="text"]').focus(function() {
$(this).removeClass("idleField").addClass("focusField");
if (this.value == this.defaultValue){
this.value = '';
}
if(this.value != this.defaultValue){
this.select();
}
});
$('input[type="text"]').blur(function() {
$(this).removeClass("focusField").addClass("idleField");
if ($.trim(this.value) == ''){
this.value = (this.defaultValue ? this.defaultValue : '');
}
});
});
\ No newline at end of file
/****************************************/
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 = '';
}
if(this.value != this.defaultValue){
this.select();
}
});
$elt.blur(function() {
$(this).removeClass("focusField").addClass("idleField");
if ($.trim(this.value) == ''){
this.value = (this.defaultValue ? this.defaultValue : '');
}
});
}
/**************************/
(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
$(document).ready( function() {
var send = false;
var cloneRequest;
$('#fileTree').fileTree({ root: $("input#workdir").val(), script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false }, function(file) {
$('#fileTree').fileTree({ root: $("input#workdir").val(), script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false }, function(file) {
selectFile(file);
});
configRadio();
......@@ -22,12 +22,12 @@ $(document).ready( function() {
$("#clone").append("Clone");
send = false;
return;
}
}
var repo_url = $("input#repo").val();
var email = "";
var name = ""
/* /^(ht|f)tps?:\/\/[a-z0-9-\.]+\.[a-z]{2,4}\/?([^\s<>\#%"\,\{\}\\|\\\^\[\]`]+)?$/ */
if($("input#repo").val() == "" || !repo_url.match(/^[\w\d\.\/:~@_-]+$/)){
if($("input#repo").val() == "" || !repo_url.match(/^[\w\d\.\/:~@_-]+$/)){
$("#error").Popup("Invalid url for the repository", {type:'alert', duration:3000});
return false;
}
......@@ -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..."){
......@@ -86,7 +86,7 @@ $(document).ready( function() {
$("#error").Popup("Your repository is cloned!", {type:'confirm', duration:3000});
$("input#repo").val("Enter the url of your repository...");
$("input#name").val("Enter the project name...");
$('#fileTree').fileTree({ root: $("input#workdir").val(), script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false }, function(file) {
$('#fileTree').fileTree({ root: $("input#workdir").val(), script: $SCRIPT_ROOT + '/readFolder', folderEvent: 'click', expandSpeed: 750, collapseSpeed: 750, multiFolder: false }, function(file) {
selectFile(file);
});
}
......@@ -97,15 +97,21 @@ $(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;
});
function configRadio(){
$("#modelist li").each(function(index) {
$("#modelist li").each(function(index) {
var boxselector = "#box" + index;
if($(this).hasClass('checked')){
$(this).removeClass('checked');
$(this).removeClass('checked');
$(boxselector).slideUp("normal");
}
if($(this).find("input:radio").is(':checked')){
......@@ -119,7 +125,7 @@ $(document).ready( function() {
}
});
}
function selectFile(file){
//nothing
return;
......
......@@ -9,27 +9,33 @@ $(document).ready( function() {
$("#info").append("Please select your file or folder into the box...");
fillContent();
});
function selectFile(file){
var relativeFile = file.replace(runnerDir + "/" + $("#softwarelist").val(), "");
$("#info").empty();
$("#info").append("Selection: " + relativeFile);
return;
}
function fillContent(){
var folder = $("#softwarelist").val();
var elt = $("option:selected", $("#softwarelist"));
$('#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'));
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(){
$("#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,14 +45,18 @@ $(document).ready( function() {
location.href = $SCRIPT_ROOT + '/editSoftwareProfile'
}
else{
$("#error").Popup(data.result, {type:'error'});
$("#error").Popup(data.result, {type:'error', duration:5000});
}
}
});
return false;
});
$("#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({
......@@ -55,21 +65,27 @@ $(document).ready( function() {
data: "name=" + $("#softwarelist").val(),
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)});
var folder = $("#softwarelist").val();
$("input#file").val("");
$("#info").empty();
$("#info").append("Please select your file or folder into the box...");
$("#softwarelist").empty();
for(i=0; i<data.result.length; i++){
$("#softwarelist").append('<option value="' + data.result[i]["md5"] +
'" title="' + data.result[i]["title"] +'" rel="' +
$("#softwarelist").append('<option value="' + data.result[i]["md5"] +
'" 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{
......@@ -78,15 +94,15 @@ $(document).ready( function() {
send = false;
}
});
return false;
return false;
});
function viewFile(file){
//User have double click on file in to the fileTree
var name = file.replace(runnerDir + "/" + $("#softwarelist").val(), "/software");
loadFileContent(file, name);
}
function loadFileContent(file, filename){
$.ajax({
type: "POST",
......@@ -99,14 +115,14 @@ $(document).ready( function() {
type: "POST",
url: $SCRIPT_ROOT + '/getFileContent',
data: {file:file, truncate:1500},
success: function(data){
success: function(data){
if(data.code == 1){
$("#inline_content").empty();
$("#inline_content").append('<h2 style="color: #4c6172; font: 18px \'Helvetica Neue\', Helvetica, Arial, sans-serif;">Inspect Software Content: ' +
filename +'</h2>');
$("#inline_content").append('<br/><div class="main_content"><pre id="editor"></pre></div>');
setupEditor();
$(".inline").colorbox({inline:true, width: "847px", onComplete:function(){
$(".inline").colorbox({inline:true, width: "847px", onComplete:function(){
editor.getSession().setValue(data.result);
}});
$(".inline").click();
......@@ -128,11 +144,11 @@ $(document).ready( function() {
}
});
}
function setupEditor(){
function setupEditor(){
editor = ace.edit("editor");
editor.setTheme("ace/theme/crimson_editor");
var CurentMode = require("ace/mode/text").Mode;
editor.getSession().setMode(new CurentMode());
editor.getSession().setTabSize(2);
......
$(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,64 +3,77 @@
{% 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">
<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/>
<p>Choose this mode if you don't have login and password for the repository and you if you don't have the possibility to
use SSH authentication. Otherwise use your public key or your login and password to clone your project by choosing https or ssh mode. Note
that, with readonly mode you can not be able to push your changes.</p>
<br/>
</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>
{{public_key}}
</textarea>
</div>
<div id="box2" style="display:none;">
<h2>Enter your username and password for https authentication access</h2><br/>
<div style="margin-left:80px; margin-bottom:20px;">
<label for='username'>Your username:&nbsp;&nbsp;</label>
<input type="text" name="username" id="username" size='20' value="Enter your username..." /><br/><br/>
<label for='password'>Your password: &nbsp;&nbsp;</label>
<input type="password" name="password" id="password" size='20' value="" class="idleField" />
</div>
<p></p>
</div>
</div>
</div>
<div class="menu-box-left">
<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>
<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/>
<p>Choose this mode if you don't have login and password for the repository and you if you don't have the possibility to
use SSH authentication. Otherwise use your public key or your login and password to clone your project by choosing https or ssh mode. Note
that, with readonly mode you can not be able to push your changes.</p>
<br/>
</div>
<div id="box1" style="display:none">
<h2>You can use this public key to setup your repository</h2><br/>
<textarea class="mb_style public_key" readonly>
{{public_key}}
</textarea>
</div>
<div id="box2" style="display:none;">
<h2>Enter your username and password for https authentication access</h2><br/>
<div style="margin-left:80px; margin-bottom:20px;">
<label for='username'>Your username:&nbsp;&nbsp;</label>
<input type="text" name="username" id="username" size='20' value="Enter your username..." /><br/><br/>
<label for='password'>Your password: &nbsp;&nbsp;</label>
<input type="password" name="password" id="password" size='20' value="" class="idleField" />
</div>
<p></p>
</div>
</div>
</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/>
<!--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,13 +56,13 @@
{% 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%">
<div id="bcontent{{item[0]}}">
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<th>Parameter Name</th><th>Parameter Value</th>
</tr>
......@@ -67,9 +71,9 @@
<td class="propertie first">{{k}}</td><td align='left'>{{item[1][k]}}</td>
</tr>
{% endfor %}
</table>
</table>
</div>
{% else %}
{% else %}
<h2>Empty Partition</h2></br>
<center><img alt="" src="{{ url_for('static', filename='images/empty.png') }}" /></center>
<br/><h2>Partition {{item[0]}} is still empty</h2>
......@@ -82,8 +86,8 @@
<ul id="slappart">
{% for item in slap_status %}
<li><input type="radio" name="slapresponse" id="{{item[0]}}" value="{{item[0]}}" />
<label for="{{item[0]}}" {% if item[1] %}style="font-weight:bold"{%endif%}>{{item[0]}}</label></li>
{% endfor %}
<label for="{{item[0]}}" {% if item[1] %}style="font-weight:bold"{%endif%}>{{item[0]}}</label></li>
{% endfor %}
</ul>
</div>
<div class="clear"></div><br/>
......@@ -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,10 +19,16 @@
<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">
<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() != ""){
$("#error").Popup($("input#fmsg").val(), {type:'info', duration:5000, load:true});
......@@ -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">
......@@ -110,11 +121,11 @@
<div id="tooltip-home" style="display:none">
<span style="font-weight:bold">QUICK ACCESS TO MENU</span><br/><br/>
<div style="margin-top:3px;border-bottom: 1px dashed #666666; heigth:1px"></div>
<ul>
<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>
<li><a href="{{ url_for('openProject', method='new')}}">Create Software Release</a></li>
</ul>
</div>
</body>
......
{% 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():
session['title'] = getProjectTitle(app.config)
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 = ''
......@@ -88,17 +122,39 @@ def inspectInstance():
file_content = 'instance_root'
result = getSvcStatus(app.config)
if len(result) == 0:
result = []
result = []
return render_template('instanceInspect.html',
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")
f = open(param_path, 'w')
f.write(content)
f.close()
result = readParameters(param_path)
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 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 "&lt;?xml version='1.0' encoding='utf-8'?&gt;"
\ No newline at end of file
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