Expose user's settings and defaults inline
This improves performance by removing two AJAX calls and a lot of JavaScript promises.pull/228/merge
parent
1fa056bb25
commit
89bfa0c536
1
NEWS
1
NEWS
|
@ -11,6 +11,7 @@ Enhancements
|
|||
- [web] improve display of tasks status
|
||||
- [web] added custom fields support from Thunderbird's address book
|
||||
- [web] added Latvian (lv) translation - thanks to Juris Balandis
|
||||
- [web] expose user's defaults and settings inline
|
||||
|
||||
Bug fixes
|
||||
- [web] respect SOGoLanguage and SOGoSupportedLanguages (#4169)
|
||||
|
|
|
@ -33,12 +33,12 @@
|
|||
};
|
||||
jsonDefaults = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxJSONPreferences";
|
||||
pageName = "UIxJSONPreferences";
|
||||
actionName = "jsonDefaults";
|
||||
};
|
||||
jsonSettings = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxJSONPreferences";
|
||||
pageName = "UIxJSONPreferences";
|
||||
actionName = "jsonSettings";
|
||||
};
|
||||
save = {
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version='1.0' standalone='yes'?>
|
||||
<container
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant">
|
||||
<script id="UserDefaults" type="text/json">
|
||||
<var:string value="jsonDefaults" const:escapeHTML="NO"/>
|
||||
</script>
|
||||
<script id="UserSettings" type="text/json">
|
||||
<var:string value="jsonSettings" const:escapeHTML="NO"/>
|
||||
</script>
|
||||
</container>
|
|
@ -58,16 +58,6 @@
|
|||
<iframe width="100%" height="100%" src="/SOGo/loading"><!-- space --></iframe>
|
||||
</div>
|
||||
</var:if>
|
||||
<script type="text/javascript">
|
||||
<var:if condition="shortUserNameForDisplay" const:value="anonymous" const:negate="YES">
|
||||
<var:if condition="hasUserSettingsKeys">
|
||||
var UserSettings =<var:string value="userSettings" const:escapeHTML="NO" />;
|
||||
</var:if>
|
||||
<var:if condition="hasUserDefaultsKeys">
|
||||
var UserDefaults = <var:string value="userDefaults" const:escapeHTML="NO" />;
|
||||
</var:if>
|
||||
</var:if>
|
||||
</script>
|
||||
|
||||
<!-- MAIN CONTENT ROW -->
|
||||
<var:component-content />
|
||||
|
@ -131,10 +121,15 @@
|
|||
|
||||
// This is the equivalent of an AJAX call to /SOGo/so/_UserLogin_/date
|
||||
var currentDay = <var:string value="currentDayDescription" const:escapeHTML="NO"/>;
|
||||
|
||||
<var:string value="commonLocalizableStrings" const:escapeHTML="NO" />
|
||||
<var:string value="productLocalizableStrings" const:escapeHTML="NO" />
|
||||
</script>
|
||||
|
||||
<var:if condition="shortUserNameForDisplay" const:value="anonymous" const:negate="YES">
|
||||
<var:component className="UIxJSONPreferences"/>
|
||||
</var:if>
|
||||
|
||||
<!-- JAVASCRIPT IMPORTS -->
|
||||
<script type="text/javascript" rsrc:src="js/vendor/lodash.min.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular.min.js"><!-- space --></script>
|
||||
|
|
|
@ -77,18 +77,15 @@
|
|||
$element.off('click', toggleZoomFcn);
|
||||
});
|
||||
|
||||
// Wait on user's defaults
|
||||
Preferences.ready().then(function() {
|
||||
$scope.$watch(function() { return vm.email; }, function(email, old) {
|
||||
if (email && vm.urlEmail != email) {
|
||||
// Email has changed or doesn't match the current URL (this happens when using md-virtual-repeat)
|
||||
showGenericAvatar();
|
||||
if (Preferences.defaults.SOGoGravatarEnabled)
|
||||
getGravatar(email);
|
||||
}
|
||||
else if (!email)
|
||||
showGenericAvatar();
|
||||
});
|
||||
$scope.$watch(function() { return vm.email; }, function(email, old) {
|
||||
if (email && vm.urlEmail != email) {
|
||||
// Email has changed or doesn't match the current URL (this happens when using md-virtual-repeat)
|
||||
showGenericAvatar();
|
||||
if (Preferences.defaults.SOGoGravatarEnabled)
|
||||
getGravatar(email);
|
||||
}
|
||||
else if (!email)
|
||||
showGenericAvatar();
|
||||
});
|
||||
|
||||
// If sg-src is defined, watch the expression for the URL of a local image
|
||||
|
|
|
@ -49,12 +49,11 @@
|
|||
$refreshTimeout: null
|
||||
});
|
||||
// Initialize sort parameters from user's settings
|
||||
Preferences.ready().then(function() {
|
||||
if (Preferences.settings.Contact.SortingState) {
|
||||
AddressBook.$query.sort = Preferences.settings.Contact.SortingState[0];
|
||||
AddressBook.$query.asc = parseInt(Preferences.settings.Contact.SortingState[1]);
|
||||
}
|
||||
});
|
||||
if (Preferences.settings.Contact.SortingState) {
|
||||
AddressBook.$query.sort = Preferences.settings.Contact.SortingState[0];
|
||||
AddressBook.$query.asc = parseInt(Preferences.settings.Contact.SortingState[1]);
|
||||
}
|
||||
|
||||
return AddressBook; // return constructor
|
||||
}];
|
||||
|
||||
|
@ -437,19 +436,15 @@
|
|||
* @desc Starts the refresh timeout for the current selected address book
|
||||
*/
|
||||
AddressBook.prototype.$startRefreshTimeout = function() {
|
||||
var _this = this;
|
||||
|
||||
if (AddressBook.$refreshTimeout)
|
||||
AddressBook.$timeout.cancel(AddressBook.$refreshTimeout);
|
||||
|
||||
AddressBook.$Preferences.ready().then(function() {
|
||||
// Restart the refresh timer, if needed
|
||||
var refreshViewCheck = AddressBook.$Preferences.defaults.SOGoRefreshViewCheck;
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually') {
|
||||
var f = angular.bind(_this, AddressBook.prototype.$reload);
|
||||
AddressBook.$refreshTimeout = AddressBook.$timeout(f, refreshViewCheck.timeInterval()*1000);
|
||||
}
|
||||
});
|
||||
// Restart the refresh timer, if needed
|
||||
var refreshViewCheck = AddressBook.$Preferences.defaults.SOGoRefreshViewCheck;
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually') {
|
||||
var f = angular.bind(this, AddressBook.prototype.$reload);
|
||||
AddressBook.$refreshTimeout = AddressBook.$timeout(f, refreshViewCheck.timeInterval()*1000);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -487,91 +482,89 @@
|
|||
if (!this.isRemote) query.partial = 1;
|
||||
}
|
||||
|
||||
return AddressBook.$Preferences.ready().then(function() {
|
||||
if (options) {
|
||||
angular.extend(query, options);
|
||||
if (dry) {
|
||||
if (!search) {
|
||||
// No query specified
|
||||
_this.$$cards = [];
|
||||
return AddressBook.$q.when(_this.$$cards);
|
||||
}
|
||||
if (options) {
|
||||
angular.extend(query, options);
|
||||
if (dry) {
|
||||
if (!search) {
|
||||
// No query specified
|
||||
_this.$$cards = [];
|
||||
return AddressBook.$q.when(_this.$$cards);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (angular.isDefined(search))
|
||||
query.value = search;
|
||||
if (angular.isDefined(search))
|
||||
query.value = search;
|
||||
|
||||
return _this.$id().then(function(addressbookId) {
|
||||
var futureData = AddressBook.$$resource.fetch(addressbookId, 'view', query);
|
||||
return _this.$id().then(function(addressbookId) {
|
||||
var futureData = AddressBook.$$resource.fetch(addressbookId, 'view', query);
|
||||
|
||||
if (dry) {
|
||||
return futureData.then(function(response) {
|
||||
var results, headers, card, index, fields, idFieldIndex,
|
||||
cards = _this.$$cards,
|
||||
compareIds = function(card) {
|
||||
return this == card.id;
|
||||
};
|
||||
if (dry) {
|
||||
return futureData.then(function(response) {
|
||||
var results, headers, card, index, fields, idFieldIndex,
|
||||
cards = _this.$$cards,
|
||||
compareIds = function(card) {
|
||||
return this == card.id;
|
||||
};
|
||||
|
||||
if (response.headers) {
|
||||
// First entry of 'headers' are keys
|
||||
fields = _.invokeMap(response.headers[0], 'toLowerCase');
|
||||
idFieldIndex = fields.indexOf('id');
|
||||
response.headers.splice(0, 1);
|
||||
if (response.headers) {
|
||||
// First entry of 'headers' are keys
|
||||
fields = _.invokeMap(response.headers[0], 'toLowerCase');
|
||||
idFieldIndex = fields.indexOf('id');
|
||||
response.headers.splice(0, 1);
|
||||
}
|
||||
|
||||
if (excludedCards)
|
||||
// Remove excluded cards from results
|
||||
results = _.filter(response.ids, function(id) {
|
||||
return _.isUndefined(_.find(excludedCards, _.bind(compareIds, id)));
|
||||
});
|
||||
else
|
||||
results = response.ids;
|
||||
|
||||
// Remove cards that no longer match the search query
|
||||
for (index = cards.length - 1; index >= 0; index--) {
|
||||
card = cards[index];
|
||||
if (_.isUndefined(_.find(results, _.bind(compareIds, card.id)))) {
|
||||
cards.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (excludedCards)
|
||||
// Remove excluded cards from results
|
||||
results = _.filter(response.ids, function(id) {
|
||||
return _.isUndefined(_.find(excludedCards, _.bind(compareIds, id)));
|
||||
});
|
||||
else
|
||||
results = response.ids;
|
||||
|
||||
// Remove cards that no longer match the search query
|
||||
for (index = cards.length - 1; index >= 0; index--) {
|
||||
card = cards[index];
|
||||
if (_.isUndefined(_.find(results, _.bind(compareIds, card.id)))) {
|
||||
cards.splice(index, 1);
|
||||
}
|
||||
// Add new cards matching the search query
|
||||
_.forEach(results, function(cardId, index) {
|
||||
if (_.isUndefined(_.find(cards, _.bind(compareIds, cardId)))) {
|
||||
var data = { pid: addressbookId, id: cardId };
|
||||
var card = new AddressBook.$Card(data, search);
|
||||
cards.splice(index, 0, card);
|
||||
}
|
||||
|
||||
// Add new cards matching the search query
|
||||
_.forEach(results, function(cardId, index) {
|
||||
if (_.isUndefined(_.find(cards, _.bind(compareIds, cardId)))) {
|
||||
var data = { pid: addressbookId, id: cardId };
|
||||
var card = new AddressBook.$Card(data, search);
|
||||
cards.splice(index, 0, card);
|
||||
}
|
||||
});
|
||||
|
||||
// Respect the order of the results
|
||||
_.forEach(results, function(cardId, index) {
|
||||
var oldIndex, removedCards;
|
||||
if (cards[index].id != cardId) {
|
||||
oldIndex = _.findIndex(cards, _.bind(compareIds, cardId));
|
||||
removedCards = cards.splice(oldIndex, 1);
|
||||
cards.splice(index, 0, removedCards[0]);
|
||||
}
|
||||
});
|
||||
|
||||
// Extend Card objects with received headers
|
||||
_.forEach(response.headers, function(data) {
|
||||
var card, index = _.findIndex(cards, _.bind(compareIds, data[idFieldIndex]));
|
||||
if (index > -1) {
|
||||
card = _.zipObject(fields, data);
|
||||
cards[index].init(card, search);
|
||||
}
|
||||
});
|
||||
|
||||
return cards;
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Unwrap promise and instantiate or extend Cards objets
|
||||
return _this.$unwrap(futureData);
|
||||
}
|
||||
});
|
||||
|
||||
// Respect the order of the results
|
||||
_.forEach(results, function(cardId, index) {
|
||||
var oldIndex, removedCards;
|
||||
if (cards[index].id != cardId) {
|
||||
oldIndex = _.findIndex(cards, _.bind(compareIds, cardId));
|
||||
removedCards = cards.splice(oldIndex, 1);
|
||||
cards.splice(index, 0, removedCards[0]);
|
||||
}
|
||||
});
|
||||
|
||||
// Extend Card objects with received headers
|
||||
_.forEach(response.headers, function(data) {
|
||||
var card, index = _.findIndex(cards, _.bind(compareIds, data[idFieldIndex]));
|
||||
if (index > -1) {
|
||||
card = _.zipObject(fields, data);
|
||||
cards[index].init(card, search);
|
||||
}
|
||||
});
|
||||
|
||||
return cards;
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Unwrap promise and instantiate or extend Cards objets
|
||||
return _this.$unwrap(futureData);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -46,13 +46,11 @@
|
|||
$Preferences: Preferences
|
||||
});
|
||||
// Initialize categories from user's defaults
|
||||
Preferences.ready().then(function() {
|
||||
if (Preferences.defaults.SOGoContactsCategories) {
|
||||
Card.$categories = Preferences.defaults.SOGoContactsCategories;
|
||||
}
|
||||
if (Preferences.defaults.SOGoAlternateAvatar)
|
||||
Card.$alternateAvatar = Preferences.defaults.SOGoAlternateAvatar;
|
||||
});
|
||||
if (Preferences.defaults.SOGoContactsCategories) {
|
||||
Card.$categories = Preferences.defaults.SOGoContactsCategories;
|
||||
}
|
||||
if (Preferences.defaults.SOGoAlternateAvatar)
|
||||
Card.$alternateAvatar = Preferences.defaults.SOGoAlternateAvatar;
|
||||
|
||||
return Card; // return constructor
|
||||
}];
|
||||
|
@ -149,9 +147,7 @@
|
|||
if (!this.$$image)
|
||||
this.$$image = this.image;
|
||||
if (!this.$$image)
|
||||
Card.$Preferences.avatar(this.$$email, 32, {no_404: true}).then(function(url) {
|
||||
_this.$$image = url;
|
||||
});
|
||||
this.$$image = Card.$Preferences.avatar(this.$$email, 32, {no_404: true});
|
||||
if (this.hasphoto)
|
||||
this.photoURL = Card.$$resource.path(this.pid, this.id, 'photo');
|
||||
if (this.isgroup)
|
||||
|
@ -177,11 +173,9 @@
|
|||
});
|
||||
// Instanciate date object of birthday
|
||||
if (this.birthday) {
|
||||
Card.$Preferences.ready().then(function() {
|
||||
var dlp = Card.$Preferences.$mdDateLocaleProvider;
|
||||
_this.birthday = _this.birthday.parseDate(dlp, '%Y-%m-%d');
|
||||
_this.$birthday = dlp.formatDate(_this.birthday);
|
||||
});
|
||||
var dlp = Card.$Preferences.$mdDateLocaleProvider;
|
||||
this.birthday = this.birthday.parseDate(dlp, '%Y-%m-%d');
|
||||
this.$birthday = dlp.formatDate(this.birthday);
|
||||
}
|
||||
|
||||
this.$loaded = angular.isDefined(this.c_name)? Card.STATUS.LOADED : Card.STATUS.NOT_LOADED;
|
||||
|
|
|
@ -136,31 +136,29 @@
|
|||
_this.$expanded = false;
|
||||
|
||||
// Set expanded folders from user's settings
|
||||
Account.$Preferences.ready().then(function() {
|
||||
var expandedFolders,
|
||||
_visit = function(mailboxes) {
|
||||
_.forEach(mailboxes, function(o) {
|
||||
o.$expanded = (expandedFolders.indexOf('/' + o.id) >= 0);
|
||||
if (o.children && o.children.length > 0) {
|
||||
_visit(o.children);
|
||||
}
|
||||
});
|
||||
};
|
||||
if (Account.$Preferences.settings.Mail.ExpandedFolders) {
|
||||
if (angular.isString(Account.$Preferences.settings.Mail.ExpandedFolders))
|
||||
// Backward compatibility support
|
||||
expandedFolders = angular.fromJson(Account.$Preferences.settings.Mail.ExpandedFolders);
|
||||
else
|
||||
expandedFolders = Account.$Preferences.settings.Mail.ExpandedFolders;
|
||||
_this.$expanded = (expandedFolders.indexOf('/' + _this.id) >= 0);
|
||||
if (expandedFolders.length > 0) {
|
||||
_visit(_this.$mailboxes);
|
||||
}
|
||||
var expandedFolders,
|
||||
_visit = function(mailboxes) {
|
||||
_.forEach(mailboxes, function(o) {
|
||||
o.$expanded = (expandedFolders.indexOf('/' + o.id) >= 0);
|
||||
if (o.children && o.children.length > 0) {
|
||||
_visit(o.children);
|
||||
}
|
||||
});
|
||||
};
|
||||
if (Account.$Preferences.settings.Mail.ExpandedFolders) {
|
||||
if (angular.isString(Account.$Preferences.settings.Mail.ExpandedFolders))
|
||||
// Backward compatibility support
|
||||
expandedFolders = angular.fromJson(Account.$Preferences.settings.Mail.ExpandedFolders);
|
||||
else
|
||||
expandedFolders = Account.$Preferences.settings.Mail.ExpandedFolders;
|
||||
_this.$expanded = (expandedFolders.indexOf('/' + _this.id) >= 0);
|
||||
if (expandedFolders.length > 0) {
|
||||
_visit(_this.$mailboxes);
|
||||
}
|
||||
if (Account.$accounts)
|
||||
_this.$expanded |= (Account.$accounts.length == 1); // Always expand single account
|
||||
_this.$flattenMailboxes({reload: true});
|
||||
});
|
||||
}
|
||||
if (Account.$accounts)
|
||||
_this.$expanded |= (Account.$accounts.length == 1); // Always expand single account
|
||||
_this.$flattenMailboxes({reload: true});
|
||||
|
||||
return _this.$mailboxes;
|
||||
});
|
||||
|
|
|
@ -48,12 +48,10 @@
|
|||
PRELOAD: PRELOAD
|
||||
});
|
||||
// Initialize sort parameters from user's settings
|
||||
Preferences.ready().then(function() {
|
||||
if (Preferences.settings.Mail.SortingState) {
|
||||
Mailbox.$query.sort = Preferences.settings.Mail.SortingState[0];
|
||||
Mailbox.$query.asc = parseInt(Preferences.settings.Mail.SortingState[1]);
|
||||
}
|
||||
});
|
||||
if (Preferences.settings.Mail.SortingState) {
|
||||
Mailbox.$query.sort = Preferences.settings.Mail.SortingState[0];
|
||||
Mailbox.$query.asc = parseInt(Preferences.settings.Mail.SortingState[1]);
|
||||
}
|
||||
|
||||
return Mailbox; // return constructor
|
||||
}];
|
||||
|
@ -343,46 +341,43 @@
|
|||
_this.$isLoading = true;
|
||||
});
|
||||
|
||||
return Mailbox.$Preferences.ready().then(function() {
|
||||
if (Mailbox.$refreshTimeout)
|
||||
Mailbox.$timeout.cancel(Mailbox.$refreshTimeout);
|
||||
|
||||
if (Mailbox.$refreshTimeout)
|
||||
Mailbox.$timeout.cancel(Mailbox.$refreshTimeout);
|
||||
if (sortingAttributes)
|
||||
// Sorting preferences are common to all mailboxes
|
||||
angular.extend(Mailbox.$query, sortingAttributes);
|
||||
|
||||
if (sortingAttributes)
|
||||
// Sorting preferences are common to all mailboxes
|
||||
angular.extend(Mailbox.$query, sortingAttributes);
|
||||
|
||||
angular.extend(options, { sortingAttributes: Mailbox.$query });
|
||||
if (angular.isDefined(filters)) {
|
||||
options.filters = _.reject(filters, function(filter) {
|
||||
return !filter.searchInput || filter.searchInput.length === 0;
|
||||
});
|
||||
// Decompose filters that match two fields
|
||||
_.forEach(options.filters, function(filter) {
|
||||
var secondFilter,
|
||||
match = filter.searchBy.match(/(\w+)_or_(\w+)/);
|
||||
if (match) {
|
||||
options.sortingAttributes.match = 'OR';
|
||||
filter.searchBy = match[1];
|
||||
secondFilter = angular.copy(filter);
|
||||
secondFilter.searchBy = match[2];
|
||||
options.filters.push(secondFilter);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Restart the refresh timer, if needed
|
||||
if (!Mailbox.$virtualMode) {
|
||||
var refreshViewCheck = Mailbox.$Preferences.defaults.SOGoRefreshViewCheck;
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually') {
|
||||
var f = angular.bind(_this, Mailbox.prototype.$filter, null, filters);
|
||||
Mailbox.$refreshTimeout = Mailbox.$timeout(f, refreshViewCheck.timeInterval()*1000);
|
||||
angular.extend(options, { sortingAttributes: Mailbox.$query });
|
||||
if (angular.isDefined(filters)) {
|
||||
options.filters = _.reject(filters, function(filter) {
|
||||
return !filter.searchInput || filter.searchInput.length === 0;
|
||||
});
|
||||
// Decompose filters that match two fields
|
||||
_.forEach(options.filters, function(filter) {
|
||||
var secondFilter,
|
||||
match = filter.searchBy.match(/(\w+)_or_(\w+)/);
|
||||
if (match) {
|
||||
options.sortingAttributes.match = 'OR';
|
||||
filter.searchBy = match[1];
|
||||
secondFilter = angular.copy(filter);
|
||||
secondFilter.searchBy = match[2];
|
||||
options.filters.push(secondFilter);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var futureMailboxData = Mailbox.$$resource.post(_this.id, 'view', options);
|
||||
return _this.$unwrap(futureMailboxData);
|
||||
});
|
||||
// Restart the refresh timer, if needed
|
||||
if (!Mailbox.$virtualMode) {
|
||||
var refreshViewCheck = Mailbox.$Preferences.defaults.SOGoRefreshViewCheck;
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually') {
|
||||
var f = angular.bind(this, Mailbox.prototype.$filter, null, filters);
|
||||
Mailbox.$refreshTimeout = Mailbox.$timeout(f, refreshViewCheck.timeInterval()*1000);
|
||||
}
|
||||
}
|
||||
|
||||
var futureMailboxData = Mailbox.$$resource.post(this.id, 'view', options);
|
||||
return this.$unwrap(futureMailboxData);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,9 +32,7 @@
|
|||
params: []
|
||||
};
|
||||
|
||||
Preferences.ready().then(function() {
|
||||
vm.showSubscribedOnly = Preferences.defaults.SOGoMailShowSubscribedFoldersOnly;
|
||||
});
|
||||
this.showSubscribedOnly = Preferences.defaults.SOGoMailShowSubscribedFoldersOnly;
|
||||
|
||||
this.refreshUnseenCount();
|
||||
|
||||
|
@ -258,7 +256,7 @@
|
|||
}; // delegate
|
||||
|
||||
this.refreshUnseenCount = function() {
|
||||
var unseenCountFolders = $window.unseenCountFolders;
|
||||
var unseenCountFolders = $window.unseenCountFolders, refreshViewCheck;
|
||||
|
||||
_.forEach(vm.accounts, function(account) {
|
||||
|
||||
|
@ -282,11 +280,9 @@
|
|||
});
|
||||
});
|
||||
|
||||
Preferences.ready().then(function() {
|
||||
var refreshViewCheck = Preferences.defaults.SOGoRefreshViewCheck;
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually')
|
||||
$timeout(vm.refreshUnseenCount, refreshViewCheck.timeInterval()*1000);
|
||||
});
|
||||
refreshViewCheck = Preferences.defaults.SOGoRefreshViewCheck;
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually')
|
||||
$timeout(vm.refreshUnseenCount, refreshViewCheck.timeInterval()*1000);
|
||||
};
|
||||
|
||||
this.isDroppableFolder = function(srcFolder, dstFolder) {
|
||||
|
|
|
@ -48,16 +48,15 @@
|
|||
$$resource: new Resource(Settings.activeUser('folderURL') + 'Mail', Settings.activeUser()),
|
||||
$avatar: angular.bind(Preferences, Preferences.avatar)
|
||||
});
|
||||
|
||||
// Initialize tags form user's defaults
|
||||
Preferences.ready().then(function() {
|
||||
if (Preferences.defaults.SOGoMailLabelsColors) {
|
||||
Message.$tags = Preferences.defaults.SOGoMailLabelsColors;
|
||||
}
|
||||
if (Preferences.defaults.SOGoMailDisplayRemoteInlineImages &&
|
||||
Preferences.defaults.SOGoMailDisplayRemoteInlineImages == 'always') {
|
||||
Message.$displayRemoteInlineImages = true;
|
||||
}
|
||||
});
|
||||
if (Preferences.defaults.SOGoMailLabelsColors) {
|
||||
Message.$tags = Preferences.defaults.SOGoMailLabelsColors;
|
||||
}
|
||||
if (Preferences.defaults.SOGoMailDisplayRemoteInlineImages &&
|
||||
Preferences.defaults.SOGoMailDisplayRemoteInlineImages == 'always') {
|
||||
Message.$displayRemoteInlineImages = true;
|
||||
}
|
||||
|
||||
return Message; // return constructor
|
||||
}];
|
||||
|
|
|
@ -65,6 +65,13 @@
|
|||
}
|
||||
});
|
||||
|
||||
// Read user's defaults
|
||||
if (Preferences.defaults.SOGoMailAutoSave)
|
||||
// Enable auto-save of draft
|
||||
vm.autosave = $timeout(vm.autosaveDrafts, Preferences.defaults.SOGoMailAutoSave*1000*60);
|
||||
// Set the locale of CKEditor
|
||||
vm.localeCode = Preferences.defaults.LocaleCode;
|
||||
|
||||
// Destroy file uploader when the controller is being deactivated
|
||||
$scope.$on('$destroy', function() { vm.uploader.destroy(); });
|
||||
|
||||
|
@ -297,14 +304,6 @@
|
|||
vm.autosave = $timeout(vm.autosaveDrafts, Preferences.defaults.SOGoMailAutoSave*1000*60);
|
||||
}
|
||||
|
||||
// Read user's defaults
|
||||
Preferences.ready().then(function() {
|
||||
if (Preferences.defaults.SOGoMailAutoSave)
|
||||
// Enable auto-save of draft
|
||||
vm.autosave = $timeout(vm.autosaveDrafts, Preferences.defaults.SOGoMailAutoSave*1000*60);
|
||||
// Set the locale of CKEditor
|
||||
vm.localeCode = Preferences.defaults.LocaleCode;
|
||||
});
|
||||
}
|
||||
|
||||
SendMessageToastController.$inject = ['$scope', '$mdToast'];
|
||||
|
|
|
@ -22,9 +22,6 @@
|
|||
controller: 'PreferencesController',
|
||||
controllerAs: 'app'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
statePreferences: statePreferences
|
||||
}
|
||||
})
|
||||
.state('preferences.general', {
|
||||
|
@ -64,13 +61,6 @@
|
|||
$urlRouterProvider.otherwise('/general');
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
statePreferences.$inject = ['Preferences'];
|
||||
function statePreferences(Preferences) {
|
||||
return Preferences;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
|
|
|
@ -8,13 +8,19 @@
|
|||
* @constructor
|
||||
*/
|
||||
function Preferences() {
|
||||
var _this = this;
|
||||
var _this = this, defaultsElement, settingsElement, data;
|
||||
|
||||
this.defaults = {};
|
||||
this.settings = {};
|
||||
|
||||
this.defaultsPromise = Preferences.$$resource.fetch("jsonDefaults").then(function(response) {
|
||||
var data = response || {};
|
||||
defaultsElement = Preferences.$document[0].getElementById('UserDefaults');
|
||||
if (defaultsElement) {
|
||||
try {
|
||||
data = angular.fromJson(defaultsElement.textContent || defaultsElement.innerHTML);
|
||||
} catch (e) {
|
||||
Preferences.$log.error("Can't parse user's defaults: " + e.message);
|
||||
data = {};
|
||||
}
|
||||
|
||||
// We swap $key -> _$key to avoid an Angular bug (https://github.com/angular/angular.js/issues/6266)
|
||||
var labels = _.fromPairs(_.map(data.SOGoMailLabelsColors, function(value, key) {
|
||||
|
@ -117,22 +123,28 @@
|
|||
_this.$mdDateLocaleProvider.msgCalendar = l('Calender');
|
||||
_this.$mdDateLocaleProvider.msgOpenCalendar = l('Open Calendar');
|
||||
_this.$mdDateLocaleProvider.parseDate = function(dateString) {
|
||||
return dateString? dateString.parseDate(_this.$mdDateLocaleProvider, data.SOGoShortDateFormat) : new Date(NaN);
|
||||
return dateString? dateString.parseDate(_this.$mdDateLocaleProvider, _this.defaults.SOGoShortDateFormat) : new Date(NaN);
|
||||
};
|
||||
_this.$mdDateLocaleProvider.formatDate = function(date) {
|
||||
return date? date.format(_this.$mdDateLocaleProvider, date.$dateFormat || data.SOGoShortDateFormat) : '';
|
||||
return date? date.format(_this.$mdDateLocaleProvider, date.$dateFormat || _this.defaults.SOGoShortDateFormat) : '';
|
||||
};
|
||||
_this.$mdDateLocaleProvider.parseTime = function(timeString) {
|
||||
return timeString? timeString.parseDate(_this.$mdDateLocaleProvider, data.SOGoTimeFormat) : new Date(NaN);
|
||||
return timeString? timeString.parseDate(_this.$mdDateLocaleProvider, _this.defaults.SOGoTimeFormat) : new Date(NaN);
|
||||
};
|
||||
_this.$mdDateLocaleProvider.formatTime = function(date) {
|
||||
return date? date.format(_this.$mdDateLocaleProvider, data.SOGoTimeFormat) : '';
|
||||
return date? date.format(_this.$mdDateLocaleProvider, _this.defaults.SOGoTimeFormat) : '';
|
||||
};
|
||||
}
|
||||
|
||||
return _this.defaults;
|
||||
});
|
||||
settingsElement = Preferences.$document[0].getElementById('UserSettings');
|
||||
if (settingsElement) {
|
||||
try {
|
||||
data = angular.fromJson(settingsElement.textContent || settingsElement.innerHTML);
|
||||
} catch (e) {
|
||||
Preferences.$log.error("Can't parse user's settings: " + e.message);
|
||||
data = {};
|
||||
}
|
||||
|
||||
this.settingsPromise = Preferences.$$resource.fetch("jsonSettings").then(function(data) {
|
||||
// We convert our PreventInvitationsWhitelist hash into a array of user
|
||||
if (data.Calendar) {
|
||||
if (data.Calendar.PreventInvitationsWhitelist) {
|
||||
|
@ -140,9 +152,7 @@
|
|||
var match = /^(.+)\s<(\S+)>$/.exec(value),
|
||||
user = new Preferences.$User({uid: key, cn: match[1], c_email: match[2]});
|
||||
if (!user.$$image)
|
||||
_this.avatar(user.c_email, 32, {no_404: true}).then(function(url) {
|
||||
user.$$image = url;
|
||||
});
|
||||
user.$$image = _this.avatar(user.c_email, 32, {no_404: true});
|
||||
return user;
|
||||
});
|
||||
}
|
||||
|
@ -151,9 +161,7 @@
|
|||
}
|
||||
|
||||
angular.extend(_this.settings, data);
|
||||
|
||||
return _this.settings;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -161,8 +169,9 @@
|
|||
* @desc The factory we'll use to register with Angular
|
||||
* @returns the Preferences constructor
|
||||
*/
|
||||
Preferences.$factory = ['$q', '$timeout', '$log', '$mdDateLocale', 'sgSettings', 'Gravatar', 'Resource', 'User', function($q, $timeout, $log, $mdDateLocaleProvider, Settings, Gravatar, Resource, User) {
|
||||
Preferences.$factory = ['$document', '$q', '$timeout', '$log', '$mdDateLocale', 'sgSettings', 'Gravatar', 'Resource', 'User', function($document, $q, $timeout, $log, $mdDateLocaleProvider, Settings, Gravatar, Resource, User) {
|
||||
angular.extend(Preferences, {
|
||||
$document: $document,
|
||||
$q: $q,
|
||||
$timeout: $timeout,
|
||||
$log: $log,
|
||||
|
@ -195,7 +204,8 @@
|
|||
* @return a combined promise
|
||||
*/
|
||||
Preferences.prototype.ready = function() {
|
||||
return Preferences.$q.all([this.defaultsPromise, this.settingsPromise]);
|
||||
Preferences.$log.warn('Preferences.ready is deprecated -- access settings/defaults directly.');
|
||||
return Preferences.$q.when(true);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -206,16 +216,14 @@
|
|||
*/
|
||||
Preferences.prototype.avatar = function(email, size, options) {
|
||||
var _this = this;
|
||||
return this.ready().then(function() {
|
||||
var alternate_avatar = _this.defaults.SOGoAlternateAvatar, url;
|
||||
if (_this.defaults.SOGoGravatarEnabled)
|
||||
url = Preferences.$gravatar(email, size, alternate_avatar, options);
|
||||
else
|
||||
url = [Preferences.$resourcesURL, 'img', 'ic_person_grey_24px.svg'].join('/');
|
||||
if (options && options.dstObject && options.dstAttr)
|
||||
options.dstObject[options.dstAttr] = url;
|
||||
return url;
|
||||
});
|
||||
var alternate_avatar = _this.defaults.SOGoAlternateAvatar, url;
|
||||
if (_this.defaults.SOGoGravatarEnabled)
|
||||
url = Preferences.$gravatar(email, size, alternate_avatar, options);
|
||||
else
|
||||
url = [Preferences.$resourcesURL, 'img', 'ic_person_grey_24px.svg'].join('/');
|
||||
if (options && options.dstObject && options.dstAttr)
|
||||
options.dstObject[options.dstAttr] = url;
|
||||
return url;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -285,12 +293,16 @@
|
|||
if (preferences.defaults.Vacation) {
|
||||
if (preferences.defaults.Vacation.startDateEnabled)
|
||||
preferences.defaults.Vacation.startDate = preferences.defaults.Vacation.startDate.getTime()/1000;
|
||||
else
|
||||
else {
|
||||
delete preferences.defaults.Vacation.startDateEnabled;
|
||||
preferences.defaults.Vacation.startDate = 0;
|
||||
}
|
||||
if (preferences.defaults.Vacation.endDateEnabled)
|
||||
preferences.defaults.Vacation.endDate = preferences.defaults.Vacation.endDate.getTime()/1000;
|
||||
else
|
||||
else {
|
||||
delete preferences.defaults.Vacation.endDateEnabled;
|
||||
preferences.defaults.Vacation.endDate = 0;
|
||||
}
|
||||
|
||||
if (preferences.defaults.Vacation.autoReplyEmailAddresses)
|
||||
preferences.defaults.Vacation.autoReplyEmailAddresses = _.filter(preferences.defaults.Vacation.autoReplyEmailAddresses.split(","), function(v) { return v.length; });
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
PreferencesController.$inject = ['$q', '$window', '$state', '$mdMedia', '$mdSidenav', '$mdDialog', '$mdToast', 'sgSettings', 'sgFocus', 'Dialog', 'User', 'Account', 'statePreferences', 'Authentication'];
|
||||
function PreferencesController($q, $window, $state, $mdMedia, $mdSidenav, $mdDialog, $mdToast, sgSettings, focus, Dialog, User, Account, statePreferences, Authentication) {
|
||||
PreferencesController.$inject = ['$q', '$window', '$state', '$mdMedia', '$mdSidenav', '$mdDialog', '$mdToast', 'sgSettings', 'sgFocus', 'Dialog', 'User', 'Account', 'Preferences', 'Authentication'];
|
||||
function PreferencesController($q, $window, $state, $mdMedia, $mdSidenav, $mdDialog, $mdToast, sgSettings, focus, Dialog, User, Account, Preferences, Authentication) {
|
||||
var vm = this, account, mailboxes = [], today = new Date(), tomorrow = today.beginOfDay().addDays(1);
|
||||
|
||||
vm.preferences = statePreferences;
|
||||
vm.preferences = Preferences;
|
||||
vm.passwords = { newPassword: null, newPasswordConfirmation: null };
|
||||
|
||||
vm.go = go;
|
||||
|
@ -60,11 +60,9 @@
|
|||
}
|
||||
|
||||
// Set alternate avatar in User service
|
||||
statePreferences.ready().then(function() {
|
||||
if (statePreferences.defaults.SOGoAlternateAvatar)
|
||||
User.$alternateAvatar = statePreferences.defaults.SOGoAlternateAvatar;
|
||||
updateVacationDates();
|
||||
});
|
||||
if (Preferences.defaults.SOGoAlternateAvatar)
|
||||
User.$alternateAvatar = Preferences.defaults.SOGoAlternateAvatar;
|
||||
updateVacationDates();
|
||||
|
||||
function go(module, form) {
|
||||
if (form.$valid) {
|
||||
|
|
|
@ -102,11 +102,9 @@
|
|||
else
|
||||
list.splice(sibling, 0, calendar);
|
||||
|
||||
this.$Preferences.ready().then(function() {
|
||||
if (Calendar.$Preferences.settings.Calendar.FoldersOrder)
|
||||
// Save list order
|
||||
Calendar.saveFoldersOrder(_.flatMap(Calendar.$findAll(), 'id'));
|
||||
});
|
||||
if (Calendar.$Preferences.settings.Calendar.FoldersOrder)
|
||||
// Save list order
|
||||
Calendar.saveFoldersOrder(_.flatMap(Calendar.$findAll(), 'id'));
|
||||
// Refresh list of calendars to fetch links associated to new calendar
|
||||
Calendar.$reloadAll();
|
||||
};
|
||||
|
|
|
@ -23,23 +23,23 @@
|
|||
vm.changeView = changeView;
|
||||
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
this.$onInit = function() {
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
Preferences.ready().then(function() {
|
||||
_formatDate(vm.selectedDate);
|
||||
});
|
||||
|
||||
// Refresh current view when the list of calendars is modified
|
||||
deregisterCalendarsList = $rootScope.$on('calendars:list', updateView);
|
||||
// Refresh current view when the list of calendars is modified
|
||||
deregisterCalendarsList = $rootScope.$on('calendars:list', updateView);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
// Destroy event listener when the controller is being deactivated
|
||||
deregisterCalendarsList();
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
$scope.$on('$destroy', function() {
|
||||
// Destroy event listener when the controller is being deactivated
|
||||
deregisterCalendarsList();
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
CalendarListController.$inject = ['$rootScope', '$scope', '$timeout', '$state', '$mdDialog', 'sgHotkeys', 'sgFocus', 'Dialog', 'Preferences', 'CalendarSettings', 'Calendar', 'Component', 'Alarm'];
|
||||
function CalendarListController($rootScope, $scope, $timeout, $state, $mdDialog, sgHotkeys, focus, Dialog, Preferences, CalendarSettings, Calendar, Component, Alarm) {
|
||||
var vm = this, hotkeys = [];
|
||||
var vm = this, hotkeys = [], type;
|
||||
|
||||
vm.component = Component;
|
||||
vm.componentType = 'events';
|
||||
|
@ -32,32 +32,32 @@
|
|||
vm.mode = { search: false, multiple: 0 };
|
||||
|
||||
|
||||
_registerHotkeys(hotkeys);
|
||||
this.$onInit = function() {
|
||||
_registerHotkeys(hotkeys);
|
||||
|
||||
// Select list based on user's settings
|
||||
Preferences.ready().then(function() {
|
||||
var type = 'events';
|
||||
// Select list based on user's settings
|
||||
type = 'events';
|
||||
if (Preferences.settings.Calendar.SelectedList == 'tasksListView') {
|
||||
vm.selectedList = 1;
|
||||
type = 'tasks';
|
||||
}
|
||||
selectComponentType(type, { reload: true }); // fetch events/tasks lists
|
||||
});
|
||||
|
||||
// Refresh current list when the list of calendars is modified
|
||||
$rootScope.$on('calendars:list', function() {
|
||||
Component.$filter(vm.componentType, { reload: true });
|
||||
});
|
||||
|
||||
// Update the component being dragged
|
||||
$rootScope.$on('calendar:dragend', updateComponentFromGhost);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
// Refresh current list when the list of calendars is modified
|
||||
$rootScope.$on('calendars:list', function() {
|
||||
Component.$filter(vm.componentType, { reload: true });
|
||||
});
|
||||
});
|
||||
|
||||
// Update the component being dragged
|
||||
$rootScope.$on('calendar:dragend', updateComponentFromGhost);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
// Deregister hotkeys
|
||||
_.forEach(hotkeys, function(key) {
|
||||
sgHotkeys.deregisterHotkey(key);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function _registerHotkeys(keys) {
|
||||
|
|
|
@ -38,47 +38,47 @@
|
|||
accept: _sortableAccept
|
||||
};
|
||||
|
||||
Preferences.ready().then(function() {
|
||||
this.$onInit = function() {
|
||||
vm.categories = _.map(Preferences.defaults.SOGoCalendarCategories, function(name) {
|
||||
return { id: name.asCSSIdentifier(),
|
||||
name: name,
|
||||
color: Preferences.defaults.SOGoCalendarCategoriesColors[name]
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
// Dispatch the event named 'calendars:list' when a calendar is activated or deactivated or
|
||||
// when the color of a calendar is changed
|
||||
$scope.$watch(
|
||||
function() {
|
||||
return _.union(
|
||||
_.map(Calendar.$calendars, function(o) { return _.pick(o, ['id', 'active', 'color']); }),
|
||||
_.map(Calendar.$subscriptions, function(o) { return _.pick(o, ['id', 'active', 'color']); }),
|
||||
_.map(Calendar.$webcalendars, function(o) { return _.pick(o, ['id', 'active', 'color']); })
|
||||
);
|
||||
},
|
||||
function(newList, oldList) {
|
||||
var commonList, ids, promise;
|
||||
// Dispatch the event named 'calendars:list' when a calendar is activated or deactivated or
|
||||
// when the color of a calendar is changed
|
||||
$scope.$watch(
|
||||
function() {
|
||||
return _.union(
|
||||
_.map(Calendar.$calendars, function(o) { return _.pick(o, ['id', 'active', 'color']); }),
|
||||
_.map(Calendar.$subscriptions, function(o) { return _.pick(o, ['id', 'active', 'color']); }),
|
||||
_.map(Calendar.$webcalendars, function(o) { return _.pick(o, ['id', 'active', 'color']); })
|
||||
);
|
||||
},
|
||||
function(newList, oldList) {
|
||||
var commonList, ids, promise;
|
||||
|
||||
// Identify which calendar has changed
|
||||
commonList = _.intersectionBy(newList, oldList, 'id');
|
||||
ids = _.map(_.filter(commonList, function(o) {
|
||||
var oldObject = _.find(oldList, { id: o.id });
|
||||
return !_.isEqual(o, oldObject);
|
||||
}), 'id');
|
||||
promise = Calendar.$q.when();
|
||||
// Identify which calendar has changed
|
||||
commonList = _.intersectionBy(newList, oldList, 'id');
|
||||
ids = _.map(_.filter(commonList, function(o) {
|
||||
var oldObject = _.find(oldList, { id: o.id });
|
||||
return !_.isEqual(o, oldObject);
|
||||
}), 'id');
|
||||
promise = Calendar.$q.when();
|
||||
|
||||
if (ids.length > 0) {
|
||||
$log.debug(ids.join(', ') + ' changed');
|
||||
promise = Calendar.saveFoldersActivation(ids);
|
||||
}
|
||||
if (ids.length > 0 || commonList.length != newList.length || commonList.length != oldList.length)
|
||||
promise.then(function() {
|
||||
$rootScope.$emit('calendars:list');
|
||||
});
|
||||
},
|
||||
true // compare for object equality
|
||||
);
|
||||
if (ids.length > 0) {
|
||||
$log.debug(ids.join(', ') + ' changed');
|
||||
promise = Calendar.saveFoldersActivation(ids);
|
||||
}
|
||||
if (ids.length > 0 || commonList.length != newList.length || commonList.length != oldList.length)
|
||||
promise.then(function() {
|
||||
$rootScope.$emit('calendars:list');
|
||||
});
|
||||
},
|
||||
true // compare for object equality
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Only allow to sort items within the same list.
|
||||
|
|
|
@ -52,28 +52,26 @@
|
|||
$refreshTimeout: null,
|
||||
$ghost: {}
|
||||
});
|
||||
Preferences.ready().then(function() {
|
||||
// Initialize filter parameters from user's settings
|
||||
if (Preferences.settings.Calendar.EventsFilterState)
|
||||
Component.$queryEvents.filterpopup = Preferences.settings.Calendar.EventsFilterState;
|
||||
if (Preferences.settings.Calendar.TasksFilterState)
|
||||
Component.$queryTasks.filterpopup = Preferences.settings.Calendar.TasksFilterState;
|
||||
if (Preferences.settings.Calendar.EventsSortingState) {
|
||||
Component.$queryEvents.sort = Preferences.settings.Calendar.EventsSortingState[0];
|
||||
Component.$queryEvents.asc = parseInt(Preferences.settings.Calendar.EventsSortingState[1]);
|
||||
}
|
||||
if (Preferences.settings.Calendar.TasksSortingState) {
|
||||
Component.$queryTasks.sort = Preferences.settings.Calendar.TasksSortingState[0];
|
||||
Component.$queryTasks.asc = parseInt(Preferences.settings.Calendar.TasksSortingState[1]);
|
||||
}
|
||||
Component.$queryTasks.show_completed = parseInt(Preferences.settings.ShowCompletedTasks);
|
||||
// Initialize categories from user's defaults
|
||||
Component.$categories = Preferences.defaults.SOGoCalendarCategoriesColors;
|
||||
// Initialize time format from user's defaults
|
||||
if (Preferences.defaults.SOGoTimeFormat) {
|
||||
Component.timeFormat = Preferences.defaults.SOGoTimeFormat;
|
||||
}
|
||||
});
|
||||
// Initialize filter parameters from user's settings
|
||||
if (Preferences.settings.Calendar.EventsFilterState)
|
||||
Component.$queryEvents.filterpopup = Preferences.settings.Calendar.EventsFilterState;
|
||||
if (Preferences.settings.Calendar.TasksFilterState)
|
||||
Component.$queryTasks.filterpopup = Preferences.settings.Calendar.TasksFilterState;
|
||||
if (Preferences.settings.Calendar.EventsSortingState) {
|
||||
Component.$queryEvents.sort = Preferences.settings.Calendar.EventsSortingState[0];
|
||||
Component.$queryEvents.asc = parseInt(Preferences.settings.Calendar.EventsSortingState[1]);
|
||||
}
|
||||
if (Preferences.settings.Calendar.TasksSortingState) {
|
||||
Component.$queryTasks.sort = Preferences.settings.Calendar.TasksSortingState[0];
|
||||
Component.$queryTasks.asc = parseInt(Preferences.settings.Calendar.TasksSortingState[1]);
|
||||
}
|
||||
Component.$queryTasks.show_completed = parseInt(Preferences.settings.ShowCompletedTasks);
|
||||
// Initialize categories from user's defaults
|
||||
Component.$categories = Preferences.defaults.SOGoCalendarCategoriesColors;
|
||||
// Initialize time format from user's defaults
|
||||
if (Preferences.defaults.SOGoTimeFormat) {
|
||||
Component.timeFormat = Preferences.defaults.SOGoTimeFormat;
|
||||
}
|
||||
|
||||
return Component; // return constructor
|
||||
}];
|
||||
|
@ -124,19 +122,15 @@
|
|||
* current view.
|
||||
*/
|
||||
Component.$startRefreshTimeout = function(type) {
|
||||
var _this = this;
|
||||
|
||||
if (Component.$refreshTimeout)
|
||||
Component.$timeout.cancel(Component.$refreshTimeout);
|
||||
|
||||
Component.$Preferences.ready().then(function() {
|
||||
// Restart the refresh timer, if needed
|
||||
var refreshViewCheck = Component.$Preferences.defaults.SOGoRefreshViewCheck;
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually') {
|
||||
var f = angular.bind(Component.$rootScope, Component.$rootScope.$emit, 'calendars:list');
|
||||
Component.$refreshTimeout = Component.$timeout(f, refreshViewCheck.timeInterval()*1000);
|
||||
}
|
||||
});
|
||||
// Restart the refresh timer, if needed
|
||||
var refreshViewCheck = Component.$Preferences.defaults.SOGoRefreshViewCheck;
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually') {
|
||||
var f = angular.bind(Component.$rootScope, Component.$rootScope.$emit, 'calendars:list');
|
||||
Component.$refreshTimeout = Component.$timeout(f, refreshViewCheck.timeInterval()*1000);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -166,44 +160,41 @@
|
|||
queryKey = '$query' + type.capitalize(),
|
||||
params = {
|
||||
day: '' + year + (month < 10?'0':'') + month + (day < 10?'0':'') + day,
|
||||
};
|
||||
},
|
||||
futureComponentData,
|
||||
dirty = false,
|
||||
otherType;
|
||||
|
||||
Component.$startRefreshTimeout(type);
|
||||
|
||||
return this.$Preferences.ready().then(function() {
|
||||
var futureComponentData,
|
||||
dirty = false,
|
||||
otherType;
|
||||
angular.extend(this.$query, params);
|
||||
|
||||
angular.extend(_this.$query, params);
|
||||
if (options) {
|
||||
_.forEach(_.keys(options), function(key) {
|
||||
// Query parameters common to events and tasks are compared
|
||||
dirty |= (_this.$query[key] && options[key] != Component.$query[key]);
|
||||
if (key == 'reload' && options[key])
|
||||
dirty = true;
|
||||
// Update either the common parameters or the type-specific parameters
|
||||
else if (angular.isDefined(_this.$query[key]))
|
||||
_this.$query[key] = options[key];
|
||||
else
|
||||
_this[queryKey][key] = options[key];
|
||||
});
|
||||
}
|
||||
|
||||
if (options) {
|
||||
_.forEach(_.keys(options), function(key) {
|
||||
// Query parameters common to events and tasks are compared
|
||||
dirty |= (_this.$query[key] && options[key] != Component.$query[key]);
|
||||
if (key == 'reload' && options[key])
|
||||
dirty = true;
|
||||
// Update either the common parameters or the type-specific parameters
|
||||
else if (angular.isDefined(_this.$query[key]))
|
||||
_this.$query[key] = options[key];
|
||||
else
|
||||
_this[queryKey][key] = options[key];
|
||||
});
|
||||
}
|
||||
// Perform query with both common and type-specific parameters
|
||||
futureComponentData = this.$$resource.fetch(null, type + 'list',
|
||||
angular.extend(this[queryKey], this.$query));
|
||||
|
||||
// Perform query with both common and type-specific parameters
|
||||
futureComponentData = _this.$$resource.fetch(null, type + 'list',
|
||||
angular.extend(_this[queryKey], _this.$query));
|
||||
// Invalidate cached results of other type if $query has changed
|
||||
if (dirty) {
|
||||
otherType = (type == 'tasks')? '$events' : '$tasks';
|
||||
delete Component[otherType];
|
||||
Component.$log.debug('force reload of ' + otherType);
|
||||
}
|
||||
|
||||
// Invalidate cached results of other type if $query has changed
|
||||
if (dirty) {
|
||||
otherType = (type == 'tasks')? '$events' : '$tasks';
|
||||
delete Component[otherType];
|
||||
Component.$log.debug('force reload of ' + otherType);
|
||||
}
|
||||
|
||||
return _this.$unwrapCollection(type, futureComponentData);
|
||||
});
|
||||
return this.$unwrapCollection(type, futureComponentData);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -256,40 +247,36 @@
|
|||
* @returns a promise of a collection of objects describing the events blocks
|
||||
*/
|
||||
Component.$eventsBlocksForView = function(view, date) {
|
||||
var _this = this;
|
||||
var firstDayOfWeek, viewAction, startDate, endDate, params;
|
||||
|
||||
return Component.$Preferences.ready().then(function(data) {
|
||||
var firstDayOfWeek, viewAction, startDate, endDate, params;
|
||||
firstDayOfWeek = Component.$Preferences.defaults.SOGoFirstDayOfWeek;
|
||||
|
||||
if (view == 'day') {
|
||||
viewAction = 'dayView';
|
||||
startDate = endDate = date;
|
||||
}
|
||||
else if (view == 'multicolumnday') {
|
||||
viewAction = 'multicolumndayView';
|
||||
startDate = endDate = date;
|
||||
}
|
||||
else if (view == 'week') {
|
||||
viewAction = 'weekView';
|
||||
startDate = date.beginOfWeek(firstDayOfWeek);
|
||||
endDate = new Date();
|
||||
endDate.setTime(startDate.getTime());
|
||||
endDate.addDays(6);
|
||||
}
|
||||
else if (view == 'month') {
|
||||
viewAction = 'monthView';
|
||||
startDate = date;
|
||||
startDate.setDate(1);
|
||||
startDate = startDate.beginOfWeek(firstDayOfWeek);
|
||||
endDate = new Date();
|
||||
endDate.setTime(date.getTime());
|
||||
endDate.setMonth(endDate.getMonth() + 1);
|
||||
endDate.addDays(-1);
|
||||
endDate = endDate.endOfWeek(firstDayOfWeek);
|
||||
}
|
||||
return _this.$eventsBlocks(viewAction, startDate, endDate);
|
||||
});
|
||||
firstDayOfWeek = Component.$Preferences.defaults.SOGoFirstDayOfWeek;
|
||||
if (view == 'day') {
|
||||
viewAction = 'dayView';
|
||||
startDate = endDate = date;
|
||||
}
|
||||
else if (view == 'multicolumnday') {
|
||||
viewAction = 'multicolumndayView';
|
||||
startDate = endDate = date;
|
||||
}
|
||||
else if (view == 'week') {
|
||||
viewAction = 'weekView';
|
||||
startDate = date.beginOfWeek(firstDayOfWeek);
|
||||
endDate = new Date();
|
||||
endDate.setTime(startDate.getTime());
|
||||
endDate.addDays(6);
|
||||
}
|
||||
else if (view == 'month') {
|
||||
viewAction = 'monthView';
|
||||
startDate = date;
|
||||
startDate.setDate(1);
|
||||
startDate = startDate.beginOfWeek(firstDayOfWeek);
|
||||
endDate = new Date();
|
||||
endDate.setTime(date.getTime());
|
||||
endDate.setMonth(endDate.getMonth() + 1);
|
||||
endDate.addDays(-1);
|
||||
endDate = endDate.endOfWeek(firstDayOfWeek);
|
||||
}
|
||||
return this.$eventsBlocks(viewAction, startDate, endDate);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -533,12 +520,10 @@
|
|||
|
||||
if (this.c_category) {
|
||||
// c_category is only defined in list mode (when calling $filter)
|
||||
Component.$Preferences.ready().then(function() {
|
||||
// Filter out categories for which there's no associated color
|
||||
_this.categories = _.invokeMap(_.filter(_this.c_category, function(name) {
|
||||
return Component.$Preferences.defaults.SOGoCalendarCategoriesColors[name];
|
||||
}), 'asCSSIdentifier');
|
||||
});
|
||||
// Filter out categories for which there's no associated color
|
||||
this.categories = _.invokeMap(_.filter(this.c_category, function(name) {
|
||||
return Component.$Preferences.defaults.SOGoCalendarCategoriesColors[name];
|
||||
}), 'asCSSIdentifier');
|
||||
}
|
||||
|
||||
// Parse recurrence rule definition and initialize default values
|
||||
|
@ -591,24 +576,22 @@
|
|||
|
||||
if (this.isNew) {
|
||||
// Set default values
|
||||
Component.$Preferences.ready().then(function() {
|
||||
var type = (_this.type == 'appointment')? 'Events' : 'Tasks';
|
||||
var type = (this.type == 'appointment')? 'Events' : 'Tasks';
|
||||
|
||||
// Set default classification
|
||||
_this.classification = Component.$Preferences.defaults['SOGoCalendar' + type + 'DefaultClassification'].toLowerCase();
|
||||
// Set default classification
|
||||
this.classification = Component.$Preferences.defaults['SOGoCalendar' + type + 'DefaultClassification'].toLowerCase();
|
||||
|
||||
// Set default alarm
|
||||
var units = { M: 'MINUTES', H: 'HOURS', D: 'DAYS', W: 'WEEKS' };
|
||||
var match = /-PT?([0-9]+)([MHDW])/.exec(Component.$Preferences.defaults.SOGoCalendarDefaultReminder);
|
||||
if (match) {
|
||||
_this.$hasAlarm = true;
|
||||
_this.alarm.quantity = parseInt(match[1]);
|
||||
_this.alarm.unit = units[match[2]];
|
||||
}
|
||||
// Set default alarm
|
||||
var units = { M: 'MINUTES', H: 'HOURS', D: 'DAYS', W: 'WEEKS' };
|
||||
var match = /-PT?([0-9]+)([MHDW])/.exec(Component.$Preferences.defaults.SOGoCalendarDefaultReminder);
|
||||
if (match) {
|
||||
this.$hasAlarm = true;
|
||||
this.alarm.quantity = parseInt(match[1]);
|
||||
this.alarm.unit = units[match[2]];
|
||||
}
|
||||
|
||||
// Set notitifications
|
||||
_this.sendAppointmentNotifications = Component.$Preferences.defaults.SOGoAppointmentSendEMailNotifications;
|
||||
});
|
||||
// Set notitifications
|
||||
this.sendAppointmentNotifications = Component.$Preferences.defaults.SOGoAppointmentSendEMailNotifications;
|
||||
}
|
||||
else if (angular.isUndefined(data.$hasAlarm)) {
|
||||
this.$hasAlarm = angular.isDefined(data.alarm);
|
||||
|
|
|
@ -116,26 +116,24 @@
|
|||
});
|
||||
if ($location.url().length === 0) {
|
||||
// Restore user's last view
|
||||
Preferences.ready().then(function() {
|
||||
var url = '/calendar/',
|
||||
view = /(.+)view/.exec(Preferences.settings.Calendar.View);
|
||||
if (view)
|
||||
url += view[1];
|
||||
else
|
||||
url += 'week';
|
||||
// Append today's date or next enabled weekday
|
||||
var now = new Date();
|
||||
if (Preferences.defaults.SOGoCalendarWeekdays) {
|
||||
var weekDays = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
|
||||
var weekDay = weekDays[now.getDay()];
|
||||
while (Preferences.defaults.SOGoCalendarWeekdays.indexOf(weekDay) < 0) {
|
||||
now.addDays(1);
|
||||
weekDay = weekDays[now.getDay()];
|
||||
}
|
||||
var url = '/calendar/',
|
||||
view = /(.+)view/.exec(Preferences.settings.Calendar.View);
|
||||
if (view)
|
||||
url += view[1];
|
||||
else
|
||||
url += 'week';
|
||||
// Append today's date or next enabled weekday
|
||||
var now = new Date();
|
||||
if (Preferences.defaults.SOGoCalendarWeekdays) {
|
||||
var weekDays = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
|
||||
var weekDay = weekDays[now.getDay()];
|
||||
while (Preferences.defaults.SOGoCalendarWeekdays.indexOf(weekDay) < 0) {
|
||||
now.addDays(1);
|
||||
weekDay = weekDays[now.getDay()];
|
||||
}
|
||||
url += '/' + now.getDayString();
|
||||
$location.replace().url(url);
|
||||
});
|
||||
}
|
||||
url += '/' + now.getDayString();
|
||||
$location.replace().url(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,17 +48,16 @@
|
|||
function initView() {
|
||||
view = new sgScrollView(element, type);
|
||||
|
||||
if (type != 'monthly')
|
||||
if (type != 'monthly') {
|
||||
// Scroll to the day start hour defined in the user's defaults
|
||||
Preferences.ready().then(function() {
|
||||
var time, hourCell, quartersOffset;
|
||||
if (Preferences.defaults.SOGoDayStartTime) {
|
||||
time = Preferences.defaults.SOGoDayStartTime.split(':');
|
||||
hourCell = document.getElementById('hour' + parseInt(time[0]));
|
||||
quartersOffset = parseInt(time[1]) * view.quarterHeight;
|
||||
view.element.scrollTop = hourCell.offsetTop + quartersOffset;
|
||||
}
|
||||
});
|
||||
var time, hourCell, quartersOffset;
|
||||
if (Preferences.defaults.SOGoDayStartTime) {
|
||||
time = Preferences.defaults.SOGoDayStartTime.split(':');
|
||||
hourCell = document.getElementById('hour' + parseInt(time[0]));
|
||||
quartersOffset = parseInt(time[1]) * view.quarterHeight;
|
||||
view.element.scrollTop = hourCell.offsetTop + quartersOffset;
|
||||
}
|
||||
}
|
||||
|
||||
// Expose quarter height to the controller
|
||||
// See sgNowLine directive
|
||||
|
|
Loading…
Reference in New Issue