Skip to content

Commit 97b0882

Browse files
committed
Show confirmation modal on contact unlink
1 parent 2a54ce0 commit 97b0882

4 files changed

Lines changed: 127 additions & 27 deletions

File tree

components/ILIAS/Contact/BuddySystem/classes/class.ilBuddySystemGUI.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818

1919
declare(strict_types=1);
2020

21+
use ILIAS\Filesystem\Stream\Streams;
22+
use ILIAS\HTTP\Response\ResponseHeader;
2123
use ILIAS\HTTP\Services;
24+
use ILIAS\UI\Factory as UIFactory;
25+
use ILIAS\UI\Renderer as UIRenderer;
2226

2327
/**
2428
* Class ilBuddySystemGUI
@@ -39,6 +43,8 @@ class ilBuddySystemGUI
3943
protected ilLanguage $lng;
4044
protected Services $http;
4145
private readonly ilGlobalTemplateInterface $main_tpl;
46+
private UIFactory $ui_factory;
47+
private UIRenderer $ui_renderer;
4248

4349
public function __construct()
4450
{
@@ -49,6 +55,8 @@ public function __construct()
4955
$this->ctrl = $DIC['ilCtrl'];
5056
$this->user = $DIC['ilUser'];
5157
$this->lng = $DIC['lng'];
58+
$this->ui_factory = $DIC->ui()->factory();
59+
$this->ui_renderer = $DIC->ui()->renderer();
5260

5361
$this->buddyList = ilBuddyList::getInstanceByGlobalUser();
5462
$this->stateFactory = ilBuddySystemRelationStateFactory::getInstance();
@@ -68,8 +76,14 @@ public static function initializeFrontend(ilGlobalTemplateInterface $page): void
6876
$DIC->language()->loadLanguageModule('buddysystem');
6977

7078
$page->addJavaScript('./assets/js/buddy_system.js');
79+
$page->addJavaScript('./assets/js/modal.min.js');
7180

7281
$config = new stdClass();
82+
$config->async_get_unlink_modal_confirmation_html = $DIC->ctrl()->getLinkTargetByClass([
83+
ilUIPluginRouterGUI::class,
84+
self::class
85+
], 'asyncGetUnlinkModalConfirmationHtml', '', true, false);
86+
7387
$config->http_post_url = $DIC->ctrl()->getFormActionByClass([
7488
ilUIPluginRouterGUI::class,
7589
self::class
@@ -87,6 +101,32 @@ public static function initializeFrontend(ilGlobalTemplateInterface $page): void
87101
}
88102
}
89103

104+
public function asyncGetUnlinkModalConfirmationHtmlCommand(): never
105+
{
106+
$confirmation_modal = $this->ui_factory->modal()->interruptive(
107+
$this->lng->txt('confirmation'),
108+
$this->lng->txt('buddy_confirm_unlink'),
109+
''
110+
)
111+
->withActionButtonLabel($this->lng->txt('confirm'));
112+
113+
$this->http->saveResponse(
114+
$this->http->response()->withBody(
115+
Streams::ofString(
116+
json_encode([
117+
"html" => $this->ui_renderer->renderAsync($confirmation_modal),
118+
"signals" => [
119+
"show" => $confirmation_modal->getShowSignal()->getId(),
120+
"close" => $confirmation_modal->getCloseSignal()->getId()
121+
]
122+
], JSON_THROW_ON_ERROR)
123+
)
124+
)->withHeader(ResponseHeader::CONTENT_TYPE, 'application/json')
125+
);
126+
$this->http->sendResponse();
127+
$this->http->close();
128+
}
129+
90130
/**
91131
* @throws RuntimeException
92132
*/

components/ILIAS/Contact/resources/buddy_system.js

Lines changed: 83 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@
2525

