Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
3pia
VISPA
VISPA web
Commits
05fd2e34
Commit
05fd2e34
authored
Oct 02, 2014
by
Benjamin Fischer
Browse files
Merge
parents
1e44561c
1c13e818
Changes
40
Hide whitespace changes
Inline
Side-by-side
vispa/controller/bus.py
View file @
05fd2e34
...
...
@@ -32,7 +32,7 @@ class BusController(AbstractController):
@
cherrypy
.
expose
@
cherrypy
.
tools
.
ajax
()
def
poll
(
self
,
timeout
=
1
0
):
def
poll
(
self
,
timeout
ms
=
1000
0
):
sid
=
cherrypy
.
session
.
id
uid
=
cherrypy
.
request
.
user
.
id
publisher
=
self
.
get_polling_publisher
(
sid
,
uid
)
...
...
@@ -40,7 +40,7 @@ class BusController(AbstractController):
return
[]
POLLING_TIMESTAMPS
[
sid
]
=
int
(
time
())
self
.
release
()
return
publisher
.
fetch
(
int
(
timeout
)
)
return
publisher
.
fetch
(
int
(
timeout
ms
)
*
0.001
)
@
cherrypy
.
expose
def
send
(
self
,
*
args
,
**
kwargs
):
...
...
vispa/controller/filesystem.py
View file @
05fd2e34
...
...
@@ -25,7 +25,8 @@ class FSController(AbstractController):
download
=
True
wid
=
cherrypy
.
request
.
private_params
.
get
(
'_workspaceId'
,
None
)
data
,
contenttype
,
_
=
self
.
handleDownload
(
path
,
wid
)
cherrypy
.
response
.
headers
[
'Content-Type'
]
=
contenttype
if
contenttype
!=
None
:
cherrypy
.
response
.
headers
[
'Content-Type'
]
=
contenttype
if
download
:
# or not isbrowserfile:
disposition
=
'attachment; filename=%s'
%
path
.
split
(
'/'
)[
-
1
]
cherrypy
.
response
.
headers
[
'Content-Disposition'
]
=
disposition
...
...
@@ -36,11 +37,11 @@ class FSController(AbstractController):
# get the content type depending on the file extension
ext
=
path
.
split
(
'.'
)[
-
1
]
mimetype
=
fs
.
get_mime_type
(
path
)
if
mimetype
is
None
:
raise
Exception
(
'The file extension
\'
%s\ is not supported by this server'
%
ext
)
#
if mimetype is None:
#
raise Exception('The file extension \'%s\ is not supported by this server' % ext)
if
not
fs
.
exists
(
path
,
'f'
):
raise
Exception
(
'The file
\'
%s
\'
does not exist'
%
path
)
raise
Message
Exception
(
'The file
\'
%s
\'
does not exist'
%
path
)
# Set the Last-Modified response header, so that
# modified-since validation code can work.
...
...
@@ -83,6 +84,19 @@ class FSAjaxController(AbstractController):
else
:
return
"Failed"
@
cherrypy
.
expose
@
cherrypy
.
tools
.
ajax
()
def
filecount
(
self
,
path
):
self
.
release_session
()
fs
=
self
.
get
(
'fs'
)
self
.
release_database
()
count
=
fs
.
get_file_count
(
path
)
if
count
<
0
:
raise
MessageException
(
"%s does not exist"
%
path
)
else
:
return
{
"count"
:
count
}
@
cherrypy
.
expose
@
cherrypy
.
tools
.
ajax
(
encoded
=
True
)
def
filelist
(
self
,
path
,
deep
=
False
,
filefilter
=
None
,
reverse
=
False
):
...
...
vispa/extensions/codeeditor/__init__.py
View file @
05fd2e34
...
...
@@ -22,6 +22,6 @@ class CodeEditorExtension(AbstractExtension):
self
.
add_js
(
"js/preview.js"
)
self
.
add_js
(
"js/prefs.js"
)
self
.
add_css
(
"css/styles.
le
ss"
)
self
.
add_css
(
"css/styles.
c
ss"
)
self
.
add_workspace_directoy
()
vispa/extensions/codeeditor/static/css/styles.css
0 → 100644
View file @
05fd2e34
.codeeditor
{
position
:
absolute
;
top
:
0px
;
right
:
0px
;
bottom
:
0px
;
left
:
0px
;
margin
:
0px
;
padding
:
0px
;
}
.codeeditor
#execute
{
min-width
:
100px
;
}
.codeeditor
#abort
{
margin-right
:
-1px
;
min-width
:
100px
;
}
.codeeditor
#command-line
{
font-family
:
Menlo
,
Monaco
,
Consolas
,
"Courier New"
,
monospace
;
}
.codeeditor-left
{
position
:
absolute
;
top
:
0px
;
right
:
none
;
bottom
:
0px
;
left
:
0px
;
width
:
100%
;
overflow
:
auto
;
border
:
1px
solid
#b8b8b8
;
border-width
:
0px
1px
0px
0px
;
}
.codeeditor-right
{
position
:
absolute
;
top
:
0px
;
right
:
0px
;
bottom
:
0px
;
left
:
none
;
width
:
0%
;
overflow
:
auto
;
padding-left
:
1px
;
}
.codeeditor-right-top
{
position
:
absolute
;
top
:
0px
;
right
:
0px
;
bottom
:
none
;
left
:
0px
;
height
:
100%
;
overflow
:
hidden
;
box-shadow
:
0px
1px
0px
#b8b8b8
;
}
.codeeditor-right-bottom
{
position
:
absolute
;
top
:
none
;
right
:
0px
;
bottom
:
0px
;
left
:
0px
;
height
:
0%
;
overflow
:
auto
;
padding
:
11px
10px
10px
10px
;
}
.codeeditor-commandline
>
*
{
border-radius
:
0px
;
}
.codeeditor-commandline
>
.input-group-addon
{
border-left
:
0px
;
}
.codeeditor-commandline
button
{
border-radius
:
0px
;
}
.codeeditor-ace
{
position
:
absolute
!important
;
top
:
0px
!important
;
right
:
0px
!important
;
bottom
:
0px
!important
;
left
:
0px
!important
;
}
.codeeditor-output
{
position
:
absolute
!important
;
top
:
35px
!important
;
right
:
0px
!important
;
bottom
:
0px
!important
;
left
:
0px
!important
;
border-radius
:
0px
;
margin
:
0px
0px
0px
1px
;
border
:
0px
;
}
.codeeditor-output-buttons
{
position
:
absolute
;
top
:
45px
;
right
:
10px
;
}
.codeeditor-right-top
pre
{
overflow
:
auto
;
}
.codeeditor-right-bottom
.well
{
position
:
absolute
;
top
:
55px
;
right
:
10px
;
bottom
:
10px
;
left
:
10px
;
padding
:
10px
;
margin
:
0px
;
white-space
:
nowrap
;
overflow-x
:
auto
;
overflow-y
:
auto
;
}
.codeeditor-right-bottom
.codeeditor-preview
{
position
:
relative
;
display
:
inline-block
;
margin
:
0px
10px
10px
0px
;
padding
:
6px
;
border-radius
:
3px
;
border
:
1px
solid
#b8b8b8
;
background-color
:
white
;
float
:
left
;
overflow
:
hidden
;
}
.codeeditor-right-bottom
.codeeditor-preview
:hover
{
border-color
:
#428bca
;
}
.codeeditor-right-bottom
.codeeditor-preview-label
{
position
:
absolute
;
top
:
0px
;
right
:
0px
;
left
:
0px
;
height
:
24px
;
text-align
:
center
;
}
.codeeditor-right-bottom
.codeeditor-preview-img
{
position
:
absolute
;
top
:
24px
;
right
:
0px
;
bottom
:
0px
;
left
:
0px
;
text-align
:
center
;
}
.codeeditor-right-bottom
.codeeditor-preview
img
{
padding-top
:
24px
;
height
:
100px
;
width
:
auto
;
}
.codeeditor-ace
div
.ace_scrollbar
{
overflow-x
:
auto
!important
;
overflow-y
:
auto
!important
;
}
vispa/extensions/demo/__init__.py
View file @
05fd2e34
...
...
@@ -31,7 +31,6 @@ class DemoExtension(AbstractExtension):
# the paths are relative to vispa/extensions/<name>/static
self
.
add_js
(
"js/extension.js"
)
self
.
add_css
(
"css/style.css"
)
self
.
add_css
(
"css/style.less"
)
# tell vispa to transfer files located in the workspace folder
# (vispa/extensions/<name>/workspace) to selected workspaces
...
...
vispa/extensions/demo/static/css/style.css
View file @
05fd2e34
/*
* This is a basic css file. In order to avoid naming collisions, you should
* use prefixes in your class names.
* This is a less-css file. It allows class mixinx, variables, anc basic
* computation tasks (addition, multiplication, etc). You can find more
* information on less-css at http://lesscss.org/. In order to avoid naming
* collisions, you should use prefixes in your class names.
*/
.demo-content
{
background-color
:
rgba
(
61
,
129
,
187
,
1.0
);
background-color
:
#3d81bb
;
}
.demo-content-text
{
color
:
#ffffff
;
padding
:
5px
10px
;
}
vispa/extensions/demo/static/css/style.less
View file @
05fd2e34
...
...
@@ -8,6 +8,10 @@
// define a variable for the text color
@content-color: #ffffff;
.demo-content {
background-color: rgba(61, 129, 187, 1.0);
}
// define a mixin class with default values
.demo-text-padding (@vertical: 5px, @horizontal: 10px) {
padding: @vertical @horizontal;
...
...
vispa/extensions/file/__init__.py
View file @
05fd2e34
...
...
@@ -44,6 +44,7 @@ class FileBrowserExtension(AbstractExtension):
self
.
add_js
(
'js/selector/selector.js'
)
self
.
add_js
(
'js/selector/actions.js'
)
self
.
add_js
(
'js/selector/items.js'
)
self
.
add_js
(
'js/selector/selections.js'
)
self
.
add_js
(
'js/selector/selectortableview.js'
)
...
...
vispa/extensions/file/static/js/base/actions.js
View file @
05fd2e34
...
...
@@ -71,7 +71,12 @@ var FileBaseActions = Class.extend({
function
(
result
)
{
if
(
result
===
true
)
{
self
.
_openWithCodeEditor
(
path
);
}
}
else
self
.
FileBase
.
instance
.
confirm
(
"
Do you want to download
\"
"
+
name
+
"
(
"
+
size
+
"
)
\"
?
"
,
function
(
res2
)
{
if
(
res2
===
true
)
{
self
.
download
();
}
});
});
}
// })
...
...
vispa/extensions/file/static/js/base/base.js
View file @
05fd2e34
...
...
@@ -49,34 +49,47 @@ var FileBase = Class.extend({
updateView
:
function
()
{
var
self
=
this
;
this
.
instance
.
setLoading
(
true
);
this
.
selections
.
unselectAll
();
// remove the links needed for the preview lightbox
$
(
"
a[data-lightbox=
"
+
this
.
view
.
previewBoxID
+
"
]
"
).
remove
();
if
(
self
.
workflow
.
lastRefresh
===
null
||
$
.
now
()
-
self
.
workflow
.
lastRefresh
>
1000
)
{
// Check if last request is less than one second away
var
promise
=
this
.
instance
.
GET
(
"
/ajax/fs/filelist
"
,
{
"
path
"
:
this
.
workflow
.
path
,
});
self
.
workflow
.
lastRefresh
=
$
.
now
();
promise
.
done
(
function
(
content
)
{
if
(
self
.
workflow
.
lastRefresh
===
null
||
$
.
now
()
-
self
.
workflow
.
lastRefresh
>
500
)
{
this
.
instance
.
GET
(
"
/ajax/fs/filecount
"
,
{
path
:
this
.
workflow
.
path
}).
done
(
function
(
res
)
{
self
.
instance
.
setLoading
(
true
,
res
.
count
>
50
?
0
:
null
);
// Check if last request is less than one second away
var
promise
=
self
.
instance
.
GET
(
"
/ajax/fs/filelist
"
,
{
"
path
"
:
self
.
workflow
.
path
});
self
.
workflow
.
lastRefresh
=
$
.
now
();
if
(
Object
.
keys
(
content
.
filelist
).
length
==
1
&&
content
.
filelist
[
0
].
warning
!==
undefined
)
{
self
.
instance
.
alert
(
content
.
filelist
[
0
].
warning
);
vispa
.
messenger
.
error
(
content
.
filelist
[
0
].
warning
);
content
.
filelist
=
[];
}
self
.
refresh
(
content
);
if
(
self
.
view
.
fileContentContainer
!==
null
)
{
self
.
selections
.
unselectAll
()
self
.
view
.
fileContentContainer
.
empty
();
};
promise
.
done
(
function
(
content
)
{
self
.
workflow
.
lastRefresh
=
$
.
now
();
if
(
Object
.
keys
(
content
.
filelist
).
length
==
1
&&
content
.
filelist
[
0
].
warning
!==
undefined
)
{
self
.
instance
.
alert
(
content
.
filelist
[
0
].
warning
);
vispa
.
messenger
.
error
(
content
.
filelist
[
0
].
warning
);
content
.
filelist
=
[];
}
self
.
refresh
(
content
);
}).
fail
(
function
(
err
)
{
self
.
instance
.
setLoading
(
false
);
});
});
}
else
{
this
.
instance
.
setLoading
(
false
);
}
},
refresh
:
function
(
content
,
sort
,
reverse
,
filter
)
{
var
self
=
this
;
if
(
!
content
)
{
return
this
;
return
;
}
sort
=
sort
===
undefined
?
this
.
workflow
.
sort
:
sort
;
reverse
=
reverse
===
undefined
?
this
.
workflow
.
reverse
:
reverse
;
...
...
@@ -100,8 +113,8 @@ var FileBase = Class.extend({
}
}
this
.
helper
.
sortItems
(
content
,
sort
,
reverse
);
this
.
menuitems
.
hideMenu
();
this
.
workflow
.
currentView
.
setContent
(
content
);
this
.
menuitems
.
hideMenu
();
this
.
instance
.
setLabel
(
this
.
workflow
.
path
,
true
);
this
.
instance
.
setLoading
(
false
);
}
...
...
vispa/extensions/file/static/js/base/view.js
View file @
05fd2e34
...
...
@@ -43,18 +43,18 @@ var FileBaseView = Class.extend({
},
// convert timestamp to dd.mm.jjjj hh:mm:ss
"
mtime
"
:
{
"
text
"
:
function
(
nodeObj
)
{
"
text
"
:
function
()
{
return
self
.
FileBase
.
helper
.
convertTimestamp
(
this
.
mtime
);
}
},
// convert size from bytes to kB, Mb, etc
"
size
"
:
{
"
text
"
:
function
(
nodeObj
)
{
"
text
"
:
function
()
{
return
self
.
FileBase
.
helper
.
convertSize
(
this
.
size
).
size
;
}
},
"
sizeSuffix
"
:
{
"
text
"
:
function
(
nodeObj
)
{
"
text
"
:
function
()
{
return
self
.
FileBase
.
helper
.
convertSize
(
this
.
size
).
sizeSuffix
;
}
}
...
...
vispa/extensions/file/static/js/base/views/symbol/view.js
View file @
05fd2e34
...
...
@@ -26,7 +26,6 @@ var Symbolview = Class.extend({
this
.
data
=
data
;
// Get the container, empty it and fill the template
this
.
fileContentContainer
.
empty
();
this
.
fileContentContainer
.
html
(
this
.
template
);
if
(
this
.
FileBase
.
instance
.
getPreference
(
"
Open
"
)
==
"
single
"
||
vispa
.
device
.
hasTouch
)
{
...
...
vispa/extensions/file/static/js/base/views/table/view.js
View file @
05fd2e34
...
...
@@ -27,7 +27,6 @@ var Tableview = Class.extend({
this
.
data
=
data
;
// Get the container, empty it and fill the template
this
.
fileContentContainer
.
empty
();
this
.
fileContentContainer
.
html
(
this
.
template
);
// Set the right path
...
...
vispa/extensions/file/static/js/menuentries.js
View file @
05fd2e34
...
...
@@ -25,6 +25,7 @@ function getFileMenuEntries() {
iconClass
:
"
glyphicon glyphicon-arrow-up
"
,
buttonClass
:
"
btn-default
"
,
callback
:
function
()
{
this
.
fb
.
workflow
.
lastRefresh
=
null
;
this
.
fb
.
workflow
.
path
=
this
.
fb
.
workflow
.
parentpath
;
this
.
fb
.
updateView
();
}
...
...
vispa/extensions/file/static/js/selector/items.js
0 → 100644
View file @
05fd2e34
var
FileSelectorItems
=
FileBaseMenuItems
.
extend
({
init
:
function
(
FileBase
)
{
this
.
_super
(
FileBase
);
this
.
FileBase
=
FileBase
;
},
getContextMenuPostion
:
function
(
event
,
contextMenu
)
{
var
menuPostion
=
{};
var
menuDimension
=
{};
// store the fileContentContainer fCC
var
fCC
=
this
.
FileBase
.
view
.
fileContentContainer
;
var
xOffsetModal
=
+
fCC
.
parent
().
parent
().
parent
().
position
().
left
+
fCC
.
parent
().
position
()
.
left
;
var
offset
=
fCC
.
offset
().
top
;
menuDimension
.
x
=
contextMenu
.
outerWidth
();
menuDimension
.
y
=
contextMenu
.
outerHeight
();
menuPostion
.
x
=
2
*
event
.
clientX
-
event
.
pageX
;
menuPostion
.
y
=
event
.
clientY
-
offset
;
menuPostion
.
x
-=
xOffsetModal
;
if
(
vispa
.
device
.
hasTouch
)
{
menuPostion
.
x
+=
5
;
menuPostion
.
y
+=
5
;
}
// Check if the side borders are reached
if
(
menuPostion
.
x
+
menuDimension
.
x
>
fCC
.
width
())
{
menuPostion
.
x
=
fCC
.
width
()
-
menuDimension
.
x
;
}
// Check if the lower border is reached
if
(
menuPostion
.
y
+
menuDimension
.
y
>
fCC
.
height
())
{
menuPostion
.
y
=
fCC
.
height
()
-
menuDimension
.
y
;
}
return
menuPostion
;
}
});
\ No newline at end of file
vispa/extensions/file/static/js/selector/selector.js
View file @
05fd2e34
...
...
@@ -68,6 +68,7 @@ var FileSelector = FileBase.extend({
// this.view = new SelectorView(this);
this
.
actions
=
new
FileSelectorActions
(
this
);
this
.
selections
=
new
FileSelectorSelections
(
this
);
this
.
menuitems
=
new
FileSelectorItems
(
this
);
this
.
workflow
.
sort
=
args
.
sort
!==
undefined
?
args
.
sort
:
this
.
workflow
.
sort
;
this
.
workflow
.
reverse
=
args
.
reverse
!==
undefined
?
args
.
reverse
:
this
.
workflow
.
reverse
;
...
...
vispa/extensions/file/static/js/shortcuts.js
View file @
05fd2e34
...
...
@@ -4,63 +4,72 @@ function getShortcuts() {
singleSelect
:
{
description
:
"
Key for selection of single files or folders
"
,
value
:
"
down:
"
+
ctrlMeta
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
workflow
.
selectmode
=
true
;
}
},
abortSingleSelect
:
{
description
:
"
Key for selection of single files or folders
"
,
value
:
"
up:
"
+
ctrlMeta
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
workflow
.
selectmode
=
false
;
}
},
copy
:
{
description
:
"
Copy current selection
"
,
value
:
ctrlMeta
+
"
+c
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
actions
.
copy
();
}
},
paste
:
{
description
:
"
Paste elements
"
,
value
:
ctrlMeta
+
"
+v
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
actions
.
paste
();
}
},
cut
:
{
description
:
"
Cut elements
"
,
value
:
ctrlMeta
+
"
+x
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
actions
.
cut
();
}
},
"
delete
"
:
{
description
:
"
Delete elements
"
,
value
:
"
del
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
actions
.
remove
();
}
},
rename
:
{
description
:
"
Rename element
"
,
value
:
ctrlMeta
+
"
+t
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
actions
.
rename
();
}
},
arrowLeft
:
{
description
:
"
Naviagtion in Filebrowser
"
,
value
:
"
left
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
selections
.
selectPrevNode
();
}
},
arrowRight
:
{
description
:
"
Naviagtion in Filebrowser
"
,
value
:
"
right
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
selections
.
selectNextNode
();
}
...
...
@@ -68,7 +77,8 @@ function getShortcuts() {
arrowDown
:
{
description
:
"
Naviagtion in Filebrowser
"
,
value
:
"
down
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
if
(
this
.
fb
.
workflow
.
currentView
.
type
==
"
Table
"
)
{
this
.
fb
.
selections
.
selectNextNode
();
}
else
{
...
...
@@ -84,7 +94,8 @@ function getShortcuts() {
arrowUp
:
{
description
:
"
Naviagtion in Filebrowser
"
,
value
:
"
up
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
if
(
this
.
fb
.
workflow
.
currentView
.
type
==
"
Table
"
)
{
this
.
fb
.
selections
.
selectPrevNode
();
}
else
{
...
...
@@ -100,7 +111,8 @@ function getShortcuts() {
open
:
{
description
:
"
Open in Filebrowser
"
,
value
:
"
return
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
var
selectedEntries
=
this
.
fb
.
selections
.
entries
;
var
nEntries
=
Object
.
keys
(
selectedEntries
).
length
;
if
(
nEntries
===
0
||
nEntries
>
1
)
{
...
...
@@ -119,7 +131,9 @@ function getShortcuts() {
up
:
{
description
:
"
Up (parentpath) in Filebrowser
"
,
value
:
"
backspace
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
workflow
.
lastRefresh
=
null
;
this
.
fb
.
workflow
.
path
=
this
.
fb
.
workflow
.
parentpath
;
this
.
fb
.
updateView
();
}
...
...
@@ -127,14 +141,16 @@ function getShortcuts() {
refresh
:
{
description
:
"
Reload the content of the current folder
"
,
value
:
"
F5
"
,
callback
:
function
()
{
callback
:
function
(
event
)
{
event
.
preventDefault
();
this
.
fb
.
updateView
();
}
},