diff --git a/www/file/file.css b/www/file/file.css index 6f5bae12b..8cc8af3a2 100644 --- a/www/file/file.css +++ b/www/file/file.css @@ -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; + } } - diff --git a/www/file/main.js b/www/file/main.js index 6bf1380a7..5f3bcee73 100644 --- a/www/file/main.js +++ b/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 = $('', {"class": "fa fa-folder-open-o folder"}); var $fileIcon = $('', {"class": "fa fa-file file"}); var $upIcon = $('', {"class": "fa fa-arrow-circle-up"}); + var $unsortedIcon = $('', {"class": "fa fa-files-o"}); var $trashIcon = $('', {"class": "fa fa-trash"}); var $trashEmptyIcon = $('', {"class": "fa fa-trash-o"}); var $collapseIcon = $('', {"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 , 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 = $('', {'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 = $('', {'class': 'title listElement', title: data.title}).text(data.title); + var $adate = $('', {'class': 'date listElement', title: getDate(data.atime)}).text(getDate(data.atime)); + var $cdate = $('', {'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 = $('', {'class': 'name'}).text(key); - var $title = $('', {'class': 'title'}).text(data.title); - var $adate = $('', {'class': 'date'}).text(getDate(data.atime)); - var $cdate = $('', {'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 = $('', {'class': 'name', title: key}).text(key); + var $subfolders = $('', {'class': 'folders listElement', title: sf}).text(sf); + var $files = $('', {'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 = $('', { 'class': spanClass }).text(key); - if(!isFolder && getViewMode() === 'list') { + if (isFolder) { + addFolderData(root[key], key, $name); + } else { addFileData(path, key, $name); } var $element = $('
  • ', { @@ -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 = $('
    ', { - 'class': 'btn-group changeViewModeContainer' + 'class': 'btn-group topButtonContainer changeViewModeContainer' }); var $listButton = $('