Skip to content

Commit 6dfb155

Browse files
committed
issue #180 fixed duplicate addressbooks showing up when an adressbook is publicly shared and delegated to a user
1 parent 93672f3 commit 6dfb155

10 files changed

+122
-58
lines changed

src/esn.contact.libs/app/addressBook/addressbook-helper.service.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
angular.module('esn.contact.libs')
33
.factory('contactAddressbookHelper', contactAddressbookHelper);
44

5-
function contactAddressbookHelper($q, contactAddressbookParser, contactDavClientService, CONTACT_ADDRESSBOOK_DAV_PROPERTIES, CONTACT_ACCEPT_HEADER) {
5+
function contactAddressbookHelper($q, contactAddressbookParser, contactDavClientService, CONTACT_ADDRESSBOOK_DAV_PROPERTIES, CONTACT_ACCEPT_HEADER, CONTACT_SHARING_SUBSCRIPTION_TYPE) {
66
return {
77
populateSubscriptionSource,
8-
formatAddressBookResponse
8+
formatAddressBookResponse,
9+
getUniqueAdressBookShells
910
};
1011

1112
function populateSubscriptionSource(addressbook) {
@@ -42,4 +43,21 @@ function contactAddressbookHelper($q, contactAddressbookParser, contactDavClient
4243

4344
return { ...response, ...formattedAddressBook };
4445
}
46+
47+
function getUniqueAdressBookShells(addressbooks) {
48+
if (!addressbooks) return;
49+
50+
const uniqueAddressbookList = addressbooks.reduce((acc, current) => {
51+
const { shell, shell: { subscriptionType } } = current;
52+
const href = shell.source ? shell.source.href : shell.href;
53+
54+
if (!acc[href] || subscriptionType === CONTACT_SHARING_SUBSCRIPTION_TYPE.delegation) {
55+
acc[href] = current;
56+
}
57+
58+
return acc;
59+
}, {});
60+
61+
return Object.values(uniqueAddressbookList);
62+
}
4563
}

src/esn.contact.libs/app/addressBook/constants.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ angular.module('esn.contact.libs')
4343
public: 'public'
4444
})
4545

46-
.constant('CONTACT_SHARING_SHARE_PRIVILEGE', '{DAV:}share');
46+
.constant('CONTACT_SHARING_SHARE_PRIVILEGE', '{DAV:}share')
47+
.constant('CONTACT_SHARING_WRITE_PRIVILEGE', '{DAV:}write');

src/linagora.esn.contact/app/addressbook/settings/main/contact-addressbook-settings-main.controller.js