2626
const BuddySystemButton = {
2727
config: {},
28+
unlinkConfirmationModal: {
29+
signals: {
30+
show: '',
31+
close: '',
32+
}
33+
},
34+
modal: null,
35+
setupConfirmationModal: false,
2836

2937
setConfig(config) {
3038
this.config = config;
@@ -40,34 +48,84 @@
4048

4149
const triggerButton = e.target.closest(triggerSelector);
4250
const container = triggerButton.closest(`.${this.config.bnt_class}`);
43-
if (triggerButton.dataset.submitted === 'true') return Promise.resolve();
44-
45-
const values = new FormData();
46-
values.append('usr_id', container.dataset.buddyId);
47-
values.append('action', triggerButton.dataset.action);
48-
values.append(`cmd[${BuddySystem.config.transition_state_cmd}]`, 1);
49-
50-
return disableButtons(container)
51-
.then(() => fetch(BuddySystem.config.http_post_url, {
52-
method: 'POST',
53-
headers: { Accept: 'application/json' },
54-
body: values,
55-
}))
56-
.then((response) => {
57-
if (!response.ok) throw new Error('Request failed');
58-
return response.json();
59-
})
60-
.then((data) => processResponse(container, data))
61-
.then(() => {
62-
container.querySelector(toggleSelector)?.focus();
63-
})
64-
.catch((error) => {
65-
console.error(error);
66-
enableButtons(container);
67-
container.querySelector(toggleSelector)?.focus();
51+
52+
const widgetClickAction = () => {
53+
if (triggerButton.dataset.submitted === 'true') return Promise.resolve();
54+
55+
const values = new FormData();
56+
values.append('usr_id', container.dataset.buddyId);
57+
values.append('action', triggerButton.dataset.action);
58+
values.append(`cmd[${BuddySystem.config.transition_state_cmd}]`, 1);
59+
60+
return disableButtons(container)
61+
.then(() => fetch(BuddySystem.config.http_post_url, {
62+
method: 'POST',
63+
headers: { Accept: 'application/json' },
64+
body: values,
65+
}))
66+
.then((response) => {
67+
if (!response.ok) throw new Error('Request failed');
68+
return response.json();
69+
})
70+
.then((data) => processResponse(container, data))
71+
.then(() => {
72+
container.querySelector(toggleSelector)?.focus();
73+
})
74+
.catch((error) => {
75+
console.error(error);
76+
enableButtons(container);
77+
container.querySelector(toggleSelector)?.focus();
78+
});
79+
};
80+
81+
if (triggerButton.dataset.action === 'unlink') {
82+
return showUnlinkConfirmationModal().then(() => {
83+
return widgetClickAction();
6884
});
85+
}
86+
87+
return widgetClickAction();
6988
};
7089

90+
const showUnlinkConfirmationModal = () => new Promise((resolve) => {
91+
if (!this.setupConfirmationModal) {
92+
fetch(BuddySystem.config.async_get_unlink_modal_confirmation_html)
93+
.then((response) => {
94+
if (!response.ok) throw new Error('Request failed');
95+
return response.json();
96+
})
97+
.then((data) => {
98+
const wrapper = document.createElement('div');
99+
const modalFragment = document.createRange().createContextualFragment(data.html);
100+
101+
wrapper.appendChild(modalFragment);
102+
document.body.append(wrapper)
103+
this.modal = wrapper.querySelector("dialog");
104+
105+
this.unlinkConfirmationModal.signals.show = data.signals.show;
106+
this.unlinkConfirmationModal.signals.close = data.signals.close
107+
108+
this.modal.querySelector('input[type="submit"]').addEventListener('click', (event) => onModalSubmitClicked(event, resolve));
109+
}).then(() => {
110+
this.setupConfirmationModal = true;
111+
global.jQuery(document).trigger(this.unlinkConfirmationModal.signals.show, {});
112+
})
113+
return;
114+
}
115+
116+
const submitButton = this.modal.querySelector('input[type="submit"]');
117+
const submitButtonClone = submitButton.cloneNode(true);
118+
submitButton.replaceWith(submitButtonClone);
119+
submitButtonClone.addEventListener('click', (event) => onModalSubmitClicked(event, resolve));
120+
global.jQuery(document).trigger(this.unlinkConfirmationModal.signals.show, {});
121+
});
122+
123+
const onModalSubmitClicked = (event, resolve) => {
124+
event.preventDefault();
125+
global.jQuery(document).trigger(this.unlinkConfirmationModal.signals.close, {});
126+
resolve();
127+
}
128+
71129
const disableButtons = (container) => new Promise((resolve) => {
72130
document.querySelectorAll(`.${this.config.bnt_class}`).forEach((btnContainer) => {
73131
if (btnContainer.dataset.buddyId === container.dataset.buddyId) {

lang/ilias_de.lang

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2769,6 +2769,7 @@ buddysystem#:#buddy_bs_state_requested_p#:#Angefragt
27692769
buddysystem#:#buddy_bs_state_unlinked#:#Nicht vernetzt
27702770
buddysystem#:#buddy_bs_state_unlinked_a#:#Nicht vernetzt
27712771
buddysystem#:#buddy_bs_state_unlinked_p#:#Nicht vernetzt
2772+
buddysystem#:#buddy_confirm_unlink#:#Möchten Sie die Verbindung zu diesem Kontakt wirklich aufheben?
27722773
buddysystem#:#buddy_enable#:#Aktiviere „Benutzerkontakte“
27732774
buddysystem#:#buddy_enable_info#:#Falls aktiviert, können Benutzer im System über Kontaktanfragen miteinander in Verbindung treten. Eine zusätzliche persönliche Einstellung ermöglicht jedem Benutzer, Kontaktaufnahmen zuzulassen oder zu verhindern.
27742775
buddysystem#:#buddy_handle_contact_request#:#Kontaktanfrage
@@ -17896,4 +17897,4 @@ wsp#:#wsp_type_ltiv#:#Zertifikat: LTI-Konsument
1789617897
wsp#:#wsp_type_scov#:#Zertifikat: SCORM
1789717898
wsp#:#wsp_type_tstv#:#Zertifikat: Test
1789817899
wsp#:#wsp_type_webr#:#Weblink
17899-
wsp#:#wsp_type_wfld#:#Ordner
17900+
wsp#:#wsp_type_wfld#:#Ordner

lang/ilias_en.lang

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2770,6 +2770,7 @@ buddysystem#:#buddy_bs_state_requested_p#:#Requested
27702770
buddysystem#:#buddy_bs_state_unlinked#:#Unlinked
27712771
buddysystem#:#buddy_bs_state_unlinked_a#:#Unlinked
27722772
buddysystem#:#buddy_bs_state_unlinked_p#:#Unlinked
2773+
buddysystem#:#buddy_confirm_unlink#:#Do you really want to disconnect from this contact?
27732774
buddysystem#:#buddy_enable#:#Activate ‘Contacts’
27742775
buddysystem#:#buddy_enable_info#:#If enabled, users are allowed to contact each other by initiating contact requests. Additionally, there is a personal user setting to allow or prevent being contacted.
27752776
buddysystem#:#buddy_handle_contact_request#:#Contact Request
@@ -17897,4 +17898,4 @@ wsp#:#wsp_type_ltiv#:#Certificate: LTI Consumer
1789717898
wsp#:#wsp_type_scov#:#Certificate: SCORM
1789817899
wsp#:#wsp_type_tstv#:#Certificate: Test
1789917900
wsp#:#wsp_type_webr#:#Weblink
17900-
wsp#:#wsp_type_wfld#:#Folder
17901+
wsp#:#wsp_type_wfld#:#Folder

0 commit comments

Comments
 (0)