Drive refactoring

This commit is contained in:
yflory
2017-06-08 17:52:00 +02:00
parent df2b00122a
commit 1c2ea04f11
7 changed files with 570 additions and 542 deletions

View File

@@ -484,6 +484,7 @@ define([
};
var getDate = function (sDate) {
if (!sDate) { return ''; }
var ret = sDate.toString();
try {
var date = new Date(sDate);
@@ -500,12 +501,15 @@ define([
return ret;
};
var openFile = function (fileEl, name) {
if (name) {
sessionStorage[Cryptpad.newPadNameKey] = name;
var openFile = function (el, href) {
if (!href) {
var data = filesOp.getFileData(el);
if (!data || !data.href) {
return void logError("Missing data for the file", el, data);
}
href = data.href;
}
window.open(fileEl);
delete sessionStorage[Cryptpad.newPadNameKey];
window.open(href);
};
var refresh = APP.refresh = function () {
@@ -528,7 +532,8 @@ define([
$name = $element.find('> .element');
}
$name.hide();
var name = path[path.length - 1];
var el = filesOp.find(path);
var name = filesOp.isFile(el) ? filesOp.getTitle(el) : path[path.length - 1];
var $input = $('<input>', {
placeholder: name,
value: name
@@ -933,19 +938,9 @@ define([
};
var getElementName = function (path) {
// Trash root
if (filesOp.isInTrashRoot(path)) { return path[0]; }
// Root or trash
if (filesOp.isPathIn(path, [ROOT, TRASH])) { return path[path.length - 1]; }
// Unsorted or template
if (filesOp.isPathIn(path, ['hrefArray'])) {
var file = filesOp.find(path);
if (filesOp.isFile(file) && filesOp.getTitle(file)) {
return filesOp.getTitle(file);
}
}
// default
return "???";
var file = filesOp.find(path);
if (!file || !filesOp.isFile(file)) { return '???'; }
return filesOp.getTitle(file);
};
// filesOp.moveElements is able to move several paths to a new location, including
// the Trash or the "Unsorted files" folder
@@ -965,8 +960,9 @@ define([
}
var msg = Messages._getKey('fm_removeSeveralDialog', [paths.length]);
if (paths.length === 1) {
var path = paths[0];
var name = path[0] === TEMPLATE ? filesOp.getTitle(filesOp.find(path)) : path[path.length - 1];
var path = paths[0].slice();
var el = filesOp.find(path);
var name = filesOp.isFile(el) ? getElementName(path) : path.pop();
msg = Messages._getKey('fm_removeDialog', [name]);
}
Cryptpad.confirm(msg, function (res) {
@@ -1093,30 +1089,27 @@ define([
// In list mode, display metadata from the filesData object
// _WORKGROUP_ : Do not display title, atime and ctime columns since we don't have files data
var addFileData = function (element, key, $span, displayTitle) {
var addFileData = function (element, $span) {
if (!filesOp.isFile(element)) { return; }
var data = filesOp.getFileData(element);
if (!data) { return void logError("No data for the file", element); }
var name = filesOp.getTitle(element);
// The element with the class '.name' is underlined when the 'li' is hovered
var $name = $('<span>', {'class': 'name', title: key}).text(key);
var $name = $('<span>', {'class': 'name', title: name}).text(name);
$span.html('');
$span.append($name);
if (!filesOp.getFileData(element)) {
return;
}
var hrefData = Cryptpad.parsePadUrl(element);
var data = filesOp.getFileData(element);
var hrefData = Cryptpad.parsePadUrl(data.href);
var type = Messages.type[hrefData.type] || hrefData.type;
var $title = $('<span>', {'class': 'title listElement', title: data.title}).text(data.title);
var $type = $('<span>', {'class': 'type listElement', title: type}).text(type);
if (hrefData.hashData && hrefData.hashData.mode === 'view') {
$type.append(' (' + Messages.readonly+ ')');
}
var $adate = $('<span>', {'class': 'atime listElement', title: getDate(data.atime)}).text(getDate(data.atime));
var $cdate = $('<span>', {'class': 'ctime listElement', title: getDate(data.ctime)}).text(getDate(data.ctime));
if (displayTitle && !isWorkgroup()) {
$span.append($title);
}
$span.append($type);
if (!isWorkgroup()) {
$span.append($adate).append($cdate);
@@ -1135,9 +1128,15 @@ define([
$span.append($name).append($subfolders).append($files);
};
var getFileIcon = function (href) {
var getFileIcon = function (id) {
var $icon = $fileIcon.clone();
var data = filesOp.getFileData(id);
if (!data) { return $icon; }
var href = data.href;
if (!href) { return $icon; }
if (href.indexOf('/pad/') !== -1) { $icon = $padIcon.clone(); }
else if (href.indexOf('/code/') !== -1) { $icon = $codeIcon.clone(); }
else if (href.indexOf('/slide/') !== -1) { $icon = $slideIcon.clone(); }
@@ -1153,7 +1152,7 @@ define([
var isTrash = path[0] === TRASH;
var newPath = path.slice();
var key;
if (isTrash && $.isArray(elPath)) {
if (isTrash && Array.isArray(elPath)) {
key = elPath[0];
elPath.forEach(function (k) { newPath.push(k); });
} else {
@@ -1178,7 +1177,7 @@ define([
if (isFolder) {
addFolderData(element, key, $element);
} else {
addFileData(element, key, $element, true);
addFileData(element, $element);
}
$element.prepend($icon).dblclick(function () {
if (isFolder) {
@@ -1186,7 +1185,7 @@ define([
return;
}
if (isTrash) { return; }
openFile(root[key], key);
openFile(root[key]);
});
$element.addClass(liClass);
$element.data('path', newPath);
@@ -1251,10 +1250,13 @@ define([
if (APP.mobile()) {
return $title;
}
var el = path[0] === SEARCH ? undefined : filesOp.find(path);
path = path[0] === SEARCH ? path.slice(0,1) : path;
path.forEach(function (p, idx) {
if (isTrash && [2,3].indexOf(idx) !== -1) { return; }
var name = p;
var $span = $('<span>', {'class': 'element'});
if (idx < path.length - 1) {
if (!noStyle) {
@@ -1265,9 +1267,10 @@ define([
module.displayDirectory(path.slice(0, sliceEnd));
});
}
} else if (idx > 0 && filesOp.isFile(el)) {
name = getElementName(path);
}
var name = p;
if (idx === 0) { name = getPrettyName(p); }
else { $title.append(' > '); }
@@ -1409,18 +1412,12 @@ define([
$block.find('a.newFolder').click(function () {
filesOp.addFolder(currentPath, null, onCreated);
});
$block.find('a.newdoc').click(function () {
var type = $(this).attr('data-type') || 'pad';
var name = Cryptpad.getDefaultName({type: type});
filesOp.addFile(currentPath, name, type, onCreated);
});
} else {
$block.find('a.newdoc').click(function () {
var type = $(this).attr('data-type') || 'pad';
sessionStorage[Cryptpad.newPadPathKey] = filesOp.isPathIn(currentPath, [TRASH]) ? '' : currentPath;
window.open('/' + type + '/');
});
}
$block.find('a.newdoc').click(function () {
var type = $(this).attr('data-type') || 'pad';
sessionStorage[Cryptpad.newPadPathKey] = filesOp.isPathIn(currentPath, [TRASH]) ? '' : currentPath;
window.open('/' + type + '/');
});
return $block;
};
@@ -1515,62 +1512,39 @@ define([
//var $fihElement = $('<span>', {'class': 'element'}).appendTo($fileHeader);
var $fhIcon = $('<span>', {'class': 'icon'});
var $fhName = $('<span>', {'class': 'name filename clickable'}).text(Messages.fm_fileName).click(onSortByClick);
var $fhTitle = $('<span>', {'class': 'title clickable'}).text(Messages.fm_title).click(onSortByClick);
var $fhType = $('<span>', {'class': 'type clickable'}).text(Messages.fm_type).click(onSortByClick);
var $fhAdate = $('<span>', {'class': 'atime clickable'}).text(Messages.fm_lastAccess).click(onSortByClick);
var $fhCdate = $('<span>', {'class': 'ctime clickable'}).text(Messages.fm_creation).click(onSortByClick);
// If displayTitle is false, it means the "name" is the title, so do not display the "name" header
$fihElement.append($fhIcon);
if (displayTitle || isWorkgroup()) {
$fihElement.append($fhName);
} else {
$fhTitle.width('auto');
}
if (!isWorkgroup()) {
$fihElement.append($fhTitle);
}
$fihElement.append($fhType);
$fihElement.append($fhIcon).append($fhName).append($fhType);
if (!isWorkgroup()) {
$fihElement.append($fhAdate).append($fhCdate);
}
addFileSortIcon($fihElement);
return $fihElement;
//return $fileHeader;
};
var sortElements = function (folder, path, oldkeys, prop, asc, useHref, useData) {
var sortElements = function (folder, path, oldkeys, prop, asc, useId) {
var root = filesOp.find(path);
var test = folder ? filesOp.isFolder : filesOp.isFile;
var keys;
if (!useData) {
keys = oldkeys.filter(function (e) {
return useHref ? test(e) : test(root[e]);
});
} else { keys = oldkeys.slice(); }
var keys = oldkeys.filter(function (e) {
return useId ? test(e) : test(root[e]);
});
if (keys.length < 2) { return keys; }
var mult = asc ? 1 : -1;
var getProp = function (el, prop) {
if (prop) {
var element = useHref || useData ? el : root[el];
var e = useData ? element : filesOp.getFileData(element);
if (!e) {
e = {
href : element,
title : Messages.fm_noname,
atime : 0,
ctime : 0
};
}
if (prop === 'type') {
var hrefData = Cryptpad.parsePadUrl(e.href);
return hrefData.type;
}
if (prop === 'atime' || prop === 'ctime') {
return new Date(e[prop]);
}
return e && e.title ? e.title.toLowerCase() : '';
if (folder) { return el.toLowerCase(); }
var id = useId ? el : root[el];
var data = filesOp.getFileData(id);
if (!data) { return ''; }
if (prop === 'type') {
var hrefData = Cryptpad.parsePadUrl(data.href);
return hrefData.type;
}
return useData ? el.title.toLowerCase() : el.toLowerCase();
if (prop === 'atime' || prop === 'ctime') {
return new Date(data[prop]);
}
return filesOp.getTitle(id).toLowerCase();
};
keys.sort(function(a, b) {
if (getProp(a, prop) < getProp(b, prop)) { return mult * -1; }
@@ -1580,7 +1554,6 @@ define([
return keys;
};
var sortTrashElements = function (folder, oldkeys, prop, asc) {
//var root = files[TRASH];
var test = folder ? filesOp.isFolder : filesOp.isFile;
var keys = oldkeys.filter(function (e) {
return test(e.element);
@@ -1606,7 +1579,6 @@ define([
if (prop === 'atime' || prop === 'ctime') {
return new Date(e[prop]);
}
return e.title.toLowerCase();
}
return el.name.toLowerCase();
};
@@ -1638,27 +1610,27 @@ define([
$container.append($fileHeader);
var keys = unsorted;
var sortBy = Cryptpad.getLSAttribute(SORT_FILE_BY);
sortBy = sortBy === "" ? sortBy = 'title' : sortBy;
sortBy = sortBy === "" ? sortBy = 'name' : sortBy;
var sortedFiles = sortElements(false, [rootName], keys, sortBy, !getSortFileDesc(), true);
sortedFiles.forEach(function (href) {
var file = filesOp.getFileData(href);
sortedFiles.forEach(function (id) {
var file = filesOp.getFileData(id);
if (!file) {
//debug("Unsorted or template returns an element not present in filesData: ", href);
file = { title: Messages.fm_noname };
//return;
}
var idx = files[rootName].indexOf(href);
var $icon = getFileIcon(href);
var ro = filesOp.isReadOnlyFile(href);
var idx = files[rootName].indexOf(id);
var $icon = getFileIcon(id);
var ro = filesOp.isReadOnlyFile(id);
// ro undefined mens it's an old hash which doesn't support read-only
var roClass = typeof(ro) === 'undefined' ? ' noreadonly' : ro ? ' readonly' : '';
var $element = $('<li>', {
'class': 'file-element element element-row' + roClass,
draggable: draggable
});
addFileData(href, file.title, $element, false);
addFileData(id, $element);
$element.prepend($icon).dblclick(function () {
openFile(href);
openFile(id);
});
var path = [rootName, idx];
$element.data('path', path);
@@ -1680,20 +1652,20 @@ define([
if (allfiles.length === 0) { return; }
var $fileHeader = getFileListHeader(false);
$container.append($fileHeader);
var keys = allfiles;
var sortedFiles = sortElements(false, [FILES_DATA], keys, Cryptpad.getLSAttribute(SORT_FILE_BY), !getSortFileDesc(), false, true);
sortedFiles.forEach(function (file) {
var $icon = getFileIcon(file.href);
var ro = filesOp.isReadOnlyFile(file.href);
// ro undefined mens it's an old hash which doesn't support read-only
var keys = filesOp.getFiles([FILES_DATA]);
var sortedFiles = sortElements(false, [FILES_DATA], keys, Cryptpad.getLSAttribute(SORT_FILE_BY), !getSortFileDesc(), true);
sortedFiles.forEach(function (id) {
var file = filesOp.getFileData(id);
var $icon = getFileIcon(id);
var ro = filesOp.isReadOnlyFile(id);
// ro undefined maens it's an old hash which doesn't support read-only
var roClass = typeof(ro) === 'undefined' ? ' noreadonly' : ro ? ' readonly' : '';
var $element = $('<li>', { 'class': 'file-element element element-row' + roClass });
addFileData(file.href, file.title, $element, false);
$element.data('path', [FILES_DATA, allfiles.indexOf(file)]);
$element.data('element', file.href);
addFileData(id, $element);
$element.data('path', [FILES_DATA, id]);
$element.data('element', id);
$element.prepend($icon).dblclick(function () {
openFile(file.href);
openFile(id);
});
$element.click(function(e) {
e.stopPropagation();
@@ -1709,24 +1681,18 @@ define([
var filesList = [];
var root = files[TRASH];
// Elements in the trash are JS arrays (several elements can have the same name)
[true,false].forEach(function (folder) {
var testElement = filesOp.isFile;
if (!folder) {
testElement = filesOp.isFolder;
Object.keys(root).forEach(function (key) {
if (!Array.isArray(root[key])) {
logError("Trash element has a wrong type", root[key]);
return;
}
Object.keys(root).forEach(function (key) {
if (!$.isArray(root[key])) {
logError("Trash element has a wrong type", root[key]);
return;
}
root[key].forEach(function (el, idx) {
if (testElement(el.element)) { return; }
var spath = [key, idx, 'element'];
filesList.push({
element: el.element,
spath: spath,
name: key
});
root[key].forEach(function (el, idx) {
if (!filesOp.isFile(el.element) && !filesOp.isFolder(el.element)) { return; }
var spath = [key, idx, 'element'];
filesList.push({
element: el.element,
spath: spath,
name: key
});
});
});
@@ -1752,8 +1718,9 @@ define([
var parsed = Cryptpad.parsePadUrl(href);
var $table = $('<table>');
var $icon = $('<td>', {'rowspan': '3', 'class': 'icon'}).append(getFileIcon(href));
var $title = $('<td>', {'class': 'col1 title'}).text(r.data.title).click(function () {
openFile(r.data.href);
var $title = $('<td>', {'class': 'col1 title'}).text(r.data.title)
.click(function () {
openFile(null, r.data.href);
});
var $typeName = $('<td>', {'class': 'label2'}).text(Messages.fm_type);
var $type = $('<td>', {'class': 'col2'}).text(Messages.type[parsed.type] || parsed.type);
@@ -2141,29 +2108,12 @@ define([
};
var stringifyPath = function (path) {
if (!$.isArray(path)) { return; }
var rootName = function (s) {
var prettyName;
switch (s) {
case ROOT:
prettyName = ROOT_NAME;
break;
case FILES_DATA:
prettyName = FILES_DATA_NAME;
break;
case TRASH:
prettyName = TRASH_NAME;
break;
default:
prettyName = s;
}
return prettyName;
};
if (!Array.isArray(path)) { return; }
var $div = $('<div>');
var i = 0;
var space = 10;
path.forEach(function (s) {
if (i === 0) { s = rootName(s); }
if (i === 0) { s = getPrettyName(s); }
$div.append($('<span>', {'style': 'margin: 0 0 0 ' + i * space + 'px;'}).text(s));
$div.append($('<br>'));
i++;
@@ -2171,11 +2121,15 @@ define([
return $div.html();
};
var getReadOnlyUrl = APP.getRO = function (href) {
if (!filesOp.isFile(href)) { return; }
var i = href.indexOf('#') + 1;
var parsed = Cryptpad.parsePadUrl(href);
var base = href.slice(0, i);
var getReadOnlyUrl = APP.getRO = function (id) {
if (!filesOp.isFile(id)) { return; }
var data = filesOp.getFileData(id);
if (!data) { return; }
var parsed = Cryptpad.parsePadUrl(data.href);
if (parsed.hashData.type !== "pad") { return; }
var origin = window.location.origin;
var i = data.href.indexOf('#') + 1;
var base = origin + data.href.slice(0, i);
var hrefsecret = Cryptpad.getSecrets(parsed.type, parsed.hash);
if (!hrefsecret.keys) { return; }
var viewHash = Cryptpad.getViewHashFromKeys(hrefsecret.channel, hrefsecret.keys);
@@ -2199,16 +2153,21 @@ define([
var base = window.location.origin;
var $d = $('<div>');
$('<strong>').text(Messages.fc_prop).appendTo($d);
var data = filesOp.getFileData(el);
if (!data || !data.href) { return void cb(void 0, $d); }
$('<br>').appendTo($d);
if (!ro) {
$('<label>', {'for': 'propLink'}).text(Messages.editShare).appendTo($d);
$('<input>', {'id': 'propLink', 'readonly': 'readonly', 'value': base + el})
$('<input>', {'id': 'propLink', 'readonly': 'readonly', 'value': base + data.href})
.click(function () { $(this).select(); })
.appendTo($d);
}
var parsed = Cryptpad.parsePadUrl(el);
var parsed = Cryptpad.parsePadUrl(data.href);
if (parsed.hashData && parsed.hashData.type === 'pad') {
var roLink = ro ? base + el : getReadOnlyUrl(base + el);
var roLink = ro ? base + data.href : getReadOnlyUrl(el);
if (roLink) {
$('<label>', {'for': 'propROLink'}).text(Messages.viewShare).appendTo($d);
$('<input>', {'id': 'propROLink', 'readonly': 'readonly', 'value': roLink})
@@ -2219,7 +2178,8 @@ define([
if (APP.loggedIn && AppConfig.enablePinning) {
// check the size of this file...
Cryptpad.getFileSize(el, function (e, bytes) {
console.log(data.href);
Cryptpad.getFileSize(data.href, function (e, bytes) {
if (e) {
// there was a problem with the RPC
logError(e);
@@ -2282,7 +2242,7 @@ define([
var el = filesOp.find(p.path);
if (filesOp.isFolder(el)) { return; }
var roUrl = getReadOnlyUrl(el);
openFile(roUrl, false);
openFile(null, roUrl);
});
}
else if ($(this).hasClass('newfolder')) {
@@ -2326,7 +2286,7 @@ define([
if (filesOp.isPathIn(p.path, [FILES_DATA])) { el = el.href; }
if (!el || filesOp.isFolder(el)) { return; }
var roUrl = getReadOnlyUrl(el);
openFile(roUrl, false);
openFile(null, roUrl);
});
}
else if ($(this).hasClass('delete')) {
@@ -2376,8 +2336,8 @@ define([
}
else if ($(this).hasClass("newdoc")) {
var type = $(this).data('type') || 'pad';
var name = Cryptpad.getDefaultName({type: type});
filesOp.addFile(path, name, type, onCreated);
sessionStorage[Cryptpad.newPadPathKey] = filesOp.isPathIn(currentPath, [TRASH]) ? '' : currentPath;
window.open('/' + type + '/');
}
module.hideMenu();
});
@@ -2577,8 +2537,10 @@ define([
atime: new Date().toISOString(),
ctime: new Date().toISOString()
};
filesOp.pushData(data);
filesOp.add(data);
filesOp.pushData(data, function (e, id) {
if (e) { return void console.error("Error while creating the default pad:", e); } // TODO LIMIT?
filesOp.add(id);
});
if (typeof(cb) === "function") { cb(); }
});
delete sessionStorage.createReadme;