diff options
Diffstat (limited to 'apps/files')
-rw-r--r-- | apps/files/appinfo/routes.php | 10 | ||||
-rw-r--r-- | apps/files/css/files.scss | 287 | ||||
-rw-r--r-- | apps/files/js/filelist.js | 27 | ||||
-rw-r--r-- | apps/files/lib/Controller/ApiController.php | 23 | ||||
-rw-r--r-- | apps/files/list.php | 3 | ||||
-rw-r--r-- | apps/files/templates/list.php | 6 | ||||
-rw-r--r-- | apps/files/templates/recentlist.php | 2 | ||||
-rw-r--r-- | apps/files/templates/simplelist.php | 2 | ||||
-rw-r--r-- | apps/files/tests/js/favoritesfilelistspec.js | 2 | ||||
-rw-r--r-- | apps/files/tests/js/fileUploadSpec.js | 2 | ||||
-rw-r--r-- | apps/files/tests/js/fileactionsSpec.js | 2 | ||||
-rw-r--r-- | apps/files/tests/js/filelistSpec.js | 2 |
12 files changed, 357 insertions, 11 deletions
diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php index b32469c8574..06806309cac 100644 --- a/apps/files/appinfo/routes.php +++ b/apps/files/appinfo/routes.php @@ -62,6 +62,16 @@ $application->registerRoutes( 'verb' => 'POST' ], [ + 'name' => 'API#showGridView', + 'url' => '/api/v1/showgridview', + 'verb' => 'POST' + ], + [ + 'name' => 'API#getGridView', + 'url' => '/api/v1/showgridview', + 'verb' => 'GET' + ], + [ 'name' => 'view#index', 'url' => '/', 'verb' => 'GET', diff --git a/apps/files/css/files.scss b/apps/files/css/files.scss index 05c9de43a24..a643cb6258f 100644 --- a/apps/files/css/files.scss +++ b/apps/files/css/files.scss @@ -172,7 +172,7 @@ table th, table th a { color: var(--color-text-maxcontrast); } table.multiselect th a { - color: #000; + color: var(--color-main-text); } table th .columntitle { display: block; @@ -262,8 +262,7 @@ table.multiselect thead { } table.multiselect thead th { - background-color: rgba(255, 255, 255, 0.95); /* like controls bar */ - color: #000; + background-color: var(--color-main-background); font-weight: bold; border-bottom: 0; } @@ -595,7 +594,13 @@ a.action > img { .summary { opacity: .3; /* add whitespace to bottom of files list to correctly show dropdowns */ - height: 300px; + height: 250px; +} +/* Less whitespace needed on link share page + * as there is a footer and action menus have fewer entries. + */ +#body-public .summary { + height: 180px; } .summary:hover, .summary:focus, @@ -723,3 +728,277 @@ table.dragshadow td.size { height: 30px; line-height: 30px; } + +/* GRID */ +#filestable.view-grid:not(.hidden) { + $grid-size: 160px; + $grid-pad: 14px; + + /* HEADER and MULTISELECT */ + thead { + tr { + display: block; + border-bottom: 1px solid var(--color-border); + background-color: var(--color-main-background); + th { + width: auto; + border: none; + } + } + } + + /* MAIN FILE LIST */ + tbody { + display: grid; + grid-template-columns: repeat(auto-fill, $grid-size); + justify-content: space-around; + row-gap: 15px; + margin: 15px 0; + + tr { + display: block; + position: relative; + height: $grid-size + 44px - $grid-pad; + border-radius: var(--border-radius); + + &:hover, &:focus, &:active, + &.selected, + &.searchresult, + .name:focus, + &.highlighted { + background-color: transparent; + + .thumbnail-wrapper, + .nametext, + .fileactions { + transition: background-color 0.3s ease; + background-color: var(--color-background-dark); + } + } + } + + td { + display: inline; + border-bottom: none; + + &.filename { + .thumbnail-wrapper { + min-width: 0; + max-width: none; + position: absolute; + width: $grid-size; + height: $grid-size; + padding: $grid-pad; // same as action icon bottom and right padding + top: 0; + left: 0; + z-index: -1; // make sure the default click is the link + + .thumbnail { + width: calc(100% - 2 * #{$grid-pad}); + height: calc(100% - 2 * #{$grid-pad}); //action icon padding + background-size: contain; + margin: 0; + border-radius: var(--border-radius); + background-repeat: no-repeat; + background-position: center; + + /* Position favorite star related to checkbox to left and 3-dot menu below + * Position is inherited from the selection while in grid view + */ + .favorite-mark { + padding: $grid-pad; + left: auto; + top: -22px; // center in corner of thumbnail + right: -22px; // center in corner of thumbnail + } + } + } + + .name { + height: 100%; + border-radius: var(--border-radius); + // since we're using thumbnail, name and actions bg + // we need to hide the overflow for the radius to show + // luckily the popovermenu is outside .name + overflow: hidden; + // we but the thumbnail in background to ensure + // the name is the default click handler + // force back the cursor which have been overrided + // and disabled for some reason... + cursor: pointer !important; + + .nametext { + display: flex; + height: 44px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + margin-top: $grid-size - $grid-pad; + padding-right: 0; + text-align: right; + line-height: 44px; + padding-left: $grid-pad; // same as action icon right padding + + .innernametext { + display: inline-block; + max-width: 80px; + } + + /* No space for extension in grid view */ + .extension { + display: none; + } + } + + .fileactions { + height: initial; + margin-top: $grid-size - $grid-pad; + display: flex; + align-items: center; + + .action { + padding: $grid-pad; + width: 44px; + height: 44px; + display: flex; + align-items: center; + justify-content: center; + + &.action-share.permanent.shared-style span { + /* Do not show "Shared" text next to icon as there is no space */ + &:not(.icon) { + display: none; + } + + /* If an avatar is present, show that instead of the icon */ + &.avatar { + display: inline-block; + position: absolute; + } + } + + /* In "Deleted files", do not show "Restore" text next to icon as there is no space */ + &.action-restore.permanent span { + &:not(.icon) { + display: none; + } + } + + /* If there is a comment, show it instead of the share icon */ + &.action-comment ~ .action-share { + display: none; + } + } + } + } + } + + /* No space for filesize and date in grid view */ + &.filesize, + &.date { + display: none; + } + + &.selection, + &.filename .favorite-mark { + position: absolute; + top: -8px; // half the checkbox width, center on corner of thumbnail + left: -8px; // half the checkbox width, center on corner of thumbnail + display: flex; + width: 44px; + height: 44px; + z-index: 10; + background: transparent; + + label { + width: 44px; + height: 44px; + display: inline-flex; + padding: $grid-pad; // like any action icon + &::before { + margin: 0; + width: $grid-pad; // 16px - border + height: $grid-pad; // 16px - border + } + } + } + + /* Position actions menu below file */ + .popovermenu { + left: 0; + width: $grid-size - 10px; // 2 * margin + margin: 0 5px; + + /* Ellipsize long entries, normally menu width is adjusted but for grid we use fixed width. */ + .menuitem span:not(.icon) { + overflow: hidden; + text-overflow: ellipsis; + } + } + } + } + + /* Center align the footer file number & size summary */ + tfoot { + display: grid; + + .summary:not(.hidden) { + display: inline-block; + margin: 0 auto; + + td { + padding-top: 50px; + + &:first-child, + &.date { + display: none; + } + + .info { + margin-left: 0; + } + } + } + } +} + +/* Grid view toggle */ +#view-toggle { + background-color: transparent; + border: none; + margin: 0; + padding: 22px; + opacity: .5; + + &:hover, + &:focus, + #showgridview:focus + & { + opacity: 1; + } +} + +/* Adjustments for link share page */ +#body-public { + #filestable.view-grid:not(.hidden) tbody td { + /* More space for filename since there is no share icon */ + &.filename .name .nametext .innernametext { + max-width: 124px; + } + + /* Position actions menu correctly below 3-dot-menu */ + .popovermenu { + left: -80px; + } + } + + /* Right-align view toggle on link share page */ + #view-toggle { + position: absolute; + right: 0; + } +} + +/* Hide legacy Gallery toggle */ +#gallery-button { + display: none; +} diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 2211505f6d5..9cc1856d52b 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -331,6 +331,11 @@ this.$el.find('thead th .columntitle').click(_.bind(this._onClickHeader, this)); + // Toggle for grid view + this.$showGridView = $('input#showgridview'); + this.$showGridView.on('change', _.bind(this._onGridviewChange, this)); + $('#view-toggle').tooltip({placement: 'bottom', trigger: 'hover'}); + this._onResize = _.debounce(_.bind(this._onResize, this), 250); $('#app-content').on('appresized', this._onResize); $(window).resize(this._onResize); @@ -592,6 +597,26 @@ }, /** + * Toggle showing gridview by default or not + * + * @returns {undefined} + */ + _onGridviewChange: function() { + var show = this.$showGridView.is(':checked'); + // only save state if user is logged in + if (OC.currentUser) { + $.post(OC.generateUrl('/apps/files/api/v1/showgridview'), { + show: show + }); + } + this.$showGridView.next('#view-toggle') + .removeClass('icon-toggle-filelist icon-toggle-pictures') + .addClass(show ? 'icon-toggle-filelist' : 'icon-toggle-pictures') + + $('.list-container').toggleClass('view-grid', show); + }, + + /** * Event handler when leaving previously hidden state */ _onShow: function(e) { @@ -2776,7 +2801,9 @@ var permissions = this.getDirectoryPermissions(); var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty); + this.$el.find('#emptycontent').toggleClass('hidden', !this.isEmpty); this.$el.find('#emptycontent .uploadmessage').toggleClass('hidden', !isCreatable || !this.isEmpty); + this.$el.find('#filestable').toggleClass('hidden', this.isEmpty); this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty); }, /** diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php index 27cd0b361c5..3085b72ac7a 100644 --- a/apps/files/lib/Controller/ApiController.php +++ b/apps/files/lib/Controller/ApiController.php @@ -38,6 +38,7 @@ use OCP\Files\NotFoundException; use OCP\IConfig; use OCP\IRequest; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Http\Response; use OCA\Files\Service\TagService; @@ -268,6 +269,28 @@ class ApiController extends Controller { } /** + * Toggle default for files grid view + * + * @NoAdminRequired + * + * @param bool $show + */ + public function showGridView($show) { + $this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', (int)$show); + return new Response(); + } + + /** + * Get default settings for the grid view + * + * @NoAdminRequired + */ + public function getGridView() { + $status = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_grid', '1') === '1'; + return new JSONResponse(['gridview' => $status]); + } + + /** * Toggle default for showing/hiding xxx folder * * @NoAdminRequired diff --git a/apps/files/list.php b/apps/files/list.php index 93044d4c587..f18dc5964b8 100644 --- a/apps/files/list.php +++ b/apps/files/list.php @@ -22,11 +22,14 @@ */ $config = \OC::$server->getConfig(); +$userSession = \OC::$server->getUserSession(); // TODO: move this to the generated config.js $publicUploadEnabled = $config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'); +$showgridview = $config->getUserValue($userSession->getUser()->getUID(), 'files', 'show_grid', true); // renders the controls and table headers template $tmpl = new OCP\Template('files', 'list', ''); $tmpl->assign('publicUploadEnabled', $publicUploadEnabled); +$tmpl->assign('showgridview', $showgridview); $tmpl->printPage(); diff --git a/apps/files/templates/list.php b/apps/files/templates/list.php index 9cae72a176f..27403594368 100644 --- a/apps/files/templates/list.php +++ b/apps/files/templates/list.php @@ -24,6 +24,10 @@ <?php endif;?> <input type="hidden" class="max_human_file_size" value="(max <?php isset($_['uploadMaxHumanFilesize']) ? p($_['uploadMaxHumanFilesize']) : ''; ?>)"> + <input type="checkbox" class="hidden-visually" id="showgridview" + <?php if($_['showgridview']) { ?>checked="checked" <?php } ?>/> + <label id="view-toggle" for="showgridview" class="button <?php p($_['showgridview'] ? 'icon-toggle-filelist' : 'icon-toggle-pictures') ?>" + title="<?php p($l->t('Toggle grid view'))?>"></label> </div> <div id="emptycontent" class="hidden"> @@ -38,7 +42,7 @@ <p></p> </div> -<table id="filestable" data-allow-public-upload="<?php p($_['publicUploadEnabled'])?>" data-preview-x="32" data-preview-y="32"> +<table id="filestable" class="list-container <?php p($_['showgridview'] ? 'view-grid' : '') ?>" data-allow-public-upload="<?php p($_['publicUploadEnabled'])?>" data-preview-x="250" data-preview-y="250"> <thead> <tr> <th id="headerSelection" class="hidden column-selection"> diff --git a/apps/files/templates/recentlist.php b/apps/files/templates/recentlist.php index cfdb95c80a0..4c269c20256 100644 --- a/apps/files/templates/recentlist.php +++ b/apps/files/templates/recentlist.php @@ -11,7 +11,7 @@ <p></p> </div> -<table id="filestable"> +<table id="filestable" class="list-container view-grid"> <thead> <tr> <th id='headerName' class="hidden column-name"> diff --git a/apps/files/templates/simplelist.php b/apps/files/templates/simplelist.php index 78adb21922f..a99607ea642 100644 --- a/apps/files/templates/simplelist.php +++ b/apps/files/templates/simplelist.php @@ -13,7 +13,7 @@ <h2><?php p($l->t('No entries found in this folder')); ?></h2> <p></p> </div> -<table id="filestable"> +<table id="filestable" class="list-container view-grid"> <thead> <tr> <th id='headerName' class="hidden column-name"> diff --git a/apps/files/tests/js/favoritesfilelistspec.js b/apps/files/tests/js/favoritesfilelistspec.js index d1421c84ee2..5a206ca4dec 100644 --- a/apps/files/tests/js/favoritesfilelistspec.js +++ b/apps/files/tests/js/favoritesfilelistspec.js @@ -25,7 +25,7 @@ describe('OCA.Files.FavoritesFileList tests', function() { '</div>' + // dummy table // TODO: at some point this will be rendered by the fileList class itself! - '<table id="filestable">' + + '<table id="filestable" class="list-container view-grid">' + '<thead><tr>' + '<th id="headerName" class="hidden column-name">' + '<a class="name columntitle" data-sort="name"><span>Name</span><span class="sort-indicator"></span></a>' + diff --git a/apps/files/tests/js/fileUploadSpec.js b/apps/files/tests/js/fileUploadSpec.js index 6dde2734f1d..ca88461fafb 100644 --- a/apps/files/tests/js/fileUploadSpec.js +++ b/apps/files/tests/js/fileUploadSpec.js @@ -117,7 +117,7 @@ describe('OC.Upload tests', function() { beforeEach(function() { $('#testArea').append( '<div id="tableContainer">' + - '<table id="filestable">' + + '<table id="filestable" class="list-container view-grid">' + '<thead><tr>' + '<th id="headerName" class="hidden column-name">' + '<input type="checkbox" id="select_all_files" class="select-all">' + diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js index 00d13859b5b..024993b310d 100644 --- a/apps/files/tests/js/fileactionsSpec.js +++ b/apps/files/tests/js/fileactionsSpec.js @@ -28,7 +28,7 @@ describe('OCA.Files.FileActions tests', function() { var $body = $('#testArea'); $body.append('<input type="hidden" id="dir" value="/subdir"></input>'); $body.append('<input type="hidden" id="permissions" value="31"></input>'); - $body.append('<table id="filestable"><tbody id="fileList"></tbody></table>'); + $body.append('<table id="filestable" class="list-container view-grid"><tbody id="fileList"></tbody></table>'); // dummy files table fileActions = new OCA.Files.FileActions(); fileActions.registerAction({ diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index 04102a84754..961761c3e86 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -88,7 +88,7 @@ describe('OCA.Files.FileList tests', function() { '<input type="file" id="file_upload_start" name="files[]" multiple="multiple">' + // dummy table // TODO: at some point this will be rendered by the fileList class itself! - '<table id="filestable">' + + '<table id="filestable" class="list-container view-grid">' + '<thead><tr>' + '<th id="headerName" class="hidden column-name">' + '<input type="checkbox" id="select_all_files" class="select-all checkbox">' + |