diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index 13fc75c65..df66e1c78 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -489,7 +489,7 @@ validate_endbeforestart = "The end date that you entered occurs before the st "A time conflict exists with one or more attendees.\nWould you like to keep the current settings anyway?" = "A time conflict exists with one or more attendees.\nWould you like to keep the current settings anyway?"; -/* apt list */ +/* events list */ "Title" = "Title"; "Start" = "Start"; "End" = "End"; @@ -502,8 +502,12 @@ vevent_class0 = "(Public event)"; vevent_class1 = "(Private event)"; vevent_class2 = "(Confidential event)"; +/* tasks list */ "Priority" = "Priority"; "Category" = "Category"; +"Status" = "Status"; + +"Descending Order" = "Descending Order"; vtodo_class0 = "(Public task)"; vtodo_class1 = "(Private task)"; diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m index c7a2ff9ab..5d3e2aa04 100644 --- a/UI/Scheduler/UIxCalListingActions.m +++ b/UI/Scheduler/UIxCalListingActions.m @@ -672,7 +672,7 @@ static NSArray *tasksFields = nil; * curl -i http://localhost/SOGo/so/sogo1/Calendar/eventslist?day=20141201\&filterpopup=view_selectedday * * @apiParam {Boolean} [asc] Descending sort when false. Defaults to true (ascending). - * @apiParam {String} [sort] Sort field. Either title, end, location, or calendarName. + * @apiParam {String} [sort] Sort field. Either title, start, end, location, or calendarName. * @apiParam {Number} [day] Selected day (YYYYMMDD) * @apiParam {String} [filterpopup] Time period. Either view_today, view_next7, view_next14, view_next31, view_thismonth, view_future, view_selectedday, or view_all * @apiParam {String} [search] Search field criteria. Either title_Category_Location or entireContent. @@ -1361,13 +1361,12 @@ _computeBlocksPosition (NSArray *blocks) * @apiExample {curl} Example usage: * curl -i http://localhost/SOGo/so/sogo1/Calendar/taskslist?filterpopup=view_all * - * @apiParam {Number} [show-completed] Show completed tasks when set to 1. Defaults to ignore completed tasks. + * @apiParam {Number} [show_completed] Show completed tasks when set to 1. Defaults to ignore completed tasks. * @apiParam {Boolean} [asc] Descending sort when false. Defaults to true (ascending). - * @apiParam {Boolean} [sort] Sort field. Either title, priority, end, location, category, or calendarname. + * @apiParam {Boolean} [sort] Sort field. Either title, priority, end, location, category, calendarname, or status. * @apiParam {Number} [day] Selected day (YYYYMMDD) * @apiParam {String} [filterpopup] Time period. Either view_today, view_next7, view_next14, view_next31, view_thismonth, view_overdue, view_incomplete, view_not_started, or view_all * @apiParam {String} [search] Search field criteria. Either title_Category_Location or entireContent. - * @apiParam {Boolean} [setud] Save 'show-completed' parameter in user's settings * * @apiSuccess (Success 200) {String[]} fields List of fields for each event definition * @apiSuccess (Success 200) {String[]} tasks List of events @@ -1413,14 +1412,10 @@ _computeBlocksPosition (NSArray *blocks) endsSecs = (unsigned int) [endDate timeIntervalSince1970]; tasksView = [request formValueForKey: @"filterpopup"]; -#warning see TODO in SchedulerUI.js about "setud" - showCompleted = [[request formValueForKey: @"show-completed"] intValue]; - if ([request formValueForKey: @"setud"]) - { - us = [[context activeUser] userSettings]; - [us setBool: showCompleted forKey: @"ShowCompletedTasks"]; - [us synchronize]; - } + showCompleted = [[request formValueForKey: @"show_completed"] intValue]; + us = [[context activeUser] userSettings]; + [us setBool: showCompleted forKey: @"ShowCompletedTasks"]; + [us synchronize]; tasks = [[self _fetchFields: tasksFields forComponentOfType: @"vtodo"] objectEnumerator]; @@ -1468,7 +1463,7 @@ _computeBlocksPosition (NSArray *blocks) [filteredTasks sortUsingSelector: @selector (compareTasksLocationAscending:)]; else if ([sort isEqualToString: @"category"]) [filteredTasks sortUsingSelector: @selector (compareTasksCategoryAscending:)]; - else if ([sort isEqualToString: @"calendarname"]) + else if ([sort isEqualToString: @"calendarName"]) [filteredTasks sortUsingSelector: @selector (compareTasksCalendarNameAscending:)]; else [filteredTasks sortUsingSelector: @selector (compareTasksAscending:)]; diff --git a/UI/Templates/SchedulerUI/UIxCalMainView.wox b/UI/Templates/SchedulerUI/UIxCalMainView.wox index 5fce7c8a6..e7cab4389 100644 --- a/UI/Templates/SchedulerUI/UIxCalMainView.wox +++ b/UI/Templates/SchedulerUI/UIxCalMainView.wox @@ -322,8 +322,8 @@
- -
+
- filter_list - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + sort + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/UI/WebServerResources/js/Scheduler/CalendarListController.js b/UI/WebServerResources/js/Scheduler/CalendarListController.js index b76153002..519a2c7b0 100644 --- a/UI/WebServerResources/js/Scheduler/CalendarListController.js +++ b/UI/WebServerResources/js/Scheduler/CalendarListController.js @@ -16,6 +16,9 @@ vm.selectComponentType = selectComponentType; vm.newComponent = newComponent; vm.filter = filter; + vm.filteredBy = filteredBy; + vm.sort = sort; + vm.sortedBy = sortedBy; vm.cancelSearch = cancelSearch; vm.mode = { search: false }; @@ -26,7 +29,7 @@ vm.selectedList = 1; type = 'tasks'; } - vm.selectComponentType(type, { reload: true }); + selectComponentType(type, { reload: true }); }); // Switch between components tabs @@ -49,15 +52,24 @@ } function filter(filterpopup) { - if (filterpopup) - Component.$query.filterpopup = filterpopup; + Component.$filter(vm.componentType, options); + } - Component.$filter(vm.componentType, { value: '' }); + function filteredBy(filterpopup) { + return Component['$query' + vm.componentType.capitalize()].filterpopup == filterpopup; + } + + function sort(field) { + Component.$filter(vm.componentType, { sort: field }); + } + + function sortedBy(field) { + return Component['$query' + vm.componentType.capitalize()].sort == field; } function cancelSearch() { vm.mode.search = false; - filter(); + Component.$filter(vm.componentType, { value: '' }); } // Refresh current list when the list of calendars is modified diff --git a/UI/WebServerResources/js/Scheduler/Component.service.js b/UI/WebServerResources/js/Scheduler/Component.service.js index a50f3e645..f3753bd30 100644 --- a/UI/WebServerResources/js/Scheduler/Component.service.js +++ b/UI/WebServerResources/js/Scheduler/Component.service.js @@ -39,11 +39,17 @@ $Preferences: Preferences, $$resource: new Resource(Settings.baseURL, Settings.activeUser), $categories: window.UserDefaults.SOGoCalendarCategoriesColors, - $query: { search: 'title_Category_Location' } + // Filter parameters common to events and tasks + $query: { value: '', search: 'title_Category_Location' }, + // Filter paramaters specific to events + $queryEvents: { sort: 'start', asc: 1, filterpopup: 'view_next7' }, + // Filter parameters specific to tasks + $queryTasks: { sort: 'status', asc: 1, filterpopup: 'view_incomplete' } }); + // Initialize filter parameters from user's settings Preferences.ready().then(function() { - Component.$query.filterpopup = Preferences.settings.CalendarDefaultFilter; - Component.$query['show-completed'] = parseInt(Preferences.settings.ShowCompletedTasks); + Component.$queryEvents.filterpopup = Preferences.settings.CalendarDefaultFilter; + Component.$queryTasks.show_completed = parseInt(Preferences.settings.ShowCompletedTasks); }); if (window.UserDefaults && window.UserDefaults.SOGoTimeFormat) Component.timeFormat = window.UserDefaults.SOGoTimeFormat; @@ -74,23 +80,33 @@ day = now.getDate(), month = now.getMonth() + 1, year = now.getFullYear(), - defaultParams = { + queryKey = '$query' + type.capitalize(), + params = { day: '' + year + (month < 10?'0':'') + month + (day < 10?'0':'') + day, }; return this.$Preferences.ready().then(function() { - var futureComponentData, dirty = false, otherType; + var futureComponentData, + dirty = false, + otherType; + + angular.extend(_this.$query, params); - angular.extend(_this.$query, defaultParams); if (options) { - _.find(_.allKeys(options), function(key) { - dirty = (options[key] != Component.$query[key]); - return dirty; + _.each(_.allKeys(options), function(key) { + // Query parameters common to events and tasks are compared + dirty |= (_this.$query[key] && options[key] != Component.$query[key]); + // Update either the common parameters or the type-specific parameters + if (angular.isDefined(_this.$query[key])) + _this.$query[key] = options[key]; + else + _this[queryKey][key] = options[key]; }) - angular.extend(_this.$query, options); } - futureComponentData = _this.$$resource.fetch(null, type + 'list', _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 otherType = (type == 'tasks')? '$events' : '$tasks';