Merge pull request #55385 from nextcloud/chore/remove-jquery-contactsmenu

chore: remove legacy jQuery contacts menu
This commit is contained in:
Andy Scherzinger 2025-09-29 00:29:25 +02:00 committed by GitHub
commit 72cab544ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 3 additions and 358 deletions

View file

@ -1,235 +0,0 @@
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
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.off();
$selector1.remove();
$selector2.off();
$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().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left 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(done) {
$('#selector1, #selector2').contactsMenu('user', 0, $appendTo);
$selector1.click();
expect(fakeServer.requests[0].method).toEqual('POST');
expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/contactsmenu/findOne');
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": []
})
);
$selector1.on('load', function() {
// FIXME: don't compare HTML one to one but check specific text in the output
expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left 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>');
done();
});
});
it('load topaction and more actions', function(done) {
$('#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');
$selector1.on('load', function() {
// FIXME: don't compare HTML one to one but check specific text in the output
expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left 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>');
done();
});
});
it('load no actions', function(done) {
$('#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');
$selector1.on('load', function() {
// FIXME: don't compare HTML one to one but check specific text in the output
expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left 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>');
done();
});
});
it('should throw an error', function(done) {
$('#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');
$selector1.on('loaderror', function() {
// FIXME: don't compare HTML one to one but check specific text in the output
expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left 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>');
done();
});
});
it('should handle 404', function(done) {
$('#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');
$selector1.on('loaderror', function() {
// FIXME: don't compare HTML one to one but check specific text in the output
expect($appendTo.html().replace(/[\r\n\t]?(\ \ +)?/g, '')).toEqual('<div class="menu popovermenu menu-left 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>');
done();
});
});
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);
});
});
});

View file

@ -1,113 +0,0 @@
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { generateUrl } from '@nextcloud/router'
import { isA11yActivation } from '@nextcloud/vue/functions/a11y'
import $ from 'jquery'
const LIST = ''
+ '<div class="menu popovermenu menu-left hidden contactsmenu-popover">'
+ ' <ul>'
+ ' <li>'
+ ' <a>'
+ ' <span class="icon-loading-small"></span>'
+ ' </a>'
+ ' </li>'
+ ' </ul>'
+ '</div>'
const entryTemplate = require('./contactsmenu/jquery_entry.handlebars')
$.fn.contactsMenu = function(shareWith, shareType, appendTo) {
// 0 - user, 4 - email, 6 - remote
const allowedTypes = [0, 4, 6]
if (allowedTypes.indexOf(shareType) === -1) {
return
}
const $div = this
appendTo.append(LIST)
const $list = appendTo.find('div.contactsmenu-popover')
$div.on('click keydown', function(event) {
if (!isA11yActivation(event)) {
return
}
if (!$list.hasClass('hidden')) {
$list.addClass('hidden')
$list.hide()
return
}
$list.removeClass('hidden')
$list.show()
if ($list.hasClass('loaded')) {
return
}
$list.addClass('loaded')
$.ajax(generateUrl('/contactsmenu/findOne'), {
method: 'POST',
data: {
shareType,
shareWith,
},
}).then(function(data) {
$list.find('ul').find('li').addClass('hidden')
let actions
if (!data.topAction) {
actions = [{
hyperlink: '#',
title: t('core', 'No action available'),
}]
} else {
actions = [data.topAction].concat(data.actions)
}
actions.forEach(function(action) {
$list.find('ul').append(entryTemplate(action))
})
$div.trigger('load')
}, function(jqXHR) {
$list.find('ul').find('li').addClass('hidden')
let title
if (jqXHR.status === 404) {
title = t('core', 'No action available')
} else {
title = t('core', 'Error fetching contact actions')
}
$list.find('ul').append(entryTemplate({
hyperlink: '#',
title,
}))
$div.trigger('loaderror', jqXHR)
})
})
$(document).click(function(event) {
const clickedList = ($list.has(event.target).length > 0)
let 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()
})
}

View file

@ -1,6 +0,0 @@
<li>
<a href="{{hyperlink}}">
{{#if icon}}<img src="{{icon}}">{{/if}}
<span>{{title}}</span>
</a>
</li>

View file

@ -6,7 +6,6 @@
import $ from 'jquery'
import './avatar.js'
import './contactsmenu.js'
import './exists.js'
import './filterattr.js'
import './ocdialog.js'

4
dist/core-main.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long