From 9d661eab23f9ba284e4a5060b5de5d868b330d45 Mon Sep 17 00:00:00 2001 From: Thomas Müller Date: Thu, 12 Sep 2013 00:40:35 +0200 Subject: adding calls to \OCA\files\lib\Helper::determineIcon($i) in files, trashbin and sharing --- apps/files/index.php | 1 + 1 file changed, 1 insertion(+) (limited to 'apps/files/index.php') diff --git a/apps/files/index.php b/apps/files/index.php index f1e120c872c..4443bf5fde0 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -75,6 +75,7 @@ foreach ($content as $i) { } $i['directory'] = $dir; $i['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($i['mimetype']); + $i['icon'] = \OCA\files\lib\Helper::determineIcon($i); $files[] = $i; } -- cgit v1.2.3 From 1304b511e9533dee4cf1125e625568c8a74719a1 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Sat, 17 Aug 2013 13:07:18 +0200 Subject: Ajax calls for "files" and "files_trashbin" apps Frontend: - The files app list now uses ajax calls to refresh the list. - Added support the browser back button (history API). - Added mask + spinner while loading file list Backend: - Added utility function in core JS for parsing query strings. - Moved file list + breadcrumb template data code to helper functions - Fixed some file paths in trashbin app to be similar to the files app --- apps/files/ajax/list.php | 38 +++--- apps/files/css/files.css | 22 ++++ apps/files/index.php | 42 +------ apps/files/js/fileactions.js | 5 +- apps/files/js/filelist.js | 137 ++++++++++++++++++++-- apps/files/js/files.js | 48 +++++--- apps/files/lib/helper.php | 65 ++++++++++ apps/files/templates/index.php | 10 +- apps/files/templates/part.list.php | 4 +- apps/files_sharing/js/share.js | 2 +- apps/files_sharing/public.php | 2 +- apps/files_trashbin/ajax/list.php | 51 ++++++++ apps/files_trashbin/index.php | 91 ++------------ apps/files_trashbin/js/filelist.js | 29 +++++ apps/files_trashbin/js/trash.js | 14 ++- apps/files_trashbin/lib/helper.php | 97 +++++++++++++++ apps/files_trashbin/templates/index.php | 3 + apps/files_trashbin/templates/part.breadcrumb.php | 4 +- apps/files_trashbin/templates/part.list.php | 3 +- core/js/js.js | 32 +++++ 20 files changed, 518 insertions(+), 181 deletions(-) create mode 100644 apps/files_trashbin/ajax/list.php create mode 100644 apps/files_trashbin/js/filelist.js create mode 100644 apps/files_trashbin/lib/helper.php (limited to 'apps/files/index.php') diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php index 14ed43cbb3a..035ffc0e393 100644 --- a/apps/files/ajax/list.php +++ b/apps/files/ajax/list.php @@ -10,36 +10,34 @@ OCP\JSON::checkLoggedIn(); // Load the files $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; + +if (!\OC\Files\Filesystem::is_dir($dir . '/')) { + header("HTTP/1.0 404 Not Found"); + exit(); +} + $doBreadcrumb = isset($_GET['breadcrumb']); $data = array(); +$baseUrl = OCP\Util::linkTo('files', 'index.php') . '?dir='; // Make breadcrumb if($doBreadcrumb) { - $breadcrumb = array(); - $pathtohere = "/"; - foreach( explode( "/", $dir ) as $i ) { - if( $i != "" ) { - $pathtohere .= "$i/"; - $breadcrumb[] = array( "dir" => $pathtohere, "name" => $i ); - } - } - - $breadcrumbNav = new OCP\Template( "files", "part.breadcrumb", "" ); - $breadcrumbNav->assign( "breadcrumb", $breadcrumb, false ); + $breadcrumb = \OCA\files\lib\Helper::makeBreadcrumb($dir); + + $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); + $breadcrumbNav->assign('breadcrumb', $breadcrumb, false); + $breadcrumbNav->assign('baseURL', $baseUrl); $data['breadcrumb'] = $breadcrumbNav->fetchPage(); } // make filelist -$files = array(); -foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $i ) { - $i["date"] = OCP\Util::formatDate($i["mtime"] ); - $i['icon'] = \OCA\files\lib\Helper::determineIcon($i); - $files[] = $i; -} +$files = \OCA\files\lib\Helper::getFiles($dir); -$list = new OCP\Template( "files", "part.list", "" ); -$list->assign( "files", $files, false ); -$data = array('files' => $list->fetchPage()); +$list = new OCP\Template("files", "part.list", ""); +$list->assign('files', $files, false); +$list->assign('baseURL', $baseUrl, false); +$list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); +$data['files'] = $list->fetchPage(); OCP\JSON::success(array('data' => $data)); diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 8053649bd55..f506a379477 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -336,3 +336,25 @@ table.dragshadow td.size { text-align: center; margin-left: -200px; } +.mask { + z-index: 50; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: white; + background-repeat: no-repeat no-repeat; + background-position: 50%; + opacity: 0.7; + filter: alpha(opacity=70); + transition: opacity 100ms; + -moz-transition: opacity 100ms; + -o-transition: opacity 100ms; + -ms-transition: opacity 100ms; + -webkit-transition: opacity 100ms; +} +.mask.transparent{ + opacity: 0; +} + diff --git a/apps/files/index.php b/apps/files/index.php index 4443bf5fde0..ec824f895b6 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -41,62 +41,25 @@ if (!\OC\Files\Filesystem::is_dir($dir . '/')) { exit(); } -function fileCmp($a, $b) { - if ($a['type'] == 'dir' and $b['type'] != 'dir') { - return -1; - } elseif ($a['type'] != 'dir' and $b['type'] == 'dir') { - return 1; - } else { - return strnatcasecmp($a['name'], $b['name']); - } -} - $files = array(); $user = OC_User::getUser(); if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we need to upgrade the cache - $content = array(); $needUpgrade = true; $freeSpace = 0; } else { - $content = \OC\Files\Filesystem::getDirectoryContent($dir); + $files = \OCA\files\lib\Helper::getFiles($dir); $freeSpace = \OC\Files\Filesystem::free_space($dir); $needUpgrade = false; } -foreach ($content as $i) { - $i['date'] = OCP\Util::formatDate($i['mtime']); - if ($i['type'] == 'file') { - $fileinfo = pathinfo($i['name']); - $i['basename'] = $fileinfo['filename']; - if (!empty($fileinfo['extension'])) { - $i['extension'] = '.' . $fileinfo['extension']; - } else { - $i['extension'] = ''; - } - } - $i['directory'] = $dir; - $i['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($i['mimetype']); - $i['icon'] = \OCA\files\lib\Helper::determineIcon($i); - $files[] = $i; -} - -usort($files, "fileCmp"); // Make breadcrumb -$breadcrumb = array(); -$pathtohere = ''; -foreach (explode('/', $dir) as $i) { - if ($i != '') { - $pathtohere .= '/' . $i; - $breadcrumb[] = array('dir' => $pathtohere, 'name' => $i); - } -} +$breadcrumb = \OCA\files\lib\Helper::makeBreadcrumb($dir); // make breadcrumb und filelist markup $list = new OCP\Template('files', 'part.list', ''); $list->assign('files', $files); $list->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir='); $list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); -$list->assign('disableSharing', false); $list->assign('isPublic', false); $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', $breadcrumb); @@ -154,5 +117,6 @@ if ($needUpgrade) { $tmpl->assign('isPublic', false); $tmpl->assign('publicUploadEnabled', $publicUploadEnabled); $tmpl->assign("encryptedFiles", \OCP\Util::encryptedFiles()); + $tmpl->assign('disableSharing', false); $tmpl->printPage(); } diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 097fe521aa6..330fe86f6b3 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -196,13 +196,12 @@ FileActions.register('all', 'Rename', OC.PERMISSION_UPDATE, function () { FileList.rename(filename); }); - FileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename) { - var dir = $('#dir').val(); + var dir = $('#dir').val() || '/'; if (dir !== '/') { dir = dir + '/'; } - window.location = OC.linkTo('files', 'index.php') + '?dir=' + encodeURIComponent(dir + filename); + FileList.changeDirectory(dir + filename); }); FileActions.setDefault('dir', 'Open'); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 29be5e0d362..c205ae32aa9 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1,7 +1,25 @@ var FileList={ useUndo:true, + postProcessList: function(){ + $('#fileList tr').each(function(){ + //little hack to set unescape filenames in attribute + $(this).attr('data-file',decodeURIComponent($(this).attr('data-file'))); + }); + }, update:function(fileListHtml) { - $('#fileList').empty().html(fileListHtml); + var $fileList = $('#fileList'); + $fileList.empty().html(fileListHtml); + $('#emptycontent').toggleClass('hidden', $fileList.find('tr').length > 0); + $fileList.find('tr').each(function () { + FileActions.display($(this).children('td.filename')); + }); + $fileList.trigger(jQuery.Event("fileActionsReady")); + FileList.postProcessList(); + // "Files" might not be loaded in extending apps + if (window.Files){ + Files.setupDragAndDrop(); + } + $fileList.trigger(jQuery.Event("updated")); }, createRow:function(type, name, iconurl, linktarget, size, lastModified, permissions){ var td, simpleSize, basename, extension; @@ -134,20 +152,83 @@ var FileList={ FileActions.display(tr.find('td.filename')); return tr; }, - refresh:function(data) { - var result = jQuery.parseJSON(data.responseText); + /** + * @brief Changes the current directory and reload the file list. + * @param targetDir target directory (non URL encoded) + * @param changeUrl false if the URL must not be changed (defaults to true) + */ + changeDirectory: function(targetDir, changeUrl){ + var $dir = $('#dir'), + url, + currentDir = $dir.val() || '/'; + targetDir = targetDir || '/'; + if (currentDir === targetDir){ + return; + } + FileList.setCurrentDir(targetDir, changeUrl); + FileList.reload(); + }, + setCurrentDir: function(targetDir, changeUrl){ + $('#dir').val(targetDir); + // Note: IE8 handling ignored for now + if (window.history.pushState && changeUrl !== false){ + url = OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(targetDir).replace(/%2F/g, '/'), + window.history.pushState({dir: targetDir}, '', url); + } + }, + /** + * @brief Reloads the file list using ajax call + */ + reload: function(){ + FileList.showMask(); + if (FileList._reloadCall){ + FileList._reloadCall.abort(); + } + FileList._reloadCall = $.ajax({ + url: OC.filePath('files','ajax','list.php'), + data: { + dir : $('#dir').val(), + breadcrumb: true + }, + error: function(result){ + FileList.reloadCallback(result); + }, + success: function(result) { + FileList.reloadCallback(result); + } + }); + }, + reloadCallback: function(result){ + var $controls = $('#controls'); + + delete FileList._reloadCall; + FileList.hideMask(); + + if (!result || result.status === 'error') { + OC.Notification.show(result.data.message); + return; + } + + if (result.status === 404){ + // go back home + FileList.changeDirectory('/'); + return; + } + if(typeof(result.data.breadcrumb) != 'undefined'){ - updateBreadcrumb(result.data.breadcrumb); + $controls.find('.crumb').remove(); + $controls.prepend(result.data.breadcrumb); + // TODO: might need refactor breadcrumb code into a new file + //resizeBreadcrumbs(true); } FileList.update(result.data.files); - resetFileActionPanel(); }, remove:function(name){ $('tr').filterAttr('data-file',name).find('td.filename').draggable('destroy'); $('tr').filterAttr('data-file',name).remove(); FileList.updateFileSummary(); if($('tr[data-file]').length==0){ - $('#emptycontent').show(); + $('#emptycontent').removeClass('hidden'); } }, insertElement:function(name,type,element){ @@ -177,7 +258,7 @@ var FileList={ }else{ $('#fileList').append(element); } - $('#emptycontent').hide(); + $('#emptycontent').addClass('hidden'); FileList.updateFileSummary(); }, loadingDone:function(name, id){ @@ -508,6 +589,30 @@ var FileList={ $connector.show(); } } + }, + showMask: function(){ + // in case one was shown before + var $mask = $('#content .mask'); + if ($mask.length){ + return; + } + + $mask = $('
'); + + $mask.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); + $('#content').append($mask); + + // block UI, but only make visible in case loading takes longer + FileList._maskTimeout = window.setTimeout(function(){ + // reset opacity + $mask.removeClass('transparent'); + }, 250); + }, + hideMask: function(){ + var $mask = $('#content .mask').remove(); + if (FileList._maskTimeout){ + window.clearTimeout(FileList._maskTimeout); + } } }; @@ -629,8 +734,8 @@ $(document).ready(function(){ } // update folder size - var size = parseInt(data.context.data('size')); - size += parseInt(file.size) ; + var size = parseInt(data.context.data('size')); + size += parseInt(file.size); data.context.attr('data-size', size); data.context.find('td.filesize').text(humanFileSize(size)); @@ -710,5 +815,19 @@ $(document).ready(function(){ $(window).trigger('beforeunload'); }); + window.onpopstate = function(e){ + var targetDir; + if (e.state && e.state.dir){ + targetDir = e.state.dir; + } + else{ + // read from URL + targetDir = (OC.parseQueryString(location.search) || {dir: '/'}).dir || '/'; + } + if (targetDir){ + FileList.changeDirectory(targetDir, false); + } + } + FileList.createFileSummary(); }); diff --git a/apps/files/js/files.js b/apps/files/js/files.js index d729077ea72..ce72c7bcb5a 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -94,29 +94,34 @@ Files={ OC.Notification.show(t('files_encryption', 'Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files.')); return; } + }, + + setupDragAndDrop: function(){ + var $fileList = $('#fileList'); + + //drag/drop of files + $fileList.find('tr td.filename').each(function(i,e){ + if ($(e).parent().data('permissions') & OC.PERMISSION_DELETE) { + $(e).draggable(dragOptions); + } + }); + + $fileList.find('tr[data-type="dir"] td.filename').each(function(i,e){ + if ($(e).parent().data('permissions') & OC.PERMISSION_CREATE){ + $(e).droppable(folderDropOptions); + } + }); } }; $(document).ready(function() { Files.displayEncryptionWarning(); Files.bindKeyboardShortcuts(document, jQuery); - $('#fileList tr').each(function(){ - //little hack to set unescape filenames in attribute - $(this).attr('data-file',decodeURIComponent($(this).attr('data-file'))); - }); + + FileList.postProcessList(); + Files.setupDragAndDrop(); $('#file_action_panel').attr('activeAction', false); - //drag/drop of files - $('#fileList tr td.filename').each(function(i,e){ - if ($(e).parent().data('permissions') & OC.PERMISSION_DELETE) { - $(e).draggable(dragOptions); - } - }); - $('#fileList tr[data-type="dir"] td.filename').each(function(i,e){ - if ($(e).parent().data('permissions') & OC.PERMISSION_CREATE){ - $(e).droppable(folderDropOptions); - } - }); $('div.crumb:not(.last)').droppable(crumbDropOptions); $('ul#apps>li:first-child').data('dir',''); if($('div.crumb').length){ @@ -335,6 +340,9 @@ $(document).ready(function() { resizeBreadcrumbs(true); + // event handlers for breadcrumb items + $('#controls').delegate('.crumb a', 'click', onClickBreadcrumb); + // display storage warnings setTimeout ( "Files.displayStorageWarnings()", 100 ); OC.Notification.setDefault(Files.displayStorageWarnings); @@ -415,10 +423,6 @@ function boolOperationFinished(data, callback) { } } -function updateBreadcrumb(breadcrumbHtml) { - $('p.nav').empty().html(breadcrumbHtml); -} - var createDragShadow = function(event){ //select dragged file var isDragSelected = $(event.target).parents('tr').find('td input:first').prop('checked'); @@ -681,3 +685,9 @@ function checkTrashStatus() { } }); } + +function onClickBreadcrumb(e){ + var $el = $(e.target).closest('.crumb'); + e.preventDefault(); + FileList.changeDirectory(decodeURIComponent($el.data('dir'))); +} diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php index 9170c6e3fc0..282f0678a9a 100644 --- a/apps/files/lib/helper.php +++ b/apps/files/lib/helper.php @@ -45,5 +45,70 @@ class Helper return \OC_Helper::mimetypeIcon($file['mimetype']); } + /** + * Comparator function to sort files alphabetically and have + * the directories appear first + * @param array $a file + * @param array $b file + * @return -1 if $a must come before $b, 1 otherwise + */ + public static function fileCmp($a, $b) { + if ($a['type'] === 'dir' and $b['type'] !== 'dir') { + return -1; + } elseif ($a['type'] !== 'dir' and $b['type'] === 'dir') { + return 1; + } else { + return strnatcasecmp($a['name'], $b['name']); + } + } + + /** + * Retrieves the contents of the given directory and + * returns it as a sorted array. + * @param string $dir path to the directory + * @return array of files + */ + public static function getFiles($dir) { + $content = \OC\Files\Filesystem::getDirectoryContent($dir); + $files = array(); + + foreach ($content as $i) { + $i['date'] = \OCP\Util::formatDate($i['mtime']); + if ($i['type'] === 'file') { + $fileinfo = pathinfo($i['name']); + $i['basename'] = $fileinfo['filename']; + if (!empty($fileinfo['extension'])) { + $i['extension'] = '.' . $fileinfo['extension']; + } else { + $i['extension'] = ''; + } + } + $i['directory'] = $dir; + $i['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($i['mimetype']); + $i['icon'] = \OCA\files\lib\Helper::determineIcon($i); + $files[] = $i; + } + usort($files, array('\OCA\files\lib\Helper', 'fileCmp')); + + return $files; + } + + /** + * Splits the given path into a breadcrumb structure. + * @param string $dir path to process + * @return array where each entry is a hash of the absolute + * directory path and its name + */ + public static function makeBreadcrumb($dir){ + $breadcrumb = array(); + $pathtohere = ''; + foreach (explode('/', $dir) as $i) { + if ($i !== '') { + $pathtohere .= '/' . $i; + $breadcrumb[] = array('dir' => $pathtohere, 'name' => $i); + } + } + return $breadcrumb; + } } diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index 29cb457cd5a..85e21380c6d 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -2,7 +2,7 @@
-
+
t('New'));?>
    @@ -55,9 +55,9 @@
