From b563528be7ca41015d6920c6dc73340b78436776 Mon Sep 17 00:00:00 2001 From: RainLoop Team Date: Wed, 28 Jan 2015 02:16:00 +0400 Subject: [PATCH] Sortable accounts list --- dev/App/User.js | 25 ++++++----- dev/Settings/User/Accounts.js | 14 ++++-- dev/Storage/User/Data.js | 4 -- dev/Storage/User/Remote.js | 11 +++++ dev/Stores/User/Account.js | 44 +++++++++++++++++++ dev/View/Popup/Compose.js | 25 ++++++++--- dev/View/User/AbstractSystemDropDown.js | 6 ++- .../0.0.0/app/libraries/RainLoop/Actions.php | 37 ++++++++++++++++ .../app/libraries/RainLoop/KeyPathHelper.php | 10 +++++ .../Views/User/SettingsAccounts.html | 2 +- 10 files changed, 150 insertions(+), 28 deletions(-) create mode 100644 dev/Stores/User/Account.js diff --git a/dev/App/User.js b/dev/App/User.js index 3f7df8e7c..5ec776440 100644 --- a/dev/App/User.js +++ b/dev/App/User.js @@ -22,7 +22,8 @@ kn = require('Knoin/Knoin'), SocialStore = require('Stores/Social'), - SettingsUserStore = require('Stores/User/Settings'), + SettingsStore = require('Stores/User/Settings'), + AccountStore = require('Stores/User/Account'), Local = require('Storage/Client'), Settings = require('Storage/Settings'), @@ -153,7 +154,7 @@ { var self = this, - iOffset = (Data.messageListPage() - 1) * SettingsUserStore.messagesPerPage() + iOffset = (Data.messageListPage() - 1) * SettingsStore.messagesPerPage() ; if (Utils.isUnd(bDropCurrenFolderCache) ? false : !!bDropCurrenFolderCache) @@ -190,12 +191,12 @@ ); } - }, Data.currentFolderFullNameRaw(), iOffset, SettingsUserStore.messagesPerPage(), Data.messageListSearch()); + }, Data.currentFolderFullNameRaw(), iOffset, SettingsStore.messagesPerPage(), Data.messageListSearch()); }; AppUser.prototype.recacheInboxMessageList = function () { - Remote.messageList(Utils.emptyFunction, Cache.getFolderInboxName(), 0, SettingsUserStore.messagesPerPage(), '', true); + Remote.messageList(Utils.emptyFunction, Cache.getFolderInboxName(), 0, SettingsStore.messagesPerPage(), '', true); }; AppUser.prototype.reloadMessageListHelper = function (bEmptyList) @@ -494,7 +495,7 @@ Remote.accountsCounts(function (sResult, oData) { if (Enums.StorageResultType.Success === sResult && oData.Result && oData.Result['Counts']) { - var aAcounts = Data.accounts(); + var aAcounts = AccountStore.collection(); _.each(oData.Result['Counts'], function (oItem) { @@ -515,12 +516,12 @@ { var self = this; - Data.accountsLoading(true); + AccountStore.loading(true); Data.identitiesLoading(true); Remote.accountsAndIdentities(function (sResult, oData) { - Data.accountsLoading(false); + AccountStore.loading(false); Data.identitiesLoading(false); if (Enums.StorageResultType.Success === sResult && oData.Result) @@ -535,13 +536,13 @@ if (Utils.isArray(oData.Result['Accounts'])) { - _.each(Data.accounts(), function (oAccount) { + _.each(AccountStore.collection(), function (oAccount) { aCounts[oAccount.email] = oAccount.count(); }); - Utils.delegateRunOnDestroy(Data.accounts()); + Utils.delegateRunOnDestroy(AccountStore.collection()); - Data.accounts(_.map(oData.Result['Accounts'], function (sValue) { + AccountStore.collection(_.map(oData.Result['Accounts'], function (sValue) { return new AccountModel(sValue, sValue !== sParentEmail, aCounts[sValue] || 0); })); } @@ -994,7 +995,7 @@ Data.messageListCount(iCount); Data.messageListSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); - Data.messageListPage(window.Math.ceil((iOffset / SettingsUserStore.messagesPerPage()) + 1)); + Data.messageListPage(window.Math.ceil((iOffset / SettingsStore.messagesPerPage()) + 1)); Data.messageListEndFolder(Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : ''); Data.messageListEndSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); Data.messageListEndPage(Data.messageListPage()); @@ -1009,7 +1010,7 @@ Cache.clearNewMessageCache(); - if (oFolder && (bCached || bUnreadCountChange || SettingsUserStore.useThreads())) + if (oFolder && (bCached || bUnreadCountChange || SettingsStore.useThreads())) { this.folderInformation(oFolder.fullNameRaw, aList); } diff --git a/dev/Settings/User/Accounts.js b/dev/Settings/User/Accounts.js index 217ba52ad..0b2b87278 100644 --- a/dev/Settings/User/Accounts.js +++ b/dev/Settings/User/Accounts.js @@ -12,7 +12,8 @@ Translator = require('Common/Translator'), Links = require('Common/Links'), - Data = require('Storage/User/Data'), + AccountStore = require('Stores/User/Account'), + Remote = require('Storage/User/Remote') ; @@ -21,10 +22,10 @@ */ function AccountsUserSettings() { - this.accounts = Data.accounts; + this.accounts = AccountStore.collection; this.processText = ko.computed(function () { - return Data.accountsLoading() ? Translator.i18n('SETTINGS_ACCOUNTS/LOADING_PROCESS') : ''; + return AccountStore.loading() ? Translator.i18n('SETTINGS_ACCOUNTS/LOADING_PROCESS') : ''; }, this); this.visibility = ko.computed(function () { @@ -46,6 +47,13 @@ ]}); } + AccountsUserSettings.prototype.scrollableOptions = function () + { + return { + + }; + }; + AccountsUserSettings.prototype.addNewAccount = function () { require('Knoin/Knoin').showScreenPopup(require('View/Popup/AddAccount')); diff --git a/dev/Storage/User/Data.js b/dev/Storage/User/Data.js index 836011c87..0a5d3e4c1 100644 --- a/dev/Storage/User/Data.js +++ b/dev/Storage/User/Data.js @@ -99,10 +99,6 @@ // security this.enableTwoFactor = ko.observable(false); - // accounts - this.accounts = ko.observableArray([]); - this.accountsLoading = ko.observable(false).extend({'throttle': 100}); - // identities this.defaultIdentityID = ko.observable(''); this.identities = ko.observableArray([]); diff --git a/dev/Storage/User/Remote.js b/dev/Storage/User/Remote.js index 11127a787..ed75f0a5c 100644 --- a/dev/Storage/User/Remote.js +++ b/dev/Storage/User/Remote.js @@ -184,6 +184,17 @@ }); }; + /** + * @param {?Function} fCallback + * @param {Array} aAccounts + */ + RemoteUserStorage.prototype.accountSortOrder = function (fCallback, aAccounts) + { + this.defaultRequest(fCallback, 'AccountSortOrder', { + 'Accounts': aAccounts + }); + }; + /** * @param {?Function} fCallback * @param {string} sId diff --git a/dev/Stores/User/Account.js b/dev/Stores/User/Account.js new file mode 100644 index 000000000..ebe1f87ff --- /dev/null +++ b/dev/Stores/User/Account.js @@ -0,0 +1,44 @@ + +(function () { + + 'use strict'; + + var + _ = require('_'), + ko = require('ko'), + + Remote = require('Storage/User/Remote') + ; + + /** + * @constructor + */ + function AccountUserStore() + { + this.loading = ko.observable(false).extend({'throttle': 100}); + + this.collection = ko.observableArray([]); + this.collectionEmailNames = ko.observableArray([]).extend({'throttle': 1000}); + this.collectionEmailNames.skipFirst = true; + + this.collection.subscribe(function (aList) { + this.collectionEmailNames(_.compact(_.map(aList, function (oItem) { + return oItem ? oItem.email : null; + }))); + }, this); + + this.collectionEmailNames.subscribe(function (aList) { + if (this.collectionEmailNames.skipFirst) + { + this.collectionEmailNames.skipFirst = false; + } + else if (aList && 1 < aList.length) + { + Remote.accountSortOrder(null, aList); + } + }, this); + } + + module.exports = new AccountUserStore(); + +}()); diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 9bfd53462..4eddf0ec3 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -770,22 +770,35 @@ sFrom = Utils.pString(sFrom); if ('' !== sFrom) { + sSignature = sSignature.replace(/{{FROM-FULL}}/g, sFrom); + + if (-1 === sFrom.indexOf(' ') && 0 < sFrom.indexOf('@')) + { + sFrom = sFrom.replace(/@(.+)$/, ''); + } + sSignature = sSignature.replace(/{{FROM}}/g, sFrom); } sSignature = sSignature.replace(/[\s]{1,2}{{FROM}}/g, '{{FROM}}'); + sSignature = sSignature.replace(/[\s]{1,2}{{FROM-FULL}}/g, '{{FROM-FULL}}'); sSignature = sSignature.replace(/{{FROM}}/g, ''); - sSignature = sSignature.replace(/{{DATE}}/g, moment().format('llll')); + sSignature = sSignature.replace(/{{FROM-FULL}}/g, ''); - if (sData && Enums.ComposeType.Empty === sComposeType && - -1 < sSignature.indexOf('{{DATA}}')) + if (-1 < sSignature.indexOf('{{DATE}}')) { - bData = true; - sSignature = sSignature.replace('{{DATA}}', sData); + sSignature = sSignature.replace(/{{DATE}}/g, moment().format('llll')); } - sSignature = sSignature.replace(/{{DATA}}/g, ''); + if (sData && Enums.ComposeType.Empty === sComposeType && + -1 < sSignature.indexOf('{{BODY}}')) + { + bData = true; + sSignature = sSignature.replace('{{BODY}}', sData); + } + + sSignature = sSignature.replace(/{{BODY}}/g, ''); if (!bHtml) { diff --git a/dev/View/User/AbstractSystemDropDown.js b/dev/View/User/AbstractSystemDropDown.js index 4d1a09258..92893e5ac 100644 --- a/dev/View/User/AbstractSystemDropDown.js +++ b/dev/View/User/AbstractSystemDropDown.js @@ -12,6 +12,8 @@ Utils = require('Common/Utils'), Links = require('Common/Links'), + AccountStore = require('Stores/User/Account'), + Settings = require('Storage/Settings'), Data = require('Storage/User/Data'), Remote = require('Storage/User/Remote'), @@ -27,9 +29,9 @@ { AbstractView.call(this, 'Right', 'SystemDropDown'); - this.accounts = Data.accounts; + this.accounts = AccountStore.collection; this.accountEmail = Data.accountEmail; - this.accountsLoading = Data.accountsLoading; + this.accountsLoading = AccountStore.loading; this.accountMenuDropdownTrigger = ko.observable(false); diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index 2904a799f..3de0a3ea5 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -1891,6 +1891,21 @@ class Actions if (1 === \count($aAccounts)) { $this->SetAccounts($oAccount, array()); + + } + else if (1 < \count($aAccounts)) + { + $sOrder = $this->StorageProvider()->Get(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + \RainLoop\KeyPathHelper::WebmailAccountsOrder($sParentEmail), + null + ); + + $aOrder = empty($sOrder) ? array() : @\json_decode($sOrder, true); + if (\is_array($aAccounts) && \is_array($aOrder) && 0 < \count($aOrder)) + { + $aAccounts = \array_merge(\array_flip($aOrder), $aAccounts); + } } return $aAccounts; @@ -2276,6 +2291,28 @@ class Actions return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aNew)); } + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoAccountSortOrder() + { + $oAccount = $this->getAccountFromToken(); + + $aList = $this->GetActionParam('Accounts', null); + if (!\is_array($aList) || 2 > \count($aList)) + { + return $this->FalseResponse(__FUNCTION__); + } + + return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + \RainLoop\KeyPathHelper::WebmailAccountsOrder($oAccount->ParentEmailHelper()), + \json_encode($aList) + )); + } + /** * @return array * diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php b/rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php index f4dd99fc3..b2d5242b1 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php @@ -24,6 +24,16 @@ class KeyPathHelper return 'Webmail/Accounts/'.$sEmail.'/Array'; } + /** + * @param string $sEmail + * + * @return string + */ + static public function WebmailAccountsOrder($sEmail) + { + return 'Webmail/AccountsSortOrder/'.$sEmail.'/Array'; + } + /** * @param string $sHash * diff --git a/rainloop/v/0.0.0/app/templates/Views/User/SettingsAccounts.html b/rainloop/v/0.0.0/app/templates/Views/User/SettingsAccounts.html index 012781a9c..ef3e81a8b 100644 --- a/rainloop/v/0.0.0/app/templates/Views/User/SettingsAccounts.html +++ b/rainloop/v/0.0.0/app/templates/Views/User/SettingsAccounts.html @@ -20,7 +20,7 @@ - +