(js) Improve search toolbar in Calendar module
- new distinct search toolbar - restored filtering options - honor user's settingspull/91/head
parent
4d4458a183
commit
9514103031
|
@ -8,9 +8,9 @@
|
|||
xmlns:label="OGo:label"
|
||||
className="UIxPageFrame"
|
||||
title="title"
|
||||
const:userDefaultsKeys="SOGoRefreshViewCheck, SOGoCalendarCategoriesColors, SOGoDefaultCalendar"
|
||||
const:userDefaultsKeys="SOGoRefreshViewCheck, SOGoCalendarCategoriesColors, SOGoDefaultCalendar, SOGoTimeFormat"
|
||||
const:userSettingsKeys="Calendar, ShowCompletedTasks"
|
||||
const:jsFiles="Scheduler.app.js, Scheduler.js, Common.js, Contacts.js">
|
||||
const:jsFiles="Scheduler.app.js, Scheduler.js, Common.js, Contacts.js, Mailer.js, Preferences.js">
|
||||
<script type="text/javascript">
|
||||
var firstDayOfWeek = <var:string value="firstDayOfWeek"/>;
|
||||
var dayStartHour = <var:string value="dayStartHour"/>;
|
||||
|
@ -314,7 +314,7 @@
|
|||
ng-controller="CalendarListController as list">
|
||||
<md-toolbar layout="column" layout-align="space-between start" class="md-tall toolbar-main">
|
||||
<div class="md-toolbar-tools md-toolbar-tools-top sg-padded" layout="row" layout-align="space-between start">
|
||||
<var:component className="UIxTopnavToolbarTemplate" />
|
||||
<!-- <var:component className="UIxTopnavToolbarTemplate" /> -->
|
||||
<div class="sg-toolbar-group-2">
|
||||
<md-button class="sg-icon-button" label:aria-label="Search">
|
||||
<md-icon>search</md-icon>
|
||||
|
@ -322,19 +322,103 @@
|
|||
</div>
|
||||
</div><!-- .md-toolbar-tools -->
|
||||
<div class="md-toolbar-tools md-toolbar-tools-bottom" layout="row" layout-align="space-between center">
|
||||
<div class="view-list sg-padded" layout="row" layout-align="space-between center"
|
||||
sg-search="list.component.$filter(list.componentType, { value: searchText, search: searchField })">
|
||||
<md-input-container class="sg-search-field-container">
|
||||
<label style="color: white"><md-icon>search</md-icon><var:string label:value="Search"/></label>
|
||||
<input name="folderSearch" type="search" style="color: white"/>
|
||||
</md-input-container>
|
||||
<!-- filter mode -->
|
||||
<div class="view-list sg-padded--right" layout="row" layout-align="space-between center"
|
||||
ng-hide="list.mode.search">
|
||||
<div class="sg-toolbar-group">
|
||||
<md-select>
|
||||
<md-option value="title_Category_Location"><var:string label:value="Title, category or location"/></md-option>
|
||||
<md-option value="entireContent"><var:string label:value="Entire content"/></md-option>
|
||||
</md-select>
|
||||
<md-button class="sg-icon-button" label:aria-label="Search"
|
||||
ng-click="list.mode.search = true">
|
||||
<md-icon>search</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
<div class="sg-toolbar-group-last">
|
||||
<md-menu>
|
||||
<md-button class="sg-icon-button" label:aria-label="Search"
|
||||
ng-click="$mdOpenMenu()">
|
||||
<md-icon>filter_list</md-icon>
|
||||
</md-button>
|
||||
<md-menu-content>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="list.filter('view_all')">
|
||||
<md-icon ng-class="{ 'icon-check': list.component.$query.filterpopup == 'view_all' }">
|
||||
<!-- selected --></md-icon> <var:string label:value="view_all"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="list.filter('view_today')">
|
||||
<md-icon ng-class="{ 'icon-check': list.component.$query.filterpopup == 'view_today' }">
|
||||
<!-- selected --></md-icon> <var:string label:value="view_today"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="list.filter('view_next7')">
|
||||
<md-icon ng-class="{ 'icon-check': list.component.$query.filterpopup == 'view_next7' }">
|
||||
<!-- selected --></md-icon> <var:string label:value="view_next7"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="list.filter('view_next14')">
|
||||
<md-icon ng-class="{ 'icon-check': list.component.$query.filterpopup == 'view_next14' }">
|
||||
<!-- selected --></md-icon> <var:string label:value="view_next14"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="list.filter('view_next31')">
|
||||
<md-icon ng-class="{ 'icon-check': list.component.$query.filterpopup == 'view_next31' }">
|
||||
<!-- selected --></md-icon><var:string label:value="view_next31"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="list.filter('view_thismonth')">
|
||||
<md-icon ng-class="{ 'icon-check': list.component.$query.filterpopup == 'view_thismonth' }">
|
||||
<!-- selected --></md-icon><var:string label:value="view_thismonth"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="list.filter('view_future')">
|
||||
<md-icon ng-class="{ 'icon-check': list.component.$query.filterpopup == 'view_future' }">
|
||||
<!-- selected --></md-icon> <var:string label:value="view_future"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="list.filter('view_selectedday')">
|
||||
<md-icon ng-class="{ 'icon-check': list.component.$query.filterpopup == 'view_selectedday' }">
|
||||
<!-- selected --></md-icon><var:string label:value="view_selectedday"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-divider ng-if="list.componentType == 'tasks'"><!-- divider --></md-menu-divider>
|
||||
<md-menu-item ng-if="list.componentType == 'tasks'">
|
||||
<md-button ng-click="list.filter()">
|
||||
<md-checkbox
|
||||
ng-model="list.component.$query['show-completed']"
|
||||
ng-true-value="1"
|
||||
ng-false-value="0"><var:string label:value="Show completed tasks"/></md-checkbox>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
</div>
|
||||
</div>
|
||||
<!-- search mode -->
|
||||
<div class="view-list sg-padded--right sg-toolbar-search" layout="row" layout-align="space-between center"
|
||||
ng-show="list.mode.search"
|
||||
sg-search="list.component.$filter(list.componentType, { value: searchText, search: searchField })">
|
||||
<md-button class="sg-icon-button"
|
||||
sg-search-cancel="list.cancelSearch()"
|
||||
label:aria-label="Back">
|
||||
<md-icon>arrow_back</md-icon>
|
||||
</md-button>
|
||||
<md-input-container>
|
||||
<input name="folderSearch" type="search" />
|
||||
</md-input-container>
|
||||
<md-input-container>
|
||||
<md-select>
|
||||
<md-option value="title_Category_Location" selected="selected"><var:string label:value="Title, category or location"/></md-option>
|
||||
<md-option value="entireContent"><var:string label:value="Entire content"/></md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
</div>
|
||||
<!-- day/week/month views -->
|
||||
<div class="sg-padded">
|
||||
<a class="sg-icon-button md-button"
|
||||
label:aria-label="Day"
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('SOGo.ContactsUI', []);
|
||||
angular.module('SOGo.MailerUI', []);
|
||||
angular.module('SOGo.PreferencesUI', []);
|
||||
|
||||
angular.module('SOGo.SchedulerUI', ['ngSanitize', 'ui.router', 'ct.ui.router.extras.sticky', 'ct.ui.router.extras.previous', 'vs-repeat', 'SOGo.Common', 'SOGo.ContactsUI'])
|
||||
angular.module('SOGo.SchedulerUI', ['ngSanitize', 'ui.router', 'ct.ui.router.extras.sticky', 'ct.ui.router.extras.previous', 'vs-repeat', 'SOGo.Common', 'SOGo.ContactsUI', 'SOGo.MailerUI', 'SOGo.PreferencesUI'])
|
||||
|
||||
.constant('sgSettings', {
|
||||
baseURL: ApplicationBaseURL,
|
||||
|
|
|
@ -6,18 +6,28 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
CalendarListController.$inject = ['$scope', '$rootScope', '$timeout', '$state', 'sgFocus', 'encodeUriFilter', 'Dialog', 'sgSettings', 'Calendar', 'Component', '$mdSidenav'];
|
||||
function CalendarListController($scope, $rootScope, $timeout, $state, focus, encodeUriFilter, Dialog, Settings, Calendar, Component, $mdSidenav) {
|
||||
CalendarListController.$inject = ['$scope', '$rootScope', '$timeout', '$state', 'sgFocus', 'encodeUriFilter', 'Dialog', 'sgSettings', 'Preferences', 'Calendar', 'Component', '$mdSidenav'];
|
||||
function CalendarListController($scope, $rootScope, $timeout, $state, focus, encodeUriFilter, Dialog, Settings, Preferences, Calendar, Component, $mdSidenav) {
|
||||
var vm = this;
|
||||
|
||||
vm.component = Component;
|
||||
vm.componentType = null;
|
||||
vm.componentType = 'events';
|
||||
vm.selectedList = 0;
|
||||
vm.selectComponentType = selectComponentType;
|
||||
vm.newComponent = newComponent;
|
||||
// TODO: should reflect last state userSettings -> Calendar -> SelectedList
|
||||
vm.selectedList = 0;
|
||||
vm.selectComponentType('tasks');
|
||||
vm.selectComponentType('events');
|
||||
vm.filter = filter;
|
||||
vm.cancelSearch = cancelSearch;
|
||||
vm.mode = { search: false };
|
||||
|
||||
// Select list based on user's settings
|
||||
Preferences.ready().then(function() {
|
||||
var type = 'events';
|
||||
if (Preferences.settings.Calendar.SelectedList == 'tasksListView') {
|
||||
vm.selectedList = 1;
|
||||
type = 'tasks';
|
||||
}
|
||||
vm.selectComponentType(type, { reload: true });
|
||||
});
|
||||
|
||||
// Switch between components tabs
|
||||
function selectComponentType(type, options) {
|
||||
|
@ -38,6 +48,18 @@
|
|||
$state.go('calendars.newComponent', { calendarId: 'personal', componentType: type });
|
||||
}
|
||||
|
||||
function filter(filterpopup) {
|
||||
if (filterpopup)
|
||||
Component.$query.filterpopup = filterpopup;
|
||||
|
||||
Component.$filter(vm.componentType, { value: '' });
|
||||
}
|
||||
|
||||
function cancelSearch() {
|
||||
vm.mode.search = false;
|
||||
filter();
|
||||
}
|
||||
|
||||
// Refresh current list when the list of calendars is modified
|
||||
$scope.$on('calendars:list', function() {
|
||||
Component.$filter(vm.componentType);
|
||||
|
|
|
@ -31,15 +31,20 @@
|
|||
* @desc The factory we'll use to register with Angular
|
||||
* @returns the Component constructor
|
||||
*/
|
||||
Component.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'Resource', function($q, $timeout, $log, Settings, Resource) {
|
||||
Component.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'Preferences', 'Resource', function($q, $timeout, $log, Settings, Preferences, Resource) {
|
||||
angular.extend(Component, {
|
||||
$q: $q,
|
||||
$timeout: $timeout,
|
||||
$log: $log,
|
||||
$Preferences: Preferences,
|
||||
$$resource: new Resource(Settings.baseURL, Settings.activeUser),
|
||||
$categories: window.UserDefaults.SOGoCalendarCategoriesColors
|
||||
$categories: window.UserDefaults.SOGoCalendarCategoriesColors,
|
||||
$query: { search: 'title_Category_Location' }
|
||||
});
|
||||
Preferences.ready().then(function() {
|
||||
Component.$query.filterpopup = Preferences.settings.CalendarDefaultFilter;
|
||||
Component.$query['show-completed'] = parseInt(Preferences.settings.ShowCompletedTasks);
|
||||
});
|
||||
|
||||
if (window.UserDefaults && window.UserDefaults.SOGoTimeFormat)
|
||||
Component.timeFormat = window.UserDefaults.SOGoTimeFormat;
|
||||
else
|
||||
|
@ -70,19 +75,32 @@
|
|||
month = now.getMonth() + 1,
|
||||
year = now.getFullYear(),
|
||||
defaultParams = {
|
||||
search: 'title_Category_Location',
|
||||
day: '' + year + (month < 10?'0':'') + month + (day < 10?'0':'') + day,
|
||||
filterpopup: 'view_thismonth'
|
||||
};
|
||||
|
||||
if (angular.isUndefined(this.$filterOptions))
|
||||
this.$filterOptions = defaultParams;
|
||||
if (options)
|
||||
angular.extend(this.$filterOptions, options);
|
||||
return this.$Preferences.ready().then(function() {
|
||||
var futureComponentData, dirty = false, otherType;
|
||||
|
||||
var futureComponentData = this.$$resource.fetch(null, type + 'list', this.$filterOptions);
|
||||
angular.extend(_this.$query, defaultParams);
|
||||
if (options) {
|
||||
_.find(_.allKeys(options), function(key) {
|
||||
dirty = (options[key] != Component.$query[key]);
|
||||
return dirty;
|
||||
})
|
||||
angular.extend(_this.$query, options);
|
||||
}
|
||||
|
||||
return this.$unwrapCollection(type, futureComponentData);
|
||||
futureComponentData = _this.$$resource.fetch(null, type + 'list', _this.$query);
|
||||
|
||||
// Invalidate cached results of other type if $query has changed
|
||||
otherType = (type == 'tasks')? '$events' : '$tasks';
|
||||
if (dirty) {
|
||||
delete Component[otherType];
|
||||
Component.$log.debug('force reload of ' + otherType);
|
||||
}
|
||||
|
||||
return _this.$unwrapCollection(type, futureComponentData);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -206,11 +224,10 @@
|
|||
*/
|
||||
Component.$unwrapCollection = function(type, futureComponentData) {
|
||||
var _this = this,
|
||||
deferred = Component.$q.defer(),
|
||||
components = [];
|
||||
|
||||
futureComponentData.then(function(data) {
|
||||
Component.$timeout(function() {
|
||||
return futureComponentData.then(function(data) {
|
||||
return Component.$timeout(function() {
|
||||
var fields = _.invoke(data.fields, 'toLowerCase');
|
||||
|
||||
// Instanciate Component objects
|
||||
|
@ -225,13 +242,9 @@
|
|||
// Save the list of components to the object model
|
||||
Component['$' + type] = components;
|
||||
|
||||
deferred.resolve(components);
|
||||
return components;
|
||||
});
|
||||
}, function(data) {
|
||||
deferred.reject();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,6 +49,9 @@ md-icon {
|
|||
|
||||
// Define CSS styles to use ng-class with md-icon
|
||||
md-icon {
|
||||
&.icon-check:before {
|
||||
content: "\e5ca";
|
||||
}
|
||||
// &.icon_public:before {
|
||||
// content: "\e80b";
|
||||
// }
|
||||
|
|
|
@ -64,7 +64,7 @@ hgroup {
|
|||
.sg-toolbar-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
&-1 {
|
||||
order: 1;
|
||||
|
@ -79,4 +79,10 @@ hgroup {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.sg-toolbar-search {
|
||||
background-color: sg-color($sogoPaper, 100);
|
||||
color: rgba(0,0,0,0.54);
|
||||
md-icon {
|
||||
color: rgba(0,0,0,0.54);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@ main {
|
|||
.sg-padded {
|
||||
padding-left: $mg;
|
||||
padding-right: $mg;
|
||||
&--right {
|
||||
padding-right: $mg;
|
||||
}
|
||||
}
|
||||
|
||||
.sg-logo {
|
||||
|
|
Loading…
Reference in New Issue