- -
t('Nothing in here. Upload something!'))?>
- +
0):?>class="hidden">t('Nothing in here. Upload something!'))?>
+ + @@ -82,7 +82,7 @@
t( 'Modified' )); ?> - + t('Unshare'))?> diff --git a/apps/files/templates/part.list.php b/apps/files/templates/part.list.php index 9e1750faddf..1e4d4d11c98 100644 --- a/apps/files/templates/part.list.php +++ b/apps/files/templates/part.list.php @@ -1,4 +1,6 @@ - + assign('mimetype', \OC\Files\Filesystem::getMimeType($path)); $tmpl->assign('fileTarget', basename($linkItem['file_target'])); $tmpl->assign('dirToken', $linkItem['token']); + $tmpl->assign('disableSharing', true); $allowPublicUploadEnabled = (bool) ($linkItem['permissions'] & OCP\PERMISSION_CREATE); if (\OCP\App::isEnabled('files_encryption')) { $allowPublicUploadEnabled = false; @@ -206,7 +207,6 @@ if (isset($path)) { } $list = new OCP\Template('files', 'part.list', ''); $list->assign('files', $files); - $list->assign('disableSharing', true); $list->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path='); $list->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download&path='); diff --git a/apps/files_trashbin/ajax/list.php b/apps/files_trashbin/ajax/list.php new file mode 100644 index 00000000000..e72e67b01d7 --- /dev/null +++ b/apps/files_trashbin/ajax/list.php @@ -0,0 +1,51 @@ +assign('breadcrumb', $breadcrumb, false); + $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php') . '?dir='); + $breadcrumbNav->assign('home', OCP\Util::linkTo('files', 'index.php')); + + $data['breadcrumb'] = $breadcrumbNav->fetchPage(); +} + +// make filelist +$files = \OCA\files_trashbin\lib\Helper::getTrashFiles($dir); + +if ($files === null){ + header("HTTP/1.0 404 Not Found"); + exit(); +} + +$dirlisting = false; +if ($dir && $dir !== '/') { + $dirlisting = true; +} + +$encodedDir = \OCP\Util::encodePath($dir); +$list = new OCP\Template('files_trashbin', 'part.list', ''); +$list->assign('files', $files, false); +$list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir='.$encodedDir); +$list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); +$list->assign('dirlisting', $dirlisting); +$list->assign('disableDownloadActions', true); +$data['files'] = $list->fetchPage(); + +OCP\JSON::success(array('data' => $data)); + diff --git a/apps/files_trashbin/index.php b/apps/files_trashbin/index.php index b7d0ef012f4..c28a88d541a 100644 --- a/apps/files_trashbin/index.php +++ b/apps/files_trashbin/index.php @@ -10,92 +10,27 @@ OCP\Util::addScript('files_trashbin', 'disableDefaultActions'); OCP\Util::addScript('files', 'fileactions'); $tmpl = new OCP\Template('files_trashbin', 'index', 'user'); -$user = \OCP\User::getUser(); -$view = new OC_Filesystemview('/'.$user.'/files_trashbin/files'); - OCP\Util::addStyle('files', 'files'); OCP\Util::addScript('files', 'filelist'); +// filelist overrides +OCP\Util::addScript('files_trashbin', 'filelist'); $dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : ''; -$result = array(); -if ($dir) { - $dirlisting = true; - $dirContent = $view->opendir($dir); - $i = 0; - if(is_resource($dirContent)) { - while(($entryName = readdir($dirContent)) !== false) { - if (!\OC\Files\Filesystem::isIgnoredDir($entryName)) { - $pos = strpos($dir.'/', '/', 1); - $tmp = substr($dir, 0, $pos); - $pos = strrpos($tmp, '.d'); - $timestamp = substr($tmp, $pos+2); - $result[] = array( - 'id' => $entryName, - 'timestamp' => $timestamp, - 'mime' => $view->getMimeType($dir.'/'.$entryName), - 'type' => $view->is_dir($dir.'/'.$entryName) ? 'dir' : 'file', - 'location' => $dir, - ); - } - } - closedir($dirContent); - } -} else { - $dirlisting = false; - $query = \OC_DB::prepare('SELECT `id`,`location`,`timestamp`,`type`,`mime` FROM `*PREFIX*files_trash` WHERE `user` = ?'); - $result = $query->execute(array($user))->fetchAll(); -} +$files = \OCA\files_trashbin\lib\Helper::getTrashFiles($dir); -$files = array(); -foreach ($result as $r) { - $i = array(); - $i['name'] = $r['id']; - $i['date'] = OCP\Util::formatDate($r['timestamp']); - $i['timestamp'] = $r['timestamp']; - $i['mimetype'] = $r['mime']; - $i['type'] = $r['type']; - if ($i['type'] === 'file') { - $fileinfo = pathinfo($r['id']); - $i['basename'] = $fileinfo['filename']; - $i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : ''; - } - $i['directory'] = $r['location']; - if ($i['directory'] === '/') { - $i['directory'] = ''; - } - $i['permissions'] = OCP\PERMISSION_READ; - $i['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($r['mime']); - $i['icon'] = \OCA\files\lib\Helper::determineIcon($i); - $files[] = $i; +// Redirect if directory does not exist +if ($files === null){ + header('Location: ' . OCP\Util::linkTo('files_trashbin', 'index.php')); + exit(); } -function fileCmp($a, $b) { - if ($a['type'] === 'dir' and $b['type'] !== 'dir') { - return -1; - } elseif ($a['type'] !== 'dir' and $b['type'] === 'dir') { - return 1; - } else { - return strnatcasecmp($a['name'], $b['name']); - } +$dirlisting = false; +if ($dir && $dir !== '/') { + $dirlisting = true; } -usort($files, "fileCmp"); - -// Make breadcrumb -$pathtohere = ''; -$breadcrumb = array(); -foreach (explode('/', $dir) as $i) { - if ($i !== '') { - if ( preg_match('/^(.+)\.d[0-9]+$/', $i, $match) ) { - $name = $match[1]; - } else { - $name = $i; - } - $pathtohere .= '/' . $i; - $breadcrumb[] = array('dir' => $pathtohere, 'name' => $name); - } -} +$breadcrumb = \OCA\files_trashbin\lib\Helper::makeBreadcrumb($dir); $breadcrumbNav = new OCP\Template('files_trashbin', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', $breadcrumb); @@ -108,7 +43,6 @@ $list->assign('files', $files); $encodedDir = \OCP\Util::encodePath($dir); $list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir='.$encodedDir); $list->assign('downloadURL', OCP\Util::linkTo('files_trashbin', 'download.php') . '?file='.$encodedDir); -$list->assign('disableSharing', true); $list->assign('dirlisting', $dirlisting); $list->assign('disableDownloadActions', true); @@ -116,6 +50,7 @@ $tmpl->assign('dirlisting', $dirlisting); $tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage()); $tmpl->assign('fileList', $list->fetchPage()); $tmpl->assign('files', $files); -$tmpl->assign('dir', \OC\Files\Filesystem::normalizePath($view->getAbsolutePath())); +$tmpl->assign('dir', $dir); +$tmpl->assign('disableSharing', true); $tmpl->printPage(); diff --git a/apps/files_trashbin/js/filelist.js b/apps/files_trashbin/js/filelist.js new file mode 100644 index 00000000000..ff3a846d860 --- /dev/null +++ b/apps/files_trashbin/js/filelist.js @@ -0,0 +1,29 @@ +// override reload with own ajax call +FileList.reload = function(){ + FileList.showMask(); + if (FileList._reloadCall){ + FileList._reloadCall.abort(); + } + $.ajax({ + url: OC.filePath('files_trashbin','ajax','list.php'), + data: { + dir : $('#dir').val(), + breadcrumb: true + }, + error: function(result) { + FileList.reloadCallback(result); + }, + success: function(result) { + FileList.reloadCallback(result); + } + }); +} + +FileList.setCurrentDir = function(targetDir, changeUrl){ + $('#dir').val(targetDir); + // Note: IE8 handling ignored for now + if (window.history.pushState && changeUrl !== false){ + url = OC.linkTo('files_trashbin', 'index.php')+"?dir="+ encodeURIComponent(targetDir).replace(/%2F/g, '/'), + window.history.pushState({dir: targetDir}, '', url); + } +} diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index 40c0bdb3829..d73eadb6011 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -171,9 +171,15 @@ $(document).ready(function() { action(filename); } } + + // event handlers for breadcrumb items + $('#controls').delegate('.crumb:not(.home) a', 'click', onClickBreadcrumb); }); - FileActions.actions.dir = {}; + FileActions.actions.dir = { + // only keep 'Open' action for navigation + 'Open': FileActions.actions.dir.Open + }; }); function processSelection(){ @@ -246,3 +252,9 @@ function disableActions() { $(".action").css("display", "none"); $(":input:checkbox").css("display", "none"); } +function onClickBreadcrumb(e){ + var $el = $(e.target).closest('.crumb'); + e.preventDefault(); + FileList.changeDirectory(decodeURIComponent($el.data('dir'))); +} + diff --git a/apps/files_trashbin/lib/helper.php b/apps/files_trashbin/lib/helper.php new file mode 100644 index 00000000000..098fc0b54b7 --- /dev/null +++ b/apps/files_trashbin/lib/helper.php @@ -0,0 +1,97 @@ +opendir($dir); + if ($dirContent === false){ + return null; + } + if(is_resource($dirContent)){ + while(($entryName = readdir($dirContent)) !== false) { + if (!\OC\Files\Filesystem::isIgnoredDir($entryName)) { + $pos = strpos($dir.'/', '/', 1); + $tmp = substr($dir, 0, $pos); + $pos = strrpos($tmp, '.d'); + $timestamp = substr($tmp, $pos+2); + $result[] = array( + 'id' => $entryName, + 'timestamp' => $timestamp, + 'mime' => $view->getMimeType($dir.'/'.$entryName), + 'type' => $view->is_dir($dir.'/'.$entryName) ? 'dir' : 'file', + 'location' => $dir, + ); + } + } + closedir($dirContent); + } + } else { + $query = \OC_DB::prepare('SELECT `id`,`location`,`timestamp`,`type`,`mime` FROM `*PREFIX*files_trash` WHERE `user` = ?'); + $result = $query->execute(array($user))->fetchAll(); + } + + $files = array(); + foreach ($result as $r) { + $i = array(); + $i['name'] = $r['id']; + $i['date'] = \OCP\Util::formatDate($r['timestamp']); + $i['timestamp'] = $r['timestamp']; + $i['mimetype'] = $r['mime']; + $i['type'] = $r['type']; + if ($i['type'] === 'file') { + $fileinfo = pathinfo($r['id']); + $i['basename'] = $fileinfo['filename']; + $i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : ''; + } + $i['directory'] = $r['location']; + if ($i['directory'] === '/') { + $i['directory'] = ''; + } + $i['permissions'] = \OCP\PERMISSION_READ; + $i['isPreviewAvailable'] = \OCP\Preview::isMimeSupported($r['mime']); + $i['icon'] = \OCA\files\lib\Helper::determineIcon($i); + $files[] = $i; + } + + usort($files, array('\OCA\files\lib\Helper', 'fileCmp')); + + return $files; + } + + /** + * Splits the given path into a breadcrumb structure. + * @param string $dir path to process + * @return array where each entry is a hash of the absolute + * directory path and its name + */ + public static function makeBreadcrumb($dir){ + // Make breadcrumb + $pathtohere = ''; + $breadcrumb = array(); + foreach (explode('/', $dir) as $i) { + if ($i !== '') { + if ( preg_match('/^(.+)\.d[0-9]+$/', $i, $match) ) { + $name = $match[1]; + } else { + $name = $i; + } + $pathtohere .= '/' . $i; + $breadcrumb[] = array('dir' => $pathtohere, 'name' => $name); + } + } + return $breadcrumb; + } +} diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php index 88c32b1f3eb..daae7753aeb 100644 --- a/apps/files_trashbin/templates/index.php +++ b/apps/files_trashbin/templates/index.php @@ -9,6 +9,9 @@
t('Nothing in here. Your trash bin is empty!'))?>
+ + + diff --git a/apps/files_trashbin/templates/part.breadcrumb.php b/apps/files_trashbin/templates/part.breadcrumb.php index 8ecab58e5c8..4acc298adbe 100644 --- a/apps/files_trashbin/templates/part.breadcrumb.php +++ b/apps/files_trashbin/templates/part.breadcrumb.php @@ -1,11 +1,11 @@ -
+
'> + data-dir='/'> t("Deleted Files")); ?>
diff --git a/apps/files_trashbin/templates/part.list.php b/apps/files_trashbin/templates/part.list.php index f7cc6b01bbb..78709d986ae 100644 --- a/apps/files_trashbin/templates/part.list.php +++ b/apps/files_trashbin/templates/part.list.php @@ -1,4 +1,3 @@ - ' id="" - data-file="" + data-file="" data-timestamp='' data-dirlisting=1 diff --git a/core/js/js.js b/core/js/js.js index 1999ff73d23..c09f80369f9 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -321,6 +321,38 @@ var OC={ var date = new Date(1000*mtime); return date.getDate()+'.'+(date.getMonth()+1)+'.'+date.getFullYear()+', '+date.getHours()+':'+date.getMinutes(); }, + /** + * Parses a URL query string into a JS map + * @param queryString query string in the format param1=1234¶m2=abcde¶m3=xyz + * @return map containing key/values matching the URL parameters + */ + parseQueryString:function(queryString){ + var parts, + components, + result = {}, + key, + value; + if (!queryString){ + return null; + } + if (queryString[0] === '?'){ + queryString = queryString.substr(1); + } + parts = queryString.split('&'); + for (var i = 0; i < parts.length; i++){ + components = parts[i].split('='); + if (!components.length){ + continue; + } + key = decodeURIComponent(components[0]); + if (!key){ + continue; + } + value = components[1]; + result[key] = value && decodeURIComponent(value); + } + return result; + }, /** * Opens a popup with the setting for an app. * @param appid String. The ID of the app e.g. 'calendar', 'contacts' or 'files'. -- cgit v1.2.3 From 364e7991a42c92affb9085082ff79f6b653de6dd Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 29 Aug 2013 23:45:02 +0200 Subject: Fixed ajax support to also update the current dir permissions --- apps/files/ajax/list.php | 4 ++++ apps/files/index.php | 14 +------------- apps/files/js/filelist.js | 16 ++++++++++++++-- apps/files/lib/helper.php | 22 ++++++++++++++++++++++ apps/files/templates/index.php | 10 ++++------ 5 files changed, 45 insertions(+), 21 deletions(-) (limited to 'apps/files/index.php') diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php index 035ffc0e393..f1b713b5534 100644 --- a/apps/files/ajax/list.php +++ b/apps/files/ajax/list.php @@ -20,6 +20,8 @@ $doBreadcrumb = isset($_GET['breadcrumb']); $data = array(); $baseUrl = OCP\Util::linkTo('files', 'index.php') . '?dir='; +$permissions = \OCA\files\lib\Helper::getDirPermissions($dir); + // Make breadcrumb if($doBreadcrumb) { $breadcrumb = \OCA\files\lib\Helper::makeBreadcrumb($dir); @@ -38,6 +40,8 @@ $list = new OCP\Template("files", "part.list", ""); $list->assign('files', $files, false); $list->assign('baseURL', $baseUrl, false); $list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); +$list->assign('isPublic', false); $data['files'] = $list->fetchPage(); +$data['permissions'] = $permissions; OCP\JSON::success(array('data' => $data)); diff --git a/apps/files/index.php b/apps/files/index.php index ec824f895b6..4b930f89024 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -65,19 +65,7 @@ $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', $breadcrumb); $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir='); -$permissions = OCP\PERMISSION_READ; -if (\OC\Files\Filesystem::isCreatable($dir . '/')) { - $permissions |= OCP\PERMISSION_CREATE; -} -if (\OC\Files\Filesystem::isUpdatable($dir . '/')) { - $permissions |= OCP\PERMISSION_UPDATE; -} -if (\OC\Files\Filesystem::isDeletable($dir . '/')) { - $permissions |= OCP\PERMISSION_DELETE; -} -if (\OC\Files\Filesystem::isSharable($dir . '/')) { - $permissions |= OCP\PERMISSION_SHARE; -} +$permissions = \OCA\files\lib\Helper::getDirPermissions($dir); if ($needUpgrade) { OCP\Util::addscript('files', 'upgrade'); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 638864d9eca..07605a7d891 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -7,9 +7,11 @@ var FileList={ }); }, update:function(fileListHtml) { - var $fileList = $('#fileList'); + var $fileList = $('#fileList'), + permissions = $('#permissions').val(), + isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; $fileList.empty().html(fileListHtml); - $('#emptycontent').toggleClass('hidden', $fileList.find('tr').length > 0); + $('#emptycontent').toggleClass('hidden', !isCreatable || $fileList.find('tr').length > 0); $fileList.find('tr').each(function () { FileActions.display($(this).children('td.filename')); }); @@ -216,6 +218,10 @@ var FileList={ return; } + if (result.data.permissions){ + FileList.setDirectoryPermissions(result.data.permissions); + } + if(typeof(result.data.breadcrumb) != 'undefined'){ $controls.find('.crumb').remove(); $controls.prepend(result.data.breadcrumb); @@ -232,6 +238,12 @@ var FileList={ FileList.update(result.data.files); }, + setDirectoryPermissions: function(permissions){ + var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; + $('#permissions').val(permissions); + $('.creatable').toggleClass('hidden', !isCreatable); + $('.notCreatable').toggleClass('hidden', isCreatable); + }, remove:function(name){ $('tr').filterAttr('data-file',name).find('td.filename').draggable('destroy'); $('tr').filterAttr('data-file',name).remove(); diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php index 282f0678a9a..3c13b8ea6e2 100644 --- a/apps/files/lib/helper.php +++ b/apps/files/lib/helper.php @@ -111,4 +111,26 @@ class Helper } return $breadcrumb; } + + /** + * Returns the numeric permissions for the given directory. + * @param string $dir directory without trailing slash + * @return numeric permissions + */ + public static function getDirPermissions($dir){ + $permissions = \OCP\PERMISSION_READ; + if (\OC\Files\Filesystem::isCreatable($dir . '/')) { + $permissions |= \OCP\PERMISSION_CREATE; + } + if (\OC\Files\Filesystem::isUpdatable($dir . '/')) { + $permissions |= \OCP\PERMISSION_UPDATE; + } + if (\OC\Files\Filesystem::isDeletable($dir . '/')) { + $permissions |= \OCP\PERMISSION_DELETE; + } + if (\OC\Files\Filesystem::isSharable($dir . '/')) { + $permissions |= \OCP\PERMISSION_SHARE; + } + return $permissions; + } } diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index 9ca115f7711..0105f4370e5 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -1,8 +1,7 @@
- -
+
t('New'));?>
    @@ -50,10 +49,9 @@
