aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files')
-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
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">' +