diff --git a/www/file/fileObject.js b/www/file/fileObject.js index 1f98171c9..3f51d7b98 100644 --- a/www/file/fileObject.js +++ b/www/file/fileObject.js @@ -21,6 +21,7 @@ define([ var log = config.log || logging; var logError = config.logError || logging; var debug = config.debug || logging; + var workgroup = config.workgroup; var exp = {}; @@ -241,6 +242,9 @@ define([ }; var checkDeletedFiles = function () { + // Nothing in FILES_DATA for workgroups + if (workgroup) { return; } + var rootFiles = getRootFiles(); var unsortedFiles = getUnsortedFiles(); var templateFiles = getTemplateFiles(); @@ -324,6 +328,7 @@ define([ // Data from filesData var getTitle = exp.getTitle = function (href) { + if (workgroup) { debug("No titles in workgroups"); return; } var data = getFileData(href); if (!href || !data) { error("getTitle called with a non-existing href: ", href); @@ -458,6 +463,21 @@ define([ if(cb) { cb(); } }; + // Import elements in the file manager + var importElements = exp.importElements = function (elements, path, cb) { + if (!elements || elements.length === 0) { return; } + console.log(elements); + var newParent = findElement(files, path); + if (!newParent) { debug("Trying to import elements into a non-existing folder"); return; } + elements.forEach(function (e) { + var el = e.el; + var key = e.name; + if (!key) { key = "???"; } // Should not happen... + newParent[key] = el; + }); + if(cb) { cb(); } + }; + var createNewFolder = exp.createNewFolder = function (folderPath, name, cb) { var parentEl = findElement(files, folderPath); var folderName = getAvailableName(parentEl, name || NEW_FOLDER_NAME); @@ -579,6 +599,7 @@ define([ var forgetPad = exp.forgetPad = function (href) { + if (workgroup) { return; } var rootFiles = getRootFiles().slice(); if (rootFiles.indexOf(href) !== -1) { removeFileFromRoot(files[ROOT], href); @@ -592,6 +613,7 @@ define([ }; var addUnsortedPad = exp.addPad = function (href, path, name) { + if (workgroup) { return; } var unsortedFiles = getUnsortedFiles(); var rootFiles = getRootFiles(); var trashFiles = getTrashFiles(); @@ -620,6 +642,7 @@ define([ // addTemplate is called when we want to add a new pad, never visited, to the templates list // first, we must add it to FILES_DATA, so the input has to be an fileDAta object var addTemplate = exp.addTemplate = function (fileData) { + if (workgroup) { return; } if (typeof fileData !== "object" || !fileData.href || !fileData.title) { return; } var href = fileData.href; @@ -635,6 +658,7 @@ define([ }; var listTemplates = exp.listTemplates = function (type) { + if (workgroup) { return; } var templateFiles = getTemplateFiles(); var res = []; templateFiles.forEach(function (f) { @@ -664,13 +688,11 @@ define([ var before = JSON.stringify(files); - if (typeof(files[ROOT]) !== "object") { debug("ROOT was not an object"); files[ROOT] = {}; } - if (typeof(files[TRASH]) !== "object") { debug("TRASH was not an object"); files[TRASH] = {}; } - if (!$.isArray(files[FILES_DATA])) { debug("FILES_DATA was not an array"); files[FILES_DATA] = []; } - if (!$.isArray(files[UNSORTED])) { debug("UNSORTED was not an array"); files[UNSORTED] = []; } - if (!$.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; } + + var fixRoot = function (element) { + if (typeof(files[ROOT]) !== "object") { debug("ROOT was not an object"); files[ROOT] = {}; } for (var el in element) { if (!isFile(element[el]) && !isFolder(element[el])) { debug("An element in ROOT was not a folder nor a file. ", element[el]); @@ -681,9 +703,8 @@ define([ } } }; - fixRoot(files[ROOT]); - var fixTrashRoot = function (tr) { + if (typeof(files[TRASH]) !== "object") { debug("TRASH was not an object"); files[TRASH] = {}; } var toClean; var addToClean = function (obj, idx) { if (typeof(obj) !== "object") { toClean.push(idx); return; } @@ -704,9 +725,8 @@ define([ } } }; - fixTrashRoot(files[TRASH]); - var fixUnsorted = function (us) { + if (!$.isArray(files[UNSORTED])) { debug("UNSORTED was not an array"); files[UNSORTED] = []; } var rootFiles = getRootFiles().slice(); var templateFiles = getTemplateFiles(); var toClean = []; @@ -722,10 +742,8 @@ define([ } }); }; - files[UNSORTED] = uniq(files[UNSORTED]); - fixUnsorted(files[UNSORTED]); - var fixTemplate = function (us) { + if (!$.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; } var rootFiles = getRootFiles().slice(); var unsortedFiles = getUnsortedFiles(); var toClean = []; @@ -741,10 +759,8 @@ define([ } }); }; - files[TEMPLATE] = uniq(files[TEMPLATE]); - fixUnsorted(files[TEMPLATE]); - var fixFilesData = function (fd) { + if (!$.isArray(files[FILES_DATA])) { debug("FILES_DATA was not an array"); files[FILES_DATA] = []; } var rootFiles = getRootFiles(); var unsortedFiles = getUnsortedFiles(); var trashFiles = getTrashFiles(); @@ -769,7 +785,16 @@ define([ } }); }; - fixFilesData(files[FILES_DATA]); + + fixRoot(files[ROOT]); + fixTrashRoot(files[TRASH]); + if (!workgroup) { + files[UNSORTED] = uniq(files[UNSORTED]); + fixUnsorted(files[UNSORTED]); + files[TEMPLATE] = uniq(files[TEMPLATE]); + fixTemplate(files[TEMPLATE]); + fixFilesData(files[FILES_DATA]); + } if (JSON.stringify(files) !== before) { debug("Your file system was corrupted. It has been cleaned so that the pads you visit can be stored safely"); diff --git a/www/file/main.js b/www/file/main.js index 8308b58f9..b7e4f5c21 100644 --- a/www/file/main.js +++ b/www/file/main.js @@ -28,6 +28,10 @@ define([ Cryptpad: Cryptpad }; + var stringify = APP.stringify = function (obj) { + return JSONSortify(obj); + }; + var ROOT = "root"; var ROOT_NAME = Messages.fm_rootName; var UNSORTED = "unsorted"; @@ -140,6 +144,11 @@ define([ }; var init = function (files) { + var ownFileManager = function () { + return Cryptpad.getUserHash() === APP.hash || localStorage.FS_hash === APP.hash; + }; + config.workgroup = !ownFileManager(); + var filesOp = FO.init(files, config); filesOp.fixFiles(); @@ -242,10 +251,6 @@ define([ } }; - var ownFileManager = function () { - return Cryptpad.getUserHash() === APP.hash || localStorage.FS_hash === APP.hash; - }; - var removeSelected = function () { $iframe.find('.selected').removeClass("selected"); }; @@ -454,6 +459,25 @@ define([ return false; }; + var getElementName = function (path) { + // Trash root + if (filesOp.isInTrashRoot(path)) { + return path[0]; + } + // Root or trash + if (filesOp.isPathInRoot(path) || filesOp.isPathInTrash(path)) { + return path[path.length - 1]; + } + // Unsorted or template + if (filesOp.isPathInUnsorted(path) || filesOp.isPathInTemplate(path)) { + var file = filesOp.findElement(files, path); + if (filesOp.isFile(file) && filesOp.getTitle(file)) { + return filesOp.getTitle(file); + } + } + // default + return "???"; + }; // filesOp.moveElements is able to move several paths to a new location, including // the Trash or the "Unsorted files" folder var moveElements = function (paths, newPath, force, cb) { @@ -485,19 +509,36 @@ define([ if ($element.hasClass('selected')) { var $selected = $iframe.find('.selected'); $selected.each(function (idx, elmt) { - if ($(elmt).data('path')) { - paths.push($(elmt).data('path')); + var ePath = $(elmt).data('path'); + if (ePath) { + var val = filesOp.findElement(files, ePath); + if (!val) { return; } // Error? A ".selected" element in not in the object + paths.push({ + path: ePath, + value: { + name: getElementName(ePath), + el: val + } + }); } }); } else { removeSelected(); $element.addClass('selected'); - paths = [path]; + var val = filesOp.findElement(files, path); + if (!val) { return; } // The element in not in the object + paths = [{ + path: path, + value: { + name: getElementName(path), + el: val + } + }]; } var data = { 'path': paths }; - ev.dataTransfer.setData("text", JSON.stringify(data)); + ev.dataTransfer.setData("text", stringify(data)); }; var onDrop = function (ev) { @@ -505,9 +546,30 @@ define([ $iframe.find('.droppable').removeClass('droppable'); var data = ev.dataTransfer.getData("text"); var oldPaths = JSON.parse(data).path; + if (!oldPaths) { return; } + + // Dropped elements can be moved from the same file manager or imported from another one. + // A moved element should be removed from its previous location + var movedPaths = []; + var importedElements = []; + oldPaths.forEach(function (p) { + var el = filesOp.findElement(files, p.path); + if (el && (stringify(el) === stringify(p.value.el) || !p.value || !p.value.el)) { + movedPaths.push(p.path); + } else { + importedElements.push(p.value); + } + }); + var newPath = $(ev.target).data('path') || $(ev.target).parent('li').data('path'); - if (!oldPaths || !oldPaths.length || !newPath) { return; } - moveElements(oldPaths, newPath, null, refresh); + console.log(newPath); + if (!newPath) { return; } + if (movedPaths && movedPaths.length) { + moveElements(movedPaths, newPath, null, refresh); + } + if (importedElements && importedElements.length) { + filesOp.importElements(importedElements, newPath, refresh); + } }; var addDragAndDropHandlers = function ($element, path, isFolder, droppable) { @@ -569,10 +631,13 @@ define([ var $type = $('', {'class': 'type listElement', title: type}).text(type); var $adate = $('', {'class': 'atime listElement', title: getDate(data.atime)}).text(getDate(data.atime)); var $cdate = $('', {'class': 'ctime listElement', title: getDate(data.ctime)}).text(getDate(data.ctime)); - if (displayTitle) { + if (displayTitle && ownFileManager()) { $span.append($title); } - $span.append($type).append($adate).append($cdate); + $span.append($type); + if (ownFileManager()) { + $span.append($adate).append($cdate); + } }; var addFolderData = function (element, key, $span) { @@ -876,10 +941,13 @@ define([ var $fhAdate = $('', {'class': 'atime'}).text(Messages.fm_lastAccess).click(onSortByClick); var $fhCdate = $('', {'class': 'ctime'}).text(Messages.fm_creation).click(onSortByClick); $fihElement.append($fhName); - if (displayTitle) { + if (displayTitle && ownFileManager()) { $fihElement.append($fhTitle); } - $fihElement.append($fhType).append($fhAdate).append($fhCdate); + $fihElement.append($fhType); + if (ownFileManager()) { + $fihElement.append($fhAdate).append($fhCdate); + } addFileSortIcon($fihElement); return $fileHeader; }; @@ -1049,6 +1117,13 @@ define([ // NOTE: Elements in the trash are not using the same storage structure as the others var displayDirectory = module.displayDirectory = function (path, force) { if (!appStatus.isReady && !force) { return; } + // Only Trash and Root are available in not-owned files manager + if (!ownFileManager() && !filesOp.isPathInTrash(path) && !filesOp.isPathInRoot(path)) { + log("TRANSLATE or REMOVE: Unable to open the selected category, displaying root"); //TODO translate + currentPath = [ROOT]; + displayDirectory(currentPath); + return; + } appStatus.ready(false); currentPath = path; $content.html(""); @@ -1274,9 +1349,11 @@ define([ var resetTree = module.resetTree = function () { $tree.html(''); createTree($tree, [ROOT]); - createUnsorted($tree, [UNSORTED]); - createTemplate($tree, [TEMPLATE]); - createAllFiles($tree, [FILES_DATA]); + if (ownFileManager()) { + createUnsorted($tree, [UNSORTED]); + createTemplate($tree, [TEMPLATE]); + createAllFiles($tree, [FILES_DATA]); + } createTrash($tree, [TRASH]); }; @@ -1518,7 +1595,7 @@ define([ // don't initialize until the store is ready. Cryptpad.ready(function () { - var storeObj = Cryptpad.getStore().getProxy && Cryptpad.getStore().getProxy().proxy ? Cryptpad.getStore().getProxy() : undefined; + var storeObj = Cryptpad.getStore().getProxy && Cryptpad.getStore().getProxy().proxy ? Cryptpad.getStore().getProxy() : undefined; Cryptpad.styleAlerts(); @@ -1528,7 +1605,7 @@ define([ APP.homePageIframe = true; } - var hash = Cryptpad.getUserHash() || window.location.hash.slice(1) || localStorage.FS_hash; + var hash = window.location.hash.slice(1) || Cryptpad.getUserHash() || localStorage.FS_hash; var secret = Cryptpad.getSecrets(hash); var readOnly = APP.readOnly = secret.keys && !secret.keys.editKeyStr; @@ -1539,12 +1616,11 @@ define([ readOnly: readOnly, validateKey: secret.keys.validateKey || undefined, crypto: Crypto.createEncryptor(secret.keys), - logging: false, - logLevel: 1, + logging: false }; var proxy; - if (storeObj) { proxy = storeObj.proxy; } + if (storeObj && !window.location.hash.slice(1)) { proxy = storeObj.proxy; } else { var rt = window.rt = module.rt = Listmap.create(listmapConfig); proxy = rt.proxy; @@ -1621,7 +1697,7 @@ define([ Cryptpad.alert(Messages.common_connectionLost); }; - if (storeObj) { + if (storeObj && !window.location.hash) { onCreate(storeObj.info); onReady(); } else {