- -
- - +
+
+
-- cgit v1.2.3 From 30a2f2f35282a4414269a7650513348b99fb7965 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 29 Aug 2013 21:56:14 +0200 Subject: Use hash part of URL for IE8 in files app Before this fix, the URL wasn't updated in IE8 when navigating into folders. This fix makes use of the hash part of URLs to make this work in IE8, since IE8 doesn't support the history API nor changing the URL without redirecting. From now, both the regular query URL "?dir=somedir" and "#?dir=somedir" will work in both IE8 and non-IE8 browsers. In IE8, query based URLs are automatically converted to hash URLs upon page load. The conversion is done on the server side by redirecting the user to the updated URL. When loading a page directly using a hash URL in the form "#?dir=somedir" in IE8, the server doesn't get the hash, so it will not return any results in that case and rely on ajax to load the first page. --- apps/files/index.php | 30 +++++++++++++++++++- apps/files/js/filelist.js | 58 +++++++++++++++++++++++++++++++++----- apps/files/templates/index.php | 3 +- apps/files_trashbin/js/filelist.js | 9 ++---- 4 files changed, 84 insertions(+), 16 deletions(-) (limited to 'apps/files/index.php') diff --git a/apps/files/index.php b/apps/files/index.php index 4b930f89024..d46d8e32eef 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -41,13 +41,40 @@ if (!\OC\Files\Filesystem::is_dir($dir . '/')) { exit(); } +$isIE8 = false; +preg_match('/MSIE (.*?);/', $_SERVER['HTTP_USER_AGENT'], $matches); +if (count($matches) > 0 && $matches[1] <= 8){ + $isIE8 = true; +} + +// if IE8 and "?dir=path" was specified, reformat the URL to use a hash like "#?dir=path" +if ($isIE8 && isset($_GET['dir'])){ + if ($dir === ''){ + $dir = '/'; + } + header('Location: ' . OCP\Util::linkTo('files', 'index.php') . '#?dir=' . \OCP\Util::encodePath($dir)); + exit(); +} + +$ajaxLoad = false; $files = array(); $user = OC_User::getUser(); if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we need to upgrade the cache $needUpgrade = true; $freeSpace = 0; } else { - $files = \OCA\files\lib\Helper::getFiles($dir); + if ($isIE8){ + // after the redirect above, the URL will have a format + // like "files#?dir=path" which means that no path was given + // (dir is not set). In that specific case, we don't return any + // files because the client will take care of switching the dir + // to the one from the hash, then ajax-load the initial file list + $files = array(); + $ajaxLoad = true; + } + else{ + $files = \OCA\files\lib\Helper::getFiles($dir); + } $freeSpace = \OC\Files\Filesystem::free_space($dir); $needUpgrade = false; } @@ -106,5 +133,6 @@ if ($needUpgrade) { $tmpl->assign('publicUploadEnabled', $publicUploadEnabled); $tmpl->assign("encryptedFiles", \OCP\Util::encryptedFiles()); $tmpl->assign('disableSharing', false); + $tmpl->assign('ajaxLoad', $ajaxLoad); $tmpl->printPage(); } diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 07605a7d891..b50d46c98d3 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -160,23 +160,31 @@ var FileList={ * @param targetDir target directory (non URL encoded) * @param changeUrl false if the URL must not be changed (defaults to true) */ - changeDirectory: function(targetDir, changeUrl){ + changeDirectory: function(targetDir, changeUrl, force){ var $dir = $('#dir'), url, currentDir = $dir.val() || '/'; targetDir = targetDir || '/'; - if (currentDir === targetDir){ + if (!force && currentDir === targetDir){ return; } FileList.setCurrentDir(targetDir, changeUrl); FileList.reload(); }, + linkTo: function(dir){ + return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); + }, setCurrentDir: function(targetDir, changeUrl){ $('#dir').val(targetDir); - // Note: IE8 handling ignored for now - if (window.history.pushState && changeUrl !== false){ - url = OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(targetDir).replace(/%2F/g, '/'), - window.history.pushState({dir: targetDir}, '', url); + if (changeUrl !== false){ + if (window.history.pushState && changeUrl !== false){ + url = FileList.linkTo(targetDir); + window.history.pushState({dir: targetDir}, '', url); + } + // use URL hash for IE8 + else{ + window.location.hash = '?dir='+ encodeURIComponent(targetDir).replace(/%2F/g, '/'); + } } }, /** @@ -837,6 +845,37 @@ $(document).ready(function(){ $(window).trigger('beforeunload'); }); + function parseHashQuery(){ + var hash = window.location.hash, + pos = hash.indexOf('?'), + query; + if (pos >= 0){ + return hash.substr(pos + 1); + } + return ''; + } + + function parseCurrentDirFromUrl(){ + var query = parseHashQuery(), + params, + dir = '/'; + // try and parse from URL hash first + if (query){ + params = OC.parseQueryString(query); + } + // else read from query attributes + if (!params){ + params = OC.parseQueryString(location.search); + } + return (params && params.dir) || '/'; + } + + // fallback to hashchange when no history support + if (!window.history.pushState){ + $(window).on('hashchange', function(){ + FileList.changeDirectory(parseCurrentDirFromUrl(), false); + }); + } window.onpopstate = function(e){ var targetDir; if (e.state && e.state.dir){ @@ -844,12 +883,17 @@ $(document).ready(function(){ } else{ // read from URL - targetDir = (OC.parseQueryString(location.search) || {dir: '/'}).dir || '/'; + targetDir = parseCurrentDirFromUrl(); } if (targetDir){ FileList.changeDirectory(targetDir, false); } } + if (parseInt($('#ajaxLoad').val(), 10) === 1){ + // need to initially switch the dir to the one from the hash (IE8) + FileList.changeDirectory(parseCurrentDirFromUrl(), false, true); + } + FileList.createFileSummary(); }); diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index 0105f4370e5..09e351d4ea8 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -55,7 +55,7 @@
-
0):?>class="hidden">t('Nothing in here. Upload something!'))?>
+
0 or !$_['ajaxLoad']):?>class="hidden">t('Nothing in here. Upload something!'))?>
@@ -120,6 +120,7 @@
+ diff --git a/apps/files_trashbin/js/filelist.js b/apps/files_trashbin/js/filelist.js index ff3a846d860..cd5a67ddfe0 100644 --- a/apps/files_trashbin/js/filelist.js +++ b/apps/files_trashbin/js/filelist.js @@ -19,11 +19,6 @@ FileList.reload = function(){ }); } -FileList.setCurrentDir = function(targetDir, changeUrl){ - $('#dir').val(targetDir); - // Note: IE8 handling ignored for now - if (window.history.pushState && changeUrl !== false){ - url = OC.linkTo('files_trashbin', 'index.php')+"?dir="+ encodeURIComponent(targetDir).replace(/%2F/g, '/'), - window.history.pushState({dir: targetDir}, '', url); - } +FileList.linkTo = function(dir){ + return OC.linkTo('files_trashbin', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); } -- cgit v1.2.3