+18-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ function contactAddressbookSettingsMainController(
1313
CONTACT_SHARING_SHARE_ACCESS,
1414
CONTACT_SHARING_SUBSCRIPTION_TYPE,
1515
CONTACT_SHARING_SHARE_ACCESS_CHOICES,
16-
CONTACT_ADDRESSBOOK_MEMBERS_RIGHTS
16+
CONTACT_ADDRESSBOOK_MEMBERS_RIGHTS,
17+
CONTACT_SHARING_WRITE_PRIVILEGE
1718
) {
1819
var self = this;
1920

@@ -62,11 +63,22 @@ function contactAddressbookSettingsMainController(
6263
}
6364

6465
function _initShareAccess() {
65-
self.shareAccess = _.find(
66-
CONTACT_SHARING_SHARE_ACCESS_CHOICES, {
67-
value: self.addressbook.shareAccess
68-
}
69-
);
66+
const { READWRITE } = CONTACT_SHARING_SHARE_ACCESS_CHOICES;
67+
68+
const access = Object.values(CONTACT_SHARING_SHARE_ACCESS_CHOICES)
69+
.find(({ value }) => value === self.addressbook.shareAccess);
70+
71+
if (!access) return;
72+
73+
if (access.value >= READWRITE.value) {
74+
self.shareAccess = access;
75+
76+
return;
77+
}
78+
79+
self.shareAccess = self.addressbook.source.rights.public === CONTACT_SHARING_WRITE_PRIVILEGE ?
80+
READWRITE :
81+
access;
7082
}
7183

7284
function _getShareOwner(sharees) {
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
'use strict';
22

3-
const _ = require('lodash');
4-
53
require('../../contact.service.js');
64

75
angular.module('linagora.esn.contact')
@@ -11,7 +9,8 @@ function contactCopyController(
119
asyncAction,
1210
contactAddressbookDisplayService,
1311
contactAddressbookService,
14-
contactService
12+
contactService,
13+
contactAddressbookHelper
1514
) {
1615
var self = this;
1716
var NOTIFICATION_MESSAGES = {
@@ -25,10 +24,11 @@ function contactCopyController(
2524

2625
function listPossibleDestinations() {
2726
contactAddressbookService.listAddressbooksUserCanCreateContact()
28-
.then(_excludeCurrentAddressbook)
2927
.then(contactAddressbookDisplayService.convertShellsToDisplayShells)
30-
.then(function(availableAddressbookDisplayShells) {
31-
self.availableAddressbookDisplayShells = availableAddressbookDisplayShells;
28+
.then(displayShells => {
29+
const uniqueShells = contactAddressbookHelper.getUniqueAdressBookShells(displayShells);
30+
31+
self.availableAddressbookDisplayShells = _excludeCurrentAddressbookShell(uniqueShells);
3232
self.selectedAddressbook = self.availableAddressbookDisplayShells[0].shell;
3333
});
3434
}
@@ -40,13 +40,9 @@ function contactCopyController(
4040
});
4141
}
4242

43-
function _excludeCurrentAddressbook(addressbooks) {
43+
function _excludeCurrentAddressbookShell(addressbookShells) {
44+
const { addressbook: { href } } = self.contact;
4445

45-
_.remove(addressbooks, function(addressbook) {
46-
return self.contact.addressbook.bookName === addressbook.bookName;
47-
});
48-
49-
return addressbooks;
46+
return addressbookShells.filter(({ shell: { href: addressbookHref } }) => addressbookHref !== href);
5047
}
5148
}
52-

src/linagora.esn.contact/app/contact/action/copy/contact-action-copy.controller.spec.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ describe('The contactActionCopyController controller', function() {
3838
}
3939

4040
var defaultAddressbookShell = {
41-
bookName: 'contacts'
41+
bookName: 'contacts',
42+
href: '0'
4243
};
4344
var addressbookShell = {
44-
bookName: 'collected'
45+
bookName: 'collected',
46+
href: '1'
4547
};
4648

4749
describe('The listPossibleDestinations function', function() {
@@ -61,7 +63,8 @@ describe('The contactActionCopyController controller', function() {
6163
controller.contact = {
6264
id: '123',
6365
addressbook: {
64-
bookName: 'contacts'
66+
bookName: 'contacts',
67+
href: '0'
6568
}
6669
};
6770
controller.listPossibleDestinations();
@@ -105,7 +108,8 @@ describe('The contactActionCopyController controller', function() {
105108
controller.contact = {
106109
id: '123',
107110
addressbook: {
108-
bookName: 'contacts'
111+
bookName: 'contacts',
112+
href: '0'
109113
}
110114
};
111115
controller.selectedAddressbook = destAddressbook;
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
'use strict';
22

3-
const _ = require('lodash');
4-
53
require('../../contact.service.js');
64

75
angular.module('linagora.esn.contact')
@@ -11,7 +9,8 @@ function contactActionMoveController(
119
asyncAction,
1210
contactAddressbookDisplayService,
1311
contactAddressbookService,
14-
contactService
12+
contactService,
13+
contactAddressbookHelper
1514
) {
1615
var self = this;
1716
var NOTIFICATION_MESSAGES = {
@@ -25,12 +24,12 @@ function contactActionMoveController(
2524

2625
function listPossbileDestinations() {
2726
contactAddressbookService.listAddressbooksUserCanCreateContact()
28-
.then(_excludeCurrentAddressbook)
2927
.then(contactAddressbookDisplayService.convertShellsToDisplayShells)
30-
.then(function(availableAddressbookDisplayShells) {
31-
self.availableAddressbookDisplayShells = availableAddressbookDisplayShells;
32-
self.selectedAddressbook = self.availableAddressbookDisplayShells[0].shell;
28+
.then(displayShells => {
29+
const uniqueShells = contactAddressbookHelper.getUniqueAdressBookShells(displayShells);
3330

31+
self.availableAddressbookDisplayShells = _excludeCurrentAddressbookShell(uniqueShells);
32+
self.selectedAddressbook = self.availableAddressbookDisplayShells[0].shell;
3433
});
3534
}
3635

@@ -40,12 +39,10 @@ function contactActionMoveController(
4039
});
4140
}
4241

43-
function _excludeCurrentAddressbook(addressbooks) {
44-
_.remove(addressbooks, function(addressbook) {
45-
return self.contact.addressbook.bookName === addressbook.bookName;
46-
});
42+
function _excludeCurrentAddressbookShell(addressbookShells) {
43+
const { addressbook: { href } } = self.contact;
4744

48-
return addressbooks;
45+
return addressbookShells.filter(({ shell: { href: addressbookHref } }) => addressbookHref !== href);
4946
}
5047
}
5148

src/linagora.esn.contact/app/contact/action/move/contact-action-move.controller.spec.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ describe('The contactActionMoveController controller', function() {
2929
});
3030

3131
defaultAddressbookShell = {
32-
bookName: 'contacts'
32+
bookName: 'contacts',
33+
href: '0'
3334
};
3435
addressbookShell = {
35-
bookName: 'collected'
36+
bookName: 'collected',
37+
href: '1'
3638
};
3739
});
3840

@@ -62,7 +64,8 @@ describe('The contactActionMoveController controller', function() {
6264
controller.contact = {
6365
id: '123',
6466
addressbook: {
65-
bookName: defaultAddressbookShell.bookName
67+
bookName: defaultAddressbookShell.bookName,
68+
href: '0'
6669
}
6770
};
6871
controller.listPossbileDestinations();

src/linagora.esn.contact/app/contact/form/contact-edition-form.directive.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ angular.module('linagora.esn.contact')
77
function contactEditionForm(
88
contactAddressbookDisplayService,
99
contactAddressbookService,
10+
contactAddressbookHelper,
1011
CONTACT_ATTRIBUTES_ORDER,
1112
CONTACT_AVATAR_SIZE
1213
) {
@@ -22,17 +23,16 @@ function contactEditionForm(
2223
$scope.CONTACT_ATTRIBUTES_ORDER = CONTACT_ATTRIBUTES_ORDER;
2324
$scope.avatarSize = CONTACT_AVATAR_SIZE.bigger;
2425

25-
contactAddressbookService.listAddressbooksUserCanCreateContact().then(function(addressbooks) {
26-
return contactAddressbookDisplayService.convertShellsToDisplayShells(addressbooks, { includePriority: true });
27-
})
28-
.then(function(addressbookDisplayShells) {
29-
$scope.availableAddressbooks = contactAddressbookDisplayService.sortAddressbookDisplayShells(addressbookDisplayShells)
30-
.map(function(addressbookDisplayShell) {
31-
return {
32-
path: addressbookDisplayShell.shell.href,
33-
displayName: addressbookDisplayShell.displayName
34-
};
35-
});
26+
contactAddressbookService.listAddressbooksUserCanCreateContact()
27+
.then(addressbooks => contactAddressbookDisplayService.convertShellsToDisplayShells(addressbooks, { includePriority: true }))
28+
.then(displayShells => {
29+
const uniqueAddressBookShells = contactAddressbookHelper.getUniqueAdressBookShells(displayShells);
30+
31+
$scope.availableAddressbooks = contactAddressbookDisplayService.sortAddressbookDisplayShells(uniqueAddressBookShells)
32+
.map(displayShell => ({
33+
path: displayShell.shell.href,
34+
displayName: displayShell.displayName
35+
}));
3636
});
3737
}
3838
};

src/linagora.esn.contact/app/sidebar/sidebar.controller.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ function ContactSidebarController(
1212
userUtils,
1313
contactAddressbookDisplayService,
1414
contactAddressbookService,
15+
contactAddressbookHelper,
1516
CONTACT_ADDRESSBOOK_EVENTS
1617
) {
1718
var self = this;
@@ -150,7 +151,7 @@ function ContactSidebarController(
150151
var categories = contactAddressbookDisplayService.categorizeDisplayShells(self.displayShells);
151152

152153
self.userAddressbooks = categories.userAddressbooks;
153-
self.sharedAddressbooks = categories.sharedAddressbooks;
154+
self.sharedAddressbooks = contactAddressbookHelper.getUniqueAdressBookShells(categories.sharedAddressbooks);
154155
self.virtualAddressbooks = categories.virtualAddressbooks;
155156
}
156157
}

src/linagora.esn.contact/app/sidebar/sidebar.controller.spec.js

+37-5
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,11 @@ describe('The ContactSidebarController controller', function() {
4646
userAPI = _userAPI_;
4747
userUtils = _userUtils_;
4848
CONTACT_ADDRESSBOOK_EVENTS = _CONTACT_ADDRESSBOOK_EVENTS_;
49-
50-
contactAddressbookDisplayService.categorizeDisplayShells = function() {
51-
return {
49+
contactAddressbookDisplayService.categorizeDisplayShells = sinon.stub()
50+
.returns({
5251
userAddressbooks: [],
5352
externalAddressbooks: []
54-
};
55-
};
53+
});
5654
});
5755
});
5856

@@ -260,6 +258,40 @@ describe('The ContactSidebarController controller', function() {
260258
]);
261259
});
262260

261+
it('should avoid listing duplicate entries when an adressbook is shared an delegated to the same user', () => {
262+
contactAddressbookService.listAddressbooks = sinon.stub().returns($q.when([]));
263+
contactAddressbookDisplayService.categorizeDisplayShells.returns({
264+
userAddressbooks: [
265+
{
266+
name: 'bookA',
267+
shell: {
268+
source: { bookId: 'user0', href: '0' }
269+
}
270+
}
271+
],
272+
sharedAddressbooks: [
273+
{
274+
name: 'bookB',
275+
shell: {
276+
source: { bookId: 'user1', href: '1' }
277+
}
278+
},
279+
{
280+
name: 'bookC',
281+
shell: {
282+
source: { bookId: 'user1', href: '1' }
283+
}
284+
}
285+
]
286+
});
287+
288+
const controller = initController();
289+
290+
$rootScope.$digest();
291+
292+
expect(controller.sharedAddressbooks.length).to.equal(1);
293+
});
294+
263295
describe('On updated address book event', function() {
264296
it('should update an address book when updated address book event is fired', function() {
265297
var addressbooks = [

0 commit comments

Comments
 (0)