# Diff to HTML by rtfpessoa

Files changed (2) hide show

1. assets/components/misSession.js +118 -0
2. assets/controllers/caseHistory_controller.js +36 -21

assets/components/misSession.js ADDED Viewed

| @@ -0,0 +1,118 @@

1 | + /**
2 | + * MIS (webSDK / widget.sovamed.ru) session helpers.
3 | + * Symfony login (ROLE_USER) and MIS session are independent.
4 | + */
5 | +
6 | + function MisSessionError() {
7 | + this.name = 'MisSessionError';
8 | + this.message = 'MIS session is not authenticated';
9 | + }
10 | +
11 | + function isAuthenticated(webSDK) {
12 | + return Boolean(webSDK?.data?.user?.authenticated);
13 | + }
14 | +
15 | + function ensureAuthenticated(webSDK) {
16 | + return new Promise(function(resolve, reject) {
17 | + if (isAuthenticated(webSDK)) {
18 | + resolve(webSDK);
19 | + return;
20 | + }
21 | +
22 | + if (typeof webSDK?.isLoggedIn === 'function') {
23 | + webSDK.isLoggedIn(webSDK.sdkOrigin).then(function(result) {
24 | + if (result?.authenticated) {
25 | + resolve(webSDK);
26 | + return;
27 | + }
28 | + reject(new MisSessionError());
29 | + }).catch(function() {
30 | + reject(new MisSessionError());
31 | + });
32 | + return;
33 | + }
34 | +
35 | + reject(new MisSessionError());
36 | + });
37 | + }
38 | +
39 | + function removeSdkOverlayModals() {
40 | + document.querySelectorAll('.wr-sdk-widget-modal').forEach(function(modal) {
41 | + modal.remove();
42 | + });
43 | + }
44 | +
45 | + /**
46 | + * Move #iframeProtocol from SDK overlay into cabinet bootstrap popup.
47 | + * openConference() must be called without container (SDK applies Guest URL fix).
48 | + */
49 | + function mountConferenceInPopup(popup) {
50 | + var iframe = document.getElementById('iframeProtocol');
51 | + var popupBody = popup?.querySelector('#popup-body');
52 | +
53 | + if (!iframe || !popupBody) {
54 | + return false;
55 | + }
56 | +
57 | + removeSdkOverlayModals();
58 | + popupBody.innerHTML = '';
59 | + popupBody.appendChild(iframe);
60 | + iframe.style.width = '100%';
61 | + iframe.style.border = 'none';
62 | + iframe.style.height = (window.innerHeight - 100) + 'px';
63 | +
64 | + var fullScreenBtn = popup.querySelector('.full-scren-modal');
65 | + if (fullScreenBtn) {
66 | + fullScreenBtn.classList.remove('d-none');
67 | + }
68 | +
69 | + popup.querySelector('.modal-dialog').classList = 'modal-dialog';
70 | + popup.querySelector('.modal-content').classList = 'modal-content';
71 | + popup.querySelector('.modal-title').innerHTML = 'Онлайн консультация';
72 | +
73 | + if (typeof $ !== 'undefined' && typeof $(popup).modal === 'function') {
74 | + $(popup).modal('show');
75 | + }
76 | +
77 | + return true;
78 | + }
79 | +
80 | + function showMisSessionExpired(popup) {
81 | + if (!popup) {
82 | + window.location.pathname = '/logout';
83 | + return;
84 | + }
85 | +
86 | + popup.querySelector('.modal-dialog').classList = 'modal-dialog';
87 | + popup.querySelector('.modal-title').innerHTML = 'Сессия виджета истекла';
88 | + popup.querySelector('#popup-body').innerHTML =
89 | + '<p class="mb-3">Личный кабинет открыт, но сессия виджета записи (MIS) истекла. ' +
90 | + 'Для оплаты и онлайн-приёма нужно войти снова — повторная авторизация в iframe не требуется.</p>' +
91 | + '<button type="button" class="btn btn-outline-secondary w-100" id="mis-session-relogin">Войти снова</button>';
92 | +
93 | + popup.querySelector('#mis-session-relogin').addEventListener('click', function() {
94 | + window.location.pathname = '/logout';
95 | + });
96 | +
97 | + if (typeof $ !== 'undefined' && typeof $(popup).modal === 'function') {
98 | + $(popup).modal('show');
99 | + }
100 | + }
101 | +
102 | + function handleMisSessionFailure(popup, error, logContext) {
103 | + if (error instanceof MisSessionError || error?.name === 'MisSessionError') {
104 | + showMisSessionExpired(popup);
105 | + return true;
106 | + }
107 | +
108 | + return false;
109 | + }
110 | +
111 | + module.exports = {
112 | + MisSessionError: MisSessionError,
113 | + isAuthenticated: isAuthenticated,
114 | + ensureAuthenticated: ensureAuthenticated,
115 | + mountConferenceInPopup: mountConferenceInPopup,
116 | + showMisSessionExpired: showMisSessionExpired,
117 | + handleMisSessionFailure: handleMisSessionFailure,
118 | + };

assets/controllers/caseHistory_controller.js CHANGED Viewed

