Merged from sub repository (filters - step 4)

This commit is contained in:
RainLoop Team 2014-12-18 00:53:46 +04:00
parent 67e45a6a6f
commit e4b286e257
58 changed files with 1176 additions and 236 deletions

View file

@ -75,6 +75,20 @@
Events.pub('interval.10m');
}, 60000 * 10);
window.setInterval(function () {
Events.pub('interval.15m');
}, 60000 * 15);
window.setInterval(function () {
Events.pub('interval.20m');
}, 60000 * 15);
window.setTimeout(function () {
window.setInterval(function () {
Events.pub('interval.5m-after5m');
}, 60000 * 5);
}, 60000 * 5);
window.setTimeout(function () {
window.setInterval(function () {
Events.pub('interval.10m-after5m');
@ -476,8 +490,32 @@
}
};
AppUser.prototype.accountsAndIdentities = function ()
AppUser.prototype.accountsCounts = function ()
{
Remote.accountsCounts(function (sResult, oData) {
if (Enums.StorageResultType.Success === sResult && oData.Result && oData.Result['Counts'])
{
var aAcounts = Data.accounts();
_.each(oData.Result['Counts'], function (oItem) {
var oAccount = _.find(aAcounts, function (oAccount) {
return oAccount && oItem[0] === oAccount.email;
});
if (oAccount)
{
oAccount.count(Utils.pInt(oItem[1]));
}
});
}
});
};
AppUser.prototype.accountsAndIdentities = function (bBoot)
{
var self = this;
Data.accountsLoading(true);
Data.identitiesLoading(true);
@ -489,6 +527,7 @@
if (Enums.StorageResultType.Success === sResult && oData.Result)
{
var
aCounts = {},
sParentEmail = Settings.settingsGet('ParentEmail'),
sAccountEmail = Data.accountEmail()
;
@ -497,12 +536,22 @@
if (Utils.isArray(oData.Result['Accounts']))
{
_.each(Data.accounts(), function (oAccount) {
aCounts[oAccount.email] = oAccount.count();
});
Utils.delegateRunOnDestroy(Data.accounts());
Data.accounts(_.map(oData.Result['Accounts'], function (sValue) {
return new AccountModel(sValue, sValue !== sParentEmail);
return new AccountModel(sValue, sValue !== sParentEmail, aCounts[sValue] || 0);
}));
}
if (Utils.isUnd(bBoot) ? false : !!bBoot)
{
self.accountsCounts();
}
if (Utils.isArray(oData.Result['Identities']))
{
Utils.delegateRunOnDestroy(Data.identities());
@ -723,8 +772,9 @@
});
if (bBoot)
{
self.folderInformationMultiply(true);
{ _.delay(function () {
self.folderInformationMultiply(true);
}, 2000);
}
}
}
@ -1342,7 +1392,7 @@
self.folderInformation(Cache.getFolderInboxName());
});
Events.sub('interval.2m', function () {
Events.sub('interval.3m', function () {
var sF = Data.currentFolderFullNameRaw();
if (Cache.getFolderInboxName() !== sF)
{
@ -1350,15 +1400,15 @@
}
});
Events.sub('interval.3m', function () {
Events.sub('interval.5m-after5m', function () {
self.folderInformationMultiply();
});
Events.sub('interval.5m', function () {
Events.sub('interval.15m', function () {
self.quota();
});
Events.sub('interval.10m', function () {
Events.sub('interval.20m', function () {
self.folders();
});
@ -1379,7 +1429,7 @@
if (Settings.capa(Enums.Capa.AdditionalAccounts) || Settings.capa(Enums.Capa.AdditionalIdentities))
{
self.accountsAndIdentities();
self.accountsAndIdentities(true);
}
_.delay(function () {

View file

@ -1253,9 +1253,11 @@
return sResult;
};
Utils.draggeblePlace = function ()
Utils.draggablePlace = function ()
{
return $('<div class="draggablePlace"><span class="text"></span>&nbsp;<i class="icon-copy icon-white visible-on-ctrl"></i><i class="icon-mail icon-white hidden-on-ctrl"></i></div>').appendTo('#rl-hidden');
return $('<div class="draggablePlace">' +
'<span class="text"></span>&nbsp;' +
'<i class="icon-copy icon-white visible-on-ctrl"></i><i class="icon-mail icon-white hidden-on-ctrl"></i></div>').appendTo('#rl-hidden');
};
Utils.defautOptionsAfterRender = function (oDomOption, oItem)

24
dev/External/ko.js vendored
View file

@ -793,6 +793,30 @@
return oTarget;
};
ko.extenders.toggleSubscribeProperty = function (oTarget, oOptions)
{
var sProp = oOptions[1];
if (sProp)
{
oTarget.subscribe(function (oPrev) {
if (oPrev && oPrev[sProp])
{
oPrev[sProp](false);
}
}, oOptions[0], 'beforeChange');
oTarget.subscribe(function (oNext) {
if (oNext && oNext[sProp])
{
oNext[sProp](true);
}
}, oOptions[0]);
}
return oTarget;
};
ko.extenders.falseTimeout = function (oTarget, iOption)
{
var Utils = require('Common/Utils');

View file

@ -17,13 +17,16 @@
*
* @param {string} sEmail
* @param {boolean=} bCanBeDelete = true
* @param {number=} iCount = 0
*/
function AccountModel(sEmail, bCanBeDelete)
function AccountModel(sEmail, bCanBeDelete, iCount)
{
AbstractModel.call(this, 'AccountModel');
this.email = sEmail;
this.count = ko.observable(iCount || 0);
this.deleteAccess = ko.observable(false);
this.canBeDalete = ko.observable(Utils.isUnd(bCanBeDelete) ? true : !!bCanBeDelete);
this.canBeEdit = this.canBeDalete;

View file

@ -21,42 +21,20 @@
{
AbstractModel.call(this, 'FilterModel');
this.isNew = ko.observable(true);
this.enabled = ko.observable(true);
this.name = ko.observable('');
this.conditionsType = ko.observable(Enums.FilterRulesType.All);
this.name.error = ko.observable(false);
this.name.focused = ko.observable(false);
this.conditions = ko.observableArray([]);
this.conditionsType = ko.observable(Enums.FilterRulesType.All);
// Actions
this.actionMarkAsRead = ko.observable(false);
this.actionSkipOtherFilters = ko.observable(true);
this.actionValue = ko.observable('');
this.actionMarkAsRead = ko.observable(false);
this.actionType = ko.observable(Enums.FiltersAction.Move);
this.actionTypeOptions = [ // TODO i18n
{'id': Enums.FiltersAction.None, 'name': 'None'},
{'id': Enums.FiltersAction.Move, 'name': ' Move to'},
// {'id': Enums.FiltersAction.Forward, 'name': 'Forward to'},
{'id': Enums.FiltersAction.Discard, 'name': 'Discard'}
];
this.enableSkipOtherFilters = ko.computed(function () {
return -1 === Utils.inArray(this.actionType(), [
Enums.FiltersAction.Move, Enums.FiltersAction.Forward, Enums.FiltersAction.Discard
]);
}, this);
this.actionSkipOtherFiltersResult = ko.computed({
'read': function () {
return this.actionSkipOtherFilters() ||
!this.enableSkipOtherFilters();
},
'write': this.actionSkipOtherFilters,
'owner': this
});
this.actionTemplate = ko.computed(function () {
@ -84,14 +62,42 @@
Utils.windowResize();
}));
this.regDisposables([this.enableSkipOtherFilters, this.actionSkipOtherFiltersResult, this.actionTemplate]);
this.regDisposables(this.name.subscribe(function (sValue) {
this.name.error('' === sValue);
}, this));
this.regDisposables([this.actionTemplate]);
this.deleteAccess = ko.observable(false);
this.canBeDalete = ko.observable(true);
}
_.extend(FilterModel.prototype, AbstractModel.prototype);
FilterModel.prototype.toJson = function ()
{
return {
'Enabled': this.enabled(),
'Name': this.name(),
'ConditionsType': this.conditionsType(),
'Conditions': _.map(this.conditions(), function (oItem) {
return oItem.toJson();
}),
'ActionMarkAsRead': this.actionMarkAsRead(),
'ActionValue': this.actionValue(),
'ActionType': this.actionType()
};
};
FilterModel.prototype.addCondition = function ()
{
this.conditions.push(new FilterConditionModel(this.conditions));
this.conditions.push(new FilterConditionModel());
};
FilterModel.prototype.removeCondition = function (oConditionToDelete)
{
this.conditions.remove(oConditionToDelete);
Utils.delegateRunOnDestroy(oConditionToDelete);
};
FilterModel.prototype.parse = function (oItem)
@ -107,6 +113,29 @@
return bResult;
};
FilterModel.prototype.cloneSelf = function ()
{
var oClone = new FilterModel();
oClone.enabled(this.enabled());
oClone.name(this.name());
oClone.name.error(this.name.error());
oClone.conditionsType(this.conditionsType());
oClone.actionMarkAsRead(this.actionMarkAsRead());
oClone.actionValue(this.actionValue());
oClone.actionType(this.actionType());
oClone.conditions(_.map(this.conditions(), function (oCondition) {
return oCondition.cloneSelf();
}));
return oClone;
};
module.exports = FilterModel;
}());

View file

@ -16,29 +16,12 @@
* @param {*} oKoList
* @constructor
*/
function FilterConditionModel(oKoList)
function FilterConditionModel()
{
AbstractModel.call(this, 'FilterConditionModel');
this.parentList = oKoList;
this.field = ko.observable(Enums.FilterConditionField.From);
this.fieldOptions = [ // TODO i18n
{'id': Enums.FilterConditionField.From, 'name': 'From'},
{'id': Enums.FilterConditionField.Recipient, 'name': 'Recipient (To or CC)'},
{'id': Enums.FilterConditionField.Subject, 'name': 'Subject'}
];
this.type = ko.observable(Enums.FilterConditionType.EqualTo);
this.typeOptions = [ // TODO i18n
{'id': Enums.FilterConditionType.EqualTo, 'name': 'Equal To'},
{'id': Enums.FilterConditionType.NotEqualTo, 'name': 'Not Equal To'},
{'id': Enums.FilterConditionType.Contains, 'name': 'Contains'},
{'id': Enums.FilterConditionType.NotContains, 'name': 'Not Contains'}
];
this.value = ko.observable('');
this.template = ko.computed(function () {
@ -60,9 +43,24 @@
_.extend(FilterConditionModel.prototype, AbstractModel.prototype);
FilterConditionModel.prototype.removeSelf = function ()
FilterConditionModel.prototype.toJson = function ()
{
this.parentList.remove(this);
return {
'Field': this.field(),
'Type': this.type(),
'Value': this.value()
};
};
FilterConditionModel.prototype.cloneSelf = function ()
{
var oClone = new FilterConditionModel();
oClone.field(this.field());
oClone.type(this.type());
oClone.value(this.value());
return oClone;
};
module.exports = FilterConditionModel;

View file

@ -6,7 +6,10 @@
var
ko = require('ko'),
Utils = require('Common/Utils')
Enums = require('Common/Enums'),
Utils = require('Common/Utils'),
Remote = require('Storage/User/Remote')
;
/**
@ -14,14 +17,80 @@
*/
function FiltersUserSettings()
{
var self = this;
this.haveChanges = ko.observable(false);
this.processText = ko.observable('');
this.visibility = ko.observable(false);
this.filters = ko.observableArray([]);
this.filters.loading = ko.observable(false);
this.filters.loading = ko.observable(false).extend({'throttle': 200});
this.filters.saving = ko.observable(false).extend({'throttle': 200});
this.filters.subscribe(function () {
Utils.windowResize();
});
this.processText = ko.computed(function () {
return this.filters.loading() ? Utils.i18n('SETTINGS_FILTERS/LOADING_PROCESS') : '';
}, this);
this.visibility = ko.computed(function () {
return '' === this.processText() ? 'hidden' : 'visible';
}, this);
this.filterForDeletion = ko.observable(null).extend({'falseTimeout': 3000}).extend(
{'toggleSubscribeProperty': [this, 'deleteAccess']});
this.saveChanges = Utils.createCommand(this, function () {
if (!this.filters.saving())
{
this.filters.saving(true);
Remote.filtersSave(function (sResult, oData) {
self.filters.saving(false);
if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
{
self.haveChanges(false);
self.updateList();
}
}, this.filters());
}
return true;
}, function () {
return this.haveChanges();
});
this.filters.subscribe(function () {
this.haveChanges(true);
}, this);
}
FiltersUserSettings.prototype.scrollableOptions = function ()
{
return {
// handle: '.drag-handle'
};
};
FiltersUserSettings.prototype.updateList = function ()
{
var self = this;
this.filters.loading(true);
// Remote.filtersGet(function (sResult, oData) {
self.filters.loading(false);
// });
};
FiltersUserSettings.prototype.deleteFilter = function (oFilter)
{
this.filters.remove(oFilter);
@ -31,11 +100,60 @@
FiltersUserSettings.prototype.addFilter = function ()
{
var
FilterModel = require('Model/Filter')
self = this,
FilterModel = require('Model/Filter'),
oNew = new FilterModel()
;
require('Knoin/Knoin').showScreenPopup(
require('View/Popup/Filter'), [new FilterModel()]);
require('View/Popup/Filter'), [oNew, function () {
self.filters.push(oNew);
self.haveChanges(true);
}, false]);
};
FiltersUserSettings.prototype.editFilter = function (oEdit)
{
var
self = this,
oCloned = oEdit.cloneSelf()
;
require('Knoin/Knoin').showScreenPopup(
require('View/Popup/Filter'), [oCloned, function () {
var
oFilters = self.filters(),
iIndex = oFilters.indexOf(oEdit)
;
if (-1 < iIndex && oFilters[iIndex])
{
Utils.delegateRunOnDestroy(oFilters[iIndex]);
oFilters[iIndex] = oCloned;
self.filters(oFilters);
self.haveChanges(true);
}
}, false]);
};
FiltersUserSettings.prototype.onBuild = function (oDom)
{
var self = this;
oDom
.on('click', '.filter-item .e-action', function () {
var oFilterItem = ko.dataFor(this);
if (oFilterItem)
{
self.editFilter(oFilterItem);
}
})
;
this.updateList();
};
module.exports = FiltersUserSettings;

View file

@ -129,15 +129,11 @@
{
this.identityForDeletion(null);
var
fRemoveFolder = function (oIdentity) {
return oIdentityToRemove === oIdentity;
}
;
if (oIdentityToRemove)
{
this.identities.remove(fRemoveFolder);
this.identities.remove(function (oIdentity) {
return oIdentityToRemove === oIdentity;
});
Remote.identityDelete(function () {
require('App/User').accountsAndIdentities();

View file

@ -631,8 +631,8 @@
iUtc = moment().unix(),
iTimeout = iUtc - 60 * 5,
aTimeouts = [],
sInboxFolderName = Cache.getFolderInboxName(),
fSearchFunction = function (aList) {
var sInboxFolderName = Cache.getFolderInboxName();
_.each(aList, function (oFolder) {
if (oFolder && sInboxFolderName !== oFolder.fullNameRaw &&
oFolder.selectable && oFolder.existen &&
@ -653,12 +653,9 @@
fSearchFunction(this.folderList());
aTimeouts.sort(function(a, b) {
if (a[0] < b[0])
{
if (a[0] < b[0]) {
return -1;
}
else if (a[0] > b[0])
{
} else if (a[0] > b[0]) {
return 1;
}

View file

@ -221,6 +221,35 @@
this.defaultRequest(fCallback, 'AccountsAndIdentities');
};
/**
* @param {?Function} fCallback
*/
RemoteUserStorage.prototype.accountsCounts = function (fCallback)
{
this.defaultRequest(fCallback, 'AccountsCounts');
};
/**
* @param {?Function} fCallback
*/
RemoteUserStorage.prototype.filtersSave = function (fCallback, aFilters)
{
this.defaultRequest(fCallback, 'FiltersSave', {
'Filters': _.map(aFilters, function (oItem) {
return oItem.toJson();
})
});
};
/**
* @param {?Function} fCallback
*/
RemoteUserStorage.prototype.filtersGet = function (fCallback)
{
this.defaultRequest(fCallback, 'Filters', {
});
};
/**
* @param {?Function} fCallback
* @param {string} sFolderFullNameRaw

View file

@ -55,5 +55,11 @@
cursor: pointer;
opacity: 0.5;
}
&.ui-sortable-helper {
.delete-filter {
display: none;
}
}
}
}

View file

@ -1,34 +1,60 @@
.b-system-drop-down {
.b-toolbar {
position: absolute;
top: 0;
right: 0;
height: 30px;
padding: 10px @rlLowMargin;
z-index: 103;
}
.e-facebook-name {
display: inline-block;
padding-top: 4px;
}
.btn.system-dropdown {
padding-left: 10px;
padding-right: 10px;
}
.button-fb-logout {
margin: 5px;
}
.email-title {
display: inline-block;
max-width: 200px;
text-align: left;
text-overflow: ellipsis;
overflow: hidden;
}
.b-system-drop-down {
.b-toolbar {
position: absolute;
top: 0;
right: 0;
height: 30px;
padding: 10px @rlLowMargin;
z-index: 103;
}
.e-facebook-name {
display: inline-block;
padding-top: 4px;
}
.btn.system-dropdown {
padding-left: 10px;
padding-right: 10px;
}
.button-fb-logout {
margin: 5px;
}
.email-title {
display: inline-block;
max-width: 200px;
text-align: left;
text-overflow: ellipsis;
overflow: hidden;
margin-right: 28px;
vertical-align: middle;
}
.account-item {
.icon-ok {
display: none;
}
&.current {
.icon-ok {
display: inline-block;
}
.icon-user {
display: none;
}
}
}
.counter {
display: inline-block;
}
.g-ui-menu .e-link.account-item {
padding-right: 5px;
}
}

View file

@ -1180,14 +1180,13 @@
if (window.google && window.google.picker)
{
var drivePicker = new window.google.picker.PickerBuilder()
.addView(
new window.google.picker.DocsView()
.setIncludeFolders(true)
)
// .addView(window.google.picker.ViewId.FOLDERS)
.addView(window.google.picker.ViewId.DOCS)
.setAppId(Settings.settingsGet('GoogleClientID'))
.setOAuthToken(oOauthToken.access_token)
.setCallback(_.bind(self.driveCallback, self, oOauthToken.access_token))
.enableFeature(window.google.picker.Feature.NAV_HIDDEN)
// .setOrigin(window.location.protocol + '//' + window.location.host)
.build()
;
@ -1205,14 +1204,9 @@
window.gapi.load('auth', {'callback': function () {
var oAuthToken = window.gapi.auth.getToken();
if (!oAuthToken)
{
window.gapi.auth.authorize({
'client_id': Settings.settingsGet('GoogleClientID'),
'scope': 'https://www.googleapis.com/auth/drive.readonly',
'immediate': true
}, function (oAuthResult) {
var
oAuthToken = window.gapi.auth.getToken(),
fResult = function (oAuthResult) {
if (oAuthResult && !oAuthResult.error)
{
var oAuthToken = window.gapi.auth.getToken();
@ -1220,23 +1214,29 @@
{
self.driveCreatePiker(oAuthToken);
}
return true;
}
else
return false;
}
;
if (!oAuthToken)
{
window.gapi.auth.authorize({
'client_id': Settings.settingsGet('GoogleClientID'),
'scope': 'https://www.googleapis.com/auth/drive.readonly',
'immediate': true
}, function (oAuthResult) {
if (!fResult(oAuthResult))
{
window.gapi.auth.authorize({
'client_id': Settings.settingsGet('GoogleClientID'),
'scope': 'https://www.googleapis.com/auth/drive.readonly',
'immediate': false
}, function (oAuthResult) {
if (oAuthResult && !oAuthResult.error)
{
var oAuthToken = window.gapi.auth.getToken();
if (oAuthToken)
{
self.driveCreatePiker(oAuthToken);
}
}
});
}, fResult);
}
});
}

View file

@ -8,6 +8,7 @@
ko = require('ko'),
Consts = require('Common/Consts'),
Enums = require('Common/Enums'),
Utils = require('Common/Utils'),
Data = require('Storage/User/Data'),
@ -24,28 +25,102 @@
{
AbstractView.call(this, 'Popups', 'PopupsFilter');
this.isNew = ko.observable(true);
this.fTrueCallback = null;
this.filter = ko.observable(null);
this.selectedFolderValue = ko.observable(Consts.Values.UnuseOptionValue);
this.folderSelectList = Data.folderMenuForMove;
this.defautOptionsAfterRender = Utils.defautOptionsAfterRender;
this.saveFilter = Utils.createCommand(this, function () {
if (this.filter())
{
if ('' === this.filter().name())
{
this.filter().name.error(true);
return false;
}
if (this.fTrueCallback)
{
this.fTrueCallback(this.filter());
}
if (this.modalVisibility())
{
Utils.delegateRun(this, 'closeCommand');
}
}
return true;
});
this.actionTypeOptions = [
{'id': Enums.FiltersAction.None, 'name': 'None @i18n'},
{'id': Enums.FiltersAction.Move, 'name': ' Move to @i18n'},
// {'id': Enums.FiltersAction.Forward, 'name': 'Forward to @i18n'},
{'id': Enums.FiltersAction.Discard, 'name': 'Discard @i18n'}
];
this.fieldOptions = [
{'id': Enums.FilterConditionField.From, 'name': 'From @i18n'},
{'id': Enums.FilterConditionField.Recipient, 'name': 'Recipient (To or CC) @i18n'},
{'id': Enums.FilterConditionField.Subject, 'name': 'Subject @i18n'}
];
this.typeOptions = [
{'id': Enums.FilterConditionType.EqualTo, 'name': 'Equal To @i18n'},
{'id': Enums.FilterConditionType.NotEqualTo, 'name': 'Not Equal To @i18n'},
{'id': Enums.FilterConditionType.Contains, 'name': 'Contains @i18n'},
{'id': Enums.FilterConditionType.NotContains, 'name': 'Not Contains @i18n'}
];
kn.constructorEnd(this);
}
kn.extendAsViewModel(['View/Popup/Filter', 'PopupsFilterViewModel'], FilterPopupView);
_.extend(FilterPopupView.prototype, AbstractView.prototype);
FilterPopupView.prototype.clearPopup = function ()
FilterPopupView.prototype.removeCondition = function (oConditionToDelete)
{
// TODO
if (this.filter())
{
this.filter().removeCondition(oConditionToDelete);
}
};
FilterPopupView.prototype.onShow = function (oFilter)
FilterPopupView.prototype.clearPopup = function ()
{
this.isNew(true);
this.fTrueCallback = null;
this.filter(null);
};
FilterPopupView.prototype.onShow = function (oFilter, fTrueCallback, bEdit)
{
this.clearPopup();
this.fTrueCallback = fTrueCallback;
this.filter(oFilter);
this.isNew(!bEdit);
if (!bEdit && oFilter)
{
oFilter.name.focused(true);
}
};
FilterPopupView.prototype.onFocus = function ()
{
if (this.isNew() && this.filter())
{
this.filter().name.focused(true);
}
};
module.exports = FilterPopupView;

View file

@ -319,7 +319,7 @@
}
var
oEl = Utils.draggeblePlace(),
oEl = Utils.draggablePlace(),
aUids = Data.messageListCheckedOrSelectedUidsWithSubMails()
;