Commit c4143d3a authored by Marcel Rieger's avatar Marcel Rieger
Browse files

Intermediate merge.

parents c29e1dad bf3a9a14
......@@ -235,24 +235,36 @@ class FSAjaxController(AbstractController):
self.release_session()
fs = self.get('fs')
self.release_database()
# get the parts
parts = kwargs['file_data']
# the html5 uploader provides following kwargs:
# index, type, name, size, files[]
# Since "files[]" ends with "[]"-brackets
# we have to use kwargs instead of args
# extract the path
# prepare the parts
parts = kwargs['files[]']
# force parts to be a list
if not isinstance(parts, list):
parts = [parts]
# get path
path = kwargs['path']
# save every part
for part in parts:
filename = fs.handle_file_name_collision(part.filename, path)
append = False
append = False
force = True
while True:
data = part.file.read(1024 * 1024)
data = part.file.read(1024 ** 2)
if len(data) <= 0:
break
success, msg = fs.save_file_content(filename, data, path=path, force=True, append=append)
success, msg = fs.save_file_content(filename, data,
path=path, force=force,
append=append)
if not success:
raise AjaxException(msg)
if not append:
append = True
......
......@@ -429,40 +429,32 @@ define(["jquery", "jclass"], function($, JClass) {
},
upload: function(path) {
// bootstrap fileinput
var self = this;
if (path === undefined) {
path = this.FileBase.instance.getState("path");
}
// already existent?
if ($(".file-input", self.FileBase.view.node).length !== 0) return;
// create new input
var input = $("<input />");
input.attr({
"type": "file",
"multiple": true,
"data-show-preview": false,
});
input.appendTo(this.FileBase.instance._nodes.content)
input.fileinput({
"uploadUrl": vispa.url.dynamic("ajax/fs/upload?path=" + path +
"&_workspaceId=" + String(self.FileBase.instance.getWorkspaceId())),
});
input = $(".file-input", self.FileBase.view.node);
// add close button
var closeButton = $("<div class='btn btn-danger'><i class='glyphicon glyphicon-remove'></i>close</div>")
.appendTo(".input-group-btn", input);
closeButton.on(vispa.hasTouch ? "tab" : "click", function() {
input.remove();
});
// events
// disable close button while upload, enable afterwards
input.on("filebatchpreupload", function() {
closeButton.toggleClass("disabled", true);
var $input = $("<input />");
$input.attr({
type : "file",
name : "files[]",
multiple: true
});
input.on("filereset", function() {
closeButton.toggleClass("disabled", false);
$input.fileupload({
url: vispa.url.dynamic("ajax/fs/upload?path=" + path +
"&_workspaceId=" + self.FileBase.instance.getWorkspaceId()),
done: function() {
//self.FileBase.updateView();
vispa.messenger.info("Upload succeeded", "glyphicon glyphicon-ok-sign");
$(this).remove();
},
fail: function() {
vispa.messenger.info("Upload failed", "glyphicon glyphicon-warning-sign");
$(this).remove();
}
});
$input.trigger("click");
},
filter: function() {
......
......@@ -15,7 +15,6 @@ define(["jquery", "jclass"], function($, JClass) {
// click event on the selection-p
var selectionP = $(".file-selection-p", node);
selectionP.on("click tap", node, function(event) {
event.stopPropagation();
// Needed to avoid double event execution
if ($(event.target).is("span")) {
return;
......@@ -42,7 +41,6 @@ define(["jquery", "jclass"], function($, JClass) {
// click on the node itself
var menuOpenString = vispa.device.hasTouch ? "taphold" : "contextmenu";
node.on(menuOpenString, function(event) {
event.stopPropagation();
var abspath = self.FileBase.helper.abspath(data.name);
var inselection = self.FileBase.selections.entries[abspath];
if (inselection === undefined) {
......@@ -65,8 +63,10 @@ define(["jquery", "jclass"], function($, JClass) {
// to be switched to tap (=single) events
openstring = vispa.device.hasTouch ? "tap" : openstring;
node.on(openstring, function(event) {
// check if event has to be accepted
if ($(event.target).is(".file-selection-p,.file-selection-checkbox")) return;
if (self.FileBase.workflow.currentView.type == "Symbol" && $(event.target).is("span")) return;
event.preventDefault();
event.stopPropagation();
if (self.FileBase.menuitems.menu.hasClass("open")) {
self.FileBase.menuitems.hideMenu();
if (prefOpenstring == "single") {
......@@ -74,7 +74,6 @@ define(["jquery", "jclass"], function($, JClass) {
}
}
if (self.FileBase.workflow.selectmode) {
event.stopPropagation();
self.FileBase.selections.changeSelection(node, true);
} else if ((vispa.device.hasTouch || openstring == "click") && Object.keys(self.FileBase
.selections
......@@ -96,7 +95,6 @@ define(["jquery", "jclass"], function($, JClass) {
self.FileBase.selections.unselectAll();
}
event.preventDefault();
event.stopPropagation();
self.FileBase.menuitems.hideMenu();
self.FileBase.selections.changeSelection(node, true);
});
......@@ -107,7 +105,6 @@ define(["jquery", "jclass"], function($, JClass) {
var self = this;
// ####################################################################
node.on("click tap", ".file-properties", function(event) {
event.stopPropagation();
event.preventDefault();
if (Object.keys(self.FileBase.selections.entries).length > 1) {
return;
......@@ -135,17 +132,20 @@ define(["jquery", "jclass"], function($, JClass) {
setupBkgEvents: function(nodeBkg) {
var self = this;
nodeBkg.on("click tap", function(event) {
// check if event has to be accepted
if (!$(event.target).is(".file-list,.file-content")) return;
if (event.timeStamp == self.lastEvent) {
return;
}
event.preventDefault();
event.stopPropagation();
self.FileBase.selections.unselectAll();
self.FileBase.menuitems.hideMenu();
});
// Don"t use hold menus on touch
var menuOpenString = vispa.device.hasTouch ? "taphold" : "contextmenu";
nodeBkg.on(menuOpenString, function(event) {
// check if event has to be accepted
if (!$(event.target).is(".file-list,.file-content")) return;
self.FileBase.selections.unselectAll();
event.preventDefault();
self.FileBase.menuitems.showMenu(event, "b");
......
define(["jquery", "jclass"], function($, JClass) {
var FileBaseMenuItems = JClass._extend({
init: function(FileBase) {
this.FileBase = FileBase;
......@@ -11,7 +11,7 @@ define(["jquery", "jclass"], function($, JClass) {
y: 36
};
},
makeMenuClickable: function() {
var self = this;
this.menu = $(".file-rightclickmenu", this.FileBase.view.fileContentContainer.parent());
......@@ -19,7 +19,7 @@ define(["jquery", "jclass"], function($, JClass) {
event.preventDefault();
self.hideMenu();
});
var events = ["openFile", "openFolder", "openFolderInNewTab", "rename", "copy", "cut", "remove", "download",
"compress", "info", "select", "createFile", "createFolder", "paste", "upload"
];
......@@ -31,7 +31,7 @@ define(["jquery", "jclass"], function($, JClass) {
});
});
},
getMenuType: function() {
var nNodesSelected = Object.keys(this.FileBase.selections.entries).length;
if (nNodesSelected === 0) {
......@@ -50,22 +50,21 @@ define(["jquery", "jclass"], function($, JClass) {
showMenu: function(event, menuType, position) {
var self = this;
event.preventDefault();
event.stopPropagation();
menuType = menuType === null || menuType === undefined ? this.getMenuType() : menuType;
this.menu.on("contextmenu", function(evt) {
evt.preventDefault();
});
if (menuType === "d") {
self.makeFolderMenu();
} else if (menuType === "f") {
self.makeFileMenu();
} else if (menuType === "b") {
self.makeBkgMenu();
} else if (menuType === "s") {
self.makeSelectionMenu();
}
if ($(window).height() < 300 || $(window).width() < 768) {
position = this.nullPosition;
if (menuType === "d") {
self.makeFolderMenu();
} else if (menuType === "f") {
self.makeFileMenu();
} else if (menuType === "b") {
self.makeBkgMenu();
} else if (menuType === "s") {
self.makeSelectionMenu();
}
if ($(window).height() < 300 || $(window).width() < 768) {
position = this.nullPosition;
}
this.menu.addClass("open");
var submenu = $("ul", this.menu);
......@@ -76,59 +75,59 @@ define(["jquery", "jclass"], function($, JClass) {
top: position.y
});
},
hideMenu: function() {
this.menu.removeClass("open");
},
getContextMenuPostion: function(event, contextMenu) {
var menuPostion = {};
var menuDimension = {};
// store the fileContentContainer fCC
var fCC = this.FileBase.view.fileContentContainer;
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;
if (vispa.device.hasTouch) {
menuPostion.x += 5;
menuPostion.y += 5;
}
// Check if the side borders are reached
//(additional 5 px in the shift are needed to prevent firefox from opening scroll bars)
if (menuPostion.x + menuDimension.x > fCC.width()) {
menuPostion.x = fCC.width() - menuDimension.x - 5;
}
// Check if the lower border is reached
//(additional 5 px in the shift are needed to prevent firefox from opening scroll bars)
if (menuPostion.y + menuDimension.y > fCC.height()) {
menuPostion.y = fCC.height() - menuDimension.y - 5;
}
return menuPostion;
},
makeFileMenu: function() {
this.menu.toggleClass("filemenu", true);
this.menu.toggleClass("foldermenu", false);
this.menu.toggleClass("bkgmenu", false);
this.menu.toggleClass("selectionmenu", false);
},
makeFolderMenu: function() {
this.menu.toggleClass("filemenu", false);
this.menu.toggleClass("foldermenu", true);
this.menu.toggleClass("bkgmenu", false);
this.menu.toggleClass("selectionmenu", false);
},
makeBkgMenu: function() {
this.menu.toggleClass("filemenu", false);
this.menu.toggleClass("foldermenu", false);
......@@ -147,7 +146,7 @@ define(["jquery", "jclass"], function($, JClass) {
$(".paste", this.menu).toggleClass("file-rightclickmenu-itemhide", true);
}
},
makeSelectionMenu: function() {
this.menu.toggleClass("filemenu", false);
this.menu.toggleClass("foldermenu", false);
......
define(["jquery", "jclass", "./bookmark"], function($, JClass, Bookmark) {
var PathBar = JClass._extend({
init: function(FileBase) {
var self = this;
self.FileBase = FileBase;
......@@ -12,7 +12,7 @@ define(["jquery", "jclass", "./bookmark"], function($, JClass, Bookmark) {
this.node = null;
this.tmpl = null;
},
setup: function(node) {
var self = this;
this.node = node;
......@@ -26,7 +26,7 @@ define(["jquery", "jclass", "./bookmark"], function($, JClass, Bookmark) {
self.optionWheel();
});
},
render: function() {
var self = this;
var clicktype = vispa.device.hasTouch ? "tap" : "click";
......@@ -82,7 +82,7 @@ define(["jquery", "jclass", "./bookmark"], function($, JClass, Bookmark) {
self.bookmark.setup(self.node);
});
},
optionWheel: function() {
var self = this;
var clicktype = vispa.device.hasTouch ? "tap" : "click";
......@@ -96,10 +96,13 @@ define(["jquery", "jclass", "./bookmark"], function($, JClass, Bookmark) {
self.FileBase.menuitems.hideMenu();
} else {
self.FileBase.menuitems.showMenu(event, null, position);
// stop propagation and close all other dropdowns manuelly
event.stopPropagation();
$(".open:not(.file-rightclickmenu)").toggleClass("open");
}
});
}
});
return PathBar;
......
......@@ -60,15 +60,15 @@ define(["jquery", "jclass"], function($, JClass) {
}
// make select-all-checkbox clickable
$(".select-all", self.fileContentContainer).click(function() {
setTimeout(function() {
$(this).prop("checked", $(this).prop("checked") ? "" : "checked");
if ($(this).prop("checked")) {
self.FileBase.selections.selectAll();
} else {
self.FileBase.selections.unselectAll();
}
}.bind(this), 0);
$(".select-all", self.fileContentContainer).click(function(event) {
// not intuitive but works
if ($(event.target).prop("checked")) {
self.FileBase.selections.unselectAll();
self.FileBase.selections.selectAll();
$(event.target).prop("checked", "checked");
} else {
self.FileBase.selections.unselectAll();
}
});
// call function for sorting carets
......@@ -144,7 +144,6 @@ define(["jquery", "jclass"], function($, JClass) {
var self = this;
$(".edit-rename", this.fileContentContainer).click(function(event) {
event.stopPropagation();
event.preventDefault();
var node = $(event.currentTarget.parentElement.parentElement);
self.FileBase.selections.unselectAll();
......@@ -153,7 +152,6 @@ define(["jquery", "jclass"], function($, JClass) {
});
$(".edit-download", this.fileContentContainer).click(function(event) {
event.stopPropagation();
event.preventDefault();
var node = $(event.currentTarget.parentElement.parentElement);
self.FileBase.selections.unselectAll();
......@@ -163,7 +161,6 @@ define(["jquery", "jclass"], function($, JClass) {
// sharing not yet implemented
$(".edit-share", this.fileContentContainer).click(function(event) {
event.stopPropagation();
event.preventDefault();
var node = $(event.currentTarget.parentElement.parentElement);
self.FileBase.selections.unselectAll();
......@@ -172,7 +169,6 @@ define(["jquery", "jclass"], function($, JClass) {
});
$(".edit-remove", this.fileContentContainer).click(function(event) {
event.stopPropagation();
event.preventDefault();
var node = $(event.currentTarget.parentElement.parentElement);
self.FileBase.selections.unselectAll();
......
......@@ -6,7 +6,7 @@ define([
"css!../css/base/file-icons",
"css!../css/base/pathbar",
"css!../css/base/views/symbol/symbol",
"css!../css/base/views/table/table",
"css!../css/base/views/table/table"
], function(extensions, FileViews, Shortcuts) {
var FileExtension = extensions.Extension._extend({
......
......@@ -355,22 +355,16 @@ class FileSystem(object):
logger.debug(p)
archive.write(p, ap)
def decompress(self, file):
def decompress(self, path):
# filepath and extract path
filepath = self.expand(file)
path = filepath.rsplit(".zip", 1)[0]
# handle folder collision for extract path
while os.path.exists(path):
end = path.rsplit("/", 1)[1]
if len(end.split("_copy")) is not 1:
counter = int(end.rsplit("_copy", 1)[1])
counter += 1
path = path.rsplit("_copy", 1)[0] + "_copy" + str(counter)
else:
path = path + "_copy1"
path = self.expand(path)
# "foo/bar/file.zip" -> ("foo/bar", "file")
dst = os.path.split(os.path.splitext(path)[0])
with ZipFile(filepath, "r") as archive:
archive.extractall(path)
with ZipFile(path, "r") as archive:
dstdir = os.path.join(dst[0], self.handle_file_name_collision(dst[1], dst[0]))
archive.extractall(dstdir)
def paste(self, path, fullsrc, cut):
# TODO
......
/*!
* @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2014 - 2015
* @package bootstrap-fileinput
* @version 4.1.9
*
* File input styling for Bootstrap 3.0
* Built for Yii Framework 2.0
* Author: Kartik Visweswaran
* Year: 2015
* For more Yii related demos visit http://demos.krajee.com
*/
.file-input {
overflow-x: auto;
}
.file-loading {
top: 0;
right: 0;
width: 25px;
height: 25px;
font-size: 999px;
text-align: right;
color: #fff;
background: transparent url('../img/loading.gif') top left no-repeat;
border: none;
}
.btn-file {
position: relative;
overflow: hidden;
}
.btn-file input[type=file] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
text-align: right;
opacity: 0;
filter: alpha(opacity=0);
opacity: 0;
background: none repeat scroll 0 0 transparent;
cursor: inherit;
display: block;
}
.file-caption .glyphicon {
display: inline-block;
min-width: 18px;
margin-top: 2px;
}
.file-caption-name {
display: inline-block;
overflow: hidden;
max-height: 20px;
padding-right: 10px;
word-break: break-all;
}
.file-caption-ellipsis {
position: absolute;
right: 10px;
margin-top: -6px;
font-size: 1.2em;
display: none;
font-weight: bold;
cursor: default;
}
.kv-has-ellipsis .file-caption-ellipsis {
display: inline;
}
.kv-has-ellipsis {
padding-right: 17px;
}
.kv-search-container .kv-search-clear {
position: absolute;
padding: 10px;
right: 0px;
}
.file-error-message {
background-color: #f2dede;
color: #a94442;
text-align: center;
border-radius: 5px;
padding: 5px;
}
.file-error-message pre, .file-error-message ul {
margin: 5px 0;
text-align: left;
}
.file-caption-disabled {
background-color: #EEEEEE;
cursor: not-allowed;
opacity: 1;
}
.file-input .btn[disabled], .file-input .btn .disabled {
cursor: not-allowed;
}
.file-preview {
border-radius: 5px;
border: 1px solid #ddd;
padding: 5px;
width: 100%;