Commit b74603bc authored by Nicolas Wavrant's avatar Nicolas Wavrant

Upgrade Slaprunner layout, logs views and fileBrowser

Conflicts:
	slapos/runner/templates/layout.html
parent 45c23e82
...@@ -58,6 +58,34 @@ class FileBrowser(object): ...@@ -58,6 +58,34 @@ class FileBrowser(object):
html += 'gsdirs.push(new gsItem("2", "%s", "%s", "0", "%s", "dir", "%s"));' % (f, ff, md5sum, mdate) html += 'gsdirs.push(new gsItem("2", "%s", "%s", "0", "%s", "dir", "%s"));' % (f, ff, md5sum, mdate)
return html return html
def fancylistDirs(self, dir, key, all=False):
dir = urllib.unquote(dir)
realdir = realpath(self.config, dir)
if not realdir:
raise NameError('Could not load directory %s: Permission denied' % dir)
fileList = []
dirList = []
i = 0
ldir = sorted(os.listdir(realdir), key=str.lower)
for f in ldir:
if f.startswith('.') and not all: # do not display this file/folder
continue
ff = os.path.join(dir, f)
realfile = os.path.join(realdir, f)
identity = "%s%s" % (key, i)
if not os.path.isdir(realfile):
regex = re.compile("(^.*)\.(.*)", re.VERBOSE)
ext = regex.sub(r'\2', f)
if ext == f:
ext = ""
dirList.append({"title": f, "key": identity,
"extraClasses": "ext_"+ext, "path": ff})
else:
fileList.append({"title": f, "key": identity,
"folder":True, "lazy":True, "path": ff})
i+=1
return (fileList + dirList)
def makeDirectory(self, dir, filename): def makeDirectory(self, dir, filename):
"""Create a directory""" """Create a directory"""
realdir = self._realdir(dir) realdir = self._realdir(dir)
...@@ -85,21 +113,21 @@ class FileBrowser(object): ...@@ -85,21 +113,21 @@ class FileBrowser(object):
lfiles = urllib.unquote(files).split(',,,') lfiles = urllib.unquote(files).split(',,,')
try: try:
# XXX-Marco do not shadow 'file' # XXX-Marco do not shadow 'file'
for file in lfiles: for item in lfiles:
file = os.path.join(realdir, file) filepath = os.path.join(realdir, item)
if not os.path.exists(file): if not item or not os.path.exists(filepath):
continue # silent skip file.... continue # silent skip file....
details = file.split('/') details = filepath.split('/')
last = details[-1] last = details[-1]
if last and last.startswith('.'): if last and last.startswith('.'):
continue # cannot delete this file/directory, to prevent security continue # cannot delete this file/directory, to prevent security
if os.path.isdir(file): if os.path.isdir(filepath):
shutil.rmtree(file) shutil.rmtree(filepath)
else: else:
os.unlink(file) os.unlink(filepath)
except Exception as e: except Exception as e:
return str(e) return str(e)
return "{result: '1'}" return "{result: '1', test: %s}" % '*'.join(lfiles)
def copyItem(self, dir, files, del_source=False): def copyItem(self, dir, files, del_source=False):
"""Copy a list of files or directory to dir""" """Copy a list of files or directory to dir"""
...@@ -147,10 +175,10 @@ class FileBrowser(object): ...@@ -147,10 +175,10 @@ class FileBrowser(object):
tofile = os.path.join(realdir, newfilename) tofile = os.path.join(realdir, newfilename)
if not os.path.exists(fromfile): if not os.path.exists(fromfile):
raise NameError('NOT ALLOWED OPERATION : File or directory does not exist') raise NameError('NOT ALLOWED OPERATION : File or directory does not exist')
if not os.path.exists(tofile): while os.path.exists(tofile):
tofile += "_1"
shutil.copy(fromfile, tofile) shutil.copy(fromfile, tofile)
return "{result: '1'}" return "{result: '1'}"
raise NameError('NOT ALLOWED OPERATION : File or directory already exists')
def uploadFile(self, dir, files): def uploadFile(self, dir, files):
"""Upload a list of files in directory dir""" """Upload a list of files in directory dir"""
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#cboxTitle{position:absolute; bottom:-25px; left:0; text-align:center; width:100%; font-weight:bold; color:#7C7C7C;} #cboxTitle{position:absolute; bottom:-25px; left:0; text-align:center; width:100%; font-weight:bold; color:#7C7C7C;}
#cboxCurrent{position:absolute; bottom:-25px; left:58px; font-weight:bold; color:#7C7C7C;} #cboxCurrent{position:absolute; bottom:-25px; left:58px; font-weight:bold; color:#7C7C7C;}
#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{position:absolute; bottom:-29px; background:url(images/controls.png) no-repeat 0px 0px; width:23px; height:23px; text-indent:-9999px;} #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{position:absolute; border: none; bottom:-29px; background:url(images/controls.png) no-repeat 0px 0px; width:23px; height:23px; text-indent:-9999px;}
#cboxPrevious{left:0px; background-position: -51px -25px;} #cboxPrevious{left:0px; background-position: -51px -25px;}
#cboxPrevious:hover{background-position:-51px 0px;} #cboxPrevious:hover{background-position:-51px 0px;}
#cboxNext{left:27px; background-position:-75px -25px;} #cboxNext{left:27px; background-position:-75px -25px;}
......
...@@ -108,7 +108,7 @@ div.browser div.gs_dir_content_files{min-height:330px;} ...@@ -108,7 +108,7 @@ div.browser div.gs_dir_content_files{min-height:330px;}
font-size: 12px; font-size: 12px;
} }
.dirs_files_table td{padding: 0;border:none} .dirs_files_table td{padding: 0;border:none}
.gsItem {padding: 4px; padding-left: 25px;} .gsItem {padding: 4px; padding-left: 27px;}
.file_ext_name { .file_ext_name {
font-weight: normal; font-weight: normal;
color: #FF6600; color: #FF6600;
...@@ -152,7 +152,10 @@ div.browser div.gs_dir_content_files{min-height:330px;} ...@@ -152,7 +152,10 @@ div.browser div.gs_dir_content_files{min-height:330px;}
background-image:url(images/file.png); background-image:url(images/file.png);
background-repeat:no-repeat; background-repeat:no-repeat;
cursor:pointer; cursor:pointer;
} margin-left: 5px;
margin-top: 2px;
padding-left: 22px;
}
.jqueryFileTree LI.wait { background: url(images/spinner.gif) left top no-repeat; } .jqueryFileTree LI.wait { background: url(images/spinner.gif) left top no-repeat; }
/* File Extensions*/ /* File Extensions*/
...@@ -285,16 +288,18 @@ div.browser div.gs_dir_content_files{min-height:330px;} ...@@ -285,16 +288,18 @@ div.browser div.gs_dir_content_files{min-height:330px;}
width: 160px; width: 160px;
z-index: 99999; z-index: 99999;
border: solid 1px #CCC; border: solid 1px #CCC;
background: #EEE; background: #ffffff;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
display: none; display: none;
box-shadow: 2px 2px 6px rgba(0,0,0,.2);
} }
.contextMenu LI { .contextMenu LI {
list-style: none; list-style: none;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
border: none;
} }
.contextMenu A { .contextMenu A {
......
slapos/runner/static/css/images/cfg.png

756 Bytes | W: | H:

slapos/runner/static/css/images/cfg.png

735 Bytes | W: | H:

slapos/runner/static/css/images/cfg.png
slapos/runner/static/css/images/cfg.png
slapos/runner/static/css/images/cfg.png
slapos/runner/static/css/images/cfg.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/code.png

655 Bytes | W: | H:

slapos/runner/static/css/images/code.png

603 Bytes | W: | H:

slapos/runner/static/css/images/code.png
slapos/runner/static/css/images/code.png
slapos/runner/static/css/images/code.png
slapos/runner/static/css/images/code.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/css.png

674 Bytes | W: | H:

slapos/runner/static/css/images/css.png

618 Bytes | W: | H:

slapos/runner/static/css/images/css.png
slapos/runner/static/css/images/css.png
slapos/runner/static/css/images/css.png
slapos/runner/static/css/images/css.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/db.png

635 Bytes | W: | H:

slapos/runner/static/css/images/db.png

579 Bytes | W: | H:

slapos/runner/static/css/images/db.png
slapos/runner/static/css/images/db.png
slapos/runner/static/css/images/db.png
slapos/runner/static/css/images/db.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/doc.png

743 Bytes | W: | H:

slapos/runner/static/css/images/doc.png

651 Bytes | W: | H:

slapos/runner/static/css/images/doc.png
slapos/runner/static/css/images/doc.png
slapos/runner/static/css/images/doc.png
slapos/runner/static/css/images/doc.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/file.png

425 Bytes | W: | H:

slapos/runner/static/css/images/file.png

294 Bytes | W: | H:

slapos/runner/static/css/images/file.png
slapos/runner/static/css/images/file.png
slapos/runner/static/css/images/file.png
slapos/runner/static/css/images/file.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/film.png

767 Bytes | W: | H:

slapos/runner/static/css/images/film.png

653 Bytes | W: | H:

slapos/runner/static/css/images/film.png
slapos/runner/static/css/images/film.png
slapos/runner/static/css/images/film.png
slapos/runner/static/css/images/film.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/flash.png

630 Bytes | W: | H:

slapos/runner/static/css/images/flash.png

582 Bytes | W: | H:

slapos/runner/static/css/images/flash.png
slapos/runner/static/css/images/flash.png
slapos/runner/static/css/images/flash.png
slapos/runner/static/css/images/flash.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/html.png

791 Bytes | W: | H:

slapos/runner/static/css/images/html.png

734 Bytes | W: | H:

slapos/runner/static/css/images/html.png
slapos/runner/static/css/images/html.png
slapos/runner/static/css/images/html.png
slapos/runner/static/css/images/html.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/java.png

417 Bytes | W: | H:

slapos/runner/static/css/images/java.png

633 Bytes | W: | H:

slapos/runner/static/css/images/java.png
slapos/runner/static/css/images/java.png
slapos/runner/static/css/images/java.png
slapos/runner/static/css/images/java.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/linux.png

720 Bytes | W: | H:

slapos/runner/static/css/images/linux.png

668 Bytes | W: | H:

slapos/runner/static/css/images/linux.png
slapos/runner/static/css/images/linux.png
slapos/runner/static/css/images/linux.png
slapos/runner/static/css/images/linux.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/music.png

691 Bytes | W: | H:

slapos/runner/static/css/images/music.png

385 Bytes | W: | H:

slapos/runner/static/css/images/music.png
slapos/runner/static/css/images/music.png
slapos/runner/static/css/images/music.png
slapos/runner/static/css/images/music.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/pdf.png

639 Bytes | W: | H:

slapos/runner/static/css/images/pdf.png

591 Bytes | W: | H:

slapos/runner/static/css/images/pdf.png
slapos/runner/static/css/images/pdf.png
slapos/runner/static/css/images/pdf.png
slapos/runner/static/css/images/pdf.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/php.png

591 Bytes | W: | H:

slapos/runner/static/css/images/php.png

538 Bytes | W: | H:

slapos/runner/static/css/images/php.png
slapos/runner/static/css/images/php.png
slapos/runner/static/css/images/php.png
slapos/runner/static/css/images/php.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/picture.png

715 Bytes | W: | H:

slapos/runner/static/css/images/picture.png

606 Bytes | W: | H:

slapos/runner/static/css/images/picture.png
slapos/runner/static/css/images/picture.png
slapos/runner/static/css/images/picture.png
slapos/runner/static/css/images/picture.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/ppt.png

661 Bytes | W: | H:

slapos/runner/static/css/images/ppt.png

588 Bytes | W: | H:

slapos/runner/static/css/images/ppt.png
slapos/runner/static/css/images/ppt.png
slapos/runner/static/css/images/ppt.png
slapos/runner/static/css/images/ppt.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/psd.png

918 Bytes | W: | H:

slapos/runner/static/css/images/psd.png

856 Bytes | W: | H:

slapos/runner/static/css/images/psd.png
slapos/runner/static/css/images/psd.png
slapos/runner/static/css/images/psd.png
slapos/runner/static/css/images/psd.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/ruby.png

676 Bytes | W: | H:

slapos/runner/static/css/images/ruby.png

626 Bytes | W: | H:

slapos/runner/static/css/images/ruby.png
slapos/runner/static/css/images/ruby.png
slapos/runner/static/css/images/ruby.png
slapos/runner/static/css/images/ruby.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/script.png

955 Bytes | W: | H:

slapos/runner/static/css/images/script.png

859 Bytes | W: | H:

slapos/runner/static/css/images/script.png
slapos/runner/static/css/images/script.png
slapos/runner/static/css/images/script.png
slapos/runner/static/css/images/script.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/txt.png

529 Bytes | W: | H:

slapos/runner/static/css/images/txt.png

342 Bytes | W: | H:

slapos/runner/static/css/images/txt.png
slapos/runner/static/css/images/txt.png
slapos/runner/static/css/images/txt.png
slapos/runner/static/css/images/txt.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/xls.png

714 Bytes | W: | H:

slapos/runner/static/css/images/xls.png

663 Bytes | W: | H:

slapos/runner/static/css/images/xls.png
slapos/runner/static/css/images/xls.png
slapos/runner/static/css/images/xls.png
slapos/runner/static/css/images/xls.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/css/images/zip.png

590 Bytes | W: | H:

slapos/runner/static/css/images/zip.png

386 Bytes | W: | H:

slapos/runner/static/css/images/zip.png
slapos/runner/static/css/images/zip.png
slapos/runner/static/css/images/zip.png
slapos/runner/static/css/images/zip.png
  • 2-up
  • Swipe
  • Onion skin
/*! jQuery UI - v1.10.3 - 2013-10-14
* http://jqueryui.com
* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css
* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}
\ No newline at end of file
/* Generic context menu styles */
.contextMenu {
position: absolute;
width: 180px;
z-index: 99999;
border: solid 1px #CCC;
background: #ffffff;
padding: 0px;
margin: 0px;
display: none;
box-shadow: 2px 2px 6px rgba(0,0,0,.2);
}
.contextMenu LI {
list-style: none;
padding: 0px;
margin: 0px;
border: none;
}
.contextMenu A {
color: #333;
text-decoration: none;
display: block;
line-height: 20px;
height: 20px;
background-position: 6px center;
background-repeat: no-repeat;
outline: none;
padding: 1px 5px;
padding-left: 28px;
}
.contextMenu LI.hover A {
color: #FFF;
background-color: #3875D7;
}
.contextMenu LI.disabled A {
color: #AAA;
cursor: default;
}
.contextMenu LI.hover.disabled A {
background-color: transparent;
}
.contextMenu LI.separator {
border-top: solid 1px #CCC;
}
/*
Adding Icons
You can add icons to the context menu by adding
classes to the respective LI element(s)
*/
.contextMenu LI.edit A { background-image: url(images/page_white_edit.png); }
.contextMenu LI.cut A { background-image: url(images/cut.png); }
.contextMenu LI.copy A { background-image: url(images/page_white_copy.png); }
.contextMenu LI.paste A { background-image: url(images/page_white_paste.png); }
.contextMenu LI.delete A { background-image: url(images/cross.png); }
.contextMenu LI.quit A { background-image: url(images/door.png); }
.contextMenu LI.newfile A { background-image: url(images/new_file.png); }
.contextMenu LI.newdir A { background-image: url(images/new_dir.png); }
.contextMenu LI.view A { background-image: url(images/mpicture.png); }
.contextMenu LI.rename A { background-image: url(images/mfile.png); }
.contextMenu LI.md5sum A { background-image: url(images/selection-select.png); }
.contextMenu LI.refresh A { background-image: url(images/refresh.png); }
\ No newline at end of file
...@@ -4,6 +4,14 @@ blockquote, q {quotes: none;} ...@@ -4,6 +4,14 @@ blockquote, q {quotes: none;}
blockquote:before, blockquote:after, q:before, q:after {content: none;} blockquote:before, blockquote:after, q:before, q:after {content: none;}
:focus {outline: 0 none;} :focus {outline: 0 none;}
img{border:0} img{border:0}
/*YAHOO RESET FONT*/
html{color:#000;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,select,p,blockquote,th,td{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}address,button,caption,cite,code,dfn,em,input,optgroup,option,select,strong,textarea,th,var{font:inherit}del,ins{text-decoration:none}li{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}q:before,q:after{content:''}abbr,acronym{border:0;font-variant:normal}sup{vertical-align:baseline}sub{vertical-align:baseline}legend{color:#000}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small}select,input,textarea,button{font:99% arial,helvetica,clean,sans-serif}table{font-size:inherit;font:100%}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%}
body{
background: #1E73BD;
height:100%;
}
a{ a{
text-decoration: none; text-decoration: none;
color: #19485C; color: #19485C;
...@@ -40,16 +48,13 @@ th{ ...@@ -40,16 +48,13 @@ th{
table.small th{padding: 4px;font-size: 16px;} table.small th{padding: 4px;font-size: 16px;}
textarea { textarea {
width:932px; width:932px;
font-family: 'Helvetica Neue',Tahoma,Helvetica,Arial,sans-serif; font-family: 'Arial,Helvetica Neue',Tahoma,Helvetica,sans-serif;
} }
body { body {
background: #1E73BD;/*#1862C4 url("../images/1307251316-background-stripes.gif") repeat #9C9C9C;*/
font-family: 'Helvetica Neue',Tahoma,Helvetica,Arial,sans-serif;
color: #000000; color: #000000;
font-size: 13px;
overflow: -moz-scrollbars-vertical; overflow: -moz-scrollbars-vertical;
overflow-y: scroll; overflow-y: scroll;
} }
#page #page
...@@ -63,8 +68,8 @@ overflow-y: scroll; ...@@ -63,8 +68,8 @@ overflow-y: scroll;
} }
#header{ #header{
height: 78px; height: 73px;
padding-top: 12px; padding-top: 10px;
width: 1014px; width: 1014px;
background: url(../images/head.png) no-repeat; background: url(../images/head.png) no-repeat;
} }
...@@ -77,16 +82,31 @@ overflow-y: scroll; ...@@ -77,16 +82,31 @@ overflow-y: scroll;
} }
#header .run{ #header .run{
margin-right: 30px; margin-right: 20px;
float: right; float: right;
} }
#running p{
float:left;
padding: 5px;
padding-right: 10px;
border-left: 4px solid #C753C4;
font-size: 1.08em;
color: #2D73B1;
}
#running p.instance{
border-left: 4px solid #1E73BD;
}
#running img{
float:left
}
#header .info{ #header .info{
font-size: 16px; font-size: 16px;
font-weight: normal; font-weight: normal;
padding-top: 3px; padding-top: 3px;
margin-left:20px;
float: left; float: left;
width: 820px; width: 700px;
height: 22px; height: 22px;
text-align: center; text-align: center;
color: #4c6172; color: #4c6172;
...@@ -104,79 +124,44 @@ overflow-y: scroll; ...@@ -104,79 +124,44 @@ overflow-y: scroll;
margin-left:5px margin-left:5px
} }
#editor { #editor, #editorViewer {
margin: 0; margin: 0;
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
} }
.wmenu{ #wmenu{
margin: 1px 0 1px 20px; margin: 1px 11px 1px 10px;
} }
.wmenu ul{ #wmenu ul{
height: 34px; width: 100%;
overflow:hidden;
} }
.space{ .space{
margin-left: 28px; margin-left: 28px;
} }
.wmenu li{ #wmenu a.slapos_run{
float:left; background: url(../images/run_button.png) center no-repeat;
} }
#wmenu a.slapos_run:hover{
.wmenu li .title_software{ background: #c2c2c2 url(../images/run_button2.png) center no-repeat;
float:left;
background: url(../images/software.png) left center no-repeat;
font-size:15px;
font-weight:bold;
color:#678dad;
cursor: default;
padding:8px;
padding-left: 20px;
padding-right: 5px;
margin-left:4px;
height: 18px;
text-shadow:1px 1px 0 #E6EDF2;
} }
#wmenu a.slapos_stop{
.wmenu li .title_instance{ background: url(../images/stop_button.png) center no-repeat;
float:left;
background: url(../images/settings2.png) left center no-repeat;
font-size:15px;
font-weight:bold;
color:#678dad;
cursor: default;
padding:8px;
padding-left: 20px;
padding-right: 5px;
height: 20px;
margin-left:2px;
text-shadow:1px 1px 0 #E6EDF2;
} }
#wmenu a.slapos_stop:hover{
.wmenu ul li.sep{border-right: 1px solid #c2c2c2; min-width:20px; height:34px} background: #c2c2c2 url(../images/stop_button2.png) center no-repeat;
.wmenu ul li a{
display:block;
height: 20px;
Color:#275777;
/*background: url(../images/sep.png) right center no-repeat;*/
border-right: 1px solid #c2c2c2;
/*font-weight:bold;*/
font-size:15px;
text-decoration:none;
padding:7px 10px 7px 10px;
} }
.wmenu ul li:last-child a {border: none} #wmenu a.main_menu{
background: url(../images/main_menu.png) center no-repeat;
.wmenu ul li a:hover, .wmenu ul li a.active{ }
color: #000;/*#0271BF;*/ #wmenu a.main_menu:hover{
background:#c2c2c2; background: #c2c2c2 url(../images/main_menu_hover.png) center no-repeat;
} }
#main #main
...@@ -214,7 +199,7 @@ overflow-y: scroll; ...@@ -214,7 +199,7 @@ overflow-y: scroll;
.content h2{ .content h2{
color: #4c6172; color: #4c6172;
font-weight: normal; font-weight: normal;
font-size: 18px; font-size: 1.4em;
} }
.content h2 a{ .content h2 a{
text-decoration:none; text-decoration:none;
...@@ -435,12 +420,12 @@ padding: 10px;height: 80px;padding-bottom:15px;} ...@@ -435,12 +420,12 @@ padding: 10px;height: 80px;padding-bottom:15px;}
} }
.file_tree_short{ .file_tree_short{
width: 228px; width: 238px;
height: 379px; height: 429px;
border: solid 1px #678dad; border: solid 1px #678dad;
background: #fff; background: #fff;
overflow: auto; overflow: auto;
padding: 5px; padding: 0px;
} }
.box_software{ .box_software{
width: 240px; width: 240px;
...@@ -495,19 +480,29 @@ h2.hight:hover{ ...@@ -495,19 +480,29 @@ h2.hight:hover{
} }
.log_content{ .log_content{
border: solid 1px #4c6172; border: solid 1px #519ADA;
padding: 2px;
width: 719px;
float: left;
}
.log_information{
border: solid 1px #519ADA;
padding: 2px; padding: 2px;
width: 200px;
float: left;
margin-left: 5px;
} }
.log { .log {
border: none; border: none;
background: #f6f7f8; background: #f6f7f8;
color: #000; color: #000;
width: 926px; width: 715px;
padding: 2px; padding: 2px;
height: 450px; height: 450px;
resize: both; resize: both;
font-size: 13px; /*font-size: 0.98em;*/
overflow-y: auto; overflow-y: auto;
white-space: pre-wrap; white-space: pre-wrap;
} }
...@@ -516,6 +511,79 @@ h2.hight:hover{ ...@@ -516,6 +511,79 @@ h2.hight:hover{
.log p{white-space: pre-wrap; width:100%} .log p{white-space: pre-wrap; width:100%}
.log p.info{white-space: pre-wrap; width:98%; font-size: 15px; margin: 5px; color:red;} .log p.info{white-space: pre-wrap; width:98%; font-size: 15px; margin: 5px; color:red;}
.log_info_box{
height: 454px;
width: 200px;
}
.log_info_box h2{
font-weight: bold;
padding: 5px;
padding-left: 20px;
text-align: left;
color: #fff;
display: block;
height: 20px;
font-size: 16px;
margin-top: 20px;
}
.log_info_box h2:first-child{
margin-top: 0;
}
.log_info_box h2.software{
background: #1E73BD;
}
.log_info_box h2.instance{
background: #C753C4;
}
#sr_run_state, #instance_run_state{
color: #000;
font-weight: bold;
margin-bottom: 10px;
}
#sr_run_state p, #instance_run_state p{
padding-top: 3px;
font-size: 16px;
}
.log_content_box{
padding: 10px 5px;
font-size: 14px;
min-height: 130px;
}
.log_content_box p{
line-height: 20px;
}
.log_content_box a{
color: #2084CA;
font-weight: bold;
}
.log_content_box a:hover{
color: #286d9e;
}
.log_info_box span.legend{
height: 22px;
width: 24px;
margin-right: 10px;
display: block;
float: left;
}
.log_info_box div.state_running span{
background: #FFC800;
}
.log_info_box div.state_terminated span{
background: #00C800;
}
.log_info_box div.state_waiting span, .log_info_box div.state_stopped{
background: #FF3131;
}
.separator{
border-bottom: 3px solid #D6D6D6;
width: 100%
}
.waitting{ .waitting{
margin-left: 10px; margin-left: 10px;
display: none; display: none;
...@@ -587,9 +655,9 @@ select { ...@@ -587,9 +655,9 @@ select {
a.lshare{ a.lshare{
background: #fff; background: #fff;
padding: 4px 7px 4px 7px; padding: 0.27em .47em;
height: 18px; height: 18px;
font-size: 15px; font-size: 1.14em;
border: solid 1px #678dad; border: solid 1px #678dad;
color: #4DA0C6; color: #4DA0C6;
text-align:center; text-align:center;
......
/*** ESSENTIAL STYLES ***/
.sf-menu, .sf-menu * {
margin: 0;
padding: 0;
list-style: none;
}
.sf-menu li {
position: relative;
}
.sf-menu ul {
position: absolute;
display: none;
top: 100%;
right: 0;
z-index: 99;
}
.sf-menu > li {
float: left;
}
.sf-menu li:hover > ul,
.sf-menu li.sfHover > ul {
display: block;
}
.sf-menu > li.right_menu{
float:right;
}
.sf-menu a {
display: block;
position: relative;
}
.sf-menu ul ul {
top: 0;
left:0;
}
/*** DEMO SKIN ***/
.sf-menu {
float: left;
margin-bottom: 1em;
}
.sf-menu ul {
box-shadow: 2px 2px 6px rgba(0,0,0,.2);
min-width: 14em; /* allow long menu items to determine submenu width */
*width: 14em; /* no auto sub width for IE7, see white-space comment below */
border: 1px solid #C2C2C2;
background: #E4E4E4;
border-left:none;
padding-bottom:2px;
}
.sf-menu li a {
display:block;
height: 20px;
color: #074A86;
border-right: 1px solid #c2c2c2;
font-weight:bold;
font-size:15px;
text-decoration:none;
padding:7px 20px;
zoom: 1; /* IE7 */
}
.sf-menu li {
white-space: nowrap; /* no need for Supersubs plugin */
*white-space: normal; /* ...unless you support IE7 (let it wrap) */
}
.sf-menu li.right_menu > a{
border-left: 1px solid #c2c2c2;
border-right:none;
width: 35px;
padding:7px;
}
.sf-menu li:hover,
.sf-menu li.sfHover {
color: #fff;/*#0271BF;*/
background:#c2c2c2;
/* only transition out, not in */
-webkit-transition: none;
transition: none;
}
.sf-menu li a:hover{
color: #fff;
}
.sf-menu ul li {
background: #E4E4E4;
cursor: pointer;
color: #000;
}
.sf-menu ul li.sep{border-bottom: 1px solid #c2c2c2; margin: 3px 0;}
.sf-menu ul li.sep:hover{
background: #E4E4E4;
}
.sf-menu ul ul li {
background: #E4E4E4;
}
.sf-menu ul ul{
border: 1px solid #C2C2C2;
border-left:none;
}
.sf-menu ul li a{
font-weight:normal;
font-size:14px;
color: #000;
height: 16px;
padding:7px;
padding-left: 15px;
border:none;
}
.sf-menu ul li:hover,
.sf-menu ul li.sfHoverhover{
background: #A3A3A3;
}
.sf-menu ul li:hover a,
.sf-menu ul li.sfHoverhover a{
color: #fff;
}
/*** arrows (for all except IE7) **/
.sf-arrows .sf-with-ul {
padding-right: 2.5em;
*padding-right: 1em; /* no CSS arrows for IE7 (lack pseudo-elements) */
}
/* styling for both css and generated arrows */
.sf-arrows .sf-with-ul:after {
content: '';
position: absolute;
top: 50%;
right: 1em;
margin-top: -3px;
height: 0;
width: 0;
/* order of following 3 rules important for fallbacks to work */
border: 5px solid transparent;
border-top-color: #dFeEFF; /* edit this to suit design (no rgba in IE8) */
border-top-color: rgba(255,255,255,.5);
}
.sf-arrows > li > .sf-with-ul:focus:after,
.sf-arrows > li:hover > .sf-with-ul:after,
.sf-arrows > .sfHover > .sf-with-ul:after {
border-top-color: white; /* IE8 fallback colour */
}
/* styling for right-facing arrows */
.sf-arrows ul .sf-with-ul:after {
margin-top: -5px;
margin-right: -3px;
border-color: transparent;
border-left-color: #dFeEFF; /* edit this to suit design (no rgba in IE8) */
border-left-color: rgba(255,255,255,.5);
}
.sf-arrows ul li > .sf-with-ul:focus:after,
.sf-arrows ul li:hover > .sf-with-ul:after,
.sf-arrows ul .sfHover > .sf-with-ul:after {
border-left-color: white;
}
This diff is collapsed.
slapos/runner/static/images/head.png

1.4 KB | W: | H:

slapos/runner/static/images/head.png

1.46 KB | W: | H:

slapos/runner/static/images/head.png
slapos/runner/static/images/head.png
slapos/runner/static/images/head.png
slapos/runner/static/images/head.png
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/images/loading.gif

3.19 KB | W: | H:

slapos/runner/static/images/loading.gif

1.81 KB | W: | H:

slapos/runner/static/images/loading.gif
slapos/runner/static/images/loading.gif
slapos/runner/static/images/loading.gif
slapos/runner/static/images/loading.gif
  • 2-up
  • Swipe
  • Onion skin
slapos/runner/static/images/main_bg_all.png

215 Bytes | W: | H:

slapos/runner/static/images/main_bg_all.png

225 Bytes | W: | H:

slapos/runner/static/images/main_bg_all.png
slapos/runner/static/images/main_bg_all.png
slapos/runner/static/images/main_bg_all.png
slapos/runner/static/images/main_bg_all.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -941,6 +941,38 @@ if (jQuery) (function(jQuery){ ...@@ -941,6 +941,38 @@ if (jQuery) (function(jQuery){
// and the MIT License and is copyright A Beautiful Site, LLC. // and the MIT License and is copyright A Beautiful Site, LLC.
// //
if(jQuery)( function() { if(jQuery)( function() {
/* Check browser version, since $.browser was removed in jQuery 1.9 */
function _checkBrowser(){
var matched, browser;
function uaMatch( ua ) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
/(msie) ([\w.]+)/.exec( ua ) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
}
matched = uaMatch( navigator.userAgent );
browser = {};
if ( matched.browser ) {
browser[ matched.browser ] = true;
browser.version = matched.version;
}
if ( browser.chrome ) {
browser.webkit = true;
} else if ( browser.webkit ) {
browser.safari = true;
}
return browser;
}
var BROWSER = jQuery.browser || _checkBrowser();
jQuery.extend(jQuery.fn, { jQuery.extend(jQuery.fn, {
contextMenu: function(o, callback, onShowMenu) { contextMenu: function(o, callback, onShowMenu) {
...@@ -1064,13 +1096,13 @@ if(jQuery)( function() { ...@@ -1064,13 +1096,13 @@ if(jQuery)( function() {
}); });
// Disable text selection // Disable text selection
if( jQuery.browser.mozilla ) { if( BROWSER.mozilla ) {
jQuery('#' + o.menu).each( function() { jQuery('#' + o.menu).each( function() {
jQuery(this).css({ jQuery(this).css({
'MozUserSelect' : 'none' 'MozUserSelect' : 'none'
}); });
}); });
} else if( jQuery.browser.msie ) { } else if( BROWSER.msie ) {
jQuery('#' + o.menu).each( function() { jQuery('#' + o.menu).each( function() {
jQuery(this).bind('selectstart.disableTextSelect', function() { jQuery(this).bind('selectstart.disableTextSelect', function() {
return false; return false;
......
/**
* hoverIntent is similar to jQuery's built-in "hover" method except that
* instead of firing the handlerIn function immediately, hoverIntent checks
* to see if the user's mouse has slowed down (beneath the sensitivity
* threshold) before firing the event. The handlerOut function is only
* called after a matching handlerIn.
*
* hoverIntent r7 // 2013.03.11 // jQuery 1.9.1+
* http://cherne.net/brian/resources/jquery.hoverIntent.html
*
* You may use hoverIntent under the terms of the MIT license. Basically that
* means you are free to use hoverIntent as long as this header is left intact.
* Copyright 2007, 2013 Brian Cherne
*
* // basic usage ... just like .hover()
* .hoverIntent( handlerIn, handlerOut )
* .hoverIntent( handlerInOut )
*
* // basic usage ... with event delegation!
* .hoverIntent( handlerIn, handlerOut, selector )
* .hoverIntent( handlerInOut, selector )
*
* // using a basic configuration object
* .hoverIntent( config )
*
* @param handlerIn function OR configuration object
* @param handlerOut function OR selector for delegation OR undefined
* @param selector selector OR undefined
* @author Brian Cherne <brian(at)cherne(dot)net>
**/
(function($) {
$.fn.hoverIntent = function(handlerIn,handlerOut,selector) {
// default configuration values
var cfg = {
interval: 100,
sensitivity: 7,
timeout: 0
};
if ( typeof handlerIn === "object" ) {
cfg = $.extend(cfg, handlerIn );
} else if ($.isFunction(handlerOut)) {
cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
} else {
cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
}
// instantiate variables
// cX, cY = current X and Y position of mouse, updated by mousemove event
// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
var cX, cY, pX, pY;
// A private function for getting mouse position
var track = function(ev) {
cX = ev.pageX;
cY = ev.pageY;
};
// A private function for comparing current and previous mouse position
var compare = function(ev,ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
// compare mouse positions to see if they've crossed the threshold
if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
$(ob).off("mousemove.hoverIntent",track);
// set hoverIntent state to true (so mouseOut can be called)
ob.hoverIntent_s = 1;
return cfg.over.apply(ob,[ev]);
} else {
// set previous coordinates for next time
pX = cX; pY = cY;
// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
}
};
// A private function for delaying the mouseOut function
var delay = function(ev,ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
ob.hoverIntent_s = 0;
return cfg.out.apply(ob,[ev]);
};
// A private function for handling mouse 'hovering'
var handleHover = function(e) {
// copy objects to be passed into t (required for event object to be passed in IE)
var ev = jQuery.extend({},e);
var ob = this;
// cancel hoverIntent timer if it exists
if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
// if e.type == "mouseenter"
if (e.type == "mouseenter") {
// set "previous" X and Y position based on initial entry point
pX = ev.pageX; pY = ev.pageY;
// update "current" X and Y position based on mousemove
$(ob).on("mousemove.hoverIntent",track);
// start polling interval (self-calling timeout) to compare mouse coordinates over time
if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
// else e.type == "mouseleave"
} else {
// unbind expensive mousemove event
$(ob).off("mousemove.hoverIntent",track);
// if hoverIntent state is true, then call the mouseOut function after the specified delay
if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
}
};
// listen for mouseenter and mouseleave
return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
};
})(jQuery);
\ No newline at end of file
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
// jQuery Context Menu Plugin
//
// Version 1.01 customized version (see comment below)
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
//
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
//
// Terms of Use
//
// This plugin is dual-licensed under the GNU General Public License
// and the MIT License and is copyright A Beautiful Site, LLC.
//
// 2011-02-17 Martin Wendt:
// Changed stopPropagation() to preventDefault() in order to make it
// work with Dynatree drag'n'drop.
// See http://code.google.com/p/dynatree/issues/detail?id=174
// 2012-09-27 Martin Wendt:
// fixed position in a fancy layout
// 2013-05-09 Martin Wendt:
// Added polyfil for $.browser (fixes compatibility with jQuery 1.9)
//
if(jQuery)( function() {
/* Check browser version, since $.browser was removed in jQuery 1.9 */
function _checkBrowser(){
var matched, browser;
function uaMatch( ua ) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
/(msie) ([\w.]+)/.exec( ua ) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
}
matched = uaMatch( navigator.userAgent );
browser = {};
if ( matched.browser ) {
browser[ matched.browser ] = true;
browser.version = matched.version;
}
if ( browser.chrome ) {
browser.webkit = true;
} else if ( browser.webkit ) {
browser.safari = true;
}
return browser;
}
var BROWSER = jQuery.browser || _checkBrowser();
$.extend($.fn, {
contextMenu: function(o, callback, onShowMenu) {
// Defaults
if( o.menu == undefined ) return false;
if( o.inSpeed == undefined ) o.inSpeed = 150;
if( o.outSpeed == undefined ) o.outSpeed = 75;
// 0 needs to be -1 for expected results (no fade)
if( o.inSpeed == 0 ) o.inSpeed = -1;
if( o.outSpeed == 0 ) o.outSpeed = -1;
// Loop each context menu
$(this).each( function() {
var el = $(this);
var offset = $(el).offset();
// Add contextMenu class
$('#' + o.menu).addClass('contextMenu');
// Simulate a true right click
$(this).mousedown( function(e) {
var evt = e;
// evt.stopPropagation();
evt.preventDefault();
$(this).mouseup( function(e) {
// e.stopPropagation();
e.preventDefault();
var srcElement = $(this);
$(this).unbind('mouseup');
if( evt.button == 2 ) {
// Hide context menus that may be showing
$(".contextMenu").hide();
// Get this context menu
var menu = $('#' + o.menu);
menu.enableContextMenuItems();
if (onShowMenu) {
if (!onShowMenu( srcElement, menu )) {
return false;
}
}
if( $(el).hasClass('disabled') ) return false;
// Detect mouse position
var d = {}, x, y;
if( self.innerHeight ) {
d.pageYOffset = self.pageYOffset;
d.pageXOffset = self.pageXOffset;
d.innerHeight = self.innerHeight;
d.innerWidth = self.innerWidth;
} else if( document.documentElement &&
document.documentElement.clientHeight ) {
d.pageYOffset = document.documentElement.scrollTop;
d.pageXOffset = document.documentElement.scrollLeft;
d.innerHeight = document.documentElement.clientHeight;
d.innerWidth = document.documentElement.clientWidth;
} else if( document.body ) {
d.pageYOffset = document.body.scrollTop;
d.pageXOffset = document.body.scrollLeft;
d.innerHeight = document.body.clientHeight;
d.innerWidth = document.body.clientWidth;
}
(e.pageX) ? x = e.pageX : x = e.clientX + d.scrollLeft;
(e.pageY) ? y = e.pageY : y = e.clientY + d.scrollTop;
// Show the menu
$(document).unbind('click');
// MW: fixed position in a fancy layout
// $(menu).css({ top: y, left: x }).fadeIn(o.inSpeed);
$(menu).fadeIn(o.inSpeed).offset({ top: y, left: x }); // must be visible, before calling offset()
// Hover events
$(menu).find('A').mouseover( function() {
$(menu).find('LI.hover').removeClass('hover');
$(this).parent().addClass('hover');
}).mouseout( function() {
$(menu).find('LI.hover').removeClass('hover');
});
// Keyboard
$(document).keypress( function(e) {
switch( e.keyCode ) {
case 38: // up
if( $(menu).find('LI.hover').size() == 0 ) {
$(menu).find('LI:last').addClass('hover');
} else {
$(menu).find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:last').addClass('hover');
}
break;
case 40: // down
if( $(menu).find('LI.hover').size() == 0 ) {
$(menu).find('LI:first').addClass('hover');
} else {
$(menu).find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:first').addClass('hover');
}
break;
case 13: // enter
$(menu).find('LI.hover A').trigger('click');
break;
case 27: // esc
$(document).trigger('click');
break
}
});
// When items are selected
$('#' + o.menu).find('A').unbind('click');
$('#' + o.menu).find('LI:not(.disabled) A').click( function() {
$(document).unbind('click').unbind('keypress');
$(".contextMenu").hide();
// Callback
if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
return false;
});
// Hide bindings
setTimeout( function() { // Delay for Mozilla
$(document).click( function() {
$(document).unbind('click').unbind('keypress');
$(menu).fadeOut(o.outSpeed);
return false;
});
}, 0);
}
});
});
// Disable text selection
if( BROWSER.mozilla ) {
$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
} else if( BROWSER.msie ) {
$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
} else {
$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
}
// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });
});
return $(this);
},
// Disable context menu items on the fly
disableContextMenuItems: function(o) {
if( o == undefined ) {
// Disable all
$(this).find('LI').addClass('disabled');
return( $(this) );
}
$(this).each( function() {
if( o != undefined ) {
var d = o.split(',');
for( var i = 0; i < d.length; i++ ) {
$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
}
}
});
return( $(this) );
},
// Enable context menu items on the fly
enableContextMenuItems: function(o) {
if( o == undefined ) {
// Enable all
$(this).find('LI.disabled').removeClass('disabled');
return( $(this) );
}
$(this).each( function() {
if( o != undefined ) {
var d = o.split(',');
for( var i = 0; i < d.length; i++ ) {
$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
}
}
});
return( $(this) );
},
// Disable context menu(s)
disableContextMenu: function() {
$(this).each( function() {
$(this).addClass('disabled');
});
return( $(this) );
},
// Enable context menu(s)
enableContextMenu: function() {
$(this).each( function() {
$(this).removeClass('disabled');
});
return( $(this) );
},
// Destroy context menu(s)
destroyContextMenu: function() {
// Destroy specified context menus
$(this).each( function() {
// Disable action
$(this).unbind('mousedown').unbind('mouseup');
});
return( $(this) );
}
});
})(jQuery);
\ No newline at end of file
This diff is collapsed.
/*
* jQuery Superfish Menu Plugin - v1.7.4
* Copyright (c) 2013 Joel Birch
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
;(function(e){"use strict";var s=function(){var s={bcClass:"sf-breadcrumb",menuClass:"sf-js-enabled",anchorClass:"sf-with-ul",menuArrowClass:"sf-arrows"},o=function(){var s=/iPhone|iPad|iPod/i.test(navigator.userAgent);return s&&e(window).load(function(){e("body").children().on("click",e.noop)}),s}(),n=function(){var e=document.documentElement.style;return"behavior"in e&&"fill"in e&&/iemobile/i.test(navigator.userAgent)}(),t=function(e,o){var n=s.menuClass;o.cssArrows&&(n+=" "+s.menuArrowClass),e.toggleClass(n)},i=function(o,n){return o.find("li."+n.pathClass).slice(0,n.pathLevels).addClass(n.hoverClass+" "+s.bcClass).filter(function(){return e(this).children(n.popUpSelector).hide().show().length}).removeClass(n.pathClass)},r=function(e){e.children("a").toggleClass(s.anchorClass)},a=function(e){var s=e.css("ms-touch-action");s="pan-y"===s?"auto":"pan-y",e.css("ms-touch-action",s)},l=function(s,t){var i="li:has("+t.popUpSelector+")";e.fn.hoverIntent&&!t.disableHI?s.hoverIntent(u,p,i):s.on("mouseenter.superfish",i,u).on("mouseleave.superfish",i,p);var r="MSPointerDown.superfish";o||(r+=" touchend.superfish"),n&&(r+=" mousedown.superfish"),s.on("focusin.superfish","li",u).on("focusout.superfish","li",p).on(r,"a",t,h)},h=function(s){var o=e(this),n=o.siblings(s.data.popUpSelector);n.length>0&&n.is(":hidden")&&(o.one("click.superfish",!1),"MSPointerDown"===s.type?o.trigger("focus"):e.proxy(u,o.parent("li"))())},u=function(){var s=e(this),o=d(s);clearTimeout(o.sfTimer),s.siblings().superfish("hide").end().superfish("show")},p=function(){var s=e(this),n=d(s);o?e.proxy(f,s,n)():(clearTimeout(n.sfTimer),n.sfTimer=setTimeout(e.proxy(f,s,n),n.delay))},f=function(s){s.retainPath=e.inArray(this[0],s.$path)>-1,this.superfish("hide"),this.parents("."+s.hoverClass).length||(s.onIdle.call(c(this)),s.$path.length&&e.proxy(u,s.$path)())},c=function(e){return e.closest("."+s.menuClass)},d=function(e){return c(e).data("sf-options")};return{hide:function(s){if(this.length){var o=this,n=d(o);if(!n)return this;var t=n.retainPath===!0?n.$path:"",i=o.find("li."+n.hoverClass).add(this).not(t).removeClass(n.hoverClass).children(n.popUpSelector),r=n.speedOut;s&&(i.show(),r=0),n.retainPath=!1,n.onBeforeHide.call(i),i.stop(!0,!0).animate(n.animationOut,r,function(){var s=e(this);n.onHide.call(s)})}return this},show:function(){var e=d(this);if(!e)return this;var s=this.addClass(e.hoverClass),o=s.children(e.popUpSelector);return e.onBeforeShow.call(o),o.stop(!0,!0).animate(e.animation,e.speed,function(){e.onShow.call(o)}),this},destroy:function(){return this.each(function(){var o,n=e(this),i=n.data("sf-options");return i?(o=n.find(i.popUpSelector).parent("li"),clearTimeout(i.sfTimer),t(n,i),r(o),a(n),n.off(".superfish").off(".hoverIntent"),o.children(i.popUpSelector).attr("style",function(e,s){return s.replace(/display[^;]+;?/g,"")}),i.$path.removeClass(i.hoverClass+" "+s.bcClass).addClass(i.pathClass),n.find("."+i.hoverClass).removeClass(i.hoverClass),i.onDestroy.call(n),n.removeData("sf-options"),void 0):!1})},init:function(o){return this.each(function(){var n=e(this);if(n.data("sf-options"))return!1;var h=e.extend({},e.fn.superfish.defaults,o),u=n.find(h.popUpSelector).parent("li");h.$path=i(n,h),n.data("sf-options",h),t(n,h),r(u),a(n),l(n,h),u.not("."+s.bcClass).superfish("hide",!0),h.onInit.call(this)})}}}();e.fn.superfish=function(o){return s[o]?s[o].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof o&&o?e.error("Method "+o+" does not exist on jQuery.fn.superfish"):s.init.apply(this,arguments)},e.fn.superfish.defaults={popUpSelector:"ul,.sf-mega",hoverClass:"sfHover",pathClass:"overrideThisToUse",pathLevels:1,delay:800,animation:{opacity:"show"},animationOut:{opacity:"hide"},speed:"normal",speedOut:"fast",cssArrows:!0,disableHI:!1,onInit:e.noop,onBeforeShow:e.noop,onShow:e.noop,onBeforeHide:e.noop,onHide:e.noop,onIdle:e.noop,onDestroy:e.noop},e.fn.extend({hideSuperfishUl:s.hide,showSuperfishUl:s.show})})(jQuery);
\ No newline at end of file
...@@ -3,10 +3,19 @@ ...@@ -3,10 +3,19 @@
{% block head %} {% block head %}
{{ super() }} {{ super() }}
<script src="{{ url_for('static', filename='js/scripts/account.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/scripts/account.js') }}" type="text/javascript" charset="utf-8"></script>
<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/jqueryTabs.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<h2 class='title'>Your personal information</h2><br/> <h2>SlapOS web runner parameters</h2><br/>
<form class="account"> <div id="tabContaier">
<ul>
<li><a href="#tab1" class="active">Your personal information</a></li>
<li><a href="#tab2">Configurations</a></li>
</ul><!-- //Tab buttons -->
<div class="tabDetails">
<div id="tab1" class="tabContents">
<form class="account">
<div class='form'> <div class='form'>
<label for="name">Your name: </label> <label for="name">Your name: </label>
<input type='text' name='name' id='name' value='{{name}}'/> <input type='text' name='name' id='name' value='{{name}}'/>
...@@ -32,10 +41,14 @@ ...@@ -32,10 +41,14 @@
<label></label> <label></label>
<input type="submit" name="update" id ="update" value="Update Account" class="button"/> <input type="submit" name="update" id ="update" value="Update Account" class="button"/>
<div class='clear'></div> <div class='clear'></div>
<br/><br/><br/>
</div> </div>
<input type="hidden" name="hasAccount" id="hasAccount" value="{{name}}"/> <input type="hidden" name="hasAccount" id="hasAccount" value="{{name}}"/>
</form> </form>
</div>
<div id="tab2" class="tabContents">
</div>
</div>
</div>
{% if username %}<div id="file_info" class="file_info">leave passwords blank to preserve your current password... {% if username %}<div id="file_info" class="file_info">leave passwords blank to preserve your current password...
</div><br/>{%endif%} </div><br/>{%endif%}
<div id="tooltip-information" style="display:none; float:left"> <div id="tooltip-information" style="display:none; float:left">
......
...@@ -13,10 +13,15 @@ ...@@ -13,10 +13,15 @@
<meta name="description" content="" /> <meta name="description" content="" />
<link href="{{ url_for('static', filename='css/styles.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" /> <link href="{{ url_for('static', filename='css/styles.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='js/jquery/jquery-1.8.0.js') }}" type="text/javascript" charset="utf-8"></script> <link href="{{ url_for('static', filename='css/superfish.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<link href="{{ url_for('static', filename='css/jquery-ui-1.10.3.custom.min.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='js/jquery/jquery-1.10.2.min.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/jquery-ui-1.10.3.custom.min.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/jquery.form.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/jquery/jquery.form.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/popup.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/jquery/popup.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/jqueryToolTip.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/jquery/jqueryToolTip.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/superfish.min.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/hoverIntent.js') }}" type="text/javascript" charset="utf-8"></script>
<script type=text/javascript> <script type=text/javascript>
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }}; $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script> </script>
...@@ -39,6 +44,11 @@ ...@@ -39,6 +44,11 @@
if(!checkSavedCmd()){ if(!checkSavedCmd()){
getRunningState(); getRunningState();
} }
$('ul.sf-menu').superfish({
delay: 600,
speed: 'fast',
cssArrows: false
});
}); });
</script> </script>
{%endif%} {%endif%}
...@@ -53,31 +63,39 @@ ...@@ -53,31 +63,39 @@
<div id="header"> <div id="header">
<div class="block_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> <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('manageProject') }}" style="float:left" title="Manage Your repositories"><img alt="" src="{{ url_for('static', filename='images/manage_repo-little.png') }}" /></a>
<div class="line"></div>
<a href="{{ url_for('shell') }}" style="float:left" title="Use the shell"><img alt="" src="{{ url_for('static', filename='images/terminal.png') }}" /></a>
<div class="line"></div> <div class="line"></div>
<a href="{{ url_for('dologout') }}" style="float:left" title="Close your session"><img alt="" src="{{ url_for('static', filename='images/logout.png') }}" /></a> <a href="{{ url_for('dologout') }}" style="float:left" title="Close your session"><img alt="" src="{{ url_for('static', filename='images/logout.png') }}" /></a>
<h2 class="info">{% block title %}{% endblock %} - {{session.title}}</h2> <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') }}" <div class="run">
height='26' title="slapgrid is currently running"/></span></div> <div id="running">
<p id="running_info" class='instance'>Building software...</p>
<img alt="" src="{{ url_for('static', filename='images/ajax_roller.gif') }}" height='26' title="slapgrid is currently running"/>
<div class="clear"></div>
</div> </div>
<div class="wmenu"> </div>
</div>
<div id="wmenu">
<ul class="sf-menu">
<li><a href="{{ url_for('editCurrentProject') }}">Editor</a></li>
<li><a href="{{ url_for('browseWorkspace') }}">Services</a></li>
<li><a href="{{ url_for('runSoftwareProfile') }}" id="softrun">Logs</a></li>
<li><a href="{{ url_for('viewSoftwareLog') }}">Terminal</a></li>
<li><a href="{{ url_for('inspectSoftware') }}">Git</a></li>
<li class='right_menu'><a class="main_menu" href="{{ url_for('viewInstanceLog') }}"></a>
<ul> <ul>
<li><a href="{{ url_for('editSoftwareProfile') }}">Profiles</a></li> <li><a href="{{ url_for('myAccount')}}">Parameters</a></li>
<li><a href="{{ url_for('browseWorkspace') }}">Workspace</a></li>
<li class='sep'></li> <li class='sep'></li>
<li><a href="{{ url_for('runSoftwareProfile') }}" id="softrun">Run software</a></li> <li><a href="#">Open Software Release</a></li>
<li><a href="{{ url_for('viewSoftwareLog') }}">Software log</a></li> <li><a href="#">Create Software Release</a></li>
<li><a href="{{ url_for('inspectSoftware') }}">SR result</a></li>
<li class='sep'></li> <li class='sep'></li>
<li><a href="{{ url_for('runInstanceProfile') }}" id="instrun">Run instance</a></li> <li><a href="{{ url_for('browseWorkspace') }}">Browse Workspace</a></li>
<li><a href="{{ url_for('viewInstanceLog') }}">Instance log</a></li> <li><a href="{{ url_for('inspectSoftware') }}">My Softwares Releases</a></li>
<li><a href="{{ url_for('inspectInstance') }}">Inspect instance</a></li> <li class='sep'></li>
<li><a id="removeIst" href="#">Destroy instance</a></li> <li><a href="{{ url_for('dologout') }}">Log out</a></li>
</ul>
</li>
<li class='right_menu'><a class="slapos_run" href="{{ url_for('runInstanceProfile') }}" id="instrun"></a>
</li>
</ul> </ul>
</div> </div>
<div class="clear"></div> <div class="clear"></div>
......
...@@ -2,14 +2,18 @@ ...@@ -2,14 +2,18 @@
{% block title %}Your current software folder{% endblock %} {% block title %}Your current software folder{% endblock %}
{% block head %} {% block head %}
{{ super() }} {{ 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/ui.fancytree.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> <link href="{{ url_for('static', filename='css/jquery.contextMenu.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='js/scripts/softwareFolder.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/jquery/jquery.contextMenu-custom.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/jquery/jquery.fancytree.min.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/ace/ace.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/ace/ace.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/ace/theme-crimson_editor.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/ace/theme-crimson_editor.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/ace/mode-buildout.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/ace/mode-buildout.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/ace/mode-python.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/ace/mode-python.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/ace/mode-php.js') }}" type="text/javascript" charset="utf-8"></script> <script src="{{ url_for('static', filename='js/ace/mode-php.js') }}" type="text/javascript" charset="utf-8"></script>
<link href="{{ url_for('static', filename='css/colorbox.css', _external=False) }}" rel="stylesheet" type="text/css" media="screen" />
<script src="{{ url_for('static', filename='js/jquery/jquery.colorbox-min.js') }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ url_for('static', filename='js/scripts/softwareFolder.js') }}" type="text/javascript" charset="utf-8"></script>
{% endblock %} {% endblock %}
{% block body %} {% block body %}
...@@ -17,23 +21,34 @@ ...@@ -17,23 +21,34 @@
<input type="hidden" name="project" id="project" value="{{project}}" /> <input type="hidden" name="project" id="project" value="{{project}}" />
<input type="hidden" name="workdir" id="workdir" value="{{workDir}}" /> <input type="hidden" name="workdir" id="workdir" value="{{workDir}}" />
<input type="hidden" name="subfolder" id="subfolder" value="" /> <input type="hidden" name="subfolder" id="subfolder" value="" />
<!-- Definition of context menu -->
<ul id="myMenu" class="contextMenu">
<li class="edit"><a href="#edit">Edit</a></li>
<li class="edit"><a href="#editfull">Open in new editor</a></li>
<li class="view"><a href="#view">Open in viewer</a></li>
<li class="rename separator"><a href="#rename">Rename</a></li>
<li class="delete "><a href="#delete">Delete</a></li>
<li class="refresh separator"><a href="#refresh">Refresh</a></li>
<li class="md5sum"><a href="#md5sum">File md5 sum</a></li>
<li class="copy separator"><a href="#copy">Copy</a></li>
<li class="cut"><a href="#cut">Cut</a></li>
<li class="paste"><a href="#paste">Paste</a></li>
<li class="newfile separator"><a href="#nfile">New File</a></li>
<li class="newdir"><a href="#nfolder">New Folder</a></li>
</ul>
<div id="software_folder"> <div id="software_folder">
<div class="software_details"> <div class="software_details">
<div>
<a href="#" id="switch" class="lshare no-right-border" style="float:left">Switch to Project</a> <a href="#" id="switch" class="lshare no-right-border" style="float:left">Switch to Project</a>
<a href="#" id="clearselect" class="lshare no-right-border" style="float:left">Reset</a> <a href="#" id="clearselect" class="lshare no-right-border" style="float:left">Reset</a>
<a href="#" id="save" class="lshare" style="float:left">Save</a> <a href="#" id="save" class="lshare" style="float:left">Save</a>
<div class="clear"></div> <div class="clear"></div>
</div>
<div id="details_box"> <div id="details_box">
<div id="fileTree" class="file_tree_short" title="Double click to edit selected file..."></div> <div id="fileTree" class="file_tree_short"></div>
<div id="fileTreeFull" style='display:none' class="file_tree_short" title="Double click to edit selected file..."></div> <div id="fileTreeFull" style='display:none' class="file_tree_short" title="Double click to edit selected file..."></div>
<div class="box_software">
<input type="text" name="file" id="file" size='12' value="Name here..." />
&nbsp;<select name="type" id="type">
<option value="file">file</option>
<option value="folder">folder</option>
</select>
&nbsp;<input type="submit" name="add" id ="add" value="Add" class="button"/>
</div>
</div> </div>
</div> </div>
<div id="code"> <div id="code">
...@@ -67,4 +82,12 @@ ...@@ -67,4 +82,12 @@
</ul> </ul>
<a href="#" id="adddevelop" class="lshare">Add to profile</a> <a href="#" id="adddevelop" class="lshare">Add to profile</a>
</div> </div>
<!-- This contains the hidden content for inline calls -->
<a id='inlineViewer' style='display:none' href="#inline_content">Inline HTML</a>
<div style='display:none'>
<div id='inline_content' style='padding:10px; background:#fff;'>
</div>
</div>
{% endblock %} {% endblock %}
...@@ -18,6 +18,38 @@ ...@@ -18,6 +18,38 @@
<label for="slow">From time to time</label> <label for="slow">From time to time</label>
</div> </div>
<br/> <br/>
<div class="log_content"><div class="log" id="salpgridLog"></div>
<textarea class="log" readonly id="manualLog" style="display:none">{{result}}</textarea></div> <div class="log_content">
<div class="log" id="salpgridLog"></div>
<textarea class="log" readonly id="manualLog" style="display:none">{{result}}</textarea>
</div>
<div class="log_information">
<div class="log_info_box">
<h2 class="software">Building State</h2>
<div class="log_content_box">
<div id="sr_run_state" class="state_running">
<span class="legend"></span>
<p>Processing</p>
<div class="clear"></div>
</div>
<p>SlapOS rebuild your software from source, allowing you to easily patch or add any free software. <a href="#">Lean how!</a></p>
</div>
<h2 class="instance">Running State</h2>
<div class="log_content_box">
<div id="instance_run_state" class="state_waiting">
<span class="legend"></span>
<p>Waiting for starting</p>
<div class="clear"></div>
</div>
<p>SlapOS configure your running environment to match your needs. <a href="#">Lean how!</a></p>
</div>
<div class="separator"></div>
<div style="height: 38px; text-align: center; padding-top: 25px;">
<a href="#" id="switch" class="lshare" rel="stop">STOP PROCESS</a>
</div>
</div>
</div>
<div class='clear'></div>
{% endblock %} {% endblock %}
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
import os import os
import shutil import shutil
import urllib import urllib
import json
from flaskext.auth import logout from flaskext.auth import logout
from flask import (Flask, request, redirect, url_for, render_template, from flask import (Flask, request, redirect, url_for, render_template,
...@@ -586,7 +587,7 @@ def fileBrowser(): ...@@ -586,7 +587,7 @@ def fileBrowser():
else: else:
opt = int(request.args.get('opt')) opt = int(request.args.get('opt'))
try: # try:
if opt == 1: if opt == 1:
#list files and directories #list files and directories
result = file_request.listDirs(dir) result = file_request.listDirs(dir)
...@@ -630,10 +631,16 @@ def fileBrowser(): ...@@ -630,10 +631,16 @@ def fileBrowser():
elif opt == 17: elif opt == 17:
#zip file #zip file
result = file_request.unzipFile(dir, filename, newfilename) result = file_request.unzipFile(dir, filename, newfilename)
elif opt == 20:
#Fancy Load folder
key = int(request.args.get('key'))
dir = request.args.get('dir').encode('utf-8')
data = file_request.fancylistDirs(dir, key)
result = json.dumps(data)
else: else:
result = "ARGS PARSE ERROR: Bad option..." result = "ARGS PARSE ERROR: Bad option..."
except Exception as e: # except Exception as e:
return str(e) # return str(e)
return result return result
......
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