| @@ -2,6 +2,7 @@ import { Controller } from 'stimulus';
2 | import Cookies from 'js-cookie';
3 | const loader = require("./../components/loader.js");
4 | const helper = require("./../components/helper.js");
5 |
6 | /*
7 | * This is an example Stimulus controller!
| @@ -248,20 +249,23 @@ export default class extends Controller {
248 | btnConfirence.setAttribute('data-filial' , data.filial)
249 | btnConfirence.addEventListener('click', function () {
250 | popup.querySelector('#popup-body').innerHTML = '';
251 | -
252 | - webSDK.openConference({
253 | - schedid: btnConfirence.dataset.id,
254 | - container: popup.querySelector('#popup-body')
255 | - }).then(function () {
256 | - popup.querySelector('.full-scren-modal').classList.remove('d-none');
257 | - document.getElementById('iframeProtocol').style.height = (window.innerHeight - 100) + 'px';
258 | - popup.querySelector('.modal-dialog').classList = 'modal-dialog';
259 | - popup.querySelector('.modal-content').classList = 'modal-content';
260 | - popup.querySelector('.modal-content').classList = 'modal-content';
261 | - popup.querySelector('.modal-title').innerHTML = 'Онлайн консультация';
262 |
263 | - $(popup).modal('show');
264 | }).catch(function (e) {
265 | if (typeof e.data?.message !== 'undefined') {
266 | var msg = e.data.message.replace('UTC+3', 'UTC+3 (московское время)');
267 | popup.querySelector('#popup-body').innerHTML = msg;
| @@ -272,9 +276,9 @@ export default class extends Controller {
272 | }
273 |
274 | helper.sendRequest({
275 | - data: {'error': e, method: 'openConference'}
276 | - }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
277 | - });
278 | });
279 |
280 | } else {
| @@ -376,7 +380,6 @@ export default class extends Controller {
376 | btnPayment.setAttribute('data-amt' , data.payment.amt);
377 | btnPayment.setAttribute('data-payprofileid' , data.payment.magazineId);
378 | btnPayment.addEventListener('click', function () {
379 | -
380 | var params = {
381 | 'orderid': Number(btnPayment.dataset.id) ,
382 | 'payprofileid': btnPayment.dataset.payprofileid,
| @@ -386,14 +389,26 @@ export default class extends Controller {
386 | 'pcode': webSDK.data.user.id,
387 | 'successurl': document.location.origin + '/case-history#pay-success',
388 | 'errorurl': document.location.origin + '/case-history#error',
389 | - 'containerId': 'popup-body',
390 | };
391 |
392 | - webSDK.loadPaymentView(params);
393 |
394 | - popup.querySelector('#popup-body').innerHTML = '';
395 | - popup.querySelector('.modal-title').innerHTML = 'Оплата';
396 | - $(popup).modal('show');
397 | });
398 | } else {
399 | btnPayment.classList.add('d-none');

2 | import Cookies from 'js-cookie';
3 | const loader = require("./../components/loader.js");
4 | const helper = require("./../components/helper.js");
5 | + const misSession = require("./../components/misSession.js");
6 |
7 | /*
8 | * This is an example Stimulus controller!
249 | btnConfirence.setAttribute('data-filial' , data.filial)
250 | btnConfirence.addEventListener('click', function () {
251 | popup.querySelector('#popup-body').innerHTML = '';
252 |
253 | + misSession.ensureAuthenticated(webSDK).then(function() {
254 | + return webSDK.openConference({
255 | + schedid: btnConfirence.dataset.id
256 | + });
257 | + }).then(function () {
258 | + if (!misSession.mountConferenceInPopup(popup)) {
259 | + throw { data: { message: 'Не удалось открыть окно онлайн-консультации.' } };
260 | + }
261 | }).catch(function (e) {
262 | + if (misSession.handleMisSessionFailure(popup, e)) {
263 | + helper.sendRequest({
264 | + data: {'error': e, method: 'openConference', reason: 'mis_session_expired'}
265 | + }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
266 | + return;
267 | + }
268 | +
269 | if (typeof e.data?.message !== 'undefined') {
270 | var msg = e.data.message.replace('UTC+3', 'UTC+3 (московское время)');
271 | popup.querySelector('#popup-body').innerHTML = msg;
276 | }
277 |
278 | helper.sendRequest({
279 | + data: {'error': e, method: 'openConference'}
280 | + }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
281 | + });
282 | });
283 |
284 | } else {
380 | btnPayment.setAttribute('data-amt' , data.payment.amt);
381 | btnPayment.setAttribute('data-payprofileid' , data.payment.magazineId);
382 | btnPayment.addEventListener('click', function () {
383 | var params = {
384 | 'orderid': Number(btnPayment.dataset.id) ,
385 | 'payprofileid': btnPayment.dataset.payprofileid,
389 | 'pcode': webSDK.data.user.id,
390 | 'successurl': document.location.origin + '/case-history#pay-success',
391 | 'errorurl': document.location.origin + '/case-history#error',
392 | + 'containerId': 'popup-body',
393 | };
394 |
395 | + misSession.ensureAuthenticated(webSDK).then(function() {
396 | + webSDK.loadPaymentView(params);
397 | + popup.querySelector('#popup-body').innerHTML = '';
398 | + popup.querySelector('.modal-title').innerHTML = 'Оплата';
399 | + $(popup).modal('show');
400 | + }).catch(function(e) {
401 | + if (misSession.handleMisSessionFailure(popup, e)) {
402 | + helper.sendRequest({
403 | + data: {'error': e, method: 'loadPaymentView', reason: 'mis_session_expired'}
404 | + }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
405 | + return;
406 | + }
407 |
408 | + helper.sendRequest({
409 | + data: {'error': e, method: 'loadPaymentView'}
410 | + }, helper.getHostname() + '/api/log', "POST", "json", true, "application/json");
411 | + });
412 | });
413 | } else {
414 | btnPayment.classList.add('d-none');