Merge pull request #4374 from nextcloud/contactsmenu_popover
add contacts popover
This commit is contained in:
commit
d89c76049f
|
@ -54,7 +54,6 @@
|
|||
|
||||
#commentsTabView .comment {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
|
@ -108,6 +107,11 @@
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#commentsTabView .authorRow>div.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#commentsTabView .comments li .message .avatar-name-wrapper,
|
||||
#commentsTabView .comment .authorRow {
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -232,6 +232,21 @@
|
|||
var $this = $(this);
|
||||
$this.avatar($this.attr('data-username'), 32);
|
||||
});
|
||||
|
||||
var username = $el.find('.avatar').data('username');
|
||||
if (username !== oc_current_user) {
|
||||
$el.find('.authorRow .avatar, .authorRow .author').contactsMenu(
|
||||
username, 0, $el.find('.authorRow'));
|
||||
}
|
||||
|
||||
var message = $el.find('.message');
|
||||
message.find('.avatar').each(function() {
|
||||
var avatar = $(this);
|
||||
var strong = $(this).next();
|
||||
var appendTo = $(this).parent();
|
||||
|
||||
$.merge(avatar, strong).contactsMenu(avatar.data('user'), 0, appendTo);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -251,7 +266,10 @@
|
|||
|
||||
// escape possible regex characters in the name
|
||||
mention = mention.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
var displayName = avatar + ' <strong>'+ _.escape(mentions[i].mentionDisplayName)+'</strong>';
|
||||
var displayName = ''
|
||||
+ '<span class="avatar-name-wrapper">'
|
||||
+ avatar + ' <strong>'+ _.escape(mentions[i].mentionDisplayName)+'</strong>'
|
||||
+ '</span>';
|
||||
|
||||
// replace every mention either at the start of the input or after a whitespace
|
||||
// followed by a non-word character.
|
||||
|
|
|
@ -153,7 +153,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
|
|||
expect($comment.find('strong:first').text()).toEqual('Thane of Cawdor');
|
||||
|
||||
expect($comment.find('.avatar[data-user=banquo]').length).toEqual(1);
|
||||
expect($comment.find('strong:last-child').text()).toEqual('Lord Banquo');
|
||||
expect($comment.find('.avatar-name-wrapper:last-child strong').text()).toEqual('Lord Banquo');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace OC\Core\Controller;
|
|||
|
||||
use OC\Contacts\ContactsMenu\Manager;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUserSession;
|
||||
|
@ -59,4 +60,20 @@ class ContactsMenuController extends Controller {
|
|||
return $this->manager->getEntries($this->userSession->getUser(), $filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
* @param integer $shareType
|
||||
* @param string $shareWith
|
||||
* @return JSONResponse
|
||||
*/
|
||||
public function findOne($shareType, $shareWith) {
|
||||
$contact = $this->manager->findOne($this->userSession->getUser(), $shareType, $shareWith);
|
||||
|
||||
if ($contact) {
|
||||
return $contact;
|
||||
} else {
|
||||
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
list-style-type: none;
|
||||
padding: 8px;
|
||||
> li {
|
||||
position: relative;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
font-weight: bold;
|
||||
|
@ -103,6 +104,7 @@
|
|||
padding: 3px 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.shareOption {
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
|
@ -159,6 +161,10 @@ a {
|
|||
padding: 6px 4px;
|
||||
}
|
||||
|
||||
.resharerInfoView.subView {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#defaultExpireMessage, .reshare {
|
||||
/* fix shared by text going out of box */
|
||||
white-space: normal;
|
||||
|
@ -185,6 +191,19 @@ a {
|
|||
color: rgba($color-main-text, .4);
|
||||
}
|
||||
|
||||
.contactsmenu-popover {
|
||||
left: -8px;
|
||||
right: auto;
|
||||
padding: 3px 6px;
|
||||
li.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
&:after {
|
||||
left: 8px;
|
||||
right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.popovermenu .datepicker {
|
||||
margin-left: 35px;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"libraries": [
|
||||
"jquery-showpassword.js",
|
||||
"jquery.avatar.js",
|
||||
"jquery.contactsmenu.js",
|
||||
"placeholder.js"
|
||||
],
|
||||
"modules": [
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/**
|
||||
* Copyright (c) 2017 Georg Ehrke <oc.list@georgehrke.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var ENTRY = ''
|
||||
+ '<li>'
|
||||
+ ' <a href="{{hyperlink}}">'
|
||||
+ ' {{#if icon}}<img src="{{icon}}">{{/if}}'
|
||||
+ ' <span>{{title}}</span>'
|
||||
+ ' </a>'
|
||||
+ '</li>';
|
||||
|
||||
var LIST = ''
|
||||
+ '<div class="menu popovermenu bubble hidden contactsmenu-popover">'
|
||||
+ ' <ul>'
|
||||
+ ' <li>'
|
||||
+ ' <a>'
|
||||
+ ' <span class="icon-loading-small"></span>'
|
||||
+ ' </a>'
|
||||
+ ' </li>'
|
||||
+ ' </ul>'
|
||||
+ '</div>';
|
||||
|
||||
$.fn.contactsMenu = function(shareWith, shareType, appendTo) {
|
||||
// 0 - user, 4 - email, 6 - remote
|
||||
var allowedTypes = [0, 4, 6];
|
||||
if (allowedTypes.indexOf(shareType) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $div = this;
|
||||
appendTo.append(LIST);
|
||||
var $list = appendTo.find('div.contactsmenu-popover');
|
||||
|
||||
$div.click(function() {
|
||||
if (!$list.hasClass('hidden')) {
|
||||
$list.addClass('hidden');
|
||||
$list.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
$list.removeClass('hidden');
|
||||
$list.show();
|
||||
|
||||
if ($list.hasClass('loaded')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$list.addClass('loaded');
|
||||
$.ajax(OC.generateUrl('/contactsmenu/findOne'), {
|
||||
method: 'POST',
|
||||
data: {
|
||||
shareType: shareType,
|
||||
shareWith: shareWith
|
||||
}
|
||||
}).then(function(data) {
|
||||
$list.find('ul').find('li').addClass('hidden');
|
||||
|
||||
var actions;
|
||||
if (!data.topAction) {
|
||||
actions = [{
|
||||
hyperlink: '#',
|
||||
title: t('core', 'No action available')
|
||||
}];
|
||||
} else {
|
||||
actions = [data.topAction].concat(data.actions);
|
||||
}
|
||||
|
||||
actions.forEach(function(action) {
|
||||
var template = Handlebars.compile(ENTRY);
|
||||
$list.find('ul').append(template(action));
|
||||
});
|
||||
|
||||
if (actions.length === 0) {
|
||||
|
||||
}
|
||||
}, function(jqXHR) {
|
||||
$list.find('ul').find('li').addClass('hidden');
|
||||
|
||||
var title;
|
||||
if (jqXHR.status === 404) {
|
||||
title = t('core', 'No action available');
|
||||
} else {
|
||||
title = t('core', 'Error fetching contact actions');
|
||||
}
|
||||
|
||||
var template = Handlebars.compile(ENTRY);
|
||||
$list.find('ul').append(template({
|
||||
hyperlink: '#',
|
||||
title: title
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
$(document).click(function(event) {
|
||||
var clickedList = ($list.has(event.target).length > 0);
|
||||
var clickedTarget = ($div.has(event.target).length > 0);
|
||||
|
||||
$div.each(function() {
|
||||
if ($(this).is(event.target)) {
|
||||
clickedTarget = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (clickedList || clickedTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
$list.addClass('hidden');
|
||||
$list.hide();
|
||||
});
|
||||
};
|
||||
}(jQuery));
|
|
@ -13,5 +13,6 @@
|
|||
"mimetypelist.js",
|
||||
"oc-backbone.js",
|
||||
"placeholder.js",
|
||||
"jquery.avatar.js"
|
||||
"jquery.avatar.js",
|
||||
"jquery.contactsmenu.js"
|
||||
]
|
||||
|
|
|
@ -100,6 +100,11 @@
|
|||
$this.avatar($this.data('username'), 32);
|
||||
});
|
||||
|
||||
this.$el.find('.reshare').contactsMenu(
|
||||
this.model.getReshareOwner(),
|
||||
OC.Share.SHARE_TYPE_USER,
|
||||
this.$el);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
'{{#each sharees}}' +
|
||||
'<li data-share-id="{{shareId}}" data-share-type="{{shareType}}" data-share-with="{{shareWith}}">' +
|
||||
'<div class="avatar {{#if modSeed}}imageplaceholderseed{{/if}}" data-username="{{shareWith}}" data-displayname="{{shareWithDisplayName}}" {{#if modSeed}}data-seed="{{shareWith}} {{shareType}}"{{/if}}></div>' +
|
||||
'<span class="has-tooltip username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' +
|
||||
'<span class="username" title="{{shareWithTitle}}">{{shareWithDisplayName}}</span>' +
|
||||
'<span class="sharingOptionsGroup">' +
|
||||
'{{#if editPermissionPossible}}' +
|
||||
'<span class="shareOption">' +
|
||||
|
@ -361,6 +361,15 @@
|
|||
this.$('.has-tooltip').tooltip({
|
||||
placement: 'bottom'
|
||||
});
|
||||
|
||||
this.$('ul.shareWithList > li').each(function() {
|
||||
var $this = $(this);
|
||||
|
||||
var shareWith = $this.data('share-with');
|
||||
var shareType = $this.data('share-type');
|
||||
|
||||
$this.find('div.avatar, span.username').contactsMenu(shareWith, shareType, $this);
|
||||
})
|
||||
} else {
|
||||
var permissionChangeShareId = parseInt(this._renderPermissionChange, 10);
|
||||
var shareWithIndex = this.model.findShareWithIndex(permissionChangeShareId);
|
||||
|
@ -399,7 +408,7 @@
|
|||
var shareId = parseInt(this._menuOpen, 10);
|
||||
if(!_.isNaN(shareId)) {
|
||||
var liSelector = 'li[data-share-id=' + shareId + ']';
|
||||
OC.showMenu(null, this.$(liSelector + ' .popovermenu'));
|
||||
OC.showMenu(null, this.$(liSelector + '.sharingOptionsGroup .popovermenu'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,7 +485,7 @@
|
|||
event.stopPropagation();
|
||||
var $element = $(event.target);
|
||||
var $li = $element.closest('li[data-share-id]');
|
||||
var $menu = $li.find('.popovermenu');
|
||||
var $menu = $li.find('.sharingOptionsGroup .popovermenu');
|
||||
|
||||
OC.showMenu(null, $menu);
|
||||
this._menuOpen = $li.data('share-id');
|
||||
|
|
|
@ -0,0 +1,213 @@
|
|||
/**
|
||||
* Copyright (c) 2017 Georg Ehrke <oc.list@georgehrke.com>
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3
|
||||
* or later.
|
||||
*
|
||||
* See the COPYING-README file.
|
||||
*
|
||||
*/
|
||||
|
||||
describe('jquery.contactsMenu tests', function() {
|
||||
|
||||
var $selector1, $selector2, $appendTo;
|
||||
|
||||
beforeEach(function() {
|
||||
$('#testArea').append($('<div id="selector1">'));
|
||||
$('#testArea').append($('<div id="selector2">'));
|
||||
$('#testArea').append($('<div id="appendTo">'));
|
||||
$selector1 = $('#selector1');
|
||||
$selector2 = $('#selector2');
|
||||
$appendTo = $('#appendTo');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
$selector1.remove();
|
||||
$selector2.remove();
|
||||
$appendTo.remove();
|
||||
});
|
||||
|
||||
describe('shareType', function() {
|
||||
it('stops if type not supported', function() {
|
||||
$selector1.contactsMenu('user', 1, $appendTo);
|
||||
expect($appendTo.children().length).toEqual(0);
|
||||
|
||||
$selector1.contactsMenu('user', 2, $appendTo);
|
||||
expect($appendTo.children().length).toEqual(0);
|
||||
|
||||
$selector1.contactsMenu('user', 3, $appendTo);
|
||||
expect($appendTo.children().length).toEqual(0);
|
||||
|
||||
$selector1.contactsMenu('user', 5, $appendTo);
|
||||
expect($appendTo.children().length).toEqual(0);
|
||||
});
|
||||
|
||||
it('append list if shareType supported', function() {
|
||||
$selector1.contactsMenu('user', 0, $appendTo);
|
||||
expect($appendTo.children().length).toEqual(1);
|
||||
expect($appendTo.html()).toEqual('<div class="menu popovermenu bubble hidden contactsmenu-popover"> <ul> <li> <a> <span class="icon-loading-small"></span> </a> </li> </ul></div>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('open on click', function() {
|
||||
it('with one selector', function() {
|
||||
$selector1.contactsMenu('user', 0, $appendTo);
|
||||
expect($appendTo.children().length).toEqual(1);
|
||||
expect($appendTo.find('div.contactsmenu-popover').hasClass('hidden')).toEqual(true);
|
||||
$selector1.click();
|
||||
expect($appendTo.find('div.contactsmenu-popover').hasClass('hidden')).toEqual(false);
|
||||
});
|
||||
|
||||
it('with multiple selectors - 1', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
|
||||
expect($appendTo.children().length).toEqual(1);
|
||||
expect($appendTo.find('div.contactsmenu-popover').hasClass('hidden')).toEqual(true);
|
||||
$selector1.click();
|
||||
expect($appendTo.find('div.contactsmenu-popover').hasClass('hidden')).toEqual(false);
|
||||
});
|
||||
|
||||
it('with multiple selectors - 2', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
|
||||
expect($appendTo.children().length).toEqual(1);
|
||||
expect($appendTo.find('div.contactsmenu-popover').hasClass('hidden')).toEqual(true);
|
||||
$selector2.click();
|
||||
expect($appendTo.find('div.contactsmenu-popover').hasClass('hidden')).toEqual(false);
|
||||
});
|
||||
|
||||
it ('should close when clicking the selector again - 1', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
|
||||
expect($appendTo.children().length).toEqual(1);
|
||||
expect($appendTo.find('div').hasClass('hidden')).toEqual(true);
|
||||
$selector1.click();
|
||||
expect($appendTo.find('div').hasClass('hidden')).toEqual(false);
|
||||
$selector1.click();
|
||||
expect($appendTo.find('div').hasClass('hidden')).toEqual(true);
|
||||
});
|
||||
|
||||
it ('should close when clicking the selector again - 1', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
|
||||
expect($appendTo.children().length).toEqual(1);
|
||||
expect($appendTo.find('div').hasClass('hidden')).toEqual(true);
|
||||
$selector1.click();
|
||||
expect($appendTo.find('div').hasClass('hidden')).toEqual(false);
|
||||
$selector2.click();
|
||||
expect($appendTo.find('div').hasClass('hidden')).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('send requests to the server and render', function() {
|
||||
it('load a topaction only', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
$selector1.click();
|
||||
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{ 'Content-Type': 'application/json; charset=utf-8' },
|
||||
JSON.stringify({
|
||||
"id": null,
|
||||
"fullName": "Name 123",
|
||||
"topAction": {
|
||||
"title": "bar@baz.wtf",
|
||||
"icon": "foo.svg",
|
||||
"hyperlink": "mailto:bar%40baz.wtf"},
|
||||
"actions": []
|
||||
})
|
||||
);
|
||||
expect(fakeServer.requests[0].method).toEqual('POST');
|
||||
expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne');
|
||||
|
||||
expect($appendTo.html()).toEqual('<div class="menu popovermenu bubble contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="mailto:bar%40baz.wtf"> <img src="foo.svg"> <span>bar@baz.wtf</span> </a></li></ul></div>');
|
||||
});
|
||||
|
||||
it('load topaction and more actions', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
$selector1.click();
|
||||
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{ 'Content-Type': 'application/json; charset=utf-8' },
|
||||
JSON.stringify({
|
||||
"id": null,
|
||||
"fullName": "Name 123",
|
||||
"topAction": {
|
||||
"title": "bar@baz.wtf",
|
||||
"icon": "foo.svg",
|
||||
"hyperlink": "mailto:bar%40baz.wtf"},
|
||||
"actions": [{
|
||||
"title": "Details",
|
||||
"icon": "details.svg",
|
||||
"hyperlink": "http:\/\/localhost\/index.php\/apps\/contacts"
|
||||
}]
|
||||
})
|
||||
);
|
||||
expect(fakeServer.requests[0].method).toEqual('POST');
|
||||
expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne');
|
||||
|
||||
expect($appendTo.html()).toEqual('<div class="menu popovermenu bubble contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="mailto:bar%40baz.wtf"> <img src="foo.svg"> <span>bar@baz.wtf</span> </a></li><li> <a href="http://localhost/index.php/apps/contacts"> <img src="details.svg"> <span>Details</span> </a></li></ul></div>');
|
||||
});
|
||||
|
||||
it('load no actions', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
$selector1.click();
|
||||
|
||||
fakeServer.requests[0].respond(
|
||||
200,
|
||||
{ 'Content-Type': 'application/json; charset=utf-8' },
|
||||
JSON.stringify({
|
||||
"id": null,
|
||||
"fullName": "Name 123",
|
||||
"topAction": null,
|
||||
"actions": []
|
||||
})
|
||||
);
|
||||
expect(fakeServer.requests[0].method).toEqual('POST');
|
||||
expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne');
|
||||
|
||||
expect($appendTo.html()).toEqual('<div class="menu popovermenu bubble contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="#"> <span>No action available</span> </a></li></ul></div>');
|
||||
});
|
||||
|
||||
it('should throw an error', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
$selector1.click();
|
||||
|
||||
fakeServer.requests[0].respond(
|
||||
400,
|
||||
{ 'Content-Type': 'application/json; charset=utf-8' },
|
||||
JSON.stringify([])
|
||||
);
|
||||
expect(fakeServer.requests[0].method).toEqual('POST');
|
||||
expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne');
|
||||
|
||||
expect($appendTo.html()).toEqual('<div class="menu popovermenu bubble contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="#"> <span>Error fetching contact actions</span> </a></li></ul></div>');
|
||||
});
|
||||
|
||||
it('should handle 404', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
$selector1.click();
|
||||
|
||||
fakeServer.requests[0].respond(
|
||||
404,
|
||||
{ 'Content-Type': 'application/json; charset=utf-8' },
|
||||
JSON.stringify([])
|
||||
);
|
||||
expect(fakeServer.requests[0].method).toEqual('POST');
|
||||
expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne');
|
||||
|
||||
expect($appendTo.html()).toEqual('<div class="menu popovermenu bubble contactsmenu-popover loaded" style="display: block;"> <ul> <li class="hidden"> <a> <span class="icon-loading-small"></span> </a> </li> <li> <a href="#"> <span>No action available</span> </a></li></ul></div>');
|
||||
});
|
||||
});
|
||||
|
||||
it('click anywhere else to close the menu', function() {
|
||||
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
|
||||
|
||||
expect($appendTo.find('div').hasClass('hidden')).toEqual(true);
|
||||
$selector1.click();
|
||||
expect($appendTo.find('div').hasClass('hidden')).toEqual(false);
|
||||
$(document).click();
|
||||
expect($appendTo.find('div').hasClass('hidden')).toEqual(true);
|
||||
});
|
||||
});
|
|
@ -61,6 +61,7 @@ $application->registerRoutes($this, [
|
|||
['name' => 'Css#getCss', 'url' => '/css/{appName}/{fileName}', 'verb' => 'GET'],
|
||||
['name' => 'Js#getJs', 'url' => '/js/{appName}/{fileName}', 'verb' => 'GET'],
|
||||
['name' => 'contactsMenu#index', 'url' => '/contactsmenu/contacts', 'verb' => 'POST'],
|
||||
['name' => 'contactsMenu#findOne', 'url' => '/contactsmenu/findOne', 'verb' => 'POST'],
|
||||
],
|
||||
'ocs' => [
|
||||
['root' => '/cloud', 'name' => 'OCS#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
|
||||
|
|
|
@ -59,6 +59,50 @@ class ContactsStore {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
* @param integer $shareType
|
||||
* @param string $shareWith
|
||||
* @return IEntry|null
|
||||
*/
|
||||
public function findOne(IUser $user, $shareType, $shareWith) {
|
||||
switch($shareType) {
|
||||
case 0:
|
||||
case 6:
|
||||
$filter = ['UID'];
|
||||
break;
|
||||
case 4:
|
||||
$filter = ['EMAIL'];
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
$userId = $user->getUID();
|
||||
$allContacts = $this->contactsManager->search($shareWith, $filter);
|
||||
$contacts = array_filter($allContacts, function($contact) use ($userId) {
|
||||
return $contact['UID'] !== $userId;
|
||||
});
|
||||
$match = null;
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
if ($shareType === 4 && isset($contact['EMAIL'])) {
|
||||
if (in_array($shareWith, $contact['EMAIL'])) {
|
||||
$match = $contact;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($shareType === 0 || $shareType === 6) {
|
||||
if ($contact['UID'] === $shareWith && $contact['isLocalSystemBook'] === true) {
|
||||
$match = $contact;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $match ? $this->contactArrayToEntry($match) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $contact
|
||||
* @return Entry
|
||||
|
|
|
@ -51,7 +51,7 @@ class Manager {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $user
|
||||
* @param IUser $user
|
||||
* @param string $filter
|
||||
* @return array
|
||||
*/
|
||||
|
@ -69,6 +69,21 @@ class Manager {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
* @param integer $shareType
|
||||
* @param string $shareWith
|
||||
* @return IEntry
|
||||
*/
|
||||
public function findOne(IUser $user, $shareType, $shareWith) {
|
||||
$entry = $this->store->findOne($user, $shareType, $shareWith);
|
||||
if ($entry) {
|
||||
$this->processEntries([$entry], $user);
|
||||
}
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IEntry[] $entries
|
||||
* @return IEntry[]
|
||||
|
|
|
@ -76,4 +76,35 @@ class ContactsMenuControllerTest extends TestCase {
|
|||
$this->assertEquals($entries, $response);
|
||||
}
|
||||
|
||||
public function testFindOne() {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$entry = $this->createMock(IEntry::class);
|
||||
$this->userSession->expects($this->once())
|
||||
->method('getUser')
|
||||
->willReturn($user);
|
||||
$this->contactsManager->expects($this->once())
|
||||
->method('findOne')
|
||||
->with($this->equalTo($user), $this->equalTo(42), $this->equalTo('test-search-phrase'))
|
||||
->willReturn($entry);
|
||||
|
||||
$response = $this->controller->findOne(42, 'test-search-phrase');
|
||||
|
||||
$this->assertEquals($entry, $response);
|
||||
}
|
||||
|
||||
public function testFindOne404() {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$this->userSession->expects($this->once())
|
||||
->method('getUser')
|
||||
->willReturn($user);
|
||||
$this->contactsManager->expects($this->once())
|
||||
->method('findOne')
|
||||
->with($this->equalTo($user), $this->equalTo(42), $this->equalTo('test-search-phrase'))
|
||||
->willReturn(null);
|
||||
|
||||
$response = $this->controller->findOne(42, 'test-search-phrase');
|
||||
|
||||
$this->assertEquals([], $response->getData());
|
||||
$this->assertEquals(404, $response->getStatus());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,4 +157,99 @@ class ContactsStoreTest extends TestCase {
|
|||
$this->assertEquals('https://photo', $entries[1]->getAvatar());
|
||||
}
|
||||
|
||||
public function testFindOneUser() {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$this->contactsManager->expects($this->once())
|
||||
->method('search')
|
||||
->with($this->equalTo('a567'), $this->equalTo(['UID']))
|
||||
->willReturn([
|
||||
[
|
||||
'UID' => 123,
|
||||
'isLocalSystemBook' => false
|
||||
],
|
||||
[
|
||||
'UID' => 'a567',
|
||||
'FN' => 'Darren Roner',
|
||||
'EMAIL' => [
|
||||
'darren@roner.au'
|
||||
],
|
||||
'isLocalSystemBook' => true
|
||||
],
|
||||
]);
|
||||
$user->expects($this->once())
|
||||
->method('getUID')
|
||||
->willReturn('user123');
|
||||
|
||||
$entry = $this->contactsStore->findOne($user, 0, 'a567');
|
||||
|
||||
$this->assertEquals([
|
||||
'darren@roner.au'
|
||||
], $entry->getEMailAddresses());
|
||||
}
|
||||
|
||||
public function testFindOneEMail() {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$this->contactsManager->expects($this->once())
|
||||
->method('search')
|
||||
->with($this->equalTo('darren@roner.au'), $this->equalTo(['EMAIL']))
|
||||
->willReturn([
|
||||
[
|
||||
'UID' => 123,
|
||||
'isLocalSystemBook' => false
|
||||
],
|
||||
[
|
||||
'UID' => 'a567',
|
||||
'FN' => 'Darren Roner',
|
||||
'EMAIL' => [
|
||||
'darren@roner.au'
|
||||
],
|
||||
'isLocalSystemBook' => false
|
||||
],
|
||||
]);
|
||||
$user->expects($this->once())
|
||||
->method('getUID')
|
||||
->willReturn('user123');
|
||||
|
||||
$entry = $this->contactsStore->findOne($user, 4, 'darren@roner.au');
|
||||
|
||||
$this->assertEquals([
|
||||
'darren@roner.au'
|
||||
], $entry->getEMailAddresses());
|
||||
}
|
||||
|
||||
public function testFindOneNotSupportedType() {
|
||||
$user = $this->createMock(IUser::class);
|
||||
|
||||
$entry = $this->contactsStore->findOne($user, 42, 'darren@roner.au');
|
||||
|
||||
$this->assertEquals(null, $entry);
|
||||
}
|
||||
|
||||
public function testFindOneNoMatches() {
|
||||
$user = $this->createMock(IUser::class);
|
||||
$this->contactsManager->expects($this->once())
|
||||
->method('search')
|
||||
->with($this->equalTo('a567'), $this->equalTo(['UID']))
|
||||
->willReturn([
|
||||
[
|
||||
'UID' => 123,
|
||||
'isLocalSystemBook' => false
|
||||
],
|
||||
[
|
||||
'UID' => 'a567',
|
||||
'FN' => 'Darren Roner',
|
||||
'EMAIL' => [
|
||||
'darren@roner.au123'
|
||||
],
|
||||
'isLocalSystemBook' => false
|
||||
],
|
||||
]);
|
||||
$user->expects($this->once())
|
||||
->method('getUID')
|
||||
->willReturn('user123');
|
||||
|
||||
$entry = $this->contactsStore->findOne($user, 0, 'a567');
|
||||
|
||||
$this->assertEquals(null, $entry);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,4 +99,49 @@ class ManagerTest extends TestCase {
|
|||
$this->assertEquals($expected, $data);
|
||||
}
|
||||
|
||||
public function testFindOne() {
|
||||
$shareTypeFilter = 42;
|
||||
$shareWithFilter = 'foobar';
|
||||
|
||||
$user = $this->createMock(IUser::class);
|
||||
$entry = current($this->generateTestEntries());
|
||||
$provider = $this->createMock(IProvider::class);
|
||||
$this->contactsStore->expects($this->once())
|
||||
->method('findOne')
|
||||
->with($user, $shareTypeFilter, $shareWithFilter)
|
||||
->willReturn($entry);
|
||||
$this->actionProviderStore->expects($this->once())
|
||||
->method('getProviders')
|
||||
->with($user)
|
||||
->willReturn([$provider]);
|
||||
$provider->expects($this->once())
|
||||
->method('process');
|
||||
|
||||
$data = $this->manager->findOne($user, $shareTypeFilter, $shareWithFilter);
|
||||
|
||||
$this->assertEquals($entry, $data);
|
||||
}
|
||||
|
||||
public function testFindOne404() {
|
||||
$shareTypeFilter = 42;
|
||||
$shareWithFilter = 'foobar';
|
||||
|
||||
$user = $this->createMock(IUser::class);
|
||||
$provider = $this->createMock(IProvider::class);
|
||||
$this->contactsStore->expects($this->once())
|
||||
->method('findOne')
|
||||
->with($user, $shareTypeFilter, $shareWithFilter)
|
||||
->willReturn(null);
|
||||
$this->actionProviderStore->expects($this->never())
|
||||
->method('getProviders')
|
||||
->with($user)
|
||||
->willReturn([$provider]);
|
||||
$provider->expects($this->never())
|
||||
->method('process');
|
||||
|
||||
$data = $this->manager->findOne($user, $shareTypeFilter, $shareWithFilter);
|
||||
|
||||
$this->assertEquals(null, $data);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue