From f535e16011b819384f4f002ea8b77956f41fe1b0 Mon Sep 17 00:00:00 2001 From: Christoph Wurst Date: Sat, 19 Nov 2016 19:58:56 +0100 Subject: [PATCH] render folders using the composite pattern (tree view) * accounts have folders * folders have subfolders Signed-off-by: Christoph Wurst --- css/mail.css | 6 --- js/templates/account.html | 4 +- js/templates/folder.html | 47 +++++--------------- js/views/{account.js => accountview.js} | 44 +++++++------------ js/views/folderlistview.js | 41 +++++++++++++++++ js/views/{folder.js => folderview.js} | 58 +++++++++++++++++-------- js/views/navigation-accounts.js | 2 +- 7 files changed, 111 insertions(+), 91 deletions(-) rename js/views/{account.js => accountview.js} (79%) create mode 100644 js/views/folderlistview.js rename js/views/{folder.js => folderview.js} (58%) diff --git a/css/mail.css b/css/mail.css index 4cfafb6930..9c49334d9a 100755 --- a/css/mail.css +++ b/css/mail.css @@ -167,12 +167,6 @@ padding-left: 32px; } -#app-navigation .with-icon ul li > a, -#app-navigation .with-icon ul li.app-navigation-entry-loading > a { - padding-left: 68px; - background-position: 44px center; -} - #app-navigation ul .collapsible.open:hover { box-shadow: inset 0 0 3px #ddd; } diff --git a/js/templates/account.html b/js/templates/account.html index f5f83f1c8f..07c27f6343 100644 --- a/js/templates/account.html +++ b/js/templates/account.html @@ -20,9 +20,7 @@ {{/if}} - - +
{{#unless isUnifiedInbox}} {{#if hasFolders}} diff --git a/js/templates/folder.html b/js/templates/folder.html index c54bac2b8c..b6f568ecfe 100644 --- a/js/templates/folder.html +++ b/js/templates/folder.html @@ -1,35 +1,12 @@ -
  • - {{#if folders}}{{/if}} - - {{name}} - {{#if count}} - {{count}} - {{/if}} - - -
  • \ No newline at end of file +{{#if folders}} + +{{/if}} + + {{name}} + {{#if count}} + {{count}} + {{/if}} + +
    \ No newline at end of file diff --git a/js/views/account.js b/js/views/accountview.js similarity index 79% rename from js/views/account.js rename to js/views/accountview.js index 1bc2509039..62dfb33419 100644 --- a/js/views/account.js +++ b/js/views/accountview.js @@ -15,19 +15,10 @@ define(function(require) { var Marionette = require('marionette'); var OC = require('OC'); var Radio = require('radio'); - var FolderView = require('views/folder'); + var FolderListView = require('views/folderlistview'); var AccountTemplate = require('text!templates/account.html'); - var SHOW_COLLAPSED = Object.seal([ - 'inbox', - 'flagged', - 'drafts', - 'sent' - ]); - - return Marionette.CompositeView.extend({ - collection: null, - model: null, + return Marionette.View.extend({ template: Handlebars.compile(AccountTemplate), templateContext: function() { var toggleCollapseMessage = this.collapsed ? t('mail', 'Show all folders') : t('mail', 'Collapse folders'); @@ -35,10 +26,9 @@ define(function(require) { isUnifiedInbox: this.model.get('accountId') === -1, toggleCollapseMessage: toggleCollapseMessage, hasMenu: this.model.get('accountId') !== -1, - hasFolders: this.collection.length > 0 + hasFolders: this.model.folders.length > 0 }; }, - collapsed: true, events: { 'click .account-toggle-collapse': 'toggleCollapse', 'click .app-navigation-entry-utils-menu-button button': 'toggleMenu', @@ -46,27 +36,20 @@ define(function(require) { 'click @ui.settingsButton': 'showAccountSettings', 'click @ui.email': 'onClick' }, + regions: { + folders: '.folders' + }, ui: { - 'email': '.mail-account-email', - 'menu': 'div.app-navigation-entry-menu', - 'deleteButton': 'button[class^="icon-delete"]', - 'settingsButton': 'button[class^="icon-rename"]' + email: '.mail-account-email', + menu: 'div.app-navigation-entry-menu', + deleteButton: 'button[class^="icon-delete"]', + settingsButton: 'button[class^="icon-rename"]' }, - // 'active' is needed to show the dotdotdot menu className: 'navigation-account', - childView: FolderView, - childViewContainer: '#mail_folders', menuShown: false, + collapsed: true, initialize: function(options) { this.model = options.model; - this.collection = this.model.folders; - }, - filter: function(child) { - if (!this.collapsed) { - return true; - } - var specialRole = child.get('specialRole'); - return SHOW_COLLAPSED.indexOf(specialRole) !== -1; }, toggleCollapse: function() { this.collapsed = !this.collapsed; @@ -120,6 +103,11 @@ define(function(require) { this.toggleMenuClass(); } }); + + this.showChildView('folders', new FolderListView({ + collection: this.model.folders, + collapsed: this.collapsed + })); }, showAccountSettings: function(e) { this.toggleMenu(e); diff --git a/js/views/folderlistview.js b/js/views/folderlistview.js new file mode 100644 index 0000000000..b1864385ef --- /dev/null +++ b/js/views/folderlistview.js @@ -0,0 +1,41 @@ +/** + * Mail + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Christoph Wurst + * @copyright Christoph Wurst 2016 + */ + +define(function(require) { + 'use strict'; + + var Marionette = require('marionette'); + var FolderView = require('views/folderview'); + + var SHOW_COLLAPSED = Object.seal([ + 'inbox', + 'flagged', + 'drafts', + 'sent' + ]); + + var FolderListView = Marionette.CollectionView.extend({ + tagName: 'ul', + childView: FolderView, + collapsed: true, + initialize: function(options) { + this.collapsed = options.collapsed; + }, + filter: function(child) { + if (!this.collapsed) { + return true; + } + var specialRole = child.get('specialRole'); + return SHOW_COLLAPSED.indexOf(specialRole) !== -1; + } + }); + + return FolderListView; +}); diff --git a/js/views/folder.js b/js/views/folderview.js similarity index 58% rename from js/views/folder.js rename to js/views/folderview.js index c81fa88210..d86c16090e 100644 --- a/js/views/folder.js +++ b/js/views/folderview.js @@ -11,14 +11,39 @@ define(function(require) { 'use strict'; - var $ = require('jquery'); - var Backbone = require('backbone'); + var _ = require('underscore'); + var Marionette = require('marionette'); var Handlebars = require('handlebars'); var OC = require('OC'); var Radio = require('radio'); var FolderTemplate = require('text!templates/folder.html'); - return Backbone.Marionette.View.extend({ + return Marionette.View.extend({ + tagName: 'li', + updateElClasses: function() { + var classes = []; + if (this.model.get('unseen')) { + classes.push('unseen'); + } + if (this.model.get('active')) { + classes.push('active'); + } + if (this.model.get('specialRole')) { + classes.push('special-' + this.model.get('specialRole')); + } + if (this.model.folders.length > 0) { + classes.push('collapsible'); + } + if (this.model.get('open')) { + classes.push('open'); + } + // .removeClass() does not work, https://bugs.jqueryui.com/ticket/9015 + this.$el.prop('class', ''); + var _this = this; + _.each(classes, function(clazz) { + _this.$el.addClass(clazz); + }); + }, template: Handlebars.compile(FolderTemplate), templateContext: function() { var count = null; @@ -39,6 +64,9 @@ define(function(require) { url: url }; }, + regions: { + folders: '.folders' + }, events: { 'click .collapse': 'collapseFolder', 'click .folder': 'loadFolder' @@ -54,24 +82,18 @@ define(function(require) { e.preventDefault(); // TODO: account should be property of folder var account = require('state').accounts.get(this.model.get('accountId')); - var folderId = $(e.currentTarget).parent().data('folder_id'); - var folder = null; - if (folderId === this.model.get('id')) { - folder = this.model; - } else { - folder = this.model.folders.get(folderId); - } - var noSelect = $(e.currentTarget).parent().data('no_select'); + var folder = this.model; + var noSelect = this.model.get('noSelect'); Radio.navigation.trigger('folder', account.get('accountId'), folder.get('id'), noSelect); }, onRender: function() { - // Get rid of that pesky wrapping-div. - // Assumes 1 child element present in template. - this.$el = this.$el.children(); - // Unwrap the element to prevent infinitely - // nesting elements during re-render. - this.$el.unwrap(); - this.setElement(this.$el); + var FolderListView = require('views/folderlistview'); + + this.showChildView('folders', new FolderListView({ + collection: this.model.folders + })); + + this.updateElClasses(); } }); }); diff --git a/js/views/navigation-accounts.js b/js/views/navigation-accounts.js index 1c1706e89c..ca6e67a72d 100644 --- a/js/views/navigation-accounts.js +++ b/js/views/navigation-accounts.js @@ -14,7 +14,7 @@ define(function(require) { var _ = require('underscore'); var $ = require('jquery'); var Marionette = require('marionette'); - var AccountView = require('views/account'); + var AccountView = require('views/accountview'); var Radio = require('radio'); /**