diff options
author | Jury Verrigni <jury.verrigni@gmail.com> | 2017-02-01 12:04:55 +0000 |
---|---|---|
committer | Alexander Weidinger <alexwegoo@gmail.com> | 2017-02-07 00:25:11 +0100 |
commit | 6529a8e9d4e668e159825a6476a3504526b487df (patch) | |
tree | 23f0acea41c97974b8ff1379897ff03d12258609 | |
parent | 9523b407cbfc5ed6643d54a9e5cafb000929f129 (diff) |
Added sort functionality (visible in settings, bottom left) (#569)
* Added sort functionality (visible in settings, bottom left)
* Fallback to fullName if the sort criteria is not set within the contact; displayName is now the default sort criteria
* Changing display name based on sort order; sorting takes both first and second name in consideration
-rw-r--r-- | js/components/contact/contact_controller.js | 27 | ||||
-rw-r--r-- | js/components/contactList/contactList_controller.js | 8 | ||||
-rw-r--r-- | js/components/sortBy/sortBy_controller.js | 16 | ||||
-rw-r--r-- | js/components/sortBy/sortBy_directive.js | 11 | ||||
-rw-r--r-- | js/filters/localeOrderBy_filter.js | 8 | ||||
-rw-r--r-- | js/models/contact_model.js | 39 | ||||
-rw-r--r-- | js/services/sortBy_service.js | 39 | ||||
-rw-r--r-- | js/tests/services/sortBy_service.js | 20 | ||||
-rw-r--r-- | templates/contact.html | 2 | ||||
-rw-r--r-- | templates/contactList.html | 2 | ||||
-rw-r--r-- | templates/main.php | 1 | ||||
-rw-r--r-- | templates/sortBy.html | 4 |
12 files changed, 172 insertions, 5 deletions
diff --git a/js/components/contact/contact_controller.js b/js/components/contact/contact_controller.js index 2d84076f..6e5daa96 100644 --- a/js/components/contact/contact_controller.js +++ b/js/components/contact/contact_controller.js @@ -1,5 +1,5 @@ angular.module('contactsApp') -.controller('contactCtrl', function($route, $routeParams) { +.controller('contactCtrl', function($route, $routeParams, SortByService) { var ctrl = this; ctrl.t = { @@ -11,4 +11,29 @@ angular.module('contactsApp') gid: $routeParams.gid, uid: ctrl.contact.uid()}); }; + + ctrl.getName = function() { + // If lastName equals to firstName then none of them is set + if (ctrl.contact.lastName() === ctrl.contact.firstName()) { + return ctrl.contact.displayName(); + } + + if (SortByService.getSortBy() === 'sortLastName') { + return ( + ctrl.contact.lastName() + ', ' + + ctrl.contact.firstName() + ' ' + + ctrl.contact.additionalNames() + ).trim(); + } + + if (SortByService.getSortBy() === 'sortFirstName') { + return ( + ctrl.contact.firstName() + ' ' + + ctrl.contact.additionalNames() + ' ' + + ctrl.contact.lastName() + ).trim(); + } + + return ctrl.contact.displayName(); + }; }); diff --git a/js/components/contactList/contactList_controller.js b/js/components/contactList/contactList_controller.js index 8d144081..a22180d2 100644 --- a/js/components/contactList/contactList_controller.js +++ b/js/components/contactList/contactList_controller.js @@ -1,5 +1,5 @@ angular.module('contactsApp') -.controller('contactlistCtrl', function($scope, $filter, $route, $routeParams, ContactService, vCardPropertiesService, SearchService) { +.controller('contactlistCtrl', function($scope, $filter, $route, $routeParams, ContactService, SortByService, vCardPropertiesService, SearchService) { var ctrl = this; ctrl.routeParams = $routeParams; @@ -9,6 +9,8 @@ angular.module('contactsApp') ctrl.show = true; ctrl.invalid = false; + ctrl.sortBy = SortByService.getSortBy(); + ctrl.t = { emptySearch : t('contacts', 'No search result for {query}', {query: ctrl.searchTerm}) }; @@ -21,6 +23,10 @@ angular.module('contactsApp') return contact.matches(SearchService.getSearchTerm()); }; + SortByService.subscribe(function(newValue) { + ctrl.sortBy = newValue; + }); + SearchService.registerObserverCallback(function(ev) { if (ev.event === 'submitSearch') { var uid = !_.isEmpty(ctrl.contactList) ? ctrl.contactList[0].uid() : undefined; diff --git a/js/components/sortBy/sortBy_controller.js b/js/components/sortBy/sortBy_controller.js new file mode 100644 index 00000000..d740f8e1 --- /dev/null +++ b/js/components/sortBy/sortBy_controller.js @@ -0,0 +1,16 @@ +angular.module('contactsApp') +.controller('sortbyCtrl', function(SortByService) { + var ctrl = this; + + var sortText = t('contacts', 'Sort by'); + ctrl.sortText = sortText; + + var sortList = SortByService.getSortByList(); + ctrl.sortList = sortList; + + ctrl.defaultOrder = SortByService.getSortBy(); + + ctrl.updateSortBy = function() { + SortByService.setSortBy(ctrl.defaultOrder); + }; +}); diff --git a/js/components/sortBy/sortBy_directive.js b/js/components/sortBy/sortBy_directive.js new file mode 100644 index 00000000..faf943a7 --- /dev/null +++ b/js/components/sortBy/sortBy_directive.js @@ -0,0 +1,11 @@ +angular.module('contactsApp') +.directive('sortby', function() { + return { + priority: 1, + scope: {}, + controller: 'sortbyCtrl', + controllerAs: 'ctrl', + bindToController: {}, + templateUrl: OC.linkTo('contacts', 'templates/sortBy.html') + }; +}); diff --git a/js/filters/localeOrderBy_filter.js b/js/filters/localeOrderBy_filter.js index f95c8496..24576fe1 100644 --- a/js/filters/localeOrderBy_filter.js +++ b/js/filters/localeOrderBy_filter.js @@ -27,10 +27,16 @@ angular.module('contactsApp') return !reverseOrder ? valueA - valueB : valueB - valueA; } + if (angular.isArray(valueA)) { + if (valueA[0] === valueB[0]) { + return !reverseOrder ? valueA[1].localeCompare(valueB[1]) : valueB[1].localeCompare(valueA[1]); + } + return !reverseOrder ? valueA[0].localeCompare(valueB[0]) : valueB[0].localeCompare(valueA[0]); + } + return 0; }); return arrayCopy; }; }]); - diff --git a/js/models/contact_model.js b/js/models/contact_model.js index 65218f4f..7ac65bc5 100644 --- a/js/models/contact_model.js +++ b/js/models/contact_model.js @@ -31,6 +31,18 @@ angular.module('contactsApp') } }, + sortFirstName: function() { + return [this.firstName(), this.lastName()]; + }, + + sortLastName: function() { + return [this.lastName(), this.firstName()]; + }, + + sortDisplayName: function() { + return this.displayName(); + }, + displayName: function() { var displayName = this.fullName() || this.org() || ''; if(angular.isArray(displayName)) { @@ -49,6 +61,33 @@ angular.module('contactsApp') }, + firstName: function() { + var property = this.getProperty('n'); + if (property) { + return property.value[1]; + } else { + return this.displayName(); + } + }, + + lastName: function() { + var property = this.getProperty('n'); + if (property) { + return property.value[0]; + } else { + return this.displayName(); + } + }, + + additionalNames: function() { + var property = this.getProperty('n'); + if (property) { + return property.value[2]; + } else { + return ''; + } + }, + fullName: function(value) { var model = this; if (angular.isDefined(value)) { diff --git a/js/services/sortBy_service.js b/js/services/sortBy_service.js new file mode 100644 index 00000000..42f0957a --- /dev/null +++ b/js/services/sortBy_service.js @@ -0,0 +1,39 @@ +angular.module('contactsApp') +.service('SortByService', function () { + var subscriptions = []; + var sortBy = 'sortDisplayName'; + + var defaultOrder = window.localStorage.getItem('contacts_default_order'); + if (defaultOrder) { + sortBy = defaultOrder; + } + + function notifyObservers () { + angular.forEach(subscriptions, function (subscription) { + if (typeof subscription === 'function') { + subscription(sortBy); + } + }); + } + + return { + subscribe: function (callback) { + subscriptions.push (callback); + }, + setSortBy: function (value) { + sortBy = value; + window.localStorage.setItem ('contacts_default_order', value); + notifyObservers (); + }, + getSortBy: function () { + return sortBy; + }, + getSortByList: function () { + return { + sortDisplayName: t('contacts', 'Display name'), + sortFirstName: t('contacts', 'First name'), + sortLastName: t('contacts', 'Last name') + }; + } + }; +}); diff --git a/js/tests/services/sortBy_service.js b/js/tests/services/sortBy_service.js new file mode 100644 index 00000000..4ea227c5 --- /dev/null +++ b/js/tests/services/sortBy_service.js @@ -0,0 +1,20 @@ +describe('sortbyService', function() { + + var $Service; + beforeEach(module('contactsApp')); + + beforeEach(inject(function(SortByService){ + $Service = SortByService; + })); + + it('should return sortDisplayName as default sorting method', function() { + expect($Service.getSortBy()).to.equal('sortDisplayName'); + }); + + it('should store sorting method', function() { + $Service.setSortBy('sortLastName'); + expect($Service.getSortBy()).to.equal( + window.localStorage.getItem('contacts_default_order') + ); + }); +}); diff --git a/templates/contact.html b/templates/contact.html index b6e68c00..ac528cdb 100644 --- a/templates/contact.html +++ b/templates/contact.html @@ -3,6 +3,6 @@ <div class="app-content-list-item-icon contact__icon" ng-show="ctrl.contact.photo()===undefined" ng-style="{'background-color': (ctrl.contact.uid() | contactColor) }">{{ ctrl.contact.displayName() | firstCharacter }}</div> <div class="app-content-list-item-star icon-star" data-starred="false"></div> <div class="app-content-list-item-failed icon-error" tooltip-placement="auto left" ng-if="ctrl.contact.failedProps.length>0" uib-tooltip="{{ ctrl.t.errorMessage }}"></div> - <div class="app-content-list-item-line-one" ng-class="{'no-line-two':!ctrl.contact.email()}">{{ ctrl.contact.displayName() | newContact }}</div> + <div class="app-content-list-item-line-one" ng-class="{'no-line-two':!ctrl.contact.email()}">{{ ctrl.getName() | newContact }}</div> <div class="app-content-list-item-line-two">{{ctrl.contact.email()}}</div> </a> diff --git a/templates/contactList.html b/templates/contactList.html index a1a99ae3..47d30067 100644 --- a/templates/contactList.html +++ b/templates/contactList.html @@ -1,6 +1,6 @@ <div style="height: 90%" class="contacts-list" ng-class="{loading: ctrl.loading, 'mobile-show': ctrl.show}"> <div class="app-content-list-item" - ng-repeat="contact in ctrl.contactList = (ctrl.contacts | contactGroupFilter:ctrl.routeParams.gid | localeOrderBy:'displayName' | filter:query) as filtered track by contact.uid()" + ng-repeat="contact in ctrl.contactList = (ctrl.contacts | contactGroupFilter:ctrl.routeParams.gid | localeOrderBy:ctrl.sortBy | filter:query) as filtered track by contact.uid()" contact data="contact" ng-click="setSelected(contact.uid())" ng-class="{active: contact.uid() === ctrl.getSelectedId()}"> diff --git a/templates/main.php b/templates/main.php index a1454dfa..e165fc73 100644 --- a/templates/main.php +++ b/templates/main.php @@ -38,6 +38,7 @@ vendor_style('select2/select2'); <div id="app-settings-content"> <addressBookList></addressBookList> <contactImport></contactImport> + <sortBy></sortBy> </div> </div> </div> diff --git a/templates/sortBy.html b/templates/sortBy.html new file mode 100644 index 00000000..d29cc605 --- /dev/null +++ b/templates/sortBy.html @@ -0,0 +1,4 @@ +<label for="contact-import">{{ctrl.sortText}}:</label> +<select ng-change="ctrl.updateSortBy()" ng-model="ctrl.defaultOrder" id="sort-by"> + <option ng-repeat="(key, value) in ctrl.sortList" ng-model="ctrl.sortList[key]" ng-selected="ctrl.defaultOrder == key" value="{{key}}">{{value}}</option> +</select> |