Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2018-10-24 16:31:23 +0300
committerGitHub <noreply@github.com>2018-10-24 16:31:23 +0300
commit37782b1084275d54474700e4ae7863b18e23dc04 (patch)
tree9481ad7bf07ae049a77dd95a0b09e43a7fb63c59
parent2ec5d2a6ded8096431978638013df4ae5d711cb3 (diff)
parentede6472e52ab019c377640eb37ca3499d51ad8be (diff)
Merge pull request #11573 from nextcloud/gridview-table
Files grid view
-rw-r--r--apps/files/appinfo/routes.php10
-rw-r--r--apps/files/css/files.scss287
-rw-r--r--apps/files/js/filelist.js27
-rw-r--r--apps/files/lib/Controller/ApiController.php23
-rw-r--r--apps/files/list.php3
-rw-r--r--apps/files/templates/list.php6
-rw-r--r--apps/files/templates/recentlist.php2
-rw-r--r--apps/files/templates/simplelist.php2
-rw-r--r--apps/files/tests/js/favoritesfilelistspec.js2
-rw-r--r--apps/files/tests/js/fileUploadSpec.js2
-rw-r--r--apps/files/tests/js/fileactionsSpec.js2
-rw-r--r--apps/files/tests/js/filelistSpec.js2
-rw-r--r--apps/files_external/templates/list.php2
-rw-r--r--apps/files_sharing/css/public.scss1
-rw-r--r--apps/files_sharing/js/public.js4
-rw-r--r--apps/files_sharing/lib/Controller/ShareController.php1
-rw-r--r--apps/files_sharing/templates/list.php2
-rw-r--r--apps/files_sharing/tests/js/publicAppSpec.js2
-rw-r--r--apps/files_sharing/tests/js/shareSpec.js6
-rw-r--r--apps/files_sharing/tests/js/sharedfilelistSpec.js4
-rw-r--r--apps/files_trashbin/templates/index.php2
-rw-r--r--apps/files_trashbin/tests/js/filelistSpec.js2
-rw-r--r--core/css/css-variables.scss1
-rw-r--r--core/css/icons.scss1
-rw-r--r--core/css/styles.scss78
-rw-r--r--core/css/variables.scss1
-rw-r--r--core/js/oc-dialogs.js33
-rw-r--r--core/templates/filepicker.html4
28 files changed, 483 insertions, 29 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">' +
diff --git a/apps/files_external/templates/list.php b/apps/files_external/templates/list.php
index ed13ed83701..20f97dd4c08 100644
--- a/apps/files_external/templates/list.php
+++ b/apps/files_external/templates/list.php
@@ -11,7 +11,7 @@
<input type="hidden" name="dir" value="" id="dir">
-<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_sharing/css/public.scss b/apps/files_sharing/css/public.scss
index 1423705ffc9..44b7e53d207 100644
--- a/apps/files_sharing/css/public.scss
+++ b/apps/files_sharing/css/public.scss
@@ -1,5 +1,4 @@
#preview {
- background: var(--color-main-background);
text-align: center;
}
diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js
index 2b7cea8d0dc..1dd9f5af6c7 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -229,10 +229,10 @@ OCA.Sharing.PublicApp = {
this.fileList.generatePreviewUrl = function (urlSpec) {
urlSpec = urlSpec || {};
if (!urlSpec.x) {
- urlSpec.x = 32;
+ urlSpec.x = this.$table.data('preview-x') || 32;
}
if (!urlSpec.y) {
- urlSpec.y = 32;
+ urlSpec.y = this.$table.data('preview-y') || 32;
}
urlSpec.x *= window.devicePixelRatio;
urlSpec.y *= window.devicePixelRatio;
diff --git a/apps/files_sharing/lib/Controller/ShareController.php b/apps/files_sharing/lib/Controller/ShareController.php
index 409762482db..1e3cbb51028 100644
--- a/apps/files_sharing/lib/Controller/ShareController.php
+++ b/apps/files_sharing/lib/Controller/ShareController.php
@@ -357,6 +357,7 @@ class ShareController extends AuthPublicShareController {
$folder->assign('isPublic', true);
$folder->assign('hideFileList', $hideFileList);
$folder->assign('publicUploadEnabled', 'no');
+ $folder->assign('showgridview', true);
$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
$folder->assign('freeSpace', $freeSpace);
diff --git a/apps/files_sharing/templates/list.php b/apps/files_sharing/templates/list.php
index ec13b5c1f77..de92037a563 100644
--- a/apps/files_sharing/templates/list.php
+++ b/apps/files_sharing/templates/list.php
@@ -10,7 +10,7 @@
<h2><?php p($l->t('No entries found in this folder')); ?></h2>
</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_sharing/tests/js/publicAppSpec.js b/apps/files_sharing/tests/js/publicAppSpec.js
index dc9000af152..9d24a7a7946 100644
--- a/apps/files_sharing/tests/js/publicAppSpec.js
+++ b/apps/files_sharing/tests/js/publicAppSpec.js
@@ -60,7 +60,7 @@ describe('OCA.Sharing.PublicApp 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">' +
diff --git a/apps/files_sharing/tests/js/shareSpec.js b/apps/files_sharing/tests/js/shareSpec.js
index 554a3a82b34..39472fdeedb 100644
--- a/apps/files_sharing/tests/js/shareSpec.js
+++ b/apps/files_sharing/tests/js/shareSpec.js
@@ -28,7 +28,7 @@ describe('OCA.Sharing.Util tests', function() {
// dummy file list
var $div = $(
'<div id="listContainer">' +
- '<table id="filestable">' +
+ '<table id="filestable" class="list-container view-grid">' +
'<thead></thead>' +
'<tbody id="fileList"></tbody>' +
'</table>' +
@@ -510,8 +510,8 @@ describe('OCA.Sharing.Util tests', function() {
OCA.Sharing.Util.attach(fileList);
fileList.setFiles(testFiles);
});
- afterEach(function() {
- shareTabSpy.restore();
+ afterEach(function() {
+ shareTabSpy.restore();
});
it('updates fileInfoModel when shares changed', function() {
diff --git a/apps/files_sharing/tests/js/sharedfilelistSpec.js b/apps/files_sharing/tests/js/sharedfilelistSpec.js
index c9e2bafcc23..b0b7c1b9b99 100644
--- a/apps/files_sharing/tests/js/sharedfilelistSpec.js
+++ b/apps/files_sharing/tests/js/sharedfilelistSpec.js
@@ -28,7 +28,7 @@ describe('OCA.Sharing.FileList 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">' +
'<input type="checkbox" id="select_all_files" class="select-all">' +
@@ -701,7 +701,7 @@ describe('OCA.Sharing.FileList tests', function() {
// dummy file list
var $div = $(
'<div>' +
- '<table id="filestable">' +
+ '<table id="filestable" class="list-container view-grid">' +
'<thead></thead>' +
'<tbody id="fileList"></tbody>' +
'</table>' +
diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php
index dd24abb5de1..054ffee6176 100644
--- a/apps/files_trashbin/templates/index.php
+++ b/apps/files_trashbin/templates/index.php
@@ -18,7 +18,7 @@
<p></p>
</div>
-<table id="filestable">
+<table id="filestable" class="list-container view-grid">
<thead>
<tr>
<th id="headerSelection" class="hidden column-selection">
diff --git a/apps/files_trashbin/tests/js/filelistSpec.js b/apps/files_trashbin/tests/js/filelistSpec.js
index e650a2f2d28..a56ee987b78 100644
--- a/apps/files_trashbin/tests/js/filelistSpec.js
+++ b/apps/files_trashbin/tests/js/filelistSpec.js
@@ -48,7 +48,7 @@ describe('OCA.Trashbin.FileList 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">' +
'<input type="checkbox" id="select_all_trash" class="select-all">' +
'<span class="name">Name</span>' +
diff --git a/core/css/css-variables.scss b/core/css/css-variables.scss
index 2f3e8aa648c..a2946672294 100644
--- a/core/css/css-variables.scss
+++ b/core/css/css-variables.scss
@@ -5,6 +5,7 @@
:root {
--color-main-text: $color-main-text;
--color-main-background: $color-main-background;
+ --color-main-background-translucent: $color-main-background-translucent;
--color-background-dark: $color-background-dark;
--color-background-darker: $color-background-darker;
diff --git a/core/css/icons.scss b/core/css/icons.scss
index ca2a179d48f..5b96d1223a7 100644
--- a/core/css/icons.scss
+++ b/core/css/icons.scss
@@ -297,6 +297,7 @@ img, object, video, button, textarea, input, select, div[contenteditable='true']
@include icon-black-white('toggle', 'actions', 1, true);
@include icon-black-white('toggle-background', 'actions', 1, true);
@include icon-black-white('toggle-pictures', 'actions', 1, true);
+@include icon-black-white('toggle-filelist', 'actions', 1, true);
@include icon-black-white('triangle-e', 'actions', 1, true);
@include icon-black-white('triangle-n', 'actions', 1, true);
@include icon-black-white('triangle-s', 'actions', 1, true);
diff --git a/core/css/styles.scss b/core/css/styles.scss
index 6f65f00df19..5f68a0d08e0 100644
--- a/core/css/styles.scss
+++ b/core/css/styles.scss
@@ -167,7 +167,7 @@ body {
height: 44px;
padding: 0;
margin: 0;
- background-color: var(--color-main-background);
+ background-color: var(--color-main-background-translucent);
z-index: 60;
-webkit-user-select: none;
-moz-user-select: none;
@@ -697,12 +697,15 @@ code {
}
/* ---- DIALOGS ---- */
-
#oc-dialog-filepicker-content {
+ position: relative;
+
.dirtree {
- width: 96%;
+ width: 100%;
flex-wrap: wrap;
padding-left: 12px;
+ padding-right: 44px;
+ box-sizing: border-box;
div:first-child a {
background-image: url('../img/places/home.svg?v=1');
@@ -722,6 +725,28 @@ code {
}
}
}
+
+ /* Grid view toggle */
+ #picker-view-toggle {
+ position: absolute;
+ background-color: transparent;
+ border: none;
+ margin: 0;
+ padding: 22px;
+ opacity: .5;
+ right: 0;
+ top: 0;
+
+ &:hover,
+ &:focus {
+ opacity: 1;
+ }
+ }
+ // keyboard focus
+ #picker-showgridview:focus + #picker-view-toggle {
+ opacity: 1;
+ }
+
.filelist-container {
box-sizing: border-box;
display: inline-block;
@@ -771,9 +796,54 @@ code {
.filesize {
text-align: right;
}
+ &.view-grid {
+ $grid-size: 120px;
+ $grid-pad: 10px;
+ $name-height: 20px;
+ display: flex;
+ flex-direction: column;
+
+ 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;
+ border-radius: var(--border-radius);
+ padding: $grid-pad;
+ display: flex;
+ flex-direction: column;
+ width: $grid-size - 2 * $grid-pad;
+
+ td {
+ border: none;
+ padding: 0;
+
+ &.filename {
+ padding: #{$grid-size - 2 * $grid-pad} 0 0 0;
+ background-position: center top;
+ background-size: contain;
+ line-height: $name-height;
+ height: $name-height;
+ }
+ &.filesize {
+ line-height: $name-height;
+ text-align: left;
+ }
+ &.date {
+ display: none;
+ }
+ }
+ }
+ }
+ }
}
.filepicker_element_selected {
- background-color: lightblue;
+ background-color: var(--color-background-darker);
}
}
diff --git a/core/css/variables.scss b/core/css/variables.scss
index 5a25f07bc34..dffd6403471 100644
--- a/core/css/variables.scss
+++ b/core/css/variables.scss
@@ -33,6 +33,7 @@
// DEPRECATED, please use CSS4 vars
$color-main-text: #222 !default; // Not #000 for better readability
$color-main-background: #fff !default;
+$color-main-background-translucent: rgba($color-main-background, .97) !default;
// used for different active/disabled states
$color-background-dark: nc-darken($color-main-background, 7%) !default;
diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js
index 7369298b8d5..5231a94f333 100644
--- a/core/js/oc-dialogs.js
+++ b/core/js/oc-dialogs.js
@@ -208,6 +208,7 @@ var OCdialogs = {
this.filepicker.loading = true;
this.filepicker.filesClient = (OCA.Sharing && OCA.Sharing.PublicApp && OCA.Sharing.PublicApp.fileList)? OCA.Sharing.PublicApp.fileList.filesClient: OC.Files.getClient();
+
$.when(this._getFilePickerTemplate()).then(function($tmpl) {
self.filepicker.loading = false;
var dialogName = 'oc-dialog-filepicker-content';
@@ -237,6 +238,11 @@ var OCdialogs = {
$('body').append(self.$filePicker);
+ self.$showGridView = $('input#picker-showgridview');
+ self.$showGridView.on('change', _.bind(self._onGridviewChange, self));
+
+ self._getGridSettings();
+
self.$filePicker.ready(function() {
self.$filelist = self.$filePicker.find('.filelist tbody');
self.$dirTree = self.$filePicker.find('.dirtree');
@@ -779,6 +785,31 @@ var OCdialogs = {
//}
return dialogDeferred.promise();
},
+ // get the gridview setting and set the input accordingly
+ _getGridSettings: function() {
+ var self = this;
+ $.get(OC.generateUrl('/apps/files/api/v1/showgridview'), function(response) {
+ self.$showGridView.checked = response.gridview;
+ self.$showGridView.next('#picker-view-toggle')
+ .removeClass('icon-toggle-filelist icon-toggle-pictures')
+ .addClass(response.gridview ? 'icon-toggle-filelist' : 'icon-toggle-pictures')
+ $('.list-container').toggleClass('view-grid', response.gridview);
+ });
+ },
+ _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('#picker-view-toggle')
+ .removeClass('icon-toggle-filelist icon-toggle-pictures')
+ .addClass(show ? 'icon-toggle-filelist' : 'icon-toggle-pictures')
+
+ $('.list-container').toggleClass('view-grid', show);
+ },
_getFilePickerTemplate: function() {
var defer = $.Deferred();
if(!this.$filePickerTemplate) {
@@ -899,6 +930,8 @@ var OCdialogs = {
if (entry.type === 'file') {
var urlSpec = {
file: dir + '/' + entry.name,
+ x: 100,
+ y: 100
};
var img = new Image();
var previewUrl = OC.generateUrl('/core/preview.png?') + $.param(urlSpec);
diff --git a/core/templates/filepicker.html b/core/templates/filepicker.html
index 215311348cb..4c66dfc707b 100644
--- a/core/templates/filepicker.html
+++ b/core/templates/filepicker.html
@@ -1,11 +1,13 @@
<div id="{dialog_name}" title="{title}">
<span class="dirtree breadcrumb"></span>
+ <input type="checkbox" class="hidden-visually" id="picker-showgridview" checked="checked" />
+ <label id="picker-view-toggle" for="picker-showgridview" class="button icon-toggle-filelist"></label>
<div class="filelist-container">
<div class="emptycontent">
<div class="icon-folder"></div>
<h2>{emptytext}</h2>
</div>
- <table id="filestable" class="filelist">
+ <table id="filestable" class="filelist list-container view-grid">
<tbody>
<tr data-entryname="{filename}" data-type="{type}">
<td class="filename"