Fix the list, find the unsorted files, ability to add a folder
parent
cfe3d38197
commit
43d93938c3
|
@ -12,7 +12,8 @@ html, body {
|
|||
}
|
||||
|
||||
.fa {
|
||||
width: 17px;
|
||||
min-width: 17px;
|
||||
margin-right: 3px;
|
||||
font-family: FontAwesome;
|
||||
}
|
||||
|
||||
|
@ -168,9 +169,10 @@ li {
|
|||
overflow: auto;
|
||||
}
|
||||
|
||||
.changeViewModeContainer {
|
||||
.topButtonContainer {
|
||||
border: 1px solid #ccc;
|
||||
float: right;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.parentFolder {
|
||||
|
@ -183,10 +185,10 @@ li {
|
|||
}
|
||||
|
||||
#folderContent {
|
||||
/*display: inline-block;*/
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#content li:hover .name {
|
||||
#content li:hover:not(.header) .name {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
@ -215,20 +217,63 @@ li {
|
|||
display: flex;
|
||||
flex-flow: row;
|
||||
align-items: center;
|
||||
padding-right: 0px;
|
||||
}
|
||||
#content .list li .element {
|
||||
display: inline-flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#content .list li.file-header {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#content .list li.header {
|
||||
cursor: default;
|
||||
color: #008;
|
||||
}
|
||||
#content .list li.header .element span {
|
||||
border-right: 1px solid #CCC;
|
||||
text-align: left;
|
||||
}
|
||||
#content .list li.header span.name {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#content .list .element span {
|
||||
margin-right: 20px;
|
||||
padding: 0px 10px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#content .list .element span.name {
|
||||
flex: 1;
|
||||
}
|
||||
#content .list .element span.date {
|
||||
width: 120px;
|
||||
width: 150px;
|
||||
}
|
||||
#content .list .element span.title {
|
||||
width: 250px;
|
||||
padding-right: 0px;
|
||||
border-right: 10px solid rgba(0, 0, 0, 0);
|
||||
}
|
||||
#content .list .element span.folders {
|
||||
width: 150px;
|
||||
}
|
||||
#content .list .element span.files {
|
||||
width: 150px;
|
||||
}
|
||||
#content div.grid .listElement {
|
||||
display: none;
|
||||
}
|
||||
@media screen and (max-width: 1000px) {
|
||||
#content .list .element span.title {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1001px) {
|
||||
#content .list .element span.title {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
231
www/file/main.js
231
www/file/main.js
|
@ -40,6 +40,8 @@ define([
|
|||
var LOCALSTORAGE_VIEWMODE = "cryptpad-file-viewMode";
|
||||
var FOLDER_CONTENT_ID = "folderContent";
|
||||
|
||||
var NEW_FOLDER_NAME = "New folder"; //TODO translate
|
||||
|
||||
var files = module.files = {
|
||||
root: {
|
||||
"Directory 1": {
|
||||
|
@ -82,12 +84,7 @@ define([
|
|||
"#hash_c": {
|
||||
ctime: "Tue Nov 08 2016 16:34:21 GMT+0100 (CET)",
|
||||
atime: "Sun Nov 06 2016 12:34:21 GMT+0100 (CET)",
|
||||
title: "Pad C With A Long Title"
|
||||
},
|
||||
"#hash_d": {
|
||||
ctime: "Tue Nov 08 2016 16:30:21 GMT+0100 (CET)",
|
||||
atime: "Tue Nov 08 2016 12:30:21 GMT+0100 (CET)",
|
||||
title: "Pad D"
|
||||
title: "Pad C With A Very Very Very Long Title"
|
||||
},
|
||||
"#hash_e": {
|
||||
ctime: "Tue Nov 08 2016 16:26:21 GMT+0100 (CET)",
|
||||
|
@ -143,6 +140,26 @@ define([
|
|||
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
|
||||
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
|
||||
title: "Code C"
|
||||
},
|
||||
"#hash_1": {
|
||||
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
|
||||
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
|
||||
title: "Code C"
|
||||
},
|
||||
"#hash_2": {
|
||||
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
|
||||
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
|
||||
title: "Code C"
|
||||
},
|
||||
"#hash_3": {
|
||||
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
|
||||
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
|
||||
title: "Code C"
|
||||
},
|
||||
"#hash_4": {
|
||||
ctime: "Tue Nov 08 2016 16:42:21 GMT+0100 (CET)",
|
||||
atime: "Tue Nov 08 2016 12:42:21 GMT+0100 (CET)",
|
||||
title: "Code C"
|
||||
}
|
||||
},
|
||||
trash: {
|
||||
|
@ -238,6 +255,7 @@ define([
|
|||
var $folderOpenedEmptyIcon = $('<span>', {"class": "fa fa-folder-open-o folder"});
|
||||
var $fileIcon = $('<span>', {"class": "fa fa-file file"});
|
||||
var $upIcon = $('<span>', {"class": "fa fa-arrow-circle-up"});
|
||||
var $unsortedIcon = $('<span>', {"class": "fa fa-files-o"});
|
||||
var $trashIcon = $('<span>', {"class": "fa fa-trash"});
|
||||
var $trashEmptyIcon = $('<span>', {"class": "fa fa-trash-o"});
|
||||
var $collapseIcon = $('<span>', {"class": "fa fa-minus-square-o expcol"});
|
||||
|
@ -284,14 +302,22 @@ define([
|
|||
|
||||
var hasSubfolder = function (element) {
|
||||
if (typeof(element) !== "object") { return false; }
|
||||
var subfolder = false;
|
||||
var subfolder = 0;
|
||||
for (var f in element) {
|
||||
subfolder = isFolder(element[f]);
|
||||
if (subfolder) { break; }
|
||||
subfolder += isFolder(element[f]) ? 1 : 0;
|
||||
}
|
||||
return subfolder;
|
||||
};
|
||||
|
||||
var hasFile = function (element) {
|
||||
if (typeof(element) !== "object") { return false; }
|
||||
var file = 0;
|
||||
for (var f in element) {
|
||||
file += isFile(element[f]) ? 1 : 0;
|
||||
}
|
||||
return file;
|
||||
};
|
||||
|
||||
var isSubpath = function (path, parentPath) {
|
||||
var pathA = parentPath.slice();
|
||||
var pathB = path.slice(0, pathA.length);
|
||||
|
@ -309,6 +335,47 @@ define([
|
|||
return newName;
|
||||
};
|
||||
|
||||
var compareFiles = function (fileA, fileB) {
|
||||
return fileA === fileB;
|
||||
};
|
||||
var isInTree = function (file, root) {
|
||||
if (isFile(root)) {
|
||||
return compareFiles(file, root);
|
||||
}
|
||||
var inTree = false;
|
||||
for (var e in root) {
|
||||
inTree = isInTree(file, root[e]);
|
||||
if (inTree) { break; }
|
||||
};
|
||||
return inTree;
|
||||
};
|
||||
var isInTrash = function (file) {
|
||||
var inTrash = false;
|
||||
var root = files[TRASH];
|
||||
for (var e in root) {
|
||||
if (!$.isArray(root[e])) { return; } //TODO error
|
||||
root[e].some(function (trashEl, idx) {
|
||||
inTrash = isInTree(file, trashEl.element);
|
||||
return inTrash;
|
||||
});
|
||||
if (inTrash) { break; }
|
||||
}
|
||||
return inTrash;
|
||||
};
|
||||
var getUnsortedFiles = function () {
|
||||
var filesData = Object.keys(files[FILES_DATA]);
|
||||
var unsorted = [];
|
||||
filesData.forEach(function (file) {
|
||||
if (!isInTree(file, files[ROOT]) && !isInTrash(file)) {
|
||||
unsorted.push(file);
|
||||
}
|
||||
});
|
||||
return unsorted;
|
||||
};
|
||||
var getSortedFiles = function () {
|
||||
console.log('get sorted files, not implemented yet');
|
||||
};
|
||||
|
||||
var compareDays = function (date1, date2) {
|
||||
var day1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate());
|
||||
var day2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate());
|
||||
|
@ -388,6 +455,16 @@ define([
|
|||
module.displayDirectory(newParentPath);
|
||||
};
|
||||
|
||||
var createNewFolder = function (folderPath, name) {
|
||||
var parentEl = findElement(files, folderPath);
|
||||
var folderName = getAvailableName(parentEl, name || NEW_FOLDER_NAME);
|
||||
parentEl[folderName] = {};
|
||||
var newPath = folderPath.slice();
|
||||
newPath.push(folderName);
|
||||
module.newFolder = newPath;
|
||||
displayDirectory(currentPath);
|
||||
};
|
||||
|
||||
// Move to trash
|
||||
var removeElement = function (path, displayTrash) {
|
||||
if (!path || path.length < 2 || path[0] !== ROOT) { return; }
|
||||
|
@ -421,8 +498,9 @@ define([
|
|||
});
|
||||
};
|
||||
|
||||
// Delete permanently
|
||||
var removeFromTrashArray = function (element, name) {
|
||||
var array = files.trash[name];
|
||||
var array = files[TRASH][name];
|
||||
if (!array || !$.isArray(array)) { return; }
|
||||
// Remove the element from the trash array
|
||||
var index = array.indexOf(element);
|
||||
|
@ -431,7 +509,7 @@ define([
|
|||
}
|
||||
// Remove the array is empty to have a cleaner object in chainpad
|
||||
if (array.length === 0) {
|
||||
delete files.trash[name];
|
||||
delete files[TRASH][name];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -473,7 +551,7 @@ define([
|
|||
};
|
||||
|
||||
var emptyTrash = function () {
|
||||
files.trash = {};
|
||||
files[TRASH] = {};
|
||||
module.displayDirectory(currentPath);
|
||||
};
|
||||
|
||||
|
@ -595,22 +673,17 @@ define([
|
|||
|
||||
var openContextMenu = function (e) {
|
||||
module.hideMenu();
|
||||
onElementClick($(e.target));
|
||||
e.stopPropagation();
|
||||
var path = $(e.target).data('path') || $(e.target).parent('li').data('path');
|
||||
var path = $(e.target).closest('li').data('path');
|
||||
if (!path) { return; }
|
||||
$contextMenu.css({
|
||||
display: "block",
|
||||
left: e.pageX,
|
||||
top: e.pageY
|
||||
});
|
||||
var $element = $(e.target);
|
||||
// $element should be the <span class="element">, find it if it's not the case
|
||||
if ($element.is('li')) {
|
||||
$element = $element.children('span.element');
|
||||
} else if (!$element.is('.element')) {
|
||||
$element = $element.parent('li').children('span.element');
|
||||
}
|
||||
var $element = $(e.target).closest('li').children('span.element');
|
||||
onElementClick($element);
|
||||
if (!$element.length) {
|
||||
console.error("Unable to locate the .element tag", e.target);
|
||||
$contextMenu.hide();
|
||||
|
@ -699,26 +772,42 @@ define([
|
|||
$element.removeClass('droppable');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var displayUnsorted = function () {
|
||||
//TODO UNSORTED
|
||||
};
|
||||
|
||||
var addFileData = function (parentPath, key, $span) {
|
||||
var parentEl = findElement(files, parentPath);
|
||||
if (!parentEl || !parentEl[key] || !isFile(parentEl[key])) { return; }
|
||||
var element = parentEl[key];
|
||||
|
||||
// The element with the class '.name' is underlined when the 'li' is hovered
|
||||
var $name = $('<span>', {'class': 'name', title: key}).text(key);
|
||||
$span.html('');
|
||||
$span.append($name);
|
||||
|
||||
if (typeof(files[FILES_DATA][element]) === "undefined") {
|
||||
return;
|
||||
}
|
||||
var data = files[FILES_DATA][element];
|
||||
var $title = $('<span>', {'class': 'title listElement', title: data.title}).text(data.title);
|
||||
var $adate = $('<span>', {'class': 'date listElement', title: getDate(data.atime)}).text(getDate(data.atime));
|
||||
var $cdate = $('<span>', {'class': 'date listElement', title: getDate(data.ctime)}).text(getDate(data.ctime));
|
||||
$span.append($title).append($adate).append($cdate);
|
||||
};
|
||||
|
||||
var addFolderData = function (element, key, $span) {
|
||||
if (!element || !isFolder(element)) { return; }
|
||||
$span.html('');
|
||||
// The element with the class '.name' is underlined when the 'li' is hovered
|
||||
$span.removeClass('name');
|
||||
var $name = $('<span>', {'class': 'name'}).text(key);
|
||||
var $title = $('<span>', {'class': 'title'}).text(data.title);
|
||||
var $adate = $('<span>', {'class': 'date'}).text(getDate(data.atime));
|
||||
var $cdate = $('<span>', {'class': 'date'}).text(getDate(data.ctime));
|
||||
$span.append($name).append($title).append($adate).append($cdate);
|
||||
return;
|
||||
var sf = hasSubfolder(element);
|
||||
var files = hasFile(element);
|
||||
var $name = $('<span>', {'class': 'name', title: key}).text(key);
|
||||
var $subfolders = $('<span>', {'class': 'folders listElement', title: sf}).text(sf);
|
||||
var $files = $('<span>', {'class': 'files listElement', title: files}).text(files);
|
||||
$span.append($name).append($subfolders).append($files);
|
||||
};
|
||||
|
||||
var createElement = function (path, elPath, root, isFolder) {
|
||||
|
@ -736,13 +825,15 @@ define([
|
|||
}
|
||||
|
||||
var $icon = $fileIcon.clone();
|
||||
var spanClass = 'file-element name element';
|
||||
var spanClass = 'file-element element';
|
||||
if (isFolder) {
|
||||
spanClass = 'folder-element name element';
|
||||
spanClass = 'folder-element element';
|
||||
$icon = isFolderEmpty(root[key]) ? $folderEmptyIcon.clone() : $folderIcon.clone();
|
||||
}
|
||||
var $name = $('<span>', { 'class': spanClass }).text(key);
|
||||
if(!isFolder && getViewMode() === 'list') {
|
||||
if (isFolder) {
|
||||
addFolderData(root[key], key, $name);
|
||||
} else {
|
||||
addFileData(path, key, $name);
|
||||
}
|
||||
var $element = $('<li>', {
|
||||
|
@ -759,13 +850,20 @@ define([
|
|||
addDragAndDropHandlers($element, newPath, isFolder, !isTrash);
|
||||
$element.click(function(e) {
|
||||
e.stopPropagation();
|
||||
//onElementClick($element, newPath);
|
||||
onElementClick($element, newPath);
|
||||
});
|
||||
if (!isTrash) {
|
||||
$element.contextmenu(openContextMenu);
|
||||
} else {
|
||||
$element.contextmenu(openTrashContextMenu);
|
||||
}
|
||||
var isNewFolder = module.newFolder && comparePath(newPath, module.newFolder);
|
||||
if (isNewFolder) {
|
||||
window.setTimeout(function() {
|
||||
displayRenameInput($name, newPath);
|
||||
}, 500);
|
||||
delete module.newFolder;
|
||||
};
|
||||
return $element;
|
||||
};
|
||||
|
||||
|
@ -813,7 +911,7 @@ define([
|
|||
|
||||
var createViewModeButton = function () {
|
||||
var $block = $('<div>', {
|
||||
'class': 'btn-group changeViewModeContainer'
|
||||
'class': 'btn-group topButtonContainer changeViewModeContainer'
|
||||
});
|
||||
|
||||
var $listButton = $('<button>', {
|
||||
|
@ -828,12 +926,14 @@ define([
|
|||
$listButton.addClass('active');
|
||||
setViewMode('list');
|
||||
$iframe.find('#' + FOLDER_CONTENT_ID).removeClass('grid');
|
||||
$iframe.find('#' + FOLDER_CONTENT_ID).addClass('list');
|
||||
});
|
||||
$gridButton.click(function () {
|
||||
$listButton.removeClass('active');
|
||||
$gridButton.addClass('active');
|
||||
setViewMode('grid');
|
||||
$iframe.find('#' + FOLDER_CONTENT_ID).addClass('grid');
|
||||
$iframe.find('#' + FOLDER_CONTENT_ID).removeClass('list');
|
||||
});
|
||||
|
||||
if (getViewMode() === 'list') {
|
||||
|
@ -845,6 +945,23 @@ define([
|
|||
return $block;
|
||||
};
|
||||
|
||||
var createNewFolderButton = function () {
|
||||
var $block = $('<div>', {
|
||||
'class': 'btn-group topButtonContainer newFolderButtonContainer'
|
||||
});
|
||||
|
||||
var $listButton = $('<button>', {
|
||||
'class': 'btn'
|
||||
}).text("NEW FOLDER"); //TODO translate
|
||||
|
||||
$listButton.click(function () {
|
||||
createNewFolder(currentPath);
|
||||
});
|
||||
|
||||
$block.append($listButton);
|
||||
return $block;
|
||||
};
|
||||
|
||||
// Display the selected directory into the content part (rightside)
|
||||
// NOTE: Elements in the trash are not using the same storage structure as the others
|
||||
var displayDirectory = module.displayDirectory = function (path) {
|
||||
|
@ -873,13 +990,31 @@ define([
|
|||
var $title = createTitle(path);
|
||||
|
||||
var $modeButton = createViewModeButton().appendTo($title);
|
||||
var $newFolderButton = createNewFolderButton().appendTo($title);
|
||||
|
||||
var $dirContent = $('<div>', {id: FOLDER_CONTENT_ID});
|
||||
if (getViewModeClass()) {
|
||||
var mode = getViewMode();
|
||||
if (mode) {
|
||||
$dirContent.addClass(getViewModeClass());
|
||||
}
|
||||
var $list = $('<ul>').appendTo($dirContent);
|
||||
|
||||
//TODO translate
|
||||
var $folderHeader = $('<li>', {'class': 'header listElement'});
|
||||
var $fohElement = $('<span>', {'class': 'element'}).appendTo($folderHeader);
|
||||
var $name = $('<span>', {'class': 'name'}).text("Folder name");
|
||||
var $subfolders = $('<span>', {'class': 'folders listElement'}).text("# of folders");
|
||||
var $files = $('<span>', {'class': 'files listElement'}).text("# of files");
|
||||
$fohElement.append($name).append($subfolders).append($files);
|
||||
var $fileHeader = $('<li>', {'class': 'file-header header listElement'});
|
||||
var $fihElement = $('<span>', {'class': 'element'}).appendTo($fileHeader);
|
||||
var $fhName = $('<span>', {'class': 'name'}).text("File name");
|
||||
var $fhTitle = $('<span>', {'class': 'title '}).text("Title");
|
||||
var $fhAdate = $('<span>', {'class': 'date'}).text("Last access");
|
||||
var $fhCdate = $('<span>', {'class': 'date'}).text("Creation");
|
||||
$fihElement.append($fhName).append($fhTitle).append($fhAdate).append($fhCdate);
|
||||
// -->
|
||||
|
||||
if (isTrashRoot) {
|
||||
// Elements in the trash are JS arrays (several elements can have the same name)
|
||||
Object.keys(root).forEach(function (key) {
|
||||
|
@ -887,6 +1022,7 @@ define([
|
|||
console.error("Trash element has a wrong type", root[key]);
|
||||
return;
|
||||
}
|
||||
if (hasSubfolder(root[key])) { $list.append($folderHeader); }
|
||||
// display sub directories
|
||||
root[key].forEach(function (el, idx) {
|
||||
if (isFile(el.element)) { return; }
|
||||
|
@ -894,6 +1030,7 @@ define([
|
|||
var $element = createElement(path, spath, root, true);
|
||||
$element.appendTo($list);
|
||||
});
|
||||
if (hasFile(root[key])) { $list.append($fileHeader); }
|
||||
// display files
|
||||
root[key].forEach(function (el, idx) {
|
||||
if (isFolder(el.element)) { return; }
|
||||
|
@ -903,12 +1040,14 @@ define([
|
|||
});
|
||||
});
|
||||
} else {
|
||||
if (hasSubfolder(root)) { $list.append($folderHeader); }
|
||||
// display sub directories
|
||||
Object.keys(root).forEach(function (key) {
|
||||
if (isFile(root[key])) { return; }
|
||||
var $element = createElement(path, key, root, true);
|
||||
$element.appendTo($list);
|
||||
});
|
||||
if (hasFile(root)) { $list.append($fileHeader); }
|
||||
// display files
|
||||
Object.keys(root).forEach(function (key) {
|
||||
if (isFolder(root[key])) { return; }
|
||||
|
@ -1024,8 +1163,31 @@ define([
|
|||
});
|
||||
};
|
||||
|
||||
var allFilesSorted = function () {
|
||||
return getUnsortedFiles().length === 0;
|
||||
};
|
||||
|
||||
var createUnsorted = function ($container, path) {
|
||||
if (allFilesSorted()) { return; }
|
||||
var $icon = $unsortedIcon.clone();
|
||||
var isOpened = comparePath(path, currentPath);
|
||||
var $unsorted = $('<span>', {
|
||||
'class': 'tree-unsorted element'
|
||||
}).text(FILES_DATA_NAME).prepend($icon)
|
||||
.click(function () {
|
||||
//module.displayDirectory(path);
|
||||
});
|
||||
var $unsortedElement = $('<li>').append($unsorted);
|
||||
$unsortedElement.addClass('root');
|
||||
$unsortedElement.data('path', [FILES_DATA]);
|
||||
if (isOpened) { $unsorted.addClass('active'); }
|
||||
|
||||
var $unsortedList = $('<ul>', { id: 'trashTree' }).append($unsortedElement);
|
||||
$container.append($unsortedList);
|
||||
};
|
||||
|
||||
var createTrash = function ($container, path) {
|
||||
var $icon = isFolderEmpty(files.trash) ? $trashEmptyIcon.clone() : $trashIcon.clone();
|
||||
var $icon = isFolderEmpty(files[TRASH]) ? $trashEmptyIcon.clone() : $trashIcon.clone();
|
||||
var isOpened = comparePath(path, currentPath);
|
||||
var $trash = $('<span>', {
|
||||
'class': 'tree-trash element'
|
||||
|
@ -1047,6 +1209,7 @@ define([
|
|||
var resetTree = module.resetTree = function () {
|
||||
$tree.html('');
|
||||
createTree($tree, [ROOT]);
|
||||
createUnsorted($tree, [FILES_DATA]);
|
||||
createTrash($tree, [TRASH]);
|
||||
};
|
||||
module.displayDirectory(currentPath);
|
||||
|
|
Loading…
Reference in New Issue