From 10734622f6f50c86a320f324491c29bbde2129ff Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Mon, 3 Mar 2025 08:11:37 +0100 Subject: [PATCH 01/25] * add lookylooky --- .env | 11 +++++++-- assets/js/createConference.js | 6 ++--- assets/js/multiframe.js | 23 +++++++++++++++---- assets/js/startWhiteboard.js | 20 +++++++++------- config/services.yaml | 2 ++ nodejs/websocket.js | 1 + .../conferenceSidebar.html.twig | 19 +++++++++++++++ .../optionsWidget/optionsExtraApps.html.twig | 12 ++++++++++ 8 files changed, 76 insertions(+), 18 deletions(-) diff --git a/.env b/.env index d3da82215..63aaf1262 100644 --- a/.env +++ b/.env @@ -116,8 +116,7 @@ LAF_SHOW_PARTICIPANTS_ON_PARTICIPANTS=0 ###> {"ldap1":"Nutzerkreis1"} ### LAF_ADDRESSBOOK_CHECKBOX_LABEL_2_VALUE={} VICH_BASE=http://dummy -LAF_WHITEBOARD_FUNCTION=0 -LAF_ETHERPAD_FUNCTION=0 + LAF_ALLOW_SET_DEPUTY=1 LAF_TERMS_AND_CONDITIONS="" LAF_USE_MULTIFRAME=1 @@ -293,16 +292,24 @@ JITSI_MEET_DEFAULT_PARTICIPANTS_PANE=0 ### { removeMultiframe(newInstance); }); @@ -85,7 +85,7 @@ function createIframe(url, title, startMaximized = true, borderColor = '') { zIndex++; }); newInstance.addEventListener('createNewMultiframe', (data) => { - createIframe(data.url,data.title,data.maximize) + createIframe(data.url,data.title,data.maximize,'',data.roomUid) }); multiframes.push(newInstance); diff --git a/assets/js/multiframe.js b/assets/js/multiframe.js index 14b0be153..a288bf92c 100644 --- a/assets/js/multiframe.js +++ b/assets/js/multiframe.js @@ -4,6 +4,7 @@ import {tooltip} from 'mdb-ui-kit'; import {setCookie} from "./cookie"; import {checkIfIsMutable, zIndex} from "./createConference"; import { Tooltip, initMDB } from "mdb-ui-kit"; +import {sendViaWebsocket} from "./websocket"; export class multiframe { @@ -15,7 +16,7 @@ export class multiframe { isPaused = false; random = null; eventListeners = {}; - + roomUid = null; constructor( url, title, @@ -26,6 +27,7 @@ export class multiframe { height, width, zIndex, + roomUid = null, ) { this.url = url; this.title = title; @@ -35,6 +37,7 @@ export class multiframe { this.height = height; this.width = width; this.zIndex = zIndex; + this.roomUid = roomUid; this.createIframe(); if (startMaximized) { this.prepareMaximize(); @@ -63,7 +66,7 @@ export class multiframe {
- +
@@ -167,7 +170,17 @@ export class multiframe { } else if (type === 'openNewIframe') { //todo in controllerklasse this.triggerCreateNewMultiframe(decoded.url, decoded.title, false); - } else if (type === 'showPlayPause') { + } + else if (type === 'openNewIframeOnOthers') { + //todo in controllerklasse + var message = { + room: decoded.room, + url: decoded.url, + title: decoded.title + } + sendViaWebsocket('openNewIframe', JSON.stringify(message)); + + }else if (type === 'showPlayPause') { this.frame.classList.add('isMutable'); this.frame.dataset.muted = "0"; this.frame.querySelector('.pauseConference').classList.remove('d-none'); @@ -416,8 +429,8 @@ export class multiframe { } - triggerCreateNewMultiframe(url, title, maximize) { - this.triggerEvent('createNewMultiframe', {url: url, title: title, maximize: maximize}) + triggerCreateNewMultiframe(url, title, maximize,roomUid=null) { + this.triggerEvent('createNewMultiframe', {url: url, title: title, maximize: maximize,roomUid:roomUid}) } } \ No newline at end of file diff --git a/assets/js/startWhiteboard.js b/assets/js/startWhiteboard.js index d3f072d93..c8e04b89e 100644 --- a/assets/js/startWhiteboard.js +++ b/assets/js/startWhiteboard.js @@ -14,7 +14,8 @@ export function initStartWhiteboard() { ele.addEventListener('click', function (ev) { var selfurl = this.dataset.selfurl; var url = this.dataset.url; - if (this.dataset.room) { + const roomUid = this.dataset.roomUid; + if (this.dataset.room && url) { var message = { room: this.dataset.room, url: url, @@ -24,14 +25,17 @@ export function initStartWhiteboard() { } if (inIframe()) { - const parentMessage = JSON.stringify({ - type: 'openNewIframe', - url: selfurl, - 'title': document.title - }); - window.parent.postMessage(parentMessage, '*'); + if (selfurl){ + const parentMessage = JSON.stringify({ + type: 'openNewIframe', + url: selfurl, + 'title': document.title, + roomUid: roomUid, + }); + window.parent.postMessage(parentMessage, '*'); + } } else { - createIframe(selfurl, document.title, false); + createIframe(selfurl, document.title, false,'',); } }) } diff --git a/config/services.yaml b/config/services.yaml index ba18e4a68..c86c417e3 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -122,6 +122,8 @@ parameters: WHITEBOARD_SECRET: '%env(WHITEBOARD_SECRET)%' WHITEBOARD_URL: '%env(WHITEBOARD_URL)%' LAF_WHITEBOARD_FUNCTION: '%env(LAF_WHITEBOARD_FUNCTION)%' + LAF_LOOKYLOOKY_FUNCTION: '%env(LAF_LOOKYLOOKY_FUNCTION)%' + LOOKYLOOKY_URL: '%env(LOOKYLOOKY_URL)%' PUBLIC_SERVER: '%env(PUBLIC_SERVER)%' PUBLIC_TEXT_HEADER: '%env(PUBLIC_TEXT_HEADER)%' PUBLIC_TEXT_SUBTITLE: '%env(PUBLIC_TEXT_SUBTITLE)%' diff --git a/nodejs/websocket.js b/nodejs/websocket.js index b98727c0c..3715de2f8 100644 --- a/nodejs/websocket.js +++ b/nodejs/websocket.js @@ -67,6 +67,7 @@ io.on("connection", async (socket) => { var jwtObj = jwt.decode(socket.handshake.query.token); for (var i = 0; i < jwtObj.rooms.length; i++) { socket.join(jwtObj.rooms[i]); + console.log(`JOin room ${jwtObj.rooms[i]}`); } var user = loginUser(socket); diff --git a/templates/conference_modules/conferenceSidebar.html.twig b/templates/conference_modules/conferenceSidebar.html.twig index f74addd86..cad7993d7 100644 --- a/templates/conference_modules/conferenceSidebar.html.twig +++ b/templates/conference_modules/conferenceSidebar.html.twig @@ -54,10 +54,12 @@ or roomPermissions(app.user,room).lobbyModerator == true) %} data-selfurl="{{ createWhitebophirLink(room,true) }}" data-room="whiteboard/{{ room.uidReal }}" + data-url="{{ createWhitebophirLink(room,false) }}" {% else %} data-selfurl="{{ createWhitebophirLink(room,false) }}" {% endif %} + data-roomUid="{{ room.uid }}" > @@ -70,6 +72,22 @@ {% endif %} {% endif %} + {% if getApplicationProperties('LAF_LOOKYLOOKY_FUNCTION') == 1 %} + +
+
+ + +
+
+ {{ 'options.whiteboard'|trans }} +
+
+ + {% endif %} {% if getApplicationProperties('LAF_ETHERPAD_FUNCTION') == 1 %} {% if name is not defined or name is null %} {% set name = 'Meetling' %} @@ -90,6 +108,7 @@ {% else %} data-selfurl="{{ createEtherpadLink(room,user) }}" {% endif %} + data-roomUid="{{ room.uid }}" > diff --git a/templates/optionsWidget/optionsExtraApps.html.twig b/templates/optionsWidget/optionsExtraApps.html.twig index f070f3bc9..578dab383 100644 --- a/templates/optionsWidget/optionsExtraApps.html.twig +++ b/templates/optionsWidget/optionsExtraApps.html.twig @@ -21,4 +21,16 @@ {{ 'options.meetingNotes'|trans }} {% endif %} +{% endif %} +{% if getApplicationProperties('LAF_LOOKYLOOKY_FUNCTION') == 1 %} + {% if room.server.disableEtherpad != true %} +
  • + + {{ 'options.lookylooky'|trans }}
  • + {% endif %} {% endif %} \ No newline at end of file From 169d37b6141583bfa82f715c27ac9157191d24d7 Mon Sep 17 00:00:00 2001 From: holema Date: Wed, 5 Mar 2025 15:03:41 +0100 Subject: [PATCH 02/25] Update Crowdin configuration file --- crowdin.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crowdin.yml b/crowdin.yml index 0f0b3a64d..1dec2b8d6 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -3,3 +3,5 @@ files: translation: /translations/messages+intl-icu.%two_letters_code%.xlf - source: /translations/form.de.yml translation: /translations/form.%two_letters_code%.yml + - source: translations/ux_message+intl-icu.de.yaml + translation: translations/ux_message+intl-icu.%two_letters_code%.yaml From 10f4abb6cd9037ab89002fdab0703ce49e30aa65 Mon Sep 17 00:00:00 2001 From: holema Date: Fri, 7 Mar 2025 08:52:02 +0100 Subject: [PATCH 03/25] Update Crowdin configuration file --- crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crowdin.yml b/crowdin.yml index 1dec2b8d6..1f5e62931 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -4,4 +4,4 @@ files: - source: /translations/form.de.yml translation: /translations/form.%two_letters_code%.yml - source: translations/ux_message+intl-icu.de.yaml - translation: translations/ux_message+intl-icu.%two_letters_code%.yaml + translation: /translations/ux_message+intl-icu.%two_letters_code%.yaml From 0d440543e39b5edd5e3b9a9fbb16ecd5df79f9a2 Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Mon, 17 Mar 2025 08:12:11 +0100 Subject: [PATCH 04/25] add looky looky --- assets/js/createConference.js | 2 +- assets/js/multiframe.js | 8 ++++---- assets/js/startWhiteboard.js | 6 +++--- en-GB/translations/ux_message+intl-icu.en.yaml | 1 - es-ES/translations/ux_message+intl-icu.es.yaml | 1 - fr/translations/ux_message+intl-icu.fr.yaml | 1 - ja/translations/ux_message+intl-icu.ja.yaml | 1 - ko/translations/ux_message+intl-icu.ko.yaml | 1 - pa-IN/translations/ux_message+intl-icu.pa.yaml | 1 - package-lock.json | 9 +++++---- package.json | 2 +- pl/translations/ux_message+intl-icu.pl.yaml | 1 - pt-BR/translations/ux_message+intl-icu.pt.yaml | 1 - public/notification.json | 3 ++- ro/translations/ux_message+intl-icu.ro.yaml | 1 - ru/translations/ux_message+intl-icu.ru.yaml | 1 - src/Service/RoomService.php | 14 ++++++++++++++ .../conference_modules/conferenceSidebar.html.twig | 7 ++++--- vi/translations/ux_message+intl-icu.vi.yaml | 1 - zh-CN/translations/ux_message+intl-icu.zh.yaml | 1 - 20 files changed, 34 insertions(+), 29 deletions(-) delete mode 100644 en-GB/translations/ux_message+intl-icu.en.yaml delete mode 100644 es-ES/translations/ux_message+intl-icu.es.yaml delete mode 100644 fr/translations/ux_message+intl-icu.fr.yaml delete mode 100644 ja/translations/ux_message+intl-icu.ja.yaml delete mode 100644 ko/translations/ux_message+intl-icu.ko.yaml delete mode 100644 pa-IN/translations/ux_message+intl-icu.pa.yaml delete mode 100644 pl/translations/ux_message+intl-icu.pl.yaml delete mode 100644 pt-BR/translations/ux_message+intl-icu.pt.yaml delete mode 100644 ro/translations/ux_message+intl-icu.ro.yaml delete mode 100644 ru/translations/ux_message+intl-icu.ru.yaml delete mode 100644 vi/translations/ux_message+intl-icu.vi.yaml delete mode 100644 zh-CN/translations/ux_message+intl-icu.zh.yaml diff --git a/assets/js/createConference.js b/assets/js/createConference.js index 0ab28901f..8f73b228e 100644 --- a/assets/js/createConference.js +++ b/assets/js/createConference.js @@ -85,7 +85,7 @@ function createIframe(url, title, startMaximized = true, borderColor = '',roomUi zIndex++; }); newInstance.addEventListener('createNewMultiframe', (data) => { - createIframe(data.url,data.title,data.maximize,'',data.roomUid) + createIframe(data.url,data.title,data.maximize,'',data.roomuid) }); multiframes.push(newInstance); diff --git a/assets/js/multiframe.js b/assets/js/multiframe.js index a288bf92c..996d933b4 100644 --- a/assets/js/multiframe.js +++ b/assets/js/multiframe.js @@ -169,12 +169,12 @@ export class multiframe { delete this.closingTimeout; } else if (type === 'openNewIframe') { //todo in controllerklasse - this.triggerCreateNewMultiframe(decoded.url, decoded.title, false); + this.triggerCreateNewMultiframe(decoded.url, decoded.title, false,decoded.roomuid); } else if (type === 'openNewIframeOnOthers') { //todo in controllerklasse var message = { - room: decoded.room, + room: this.roomUid, url: decoded.url, title: decoded.title } @@ -429,8 +429,8 @@ export class multiframe { } - triggerCreateNewMultiframe(url, title, maximize,roomUid=null) { - this.triggerEvent('createNewMultiframe', {url: url, title: title, maximize: maximize,roomUid:roomUid}) + triggerCreateNewMultiframe(url, title, maximize,roomuid=null) { + this.triggerEvent('createNewMultiframe', {url: url, title: title, maximize: maximize,roomuid:roomuid}) } } \ No newline at end of file diff --git a/assets/js/startWhiteboard.js b/assets/js/startWhiteboard.js index c8e04b89e..21b333786 100644 --- a/assets/js/startWhiteboard.js +++ b/assets/js/startWhiteboard.js @@ -14,7 +14,7 @@ export function initStartWhiteboard() { ele.addEventListener('click', function (ev) { var selfurl = this.dataset.selfurl; var url = this.dataset.url; - const roomUid = this.dataset.roomUid; + const roomUid = this.dataset.roomuid||null; if (this.dataset.room && url) { var message = { room: this.dataset.room, @@ -30,12 +30,12 @@ export function initStartWhiteboard() { type: 'openNewIframe', url: selfurl, 'title': document.title, - roomUid: roomUid, + roomuid: roomUid, }); window.parent.postMessage(parentMessage, '*'); } } else { - createIframe(selfurl, document.title, false,'',); + createIframe(selfurl, document.title, false,'',roomUid); } }) } diff --git a/en-GB/translations/ux_message+intl-icu.en.yaml b/en-GB/translations/ux_message+intl-icu.en.yaml deleted file mode 100644 index 528f21766..000000000 --- a/en-GB/translations/ux_message+intl-icu.en.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/es-ES/translations/ux_message+intl-icu.es.yaml b/es-ES/translations/ux_message+intl-icu.es.yaml deleted file mode 100644 index 528f21766..000000000 --- a/es-ES/translations/ux_message+intl-icu.es.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/fr/translations/ux_message+intl-icu.fr.yaml b/fr/translations/ux_message+intl-icu.fr.yaml deleted file mode 100644 index 528f21766..000000000 --- a/fr/translations/ux_message+intl-icu.fr.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/ja/translations/ux_message+intl-icu.ja.yaml b/ja/translations/ux_message+intl-icu.ja.yaml deleted file mode 100644 index 528f21766..000000000 --- a/ja/translations/ux_message+intl-icu.ja.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/ko/translations/ux_message+intl-icu.ko.yaml b/ko/translations/ux_message+intl-icu.ko.yaml deleted file mode 100644 index 528f21766..000000000 --- a/ko/translations/ux_message+intl-icu.ko.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/pa-IN/translations/ux_message+intl-icu.pa.yaml b/pa-IN/translations/ux_message+intl-icu.pa.yaml deleted file mode 100644 index 528f21766..000000000 --- a/pa-IN/translations/ux_message+intl-icu.pa.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/package-lock.json b/package-lock.json index 2fe07bb94..0b3d18f27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,7 @@ "file-loader": "^6.2.0", "flatpickr": "^4.6.9", "fs": "^0.0.1-security", - "h2-invent-apps": "^2.4.0", + "h2-invent-apps": "^2.5.0", "h2-invent-material-tabs": "^1.10.0", "hotkeys-js": "^3.9.4", "interactjs": "^1.10.17", @@ -6105,9 +6105,10 @@ "dev": true }, "node_modules/h2-invent-apps": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/h2-invent-apps/-/h2-invent-apps-2.4.0.tgz", - "integrity": "sha512-oa3e4nQnCpRdQQwtxsi0CukUCnlxYZ/lm6kpIChf7jmAEjxLVILx69yLavR0v08h1GhOYL5GFQAciiuZHxdSlg==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/h2-invent-apps/-/h2-invent-apps-2.5.2.tgz", + "integrity": "sha512-TzBLC573E/diS2o8pFzwvrD+yVISGMp5SHRT8oEWsmZviTZp/LBuH1CAof9fptwJN3POA5vTh0Rt0qWfdKFAuQ==", + "license": "ISC", "dependencies": { "toastr": "^2.1.4" } diff --git a/package.json b/package.json index 2f5ec45d2..161405118 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "file-loader": "^6.2.0", "flatpickr": "^4.6.9", "fs": "^0.0.1-security", - "h2-invent-apps": "^2.4.0", + "h2-invent-apps": "^2.5.0", "h2-invent-material-tabs": "^1.10.0", "hotkeys-js": "^3.9.4", "interactjs": "^1.10.17", diff --git a/pl/translations/ux_message+intl-icu.pl.yaml b/pl/translations/ux_message+intl-icu.pl.yaml deleted file mode 100644 index 528f21766..000000000 --- a/pl/translations/ux_message+intl-icu.pl.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/pt-BR/translations/ux_message+intl-icu.pt.yaml b/pt-BR/translations/ux_message+intl-icu.pt.yaml deleted file mode 100644 index 528f21766..000000000 --- a/pt-BR/translations/ux_message+intl-icu.pt.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/public/notification.json b/public/notification.json index b4e1611db..5c468cb28 100644 --- a/public/notification.json +++ b/public/notification.json @@ -1,6 +1,7 @@ [ {"text": "Auf Grund eines Server Updates steht der PantherAdmin am kommenden Freitag 19.07.2024 ab 13 Uhr nicht zur Verfügung", "head": "PantherAdmin Wartungsarbeiten", - "type": "info" + "type": "info", + "identifier": "pantherupdate" } ] \ No newline at end of file diff --git a/ro/translations/ux_message+intl-icu.ro.yaml b/ro/translations/ux_message+intl-icu.ro.yaml deleted file mode 100644 index 528f21766..000000000 --- a/ro/translations/ux_message+intl-icu.ro.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/ru/translations/ux_message+intl-icu.ru.yaml b/ru/translations/ux_message+intl-icu.ru.yaml deleted file mode 100644 index 528f21766..000000000 --- a/ru/translations/ux_message+intl-icu.ru.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/src/Service/RoomService.php b/src/Service/RoomService.php index 2ee47f75f..dddf8a2fc 100644 --- a/src/Service/RoomService.php +++ b/src/Service/RoomService.php @@ -167,6 +167,10 @@ function genereateJwtPayload($userName, Rooms $room, Server $server, $moderator, "sub" => $room->getServer()->getUrl(), "room" => $room->getUid(), "context" => [ + 'room'=>[ + 'name'=>$room->getName() + + ], 'user' => [ 'name' => $userName, ], @@ -176,7 +180,17 @@ function genereateJwtPayload($userName, Rooms $room, Server $server, $moderator, if ($userName === 'Meetling' && $server->isLiveKitServer()){ $payload['context']['user']['name'] = ''; } + if ($server->getJigasiNumberUrl()){ + try { + $dialInNumbers = json_decode($server->getJigasiNumberUrl(),true); + $payload['context']['room']['dialIn']['numbers']=$dialInNumbers['numbers']; + $payload['context']['room']['dialIn']['pin']=$room->getCallerRoom()->getCallerId(); + }catch (\Exception $exception){ + $this->logger->error($exception->getMessage()); + } + + } if ($server->isLiveKitServer()) { try { $encSecret = $this->generateEncryptedSecret($server); diff --git a/templates/conference_modules/conferenceSidebar.html.twig b/templates/conference_modules/conferenceSidebar.html.twig index e52dc4b73..66db5da09 100644 --- a/templates/conference_modules/conferenceSidebar.html.twig +++ b/templates/conference_modules/conferenceSidebar.html.twig @@ -79,8 +79,9 @@
    @@ -106,7 +107,7 @@ or roomPermissions(app.user,room).moderator == true or roomPermissions(app.user,room).lobbyModerator == true) %} data-selfurl="{{ createEtherpadLink(room,user) }}" - data-room="whiteboard/{{ room.uidReal }}" + data-room="etherpad/{{ room.uidReal }}" data-url="{{ createEtherpadLink(room) }}" {% else %} data-selfurl="{{ createEtherpadLink(room,user) }}" diff --git a/vi/translations/ux_message+intl-icu.vi.yaml b/vi/translations/ux_message+intl-icu.vi.yaml deleted file mode 100644 index 528f21766..000000000 --- a/vi/translations/ux_message+intl-icu.vi.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. diff --git a/zh-CN/translations/ux_message+intl-icu.zh.yaml b/zh-CN/translations/ux_message+intl-icu.zh.yaml deleted file mode 100644 index 528f21766..000000000 --- a/zh-CN/translations/ux_message+intl-icu.zh.yaml +++ /dev/null @@ -1 +0,0 @@ -email_send_invitation: Einladung wurde erfolgreich an {email} versendet. From d2176859296733be34d716ef3877fe3b02697a84 Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Thu, 20 Mar 2025 16:29:23 +0100 Subject: [PATCH 05/25] * remove min-heigt from body on all join pages --- assets/js/createConference.js | 56 +++++++++++++------ assets/js/multiframe.js | 12 +++- nodejs/websocket.js | 2 + nodejs/websocketState.mjs | 18 ++++-- .../conferenceSidebar.html.twig | 9 ++- templates/lobby/index.html.twig | 4 +- templates/lobby/livekit.html.twig | 4 +- templates/lobby_participants/index.html.twig | 4 +- templates/start/index.html.twig | 2 +- 9 files changed, 74 insertions(+), 37 deletions(-) diff --git a/assets/js/createConference.js b/assets/js/createConference.js index 8f73b228e..87a466549 100644 --- a/assets/js/createConference.js +++ b/assets/js/createConference.js @@ -5,6 +5,7 @@ import {Tooltip} from 'mdb-ui-kit'; import $ from "jquery"; import {setCookie, getCookie} from './cookie' import {multiframe} from "./multiframe"; +import {sendViaWebsocket} from "./websocket"; let counter = 50; @@ -20,7 +21,7 @@ let startWidth = null; let startHeight = null; let startTransform = null; let tryfullscreen = null; - +let blockedUrls = []; function initStartIframe() { @@ -39,9 +40,9 @@ function initStartIframe() { e.preventDefault(); var target = e.target.closest('.startIframe') if ("iframetoast" in target.dataset) { - setSnackbar(target.dataset.iframetoast, '','danger'); + setSnackbar(target.dataset.iframetoast, '', 'danger'); } else { - const isMaximized= getCookie('startMaximized')?getCookie('startMaximized'):1; + const isMaximized = getCookie('startMaximized') ? getCookie('startMaximized') : 1; createIframe(target.href, target.dataset.roomname, isMaximized == 1, true, target.dataset.bordercolor); } } @@ -54,8 +55,7 @@ function initStartIframe() { } - -function createIframe(url, title, startMaximized = true, borderColor = '',roomUid = null) { +function createIframe(url, title, startMaximized = true, borderColor = '', roomUid = null) { width = window.innerWidth * 0.75; height = window.innerHeight * 0.75; @@ -65,13 +65,17 @@ function createIframe(url, title, startMaximized = true, borderColor = '',roomUi var random = md5(urlPath); const existingMultiframe = multiframeCheck(random); - if (existingMultiframe){ + const isInBlockedUrl = checkIfUrlIsBlocked(url); + if (isInBlockedUrl) { + return; + } + if (existingMultiframe) { existingMultiframe.restoreWindowFromMaximized(); existingMultiframe.restoreMinimized(); existingMultiframe.moveInForeground(); - }else { - const newInstance = new multiframe(url,title,startMaximized,borderColor,counter,counter,height,width,multiframes.length+zIndexOffset,roomUid); + } else { + const newInstance = new multiframe(url, title, startMaximized, borderColor, counter, counter, height, width, multiframes.length + zIndexOffset, roomUid); newInstance.addEventListener('remove', () => { removeMultiframe(newInstance); }); @@ -82,10 +86,16 @@ function createIframe(url, title, startMaximized = true, borderColor = '',roomUi removeInteraction(newInstance.frame); }); newInstance.addEventListener('incrementZindex', () => { - zIndex++; + zIndex++; }); newInstance.addEventListener('createNewMultiframe', (data) => { - createIframe(data.url,data.title,data.maximize,'',data.roomuid) + createIframe(data.url, data.title, data.maximize, '', data.roomuid) + }); + newInstance.addEventListener('blockUrlForMultiframe', (data) => { + blockedUrls.push(data.url); + }); + newInstance.addEventListener('openNewMultiframe', (data) => { + sendViaWebsocket('openNewIframe',JSON.stringify(data)); }); multiframes.push(newInstance); @@ -93,22 +103,30 @@ function createIframe(url, title, startMaximized = true, borderColor = '',roomUi counter += 40; if (isFullscreen()) { - if (document){ + if (document) { document.exitFullscreen(); } } } + +function checkIfUrlIsBlocked(url) { + return blockedUrls.includes(url) +} + function multiframeCheck(random) { - return multiframes.some(instance => instance.random === random); + return multiframes.find(instance => instance.random === random); } + function getMultiframeFromHtmlFrame(frame) { - const res= multiframes.find(instance => instance.frame === frame); + const res = multiframes.find(instance => instance.frame === frame); return res; } + function getotherFramesNotActual(instance) { const res = multiframes.filter(frame => frame !== instance); return res; } + function removeMultiframe(instance) { multiframes = multiframes.filter(i => i !== instance); @@ -157,6 +175,7 @@ function switchDragOff() { return null; } } + function moveActualToForeground(actualFrame) { if (actualFrame.isMutable) { actualFrame.playFrame(); @@ -171,7 +190,7 @@ function moveActualToForeground(actualFrame) { const totalFrames = multiframes.length; // Setze das z-index des aktuellen Frames auf die Anzahl der Frames (höchstes z-index) - actualFrame.setZindex(totalFrames +zIndexOffset); + actualFrame.setZindex(totalFrames + zIndexOffset); actualFrame.moveInForeground(); // Sortiere die anderen Frames nach ihrem aktuellen z-index const otherFrames = getotherFramesNotActual(actualFrame) @@ -181,10 +200,11 @@ function moveActualToForeground(actualFrame) { // Vergib die z-index-Werte beginnend bei 1 let zIndex = 1; otherFrames.forEach(frame => { - frame.setZindex(zIndex+zIndexOffset); + frame.setZindex(zIndex + zIndexOffset); zIndex++; }); } + function addInteractions(ele) { const position = {x: counter, y: counter} @@ -372,7 +392,7 @@ function addInteractions(ele) { function makeBlury(frame) { var content = frame.querySelector('.iframeFrame'); - content.style.visibility='hidden'; + content.style.visibility = 'hidden'; frame.style.opacity = 0.5; // for (var f of frames) { // f.insertAdjacentHTML('afterbegin', '
    '); @@ -390,6 +410,7 @@ function removeBlury(frame) { function checkIfIsMutable(frame) { } + // function checkIfIsMutable(frame) { // if (frame.classList.contains('isMutable')) { // var actualPause = frame.querySelector('.pauseConference') @@ -435,4 +456,5 @@ function addOverlayOverAllMultiframes() { function removeOverlayFromAllMultiframes() { document.querySelectorAll('.iframe-overlay').forEach(overlay => overlay.remove()); } -export {initStartIframe, createIframe, checkIfIsMutable} + +export {initStartIframe, createIframe, checkIfIsMutable} diff --git a/assets/js/multiframe.js b/assets/js/multiframe.js index 996d933b4..96198c189 100644 --- a/assets/js/multiframe.js +++ b/assets/js/multiframe.js @@ -172,13 +172,13 @@ export class multiframe { this.triggerCreateNewMultiframe(decoded.url, decoded.title, false,decoded.roomuid); } else if (type === 'openNewIframeOnOthers') { - //todo in controllerklasse + this.triggerBlockUrlForMultiframe(decoded.url); var message = { room: this.roomUid, url: decoded.url, title: decoded.title } - sendViaWebsocket('openNewIframe', JSON.stringify(message)); + this.triggerOpenNewFrameOnOthers(message); }else if (type === 'showPlayPause') { this.frame.classList.add('isMutable'); @@ -433,4 +433,12 @@ export class multiframe { this.triggerEvent('createNewMultiframe', {url: url, title: title, maximize: maximize,roomuid:roomuid}) } + triggerBlockUrlForMultiframe(url) { + this.triggerEvent('blockUrlForMultiframe', {url: url}) + + } + triggerOpenNewFrameOnOthers(data) { + this.triggerEvent('openNewMultiframe', data) + + } } \ No newline at end of file diff --git a/nodejs/websocket.js b/nodejs/websocket.js index 3715de2f8..2f7518c13 100644 --- a/nodejs/websocket.js +++ b/nodejs/websocket.js @@ -65,6 +65,8 @@ io.use(function (socket, next) { io.on("connection", async (socket) => { var jwtObj = jwt.decode(socket.handshake.query.token); + console.log(jwtObj.rooms); + for (var i = 0; i < jwtObj.rooms.length; i++) { socket.join(jwtObj.rooms[i]); console.log(`JOin room ${jwtObj.rooms[i]}`); diff --git a/nodejs/websocketState.mjs b/nodejs/websocketState.mjs index 07f8cb22b..95981f704 100644 --- a/nodejs/websocketState.mjs +++ b/nodejs/websocketState.mjs @@ -78,11 +78,17 @@ function sendStatusToOwnUSer(socket) { } function sendNewIframe(socket, data) { - var message = JSON.parse(data); - socket.to(message.room).emit('openNewIframe', JSON.stringify({ - url: message.url, - title: message.title - } + try { + var message = JSON.parse(data); + console.log(data); + socket.to(message.room).emit('openNewIframe', JSON.stringify({ + url: message.url, + title: message.title + } + ) ) - ) + }catch (e) { + console.log(e) + } + } diff --git a/templates/conference_modules/conferenceSidebar.html.twig b/templates/conference_modules/conferenceSidebar.html.twig index 66db5da09..5f8763bb4 100644 --- a/templates/conference_modules/conferenceSidebar.html.twig +++ b/templates/conference_modules/conferenceSidebar.html.twig @@ -56,8 +56,7 @@ or roomPermissions(app.user,room).moderator == true or roomPermissions(app.user,room).lobbyModerator == true) %} data-selfurl="{{ createWhitebophirLink(room,true) }}" - data-room="whiteboard/{{ room.uidReal }}" - + data-room="{{ room.uidReal }}" data-url="{{ createWhitebophirLink(room,false) }}" {% else %} data-selfurl="{{ createWhitebophirLink(room,false) }}" @@ -80,8 +79,8 @@
    @@ -107,7 +106,7 @@ or roomPermissions(app.user,room).moderator == true or roomPermissions(app.user,room).lobbyModerator == true) %} data-selfurl="{{ createEtherpadLink(room,user) }}" - data-room="etherpad/{{ room.uidReal }}" + data-room="{{ room.uidReal }}" data-url="{{ createEtherpadLink(room) }}" {% else %} data-selfurl="{{ createEtherpadLink(room,user) }}" diff --git a/templates/lobby/index.html.twig b/templates/lobby/index.html.twig index bdd49704b..307b36317 100644 --- a/templates/lobby/index.html.twig +++ b/templates/lobby/index.html.twig @@ -245,13 +245,13 @@ 'lobby_moderator/'~room.uidReal, 'lobby_broadcast_websocket/'~ room.uidReal, 'lobby_personal'~room.uidReal~app.user.uid, - 'whiteboard/'~room.uidReal + room.uidReal ] %} {% else %} {% set topics =[ 'lobby_moderator/'~room.uidReal, 'lobby_broadcast_websocket/'~ room.uidReal, - 'whiteboard/'~room.uidReal + room.uidReal ] %} {% endif %} var topic ={{ mercure(topics)|json_encode(constant('JSON_UNESCAPED_SLASHES') b-or constant('JSON_HEX_TAG'))|raw }}; diff --git a/templates/lobby/livekit.html.twig b/templates/lobby/livekit.html.twig index 66b1a5a2f..17a3a36c4 100644 --- a/templates/lobby/livekit.html.twig +++ b/templates/lobby/livekit.html.twig @@ -212,13 +212,13 @@ 'lobby_moderator/'~room.uidReal, 'lobby_broadcast_websocket/'~ room.uidReal, 'lobby_personal'~room.uidReal~app.user.uid, - 'whiteboard/'~room.uidReal + room.uidReal ] %} {% else %} {% set topics =[ 'lobby_moderator/'~room.uidReal, 'lobby_broadcast_websocket/'~ room.uidReal, - 'whiteboard/'~room.uidReal + room.uidReal ] %} {% endif %} var topic ={{ mercure(topics)|json_encode(constant('JSON_UNESCAPED_SLASHES') b-or constant('JSON_HEX_TAG'))|raw }}; diff --git a/templates/lobby_participants/index.html.twig b/templates/lobby_participants/index.html.twig index 31cff2155..b6a3f8aed 100644 --- a/templates/lobby_participants/index.html.twig +++ b/templates/lobby_participants/index.html.twig @@ -189,13 +189,13 @@ 'lobby_WaitingUser_websocket/'~ user.uid, 'lobby_broadcast_websocket/'~room.uidReal, 'lobby_personal'~room.uidReal~user.user.uid, - 'whiteboard/'~room.uidReal + room.uidReal ] %} {% else %} {% set topics = [ 'lobby_WaitingUser_websocket/'~ user.uid, 'lobby_broadcast_websocket/'~room.uidReal, - 'whiteboard/'~room.uidReal + room.uidReal ] %} {% endif %} var topic ={{ mercure(topics)|json_encode(constant('JSON_UNESCAPED_SLASHES') b-or constant('JSON_HEX_TAG'))|raw }}; diff --git a/templates/start/index.html.twig b/templates/start/index.html.twig index b8add3fd0..28f883dcd 100644 --- a/templates/start/index.html.twig +++ b/templates/start/index.html.twig @@ -115,7 +115,7 @@ var conferenzeName = '{{ room.name }}'; var topic = {{ mercure(absolute_url(path('lobby_moderator',{'uid':room.uidReal})))|json_encode(constant('JSON_UNESCAPED_SLASHES') b-or constant('JSON_HEX_TAG'))|raw }}; var topicBroadcast = {{ mercure(absolute_url(path('lobby_broadcast_websocket',{'roomUid':room.uidReal})))|json_encode(constant('JSON_UNESCAPED_SLASHES') b-or constant('JSON_HEX_TAG'))|raw }}; - var websocketTopics = "{{ getJwtforWebsocket(['whiteboard/'~room.uidReal],app.user) }}"; + var websocketTopics = "{{ getJwtforWebsocket([room.uidReal],app.user) }}"; var websocketUrl = "{{ getUrlforWebsocket() }}"; From 2a16d539edc5b02961966bbc6ad64928a1e44052 Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Thu, 20 Mar 2025 16:32:21 +0100 Subject: [PATCH 06/25] * remove min-heigt from body on all join pages --- nodejs/websocket.js | 1 - nodejs/websocketState.mjs | 1 - 2 files changed, 2 deletions(-) diff --git a/nodejs/websocket.js b/nodejs/websocket.js index 2f7518c13..0ac67fd1b 100644 --- a/nodejs/websocket.js +++ b/nodejs/websocket.js @@ -68,7 +68,6 @@ io.on("connection", async (socket) => { console.log(jwtObj.rooms); for (var i = 0; i < jwtObj.rooms.length; i++) { - socket.join(jwtObj.rooms[i]); console.log(`JOin room ${jwtObj.rooms[i]}`); } var user = loginUser(socket); diff --git a/nodejs/websocketState.mjs b/nodejs/websocketState.mjs index 95981f704..469ddc0c4 100644 --- a/nodejs/websocketState.mjs +++ b/nodejs/websocketState.mjs @@ -80,7 +80,6 @@ function sendStatusToOwnUSer(socket) { function sendNewIframe(socket, data) { try { var message = JSON.parse(data); - console.log(data); socket.to(message.room).emit('openNewIframe', JSON.stringify({ url: message.url, title: message.title From 63a2d9ba55799316b86b028164d6ead8e52ed595 Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Thu, 20 Mar 2025 16:34:16 +0100 Subject: [PATCH 07/25] * remove min-heigt from body on all join pages --- RELEASE_NOTE.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/RELEASE_NOTE.md b/RELEASE_NOTE.md index e098429a9..b3da80755 100644 --- a/RELEASE_NOTE.md +++ b/RELEASE_NOTE.md @@ -1,14 +1,8 @@ # Release Note 1.2 ## Features: -* **Improved Sidenavigation in the Conference**: - * Better overview of all Add-Ons during the conference - * New invitation Modal inside the conference +* **LookyLooky** The great new document sharing tool https://github.com/H2-invent/lookylooky ## Improvements: -* Invite Participants faster with the new invitation modal from the new sidenavigation inside the conference ## Bug Fixes: -* Collapse the Sidenavigation on mobile devices -* Calendly disconnection fails when token was removed in advance in calndly -* Open invitation modal in open conferneces onyl on moderators \ No newline at end of file From ef770bddf1870dbe0485ebf2abf479cace3cb41b Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Fri, 21 Mar 2025 16:19:14 +0100 Subject: [PATCH 08/25] add looky looky --- README.md | 4 ++-- RELEASE_NOTE.md | 5 ++++- assets/css/layout/_browserWindow.scss | 6 +++++- nodejs/websocket.js | 2 +- nodejs/websocketState.mjs | 1 + 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b9a213710..a6ef71aa2 100644 --- a/README.md +++ b/README.md @@ -68,13 +68,13 @@ To join the community talk, please click on the subscription link provided: http Once you have subscribed, we will send you a reminder closer to the date of the talk. We hope to see you there! ### Mailinglist -[Join here](https://verteiler.h2-invent.com/?p=subscribe&id=1) +[Join here](https://lists.h2-invent.com/forms/nfrm_weLJnLY5) If you want to be notified, if there are new updates or releases, you can subscribe to the __Jitsi Admin Update__ mailing list. H2 invent will send out information to the mailing list concering releases, updates or new features. This is __not__ a marketing newsletter. -If you want to join the mailing list just click on the link [Mailing List](https://verteiler.h2-invent.com/?p=subscribe&id=1) and enter your email address. +If you want to join the mailing list just click on the link [Mailing List](https://lists.h2-invent.com/forms/nfrm_weLJnLY5) and enter your email address. We use a double-opt-in process where you will receive a confirmation email containing a link with with you confirm, that you want to join to mailing list. diff --git a/RELEASE_NOTE.md b/RELEASE_NOTE.md index b3da80755..48f94ddf6 100644 --- a/RELEASE_NOTE.md +++ b/RELEASE_NOTE.md @@ -1,8 +1,11 @@ # Release Note 1.2 ## Features: -* **LookyLooky** The great new document sharing tool https://github.com/H2-invent/lookylooky +* **LookyLooky** The great new document sharing tool [LookyLooky GIthub Repo](https://github.com/H2-invent/lookylooky) ## Improvements: ## Bug Fixes: + +# Mailinglist +To get the lastest updates subscripe to the newsletter [Subscripe here](https://lists.h2-invent.com/forms/nfrm_weLJnLY5) \ No newline at end of file diff --git a/assets/css/layout/_browserWindow.scss b/assets/css/layout/_browserWindow.scss index b60430af8..68969a925 100644 --- a/assets/css/layout/_browserWindow.scss +++ b/assets/css/layout/_browserWindow.scss @@ -172,7 +172,11 @@ -ms-transition-delay: 0.25s; -o-transition-delay: 0.25s; transition-delay: 0.25s; - + position: absolute!important; + left: 0; + border-radius: 8px; + overflow: hidden; + box-shadow: $box-shadow; } } diff --git a/nodejs/websocket.js b/nodejs/websocket.js index 0ac67fd1b..0a0d003a1 100644 --- a/nodejs/websocket.js +++ b/nodejs/websocket.js @@ -68,7 +68,7 @@ io.on("connection", async (socket) => { console.log(jwtObj.rooms); for (var i = 0; i < jwtObj.rooms.length; i++) { - console.log(`JOin room ${jwtObj.rooms[i]}`); + socket.join(jwtObj.rooms[i]) } var user = loginUser(socket); diff --git a/nodejs/websocketState.mjs b/nodejs/websocketState.mjs index 469ddc0c4..645eb01e1 100644 --- a/nodejs/websocketState.mjs +++ b/nodejs/websocketState.mjs @@ -49,6 +49,7 @@ export function websocketState(event, socket, message) { sendStatus(socket); break; case 'openNewIframe': + console.log(message); sendNewIframe(socket, message) break; case 'giveOnlineStatus': From 018b243d5cbc0773d7e8c49f67b464a2664f92c1 Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Wed, 26 Mar 2025 14:04:14 +0100 Subject: [PATCH 09/25] * add new dialog system --- assets/js/createDialog.js | 21 ++++++ assets/js/lobbyNotification.js | 27 ++++++- assets/js/myToastr.js | 72 ++++++++++--------- package-lock.json | 7 ++ package.json | 1 + src/Service/Lobby/DirectSendService.php | 36 ++++++++++ .../AdhocMeetingWebsocketService.php | 70 +++++++++++++----- 7 files changed, 182 insertions(+), 52 deletions(-) create mode 100644 assets/js/createDialog.js diff --git a/assets/js/createDialog.js b/assets/js/createDialog.js new file mode 100644 index 000000000..8f7fb7d45 --- /dev/null +++ b/assets/js/createDialog.js @@ -0,0 +1,21 @@ +import Swal from 'sweetalert2'; + +export function showDialog(data) { + if (data.type !== 'dialog') return; + + const buttonsHtml = data.buttons.map((button, index) => { + const dataAttributes = button.data ? Object.entries(button.data).map(([key, value]) => `data-${key}='${value}'`).join(' ') : ''; + return ` + ${button.text} + `; + }).join(' '); + + Swal.fire({ + title: data.header, + backdrop: false, + html: `

    ${data.text}

    ${buttonsHtml}`, + icon: data.dialogType, + showConfirmButton: false + }); +} + diff --git a/assets/js/lobbyNotification.js b/assets/js/lobbyNotification.js index 59279d477..7616aaf28 100644 --- a/assets/js/lobbyNotification.js +++ b/assets/js/lobbyNotification.js @@ -15,6 +15,7 @@ import {close, inIframe} from './moderatorIframe' import {initStarSend} from "./endModal"; import { Tooltip, initMDB } from "mdb-ui-kit"; import {initAllComponents} from "./confirmation"; +import {showDialog} from "./createDialog"; var callersoundplay = new Audio(callerSound); callersoundplay.loop = true; @@ -32,6 +33,10 @@ function masterNotify(data) { Push.Permission.request(); if (data.type === 'notification') { notifymoderator(data) + }else if (data.type === 'browserPush') { + showPush(data) + }else if (data.type === 'playSound') { + showPush(data) } else if (data.type === 'cleanNotification') { deleteToast(data.messageId); } else if (data.type === 'refresh') { @@ -42,7 +47,10 @@ function masterNotify(data) { redirect(data); } else if (data.type === 'snackbar') { setSnackbar(data.message,'', data.color, false,'0x00',data.closeAfter) - } else if (data.type === 'newJitsi') { + } + else if (data.type === 'dialog') { + showDialog(data); + }else if (data.type === 'newJitsi') { //do nothing. Is handeled somewhere localy } else if (data.type === 'refreshDashboard') { refreshDashboard(); @@ -178,6 +186,22 @@ function showPush(data) { }, 2500) }, Math.floor(Math.random() * 50) + 50); } +function playSound(data) { + setTimeout(function () { + TabUtils.lockFunction('notification' + data.messageId, function () { + if (data.soundName === ' caller'){ + var audio = new Audio(callerSound); + audio.play(); + }else if (data.soundName === 'notfication'){ + var audio = new Audio(notificationSound); + audio.play(); + }else if (data.soundName === 'newMessage'){ + var audio = new Audio(newMessageSound); + audio.play(); + } + }, 2500) + }, Math.floor(Math.random() * 50) + 50); +} function callAddhock(data) { setTimeout(function () { @@ -199,6 +223,7 @@ function callAddhock(data) { }, 5000) }, Math.floor(Math.random() * 50) + 50); + setSnackbar(data.message,'Lobby', data.color, true); } diff --git a/assets/js/myToastr.js b/assets/js/myToastr.js index 99e6cce02..b107b7ebd 100644 --- a/assets/js/myToastr.js +++ b/assets/js/myToastr.js @@ -1,45 +1,53 @@ -import * as Toastr from "toastr"; - -Toastr.options = { - "closeButton": true, - "debug": false, - "newestOnTop": true, - "progressBar": true, - "positionClass": "toast-top-right", - "preventDuplicates": true, - "onclick": null, - "showDuration": "300", - "hideDuration": "1000", - "timeOut": "0", - "extendedTimeOut": "200", - "showEasing": "swing", - "hideEasing": "linear", - "showMethod": "fadeIn", - "hideMethod": "fadeOut" -} +import Swal from "sweetalert2"; +import * as Snackbar from 'node-snackbar' +// +// Toastr.options = { +// "closeButton": true, +// "debug": false, +// "newestOnTop": true, +// "progressBar": true, +// "positionClass": "toast-top-right", +// "preventDuplicates": true, +// "onclick": null, +// "showDuration": "300", +// "hideDuration": "1000", +// "timeOut": "0", +// "extendedTimeOut": "200", +// "showEasing": "swing", +// "hideEasing": "linear", +// "showMethod": "fadeIn", +// "hideMethod": "fadeOut" +// } function setSnackbar(text,title, color, closeWithHover = false, id = '0x00',timeout=0) { + if (color === 'danger') { color = 'error'; } - Toastr.options.timeOut = timeout; - if (closeWithHover === true) { - Toastr.options.timeOut = 0; - Toastr.options.extendedTimeOut = 0; - } else { - Toastr.options.extendedTimeOut = 200; - } - text = '' + text; - if (title!==''){ - Toastr[color](text,title); - }else { - Toastr[color](text); - } + Snackbar.show({ + text: text + }) + // Toastr.options.timeOut = timeout; + // if (closeWithHover === true) { + // Toastr.options.timeOut = 0; + // Toastr.options.extendedTimeOut = 0; + // } else { + // Toastr.options.extendedTimeOut = 200; + // } + // text = '' + text; + // if (title!==''){ + // Toastr[color](text,title); + // }else { + // Toastr[color](text); + // } } +function setDiolog(header, text,buttons) { + +} function deleteToast(id) { var tid = '#jitsi_toastr_' + id; if (document.querySelector(tid)) { diff --git a/package-lock.json b/package-lock.json index 0b3d18f27..594eae8a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "moment": "^2.29.1", "moveable": "^0.36.3", "net": "^1.0.2", + "node-snackbar": "^0.1.16", "node-waves": "^0.7.6", "popper.js": "^1.16.1", "pretty-print-json": "^1.3.1", @@ -8221,6 +8222,12 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" }, + "node_modules/node-snackbar": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/node-snackbar/-/node-snackbar-0.1.16.tgz", + "integrity": "sha512-3s43QMKgABXdnqUfpKAXG+WlvS8bbuO6n6LAOmmLNZs87CGdpexqfGYCktFVi9NHFgREwNJARgeVTLOFAf2MQg==", + "license": "MIT" + }, "node_modules/node-waves": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/node-waves/-/node-waves-0.7.6.tgz", diff --git a/package.json b/package.json index 161405118..9199b6ff3 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "moment": "^2.29.1", "moveable": "^0.36.3", "net": "^1.0.2", + "node-snackbar": "^0.1.16", "node-waves": "^0.7.6", "popper.js": "^1.16.1", "pretty-print-json": "^1.3.1", diff --git a/src/Service/Lobby/DirectSendService.php b/src/Service/Lobby/DirectSendService.php index c58241bd6..fddc9fcbd 100644 --- a/src/Service/Lobby/DirectSendService.php +++ b/src/Service/Lobby/DirectSendService.php @@ -62,6 +62,21 @@ public function sendSnackbar($topic, $text, $color, $closeAfterMs = null) return $this->publisher->publish($update); } + public function sendDialog($topic, $header, $text, $type='question', $buttons=[]) + { + $data = [ + 'type' => 'dialog', + 'header' => $header, + 'text' => $text, + 'buttons' => $buttons, + 'dialogType' => $type + + ]; + + $update = new Update($topic, json_encode($data)); + return $this->publisher->publish($update); + } + public function sendMessage($topic, $message, string $from) { $data = [ @@ -100,6 +115,27 @@ public function sendBrowserNotification($topic, $title, $message, $pushMessage, return $this->publisher->publish($update); } + public function sendBrowserPush($topic, $title, $pushMessage, $id) + { + $data = [ + 'type' => 'browserPush', + 'title' => $title, + 'pushNotification' => $pushMessage, + 'messageId' => $id, + ]; + $update = new Update($topic, json_encode($data)); + return $this->publisher->publish($update); + } + public function sendPlaySound($topic, $soundName, $id) + { + $data = [ + 'type' => 'playSound', + 'soundName' => $soundName, + 'messageId' => $id, + ]; + $update = new Update($topic, json_encode($data)); + return $this->publisher->publish($update); + } public function sendCleanBrowserNotification($topic, $id) { $data = [ diff --git a/src/Service/adhocmeeting/AdhocMeetingWebsocketService.php b/src/Service/adhocmeeting/AdhocMeetingWebsocketService.php index 8d15396e8..fb8cb9e2e 100644 --- a/src/Service/adhocmeeting/AdhocMeetingWebsocketService.php +++ b/src/Service/adhocmeeting/AdhocMeetingWebsocketService.php @@ -14,35 +14,67 @@ class AdhocMeetingWebsocketService { public function __construct( - private ParameterBagInterface $parameterBag, - private TranslatorInterface $translator, - private DirectSendService $directSendService, - private UrlGeneratorInterface $urlGen, - private ThemeService $theme, + private ParameterBagInterface $parameterBag, + private TranslatorInterface $translator, + private DirectSendService $directSendService, + private UrlGeneratorInterface $urlGen, + private ThemeService $theme, ) { } - +//todo umbau auf dialog kein toast mehr public function sendAddhocMeetingWebsocket(User $reciever, User $creator, Rooms $room): void { $topic = 'personal/' . $reciever->getUid(); - $format = '%s
    %s '; - $toastText = sprintf( - $format, - $this->translator->trans('addhock.notification.pushMessage', ['{name}' => $creator->getFormatedName($this->parameterBag->get('laf_showName'))]), - $this->urlGen->generate('room_join', ['room' => $room->getId(), 't' => 'b']), - $room->getSecondaryName() ?: $room->getName(), - $this->translator->trans('Hier beitreten'), + $header = $this->translator->trans('addhock.notification.title'); + $text = $this->translator->trans('addhock.notification.pushMessage', ['{name}' => $creator->getFormatedName($this->parameterBag->get('laf_showName'))]); + $dialogType = 'question'; + $button = [ + [ + 'class' => 'btn btn-success ' . $this->theme->getApplicationProperties('LAF_USE_MULTIFRAME') == 1 ? 'startIframe' : '', + 'text' => ' ' . $this->translator->trans('Hier beitreten'), + 'link' => $this->urlGen->generate('room_join', ['room' => $room->getId(), 't' => 'b']), + 'data' => + [ + 'roomname' => $room->getSecondaryName() ?: $room->getName() + ] + ], + [ + 'class' => 'btn btn-danger ', + 'text' => ' ', + 'data' => [], + ] + ]; + +// $format = '%s +//
    %s '; +// $toastText = sprintf( +// $format, +// $this->translator->trans('addhock.notification.pushMessage', ['{name}' => $creator->getFormatedName($this->parameterBag->get('laf_showName'))]), +// $this->urlGen->generate('room_join', ['room' => $room->getId(), 't' => 'b']), +// $room->getSecondaryName() ?: $room->getName(), +// $this->translator->trans('Hier beitreten'), +// ); + $this->directSendService->sendDialog( + $topic, + $header, + $text, + $dialogType, + $button ); - $this->directSendService->sendCallAdhockmeeding( - $this->translator->trans('addhock.notification.title'), + $this->directSendService->sendBrowserPush( + $topic, + $header, + $text, + md5(uniqid()) + ); + + $this->directSendService->sendPlaySound( $topic, - $toastText, - $this->translator->trans('addhock.notification.pushMessage', ['{name}' => $creator->getFormatedName($this->parameterBag->get('laf_showName'))]), - 60000, - $room->getUid() + 'caller', + md5(uniqid()) ); } } From 175d49c97493a6c061c3b76817e8b3d96d1c7b19 Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Tue, 1 Apr 2025 13:27:45 +0200 Subject: [PATCH 10/25] refactor toast --- assets/js/createDialog.js | 9 ++++++++- .../AdhocMeetingWebsocketService.php | 2 +- src/Service/webhook/RoomWebhookService.php | 20 +++++++++---------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/assets/js/createDialog.js b/assets/js/createDialog.js index 8f7fb7d45..0a2c51872 100644 --- a/assets/js/createDialog.js +++ b/assets/js/createDialog.js @@ -15,7 +15,14 @@ export function showDialog(data) { backdrop: false, html: `

    ${data.text}

    ${buttonsHtml}`, icon: data.dialogType, - showConfirmButton: false + showConfirmButton: false, + didRender: () => { + data.buttons.forEach((button, index) => { + document.getElementById(`swal-btn-${index}`).addEventListener('click', () => { + Swal.close(); + }); + }); + } }); } diff --git a/src/Service/adhocmeeting/AdhocMeetingWebsocketService.php b/src/Service/adhocmeeting/AdhocMeetingWebsocketService.php index fb8cb9e2e..e4343ba23 100644 --- a/src/Service/adhocmeeting/AdhocMeetingWebsocketService.php +++ b/src/Service/adhocmeeting/AdhocMeetingWebsocketService.php @@ -33,7 +33,7 @@ public function sendAddhocMeetingWebsocket(User $reciever, User $creator, Rooms $dialogType = 'question'; $button = [ [ - 'class' => 'btn btn-success ' . $this->theme->getApplicationProperties('LAF_USE_MULTIFRAME') == 1 ? 'startIframe' : '', + 'class' => 'btn btn-success ' . ($this->theme->getApplicationProperties('LAF_USE_MULTIFRAME') == 1 ? 'startIframe' : ''), 'text' => ' ' . $this->translator->trans('Hier beitreten'), 'link' => $this->urlGen->generate('room_join', ['room' => $room->getId(), 't' => 'b']), 'data' => diff --git a/src/Service/webhook/RoomWebhookService.php b/src/Service/webhook/RoomWebhookService.php index c05c557f1..07a3fadad 100644 --- a/src/Service/webhook/RoomWebhookService.php +++ b/src/Service/webhook/RoomWebhookService.php @@ -46,7 +46,7 @@ public function startWebhook($data): ?string $res = $this->roomCreated( $data['room_name'], $data['is_breakout'], - isset($data['breakout_room_id']) ? $data['breakout_room_id'] : null, + $data['breakout_room_id'] ?? null, $data['room_jid'], $data['created_at'] ); @@ -54,7 +54,7 @@ public function startWebhook($data): ?string case 'muc-room-destroyed': $res = $this->roomDestroyed( $data['is_breakout'], - isset($data['breakout_room_id']) ? $data['breakout_room_id'] : null, + $data['breakout_room_id'] ?? null, $data['room_jid'], $data['destroyed_at'] ); @@ -62,11 +62,11 @@ public function startWebhook($data): ?string case 'muc-occupant-joined': $res = $this->roomParticipantJoin( $data['is_breakout'], - isset($data['breakout_room_id']) ? $data['breakout_room_id'] : null, + $data['breakout_room_id'] ?? null, $data['room_jid'], $data['occupant']['occupant_jid'], $data['occupant']['joined_at'], - isset($data['occupant']['name']) ? $data['occupant']['name'] : null + $data['occupant']['name'] ?? null ); break; @@ -90,7 +90,7 @@ public function startWebhook($data): ?string public function roomCreated( string $roomName, - bool $isBreakout, + ?bool $isBreakout, ?string $breakoutRoomId, string $roomJid, int $createdAt @@ -152,7 +152,7 @@ public function roomCreated( public function roomDestroyed( - bool $isBreakout, + ?bool $isBreakout, ?string $breakoutRoomId, string $roomJid, int $destroyedAt @@ -224,7 +224,7 @@ public function roomDestroyed( } public function roomParticipantJoin( - ?bool $isBreakput, + ?bool $isBreakout, ?string $breakoutRoomName, string $roomJId, string $occupantJId, @@ -234,7 +234,7 @@ public function roomParticipantJoin( { try { - if ($isBreakput === true) { + if ($isBreakout === true) { $this->logger->debug('This is a breakoutRoom', ['breakout_room_id ' => $breakoutRoomName, 'room_jid' => $roomJId]); return 'Room is a breakout room we don`t join the participant'; } @@ -274,7 +274,7 @@ public function roomParticipantJoin( public function roomParticipantLeft( - bool $isBreakout, + ?bool $isBreakout, ?string $breakoutRoomId, string $occupantJid, int $leftAt, @@ -315,7 +315,7 @@ public function roomParticipantLeft( return null; } - public function clenRoomStatus(RoomStatus $roomStatus) + public function clenRoomStatus(RoomStatus $roomStatus): void { if (!$roomStatus->getRoom()) { foreach ($roomStatus->getRoomStatusParticipants() as $data) { From f2c005b7a2992281cf7e92bfb9234a159e00bc4e Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Sat, 5 Apr 2025 22:53:22 +0200 Subject: [PATCH 11/25] refactor toast --- src/Service/api/EventSyncApiService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/api/EventSyncApiService.php b/src/Service/api/EventSyncApiService.php index cbc3f9017..a2862b08c 100644 --- a/src/Service/api/EventSyncApiService.php +++ b/src/Service/api/EventSyncApiService.php @@ -18,7 +18,7 @@ public function getCallerSessionFromUid(string $uid):array if ($roomStatus){ return ['status'=>'ROOM_STARTED']; }else{ - return ['status'=>'ROOOM_CLOSED']; + return ['status'=>'ROOM_CLOSED']; } } } \ No newline at end of file From aaf506deb8e7f4cb7ec48dcf3376b159d1d54666 Mon Sep 17 00:00:00 2001 From: h2entwicklung Date: Mon, 5 May 2025 16:34:49 +0200 Subject: [PATCH 12/25] * fix unittests --- .env | 1 + assets/css/layout/_browserWindow.scss | 1 + assets/js/adhoc.js | 1 + assets/js/confirmation.js | 3 + assets/js/createDialog.js | 1 + assets/js/frontend.js | 2 + assets/js/lobbyModerator.js | 1 + assets/js/lobbyParticipant.js | 1 + config/packages/twig.yaml | 4 +- config/services.yaml | 1 + package-lock.json | 35 +++++++ package.json | 2 + src/Controller/DashboardController.php | 9 ++ src/Controller/OwnRoomController.php | 15 +++ src/Controller/PublicConferenceController.php | 6 +- src/EventListener/OAuthRedirectListener.php | 41 ++++++++ src/Form/CalendlyTokenType.php | 2 +- src/Form/Type/AddressGroupType.php | 2 +- src/Form/Type/JoinMyRoomType.php | 2 +- src/Form/Type/JoinViewType.php | 6 +- src/Form/Type/PublicConferenceType.php | 5 +- src/Form/Type/PublicRegisterType.php | 6 +- src/Form/Type/RepeaterType.php | 14 +-- src/Service/webhook/RoomWebhookService.php | 8 +- src/UtilsHelper.php | 95 ++++++++++++++++--- templates/base/__profileModal.html.twig | 3 + .../conferenceSidebar.html.twig | 53 ++++++----- templates/form/ja_theme.html.twig | 49 ++++++++++ templates/lobby/__lobbyParticipants.html.twig | 7 +- templates/public_conference/index.html.twig | 15 ++- templates/repeater/index.html.twig | 4 +- ...ConferenceMapperControllerCallerIdTest.php | 4 +- .../ConferenceMapperControllerTest.php | 2 +- .../EventSyncRelaisControllerTest.php | 2 +- .../JitsiEventSyncApiControllerTest.php | 2 +- .../service/JItsiEventSyncAPITest.php | 2 +- tests/Join/IpJoinTest.php | 4 +- tests/Join/JoinControllerTest.php | 2 +- tests/Join/JoinServiceTest.php | 6 +- tests/Join/JwtTest.php | 3 + tests/Tag/RoomTagControllerTest.php | 4 +- translations/messages+intl-icu.de.xlf | 2 +- 42 files changed, 336 insertions(+), 92 deletions(-) create mode 100644 src/EventListener/OAuthRedirectListener.php diff --git a/.env b/.env index 63aaf1262..d598a7372 100644 --- a/.env +++ b/.env @@ -125,6 +125,7 @@ LAF_HIDE_PROFILEPICTURE=0 LAF_SHOW_TAG_TRANSPARENT_BACKGROUND=0 LAF_DEFAULT_ONLINE_STATUS=1 LAF_FLOATING_TAG_FORCE_SHOW=1 +LAF_SHOW_CALENDLY=1 ###< LaF ### ###> Default Jitsi Server ### diff --git a/assets/css/layout/_browserWindow.scss b/assets/css/layout/_browserWindow.scss index 68969a925..fc5ba5eea 100644 --- a/assets/css/layout/_browserWindow.scss +++ b/assets/css/layout/_browserWindow.scss @@ -198,6 +198,7 @@ .pausedFrame { position: absolute; + z-index: 50; top: 0; left: 0; width: 100%; diff --git a/assets/js/adhoc.js b/assets/js/adhoc.js index 69bc52fd2..2ad28507c 100644 --- a/assets/js/adhoc.js +++ b/assets/js/adhoc.js @@ -35,6 +35,7 @@ function initconfirmLoadOpenPopUp() { showCancelButton: true, confirmButtonText: ok, cancelButtonText: cancel, + heightAuto: false, customClass: { confirmButton: 'btn btn-outline-danger', cancelButton: 'btn btn-outline-primary', diff --git a/assets/js/confirmation.js b/assets/js/confirmation.js index b1856f1bf..cca1e8636 100644 --- a/assets/js/confirmation.js +++ b/assets/js/confirmation.js @@ -103,6 +103,7 @@ function initconfirmHref() { backdrop: false, showCancelButton: true, cancelButtonText: cancel, + heightAuto: false, customClass: { confirmButton: 'btn-danger btn', cancelButton: 'btn-outline-primary btn' @@ -133,6 +134,7 @@ function initconfirmLoadOpenPopUp() { backdrop: false, showCancelButton: true, cancelButtonText: cancel, + heightAuto: false, customClass: { confirmButton: 'btn-danger btn', cancelButton: 'btn-outline-primary btn' @@ -175,6 +177,7 @@ function initConfirmDirectSendHref() { backdrop: false, showCancelButton: true, cancelButtonText: 'Abbrechen', // Übersetzung anpassen + heightAuto: false, customClass: { confirmButton: 'btn-danger btn', cancelButton: 'btn-outline-primary btn' diff --git a/assets/js/createDialog.js b/assets/js/createDialog.js index 0a2c51872..d9b35dd6d 100644 --- a/assets/js/createDialog.js +++ b/assets/js/createDialog.js @@ -16,6 +16,7 @@ export function showDialog(data) { html: `

    ${data.text}

    ${buttonsHtml}`, icon: data.dialogType, showConfirmButton: false, + heightAuto: false, didRender: () => { data.buttons.forEach((button, index) => { document.getElementById(`swal-btn-${index}`).addEventListener('click', () => { diff --git a/assets/js/frontend.js b/assets/js/frontend.js index ffaa902e0..b6482e42b 100644 --- a/assets/js/frontend.js +++ b/assets/js/frontend.js @@ -12,6 +12,7 @@ import {initSchedulePublic} from './scheduling' import {initGenerell} from './init'; import {setSnackbar} from "./myToastr"; import * as h2Button from "h2-invent-apps"; +import {initAllComponents} from "./confirmation"; $(document).ready(function () { initGenerell(); @@ -30,6 +31,7 @@ $(window).on('load', function () { initMDB({ Popover }); + initAllComponents(); $('[data-mdb-toggle="toastr"]').click(function (e) { setSnackbar($(this).data('text'),'',$(this).data('type')) diff --git a/assets/js/lobbyModerator.js b/assets/js/lobbyModerator.js index e37058c75..2201fde78 100644 --- a/assets/js/lobbyModerator.js +++ b/assets/js/lobbyModerator.js @@ -155,6 +155,7 @@ function askHangup() { showCancelButton: true, confirmButtonText: hangupText, cancelButtonText: cancel, + heightAuto: false, customClass: { confirmButton: 'btn-danger btn', denyButton: 'btn-danger btn', diff --git a/assets/js/lobbyParticipant.js b/assets/js/lobbyParticipant.js index 129a754c1..6b5efee1c 100644 --- a/assets/js/lobbyParticipant.js +++ b/assets/js/lobbyParticipant.js @@ -266,6 +266,7 @@ function askHangup() { showCancelButton: true, confirmButtonText: hangupText, cancelButtonText: cancel, + heightAuto: false, customClass: { confirmButton: 'btn-danger btn', cancelButton: 'btn-outline-primary btn' diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml index 80c5e7c52..e181b9dd2 100644 --- a/config/packages/twig.yaml +++ b/config/packages/twig.yaml @@ -3,7 +3,9 @@ twig: debug: '%kernel.debug%' strict_variables: '%kernel.debug%' exception_controller: null - form_themes: ['bootstrap_4_layout.html.twig','form/ja_theme.html.twig'] + form_themes: + - 'bootstrap_4_layout.html.twig' + - 'form/ja_theme.html.twig' paths: '%kernel.project_dir%/public/mail/css': css globals: diff --git a/config/services.yaml b/config/services.yaml index c86c417e3..0cfa8237f 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -49,6 +49,7 @@ parameters: LAF_DEFAULT_ONLINE_STATUS: '%env(LAF_DEFAULT_ONLINE_STATUS)%' LAF_FLOATING_TAG_FORCE_SHOW: '%env(LAF_FLOATING_TAG_FORCE_SHOW)%' LAF_RESEND_SUBSCRIPTION_DOUBLE_OPTIN_EMAIL: '%env(LAF_RESEND_SUBSCRIPTION_DOUBLE_OPTIN_EMAIL)%' + LAF_SHOW_CALENDLY: '%env(LAF_SHOW_CALENDLY)%' enterprise_noExternal: '%env(enterprise_noExternal)%' enterprise_theme_url: '%env(enterprise_theme_url)%' diff --git a/package-lock.json b/package-lock.json index 594eae8a8..afd71dd2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,7 +57,9 @@ }, "devDependencies": { "@babel/plugin-proposal-class-properties": "^7.18.6", + "@hotwired/stimulus": "^3.0.0", "@symfony/ux-translator": "file:vendor/symfony/ux-translator/assets", + "@symfony/ux-typed": "file:vendor/symfony/ux-typed/assets", "@symfony/webpack-encore": "^4.0.0", "chromedriver": "^105.0.0", "core-js": "^3.8.1", @@ -66,6 +68,7 @@ "regenerator-runtime": "^0.13.7", "sass-loader": "^13.0.0", "socket.io-client": "^4.6.1", + "typed.js": "^2.0", "webpack-notifier": "^1.12.0" } }, @@ -1986,6 +1989,13 @@ "resolved": "https://registry.npmjs.org/@holema/mdtimepicker/-/mdtimepicker-1.1.0.tgz", "integrity": "sha512-SrYE/AWLqYgqE9FXmnbyPvYGB60Z+mDn+UuKzTcma2ZLEtyzVs8qiKAkZYFPa3M4Z5zsESLFm8kDllSbrMeD2A==" }, + "node_modules/@hotwired/stimulus": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@hotwired/stimulus/-/stimulus-3.2.2.tgz", + "integrity": "sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==", + "dev": true, + "license": "MIT" + }, "node_modules/@interactjs/types": { "version": "1.10.17", "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.17.tgz", @@ -2338,6 +2348,10 @@ "resolved": "vendor/symfony/ux-translator/assets", "link": true }, + "node_modules/@symfony/ux-typed": { + "resolved": "vendor/symfony/ux-typed/assets", + "link": true + }, "node_modules/@symfony/webpack-encore": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@symfony/webpack-encore/-/webpack-encore-4.2.0.tgz", @@ -10968,6 +10982,13 @@ "node": ">= 0.6" } }, + "node_modules/typed.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typed.js/-/typed.js-2.1.0.tgz", + "integrity": "sha512-bDuXEf7YcaKN4g08NMTUM6G90XU25CK3bh6U0THC/Mod/QPKlEt9g/EjvbYB8x2Qwr2p6J6I3NrsoYaVnY6wsQ==", + "dev": true, + "license": "MIT" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -11918,6 +11939,20 @@ "optional": false } } + }, + "vendor/symfony/ux-typed/assets": { + "name": "@symfony/ux-typed", + "version": "2.23.0", + "dev": true, + "license": "MIT", + "devDependencies": { + "@hotwired/stimulus": "^3.0.0", + "typed.js": "^2.0" + }, + "peerDependencies": { + "@hotwired/stimulus": "^3.0.0", + "typed.js": "^2.0" + } } } } diff --git a/package.json b/package.json index 9199b6ff3..cccc28e54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "devDependencies": { "@babel/plugin-proposal-class-properties": "^7.18.6", + "@hotwired/stimulus": "^3.0.0", "@symfony/ux-translator": "file:vendor/symfony/ux-translator/assets", "@symfony/webpack-encore": "^4.0.0", "chromedriver": "^105.0.0", @@ -10,6 +11,7 @@ "regenerator-runtime": "^0.13.7", "sass-loader": "^13.0.0", "socket.io-client": "^4.6.1", + "typed.js": "^2.0", "webpack-notifier": "^1.12.0" }, "license": "UNLICENSED", diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php index f996a5cb1..bcea5870e 100644 --- a/src/Controller/DashboardController.php +++ b/src/Controller/DashboardController.php @@ -79,6 +79,7 @@ public function dashboard( ], ); } + $roomsFuture = $this->doctrine->getRepository(Rooms::class)->findRoomsInFuture($this->getUser()); $r = []; @@ -180,6 +181,14 @@ public function dashboard( } + $res->headers->setCookie( + Cookie::create( + 'is_loggedIn_user', + 1, + time() + (2 * 365 * 24 * 60 * 60), + '/', // Path. + ) + ); return $res; } diff --git a/src/Controller/OwnRoomController.php b/src/Controller/OwnRoomController.php index 89792a831..cf72df380 100644 --- a/src/Controller/OwnRoomController.php +++ b/src/Controller/OwnRoomController.php @@ -27,13 +27,16 @@ class OwnRoomController extends JitsiAdminController { #[Route(path: '/myRoom/start/{uid}', name: 'own_room_startPage')] + #[Route(path: '/room/myRoom/start/{uid}', name: 'own_room_startPage_protected')] public function index($uid, Request $request, RoomService $roomService, TranslatorInterface $translator, StartMeetingService $startMeetingService): Response { + $session = $request->getSession(); $rooms = $this->doctrine->getRepository(Rooms::class)->findOneBy(['uid' => $uid, 'totalOpenRooms' => true]); if (!$rooms) { $this->addFlash('danger', $translator->trans('Konferenz nicht gefunden. Zugangsdaten erneut eingeben')); return $this->redirectToRoute('join_index_no_slug'); } + if (!StartMeetingService::checkTime($rooms)) { $startPrint = $rooms->getTimeZone() ? clone ($rooms->getStartUtc())->setTimeZone(new \DateTimeZone($rooms->getTimeZone())) : $rooms->getStart(); $startPrint->modify('-30min'); @@ -51,7 +54,19 @@ public function index($uid, Request $request, RoomService $roomService, Translat } $data = []; + if (!$this->getUser() && $request->cookies->get('is_loggedIn_user')== 1) { // the user was logged in the past, so we send him to the login page + + if ($session->get('login_attempted')) {// second try + $session->remove('login_attempted'); // Zurücksetzen + $response = $this->redirectToRoute('own_room_startPage',['uid' => $rooms->getUid()]); + $response->headers->clearCookie('is_loggedIn_user'); + return $response; + } + $session->set('login_attempted', true); + return $this->redirectToRoute('own_room_startPage_protected',['uid' => $rooms->getUid()]); + } if ($this->getUser()) { + $session->remove('login_attempted'); // Zurücksetzen $data['name'] = $this->getUser()->getFirstName() . ' ' . $this->getUser()->getLastName(); } elseif ($request->get('name')) { $data['name'] = base64_decode($request->get('name')); diff --git a/src/Controller/PublicConferenceController.php b/src/Controller/PublicConferenceController.php index 08aa6855f..410405abc 100644 --- a/src/Controller/PublicConferenceController.php +++ b/src/Controller/PublicConferenceController.php @@ -50,10 +50,14 @@ public function index(Request $request): Response return $this->redirectToRoute('dashboard'); } $data = [ - 'roomName' => UtilsHelper::readable_random_string(20), + 'server'=>$this->server, + 'roomName' => UtilsHelper::readable_random_string(5), 'myName'=> $this->requestStack->getSession()->get('myName')?:'' ]; $form = $this->createForm(PublicConferenceType::class, $data); + if ($this->server->isLiveKitServer()){ + $form->remove('myName'); + } $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $data = $form->getData(); diff --git a/src/EventListener/OAuthRedirectListener.php b/src/EventListener/OAuthRedirectListener.php new file mode 100644 index 000000000..928e2ae55 --- /dev/null +++ b/src/EventListener/OAuthRedirectListener.php @@ -0,0 +1,41 @@ +getRequest(); + $route = $request->attributes->get('_route'); + + // Nur für bestimmte Pfade aktiv (z. B. beginnt mit /myRoom/start/) + $path = $request->getPathInfo(); + if (!str_starts_with($path, '/myRoom/start/')) { + return; + } + + $cookie = $request->cookies->get('was_logged_in'); + + if ($cookie === '1' && !$request->getSession()->has('oauth_authenticated')) { + // Aktuelle URL merken für Rückleitung + $this->session->set('target_path', $request->getUri()); + + // Weiterleitung zu Keycloak Login + $redirectUrl = $this->router->generate('connect_keycloak_start'); + + $event->setResponse(new RedirectResponse($redirectUrl)); + } + } + +} \ No newline at end of file diff --git a/src/Form/CalendlyTokenType.php b/src/Form/CalendlyTokenType.php index 92006ca57..b9890818b 100644 --- a/src/Form/CalendlyTokenType.php +++ b/src/Form/CalendlyTokenType.php @@ -35,7 +35,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'required' => true, ] ) - ->add('calendly_token', TextareaType::class, ['attr' => ['placeholder' => 'label.calendlyToken'], 'label' => false, 'required' => true, 'translation_domain' => 'form']) + ->add('calendly_token', TextareaType::class, ['attr' => ['placeholder' => 'label.calendlyToken'], 'label' => 'label.calendlyToken', 'required' => true, 'translation_domain' => 'form']) ->add('submit', SubmitType::class, ['attr' => ['class' => 'btn btn-primary'], 'label' => 'label.speichern', 'translation_domain' => 'form']);; } diff --git a/src/Form/Type/AddressGroupType.php b/src/Form/Type/AddressGroupType.php index e76caccc6..609e6936e 100644 --- a/src/Form/Type/AddressGroupType.php +++ b/src/Form/Type/AddressGroupType.php @@ -35,7 +35,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $user = $options['user']; $builder - ->add('name', TextType::class, ['attr' => ['placeholder' => 'label.addressgroupName'], 'label' => false, 'required' => true, 'translation_domain' => 'form']) + ->add('name', TextType::class, ['attr' => ['placeholder' => 'label.addressgroupName'], 'label' => 'label.addressgroupName', 'required' => true, 'translation_domain' => 'form']) ->add( 'member', UserLineType::class, diff --git a/src/Form/Type/JoinMyRoomType.php b/src/Form/Type/JoinMyRoomType.php index 91f656d8e..812494b4d 100644 --- a/src/Form/Type/JoinMyRoomType.php +++ b/src/Form/Type/JoinMyRoomType.php @@ -31,7 +31,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) { $builder - ->add('name', TextType::class, ['attr' => ['placeholder' => 'label.name'], 'label' => false, 'required' => true, 'translation_domain' => 'form']); + ->add('name', TextType::class, ['attr' => ['placeholder' => 'label.name'], 'label' => 'label.name', 'required' => true, 'translation_domain' => 'form']); if ($this->themeService->getApplicationProperties('start_dropdown_allow_browser')) { $builder->add('joinBrowser', SubmitType::class, ['attr' => ['class' => 'btn btn-primary btn-block '], 'label' => 'label.beitretenBrowser', 'translation_domain' => 'form']); diff --git a/src/Form/Type/JoinViewType.php b/src/Form/Type/JoinViewType.php index 1c573eba4..6be949d71 100644 --- a/src/Form/Type/JoinViewType.php +++ b/src/Form/Type/JoinViewType.php @@ -31,9 +31,9 @@ public function buildForm(FormBuilderInterface $builder, array $options) { $builder - ->add('uid', TextType::class, ['attr' => ['placeholder' => 'label.konferenzId'], 'label' => false, 'required' => true, 'translation_domain' => 'form']) - ->add('email', TextType::class, ['attr' => ['placeholder' => 'label.email'], 'label' => false, 'required' => true, 'translation_domain' => 'form']) - ->add('name', TextType::class, ['attr' => ['placeholder' => 'label.name'], 'label' => false, 'required' => true, 'translation_domain' => 'form']); + ->add('uid', TextType::class, ['attr' => ['placeholder' => 'label.konferenzId'], 'label' => 'label.konferenzId', 'required' => true, 'translation_domain' => 'form']) + ->add('email', TextType::class, ['attr' => ['placeholder' => 'label.email'], 'label' => 'label.email', 'required' => true, 'translation_domain' => 'form']) + ->add('name', TextType::class, ['attr' => ['placeholder' => 'label.name'], 'label' => 'label.name', 'required' => true, 'translation_domain' => 'form']); if ($this->themeService->getApplicationProperties('start_dropdown_allow_browser')) { $builder->add('joinBrowser', SubmitType::class, ['attr' => ['class' => 'btn btn-primary btn-block '], 'label' => 'label.beitretenBrowser', 'translation_domain' => 'form']); } diff --git a/src/Form/Type/PublicConferenceType.php b/src/Form/Type/PublicConferenceType.php index 742e3d871..e141f646c 100644 --- a/src/Form/Type/PublicConferenceType.php +++ b/src/Form/Type/PublicConferenceType.php @@ -24,9 +24,10 @@ class PublicConferenceType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { + $builder - ->add('myName', TextType::class, ['attr' => ['placeholder' => 'label.myName'], 'label' => false, 'required' => true, 'translation_domain' => 'form']) - ->add('roomName', TextType::class, ['attr' => ['class' => 'mt-3','placeholder' => 'label.konferenzName'], 'label' => false, 'required' => true, 'translation_domain' => 'form']) + ->add('myName', TextType::class, ['attr' => ['placeholder' => 'label.myName'], 'label' => 'label.myName', 'required' => true, 'translation_domain' => 'form']) + ->add('roomName', TextType::class, ['attr' => ['class' => 'mt-3','placeholder' => 'label.konferenzName'], 'label' => 'label.konferenzName', 'required' => true, 'translation_domain' => 'form']) ->add('submit', SubmitType::class, array('attr' => array('class' => 'btn btn-outline-primary btn-block mt-3'), 'label' => 'label.go', 'translation_domain' => 'form'),); } diff --git a/src/Form/Type/PublicRegisterType.php b/src/Form/Type/PublicRegisterType.php index 9298a9802..635a61ce6 100644 --- a/src/Form/Type/PublicRegisterType.php +++ b/src/Form/Type/PublicRegisterType.php @@ -22,9 +22,9 @@ public function buildForm(FormBuilderInterface $builder, array $options) { $builder - ->add('firstName', TextType::class, ['attr' => ['placeholder' => 'label.vorname'], 'label' => false, 'required' => true, 'translation_domain' => 'form']) - ->add('lastName', TextType::class, ['attr' => ['placeholder' => 'label.nachname'], 'label' => false, 'required' => true, 'translation_domain' => 'form']) - ->add('email', TextType::class, ['attr' => ['placeholder' => 'label.email'], 'label' => false, 'required' => true, 'translation_domain' => 'form']) + ->add('firstName', TextType::class, ['attr' => ['placeholder' => 'label.vorname'], 'label' => 'label.vorname', 'required' => true, 'translation_domain' => 'form']) + ->add('lastName', TextType::class, ['attr' => ['placeholder' => 'label.nachname'], 'label' => 'label.nachname', 'required' => true, 'translation_domain' => 'form']) + ->add('email', TextType::class, ['attr' => ['placeholder' => 'label.email'], 'label' => 'label.email', 'required' => true, 'translation_domain' => 'form']) ->add('subscribe', SubmitType::class, ['attr' => ['class' => 'btn btn-primary btn-block '], 'label' => 'label.subscribe', 'translation_domain' => 'form']); } diff --git a/src/Form/Type/RepeaterType.php b/src/Form/Type/RepeaterType.php index eaa320186..a52516552 100644 --- a/src/Form/Type/RepeaterType.php +++ b/src/Form/Type/RepeaterType.php @@ -61,10 +61,10 @@ public function buildForm(FormBuilderInterface $builder, array $options) // 'multiple' => true, // 'translation_domain' => 'form' // ]) - ->add('repeaterDays', NumberType::class, ['label' => false, 'required' => false, 'attr' => ['placeholder' => 'label.repeaterDays'], 'translation_domain' => 'form']) - ->add('repeaterWeeks', NumberType::class, ['label' => false, 'required' => false, 'attr' => ['placeholder' => 'label.repeaterWeeks'], 'translation_domain' => 'form']) - ->add('repeatMontly', NumberType::class, ['label' => false, 'required' => false, 'attr' => ['placeholder' => 'label.repeatMontly'], 'translation_domain' => 'form']) - ->add('repeatYearly', NumberType::class, ['label' => false, 'required' => false, 'attr' => ['placeholder' => 'label.repeatYearly'], 'translation_domain' => 'form']) + ->add('repeaterDays', NumberType::class, ['label' => 'label.repeaterDays', 'required' => false, 'attr' => ['placeholder' => 'label.repeaterDays'], 'translation_domain' => 'form']) + ->add('repeaterWeeks', NumberType::class, ['label' => 'label.repeaterWeeks', 'required' => false, 'attr' => ['placeholder' => 'label.repeaterWeeks'], 'translation_domain' => 'form']) + ->add('repeatMontly', NumberType::class, ['label' => 'label.repeatMontly', 'required' => false, 'attr' => ['placeholder' => 'label.repeatMontly'], 'translation_domain' => 'form']) + ->add('repeatYearly', NumberType::class, ['label' => 'label.repeatYearly', 'required' => false, 'attr' => ['placeholder' => 'label.repeatYearly'], 'translation_domain' => 'form']) ->add( 'repatMonthRelativNumber', ChoiceType::class, @@ -95,7 +95,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'label' => 'label.montlyRelativeWeekday', 'translation_domain' => 'form'] ) - ->add('repeatMonthlyRelativeHowOften', NumberType::class, ['label' => false, 'required' => false, 'attr' => ['placeholder' => 'label.repeatMontly'], 'translation_domain' => 'form']) + ->add('repeatMonthlyRelativeHowOften', NumberType::class, ['label' => 'label.repeatMontly', 'required' => false, 'attr' => ['placeholder' => 'label.repeatMontly'], 'translation_domain' => 'form']) ->add( 'repeatYearlyRelativeNumber', ChoiceType::class, @@ -147,8 +147,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'label' => 'label.montlyRelativeMonth', 'translation_domain' => 'form'] ) - ->add('repeatYearlyRelativeHowOften', NumberType::class, ['label' => false, 'required' => false, 'attr' => ['placeholder' => 'label.repeatYearly'], 'translation_domain' => 'form']) - ->add('repetation', NumberType::class, ['label' => false, 'required' => true, 'attr' => ['placeholder' => 'label.repetation'], 'translation_domain' => 'form']) + ->add('repeatYearlyRelativeHowOften', NumberType::class, ['label' => 'label.repeatYearly', 'required' => false, 'attr' => ['placeholder' => 'label.repeatYearly'], 'translation_domain' => 'form']) + ->add('repetation', NumberType::class, ['label' => 'label.repetation', 'required' => true, 'attr' => ['placeholder' => 'label.repetation'], 'translation_domain' => 'form']) ->add('submit', SubmitType::class, ['attr' => ['class' => 'btn btn-outline-primary'], 'label' => 'label.speichern', 'translation_domain' => 'form']); } diff --git a/src/Service/webhook/RoomWebhookService.php b/src/Service/webhook/RoomWebhookService.php index 07a3fadad..099da6df2 100644 --- a/src/Service/webhook/RoomWebhookService.php +++ b/src/Service/webhook/RoomWebhookService.php @@ -45,7 +45,7 @@ public function startWebhook($data): ?string case 'muc-room-created': $res = $this->roomCreated( $data['room_name'], - $data['is_breakout'], + $data['is_breakout']??null, $data['breakout_room_id'] ?? null, $data['room_jid'], $data['created_at'] @@ -53,7 +53,7 @@ public function startWebhook($data): ?string break; case 'muc-room-destroyed': $res = $this->roomDestroyed( - $data['is_breakout'], + $data['is_breakout']??null, $data['breakout_room_id'] ?? null, $data['room_jid'], $data['destroyed_at'] @@ -61,7 +61,7 @@ public function startWebhook($data): ?string break; case 'muc-occupant-joined': $res = $this->roomParticipantJoin( - $data['is_breakout'], + $data['is_breakout']??null, $data['breakout_room_id'] ?? null, $data['room_jid'], $data['occupant']['occupant_jid'], @@ -72,7 +72,7 @@ public function startWebhook($data): ?string break; case 'muc-occupant-left': $res = $this->roomParticipantLeft( - $data['is_breakout'], + $data['is_breakout']??null, $data['breakout_room_id'] ?? null, $data['occupant']['occupant_jid'], $data['occupant']['left_at'], diff --git a/src/UtilsHelper.php b/src/UtilsHelper.php index 4b542fdc2..73a5d438d 100644 --- a/src/UtilsHelper.php +++ b/src/UtilsHelper.php @@ -25,20 +25,87 @@ public static function slugifywithDot($urlString) public static function readable_random_string($length = 6) { - $string = ''; - $vowels = array("a", "e", "i", "o", "u"); - $consonants = array( - 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', - 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z' - ); - - $max = $length / 2; - for ($i = 1; $i <= $max; $i++) { - $string .= $consonants[rand(0, 19)]; - $string .= $vowels[rand(0, 4)]; - } - - return $string; + $nouns = [ + 'cat', 'dog', 'robot', 'moon', 'tree', 'fish', 'flower', 'cloud', 'book', 'child', + 'star', 'mountain', 'river', 'stone', 'ocean', 'leaf', 'sun', 'window', 'dream', 'car', + 'ghost', 'house', 'hat', 'bottle', 'field', 'forest', 'shoe', 'mirror', 'sky', 'train', + 'music', 'door', 'chair', 'phone', 'apple', 'banana', 'monster', 'lamp', 'table', 'dragon', + 'storm', 'road', 'tiger', 'pencil', 'beach', 'pirate', 'camera', 'castle', 'guitar', 'keyboard', + 'socks', 'tunnel', 'planet', 'rabbit', 'wizard', 'balloon', 'shadow', 'message', 'engine', 'helicopter', + 'plane', 'ball', 'basket', 'clock', 'toaster', 'engineer', 'rocket', 'helmet', 'card', 'potion', + 'map', 'snowflake', 'arrow', 'cup', 'flame', 'ladder', 'cookie', 'cave', 'fire', 'whale', + 'feather', 'bubble', 'coin', 'circle', 'paint', 'sign', 'rope', 'suitcase', 'ship', 'lantern', + 'flag', 'wall', 'gem', 'quill', 'net', 'bridge', 'crown', 'bookcase', 'bell', 'breeze', + 'sandwich', 'telescope', 'owl', 'raven', 'duck', 'flock', 'nest', 'branch', 'seed', 'root', + 'note', 'flute', 'violin', 'portal', 'gate', 'key', 'lock', 'nail', 'glove', 'hammer', + 'brush', 'shell', 'chessboard', 'candle', 'box', 'tower', 'island', 'wave', 'glow', 'bug', + 'circuit', 'screen', 'wheel', 'gear', 'code', 'laser', 'crystal', 'sock', 'wire', 'spring', + 'nut', 'bolt', 'fountain', 'hose', 'dust', 'ink', 'sponge', 'torch', 'antenna', 'radar', + 'fog', 'glitch', 'pixel', 'echo', 'sound', 'trail', 'mist', 'beam', 'flare', 'spark', + 'ring', 'chain', 'vine', 'iceberg', 'tent', 'ballpit', 'mushroom', 'hammock', 'beetle', 'pillow' + ]; + + $adjectives = [ + 'blue', 'green', 'quiet', 'strange', 'tiny', 'lazy', 'brave', 'happy', 'fuzzy', 'bright', + 'shiny', 'cold', 'hot', 'warm', 'gentle', 'wild', 'soft', 'hard', 'silent', 'loud', + 'fast', 'slow', 'ancient', 'modern', 'funny', 'sad', 'angry', 'weird', 'friendly', 'fierce', + 'bold', 'timid', 'rich', 'poor', 'young', 'old', 'massive', 'small', 'giant', 'sharp', + 'dull', 'golden', 'silver', 'broken', 'new', 'used', 'rusty', 'clean', 'dirty', 'sparkling', + 'dark', 'light', 'purple', 'yellow', 'orange', 'pink', 'red', 'black', 'white', 'gray', + 'striped', 'spotted', 'fluffy', 'hairy', 'bald', 'spiky', 'sneaky', 'clumsy', 'sleepy', 'alert', + 'magical', 'mystic', 'robotic', 'natural', 'round', 'square', 'triangular', 'flat', 'hollow', 'solid', + 'creaky', 'noisy', 'icy', 'burning', 'wet', 'dry', 'sticky', 'smooth', 'rough', 'bumpy', + 'twisted', 'melting', 'frozen', 'alive', 'dead', 'electric', 'solar', 'mechanical', 'digital', 'analog', + 'playful', 'serious', 'curious', 'shy', 'wise', 'clever', 'lucky', 'unlucky', 'calm', 'stormy', + 'hectic', 'peaceful', 'fearless', 'colorful', 'cloudy', 'sunny', 'windy', 'dusty', 'muddy', 'greasy', + 'fragrant', 'smelly', 'tasty', 'bitter', 'sweet', 'sour', 'salty', 'savory', 'juicy', 'dry', + 'crunchy', 'chewy', 'bland', 'spicy', 'burnt', 'raw', 'cooked', 'boiled', 'fried', 'grilled', + 'steamed', 'baked', 'roasted', 'frozen', 'chilled', 'warm', 'cozy', 'drafty', 'humid', 'icy', + 'stormy', 'snowy', 'rainy', 'foggy', 'misty', 'clear', 'blazing', 'glowing', 'dim', 'twinkling' + ]; + + $verbs = [ + 'jumps', 'runs', 'flies', 'sleeps', 'dances', 'floats', 'hides', 'sings', 'crawls', 'spins', + 'rolls', 'slides', 'dives', 'climbs', 'skips', 'wanders', 'travels', 'glows', 'explodes', 'screams', + 'whispers', 'laughs', 'cries', 'smiles', 'shakes', 'builds', 'destroys', 'paints', 'writes', 'draws', + 'blinks', 'waves', 'drives', 'bakes', 'burns', 'eats', 'drinks', 'sits', 'stands', 'waits', + 'listens', 'hears', 'sees', 'touches', 'grabs', 'throws', 'catches', 'pushes', 'pulls', 'breaks', + 'fixes', 'turns', 'opens', 'closes', 'locks', 'unlocks', 'connects', 'disconnects', 'charges', 'zaps', + 'programs', 'downloads', 'uploads', 'types', 'codes', 'transforms', 'melts', 'freezes', 'evaporates', 'grows', + 'shrinks', 'multiplies', 'divides', 'fades', 'flashes', 'vibrates', 'glitches', 'buzzes', 'rings', 'echoes', + 'flickers', 'crashes', 'spreads', 'collapses', 'emerges', 'vanishes', 'appears', 'hovers', 'drifts', 'storms', + 'rains', 'snows', 'thunders', 'booms', 'bounces', 'twists', 'shines', 'spits', 'howls', 'claps', + 'cheers', 'groans', 'moans', 'rattles', 'snaps', 'squeaks', 'snores', 'yawns', 'gulps', 'growls', + 'chirps', 'croaks', 'bleats', 'roars', 'meows', 'barks', 'quacks', 'neighs', 'oinks', 'buzzes', + 'clicks', 'ticks', 'beeps', 'whistles', 'chants', 'murmurs', 'hums', 'clunks', 'zips', 'plops' + ]; + + $prepositions = [ + 'under', 'over', 'behind', 'beside', 'on', 'near', 'above', 'below', 'between', 'within', + 'around', 'across', 'against', 'through', 'into', 'out of', 'next to', 'in front of', 'beneath', 'at', + 'by', 'with', 'without', 'before', 'after', 'along', 'towards', 'onto', 'off', 'beyond', + 'amid', 'among', 'inside', 'outside', 'around', 'upon', 'down', 'up', 'past', 'alongside', + 'opposite', 'nearby', 'beneath', 'underneath', 'in', 'on top of', 'about', 'concerning', 'despite', 'during', + 'except', 'like', 'unlike', 'via', 'per', 'amidst', 'amongst', 'notwithstanding', 'since', 'till', + 'throughout', 'to', 'toward', 'underneath', 'versus', 'via', 'within', 'without', 'as', 'barring', + 'counting', 'following', 'excluding', 'including', 'notwithstanding', 'regarding', 'respecting', 'save', 'than', 'until', + 'versus', 'upon', 'aboard', 'across from', 'ahead of', 'apart from', 'as far as', 'as of', 'as well as', 'aside from', + 'atop', 'because of', 'close to', 'due to', 'far from', 'inside of', 'near to', 'next to', 'on behalf of', 'on top of', + 'out from', 'outside of', 'prior to', 'pursuant to', 'rather than', 'subsequent to', 'such as', 'thanks to', 'together with', 'up to' + ]; + + // Pick random words + $adj1 = $adjectives[array_rand($adjectives)]; + $noun1 = $nouns[array_rand($nouns)]; + $verb = $verbs[array_rand($verbs)]; + $prep = $prepositions[array_rand($prepositions)]; + $adj2 = $adjectives[array_rand($adjectives)]; + $noun2 = $nouns[array_rand($nouns)]; + + // Build sentence + $sentence = "The $adj1 $noun1 $verb $prep the $adj2 $noun2"; + + return ucfirst($sentence); } public static function isAllowedToOrganizeRoom(?User $user, ?Rooms $room): bool diff --git a/templates/base/__profileModal.html.twig b/templates/base/__profileModal.html.twig index 74aee567e..107966877 100644 --- a/templates/base/__profileModal.html.twig +++ b/templates/base/__profileModal.html.twig @@ -158,6 +158,8 @@
    {% endif %} + + {% if getApplicationProperties('LAF_SHOW_CALENDLY') != false %}
    {{ 'calendly.header'|trans }}
    @@ -173,6 +175,7 @@
    {{'calendly.connection.connected'|trans }}
    {{ 'callendly.disconnect'|trans }} {% endif %} + {% endif %}
    diff --git a/templates/conference_modules/conferenceSidebar.html.twig b/templates/conference_modules/conferenceSidebar.html.twig index 5f8763bb4..f6b4f9311 100644 --- a/templates/conference_modules/conferenceSidebar.html.twig +++ b/templates/conference_modules/conferenceSidebar.html.twig @@ -1,4 +1,3 @@ - {% set logo_small = httpsAbolutUrl(asset('logo_small.png')) %} {% if server is defined and server is not null and server.logoUrl is not null %} @@ -21,26 +20,28 @@ var schowNameInWidgets = "{{ user|nameOfUserNoSymbol }}"; {% endif %} - +
    {% if room is defined and room is not null %} - {% if room.server.disableChat != true %} + {% if not room.server.liveKitServer %} + {% if room.server.disableChat != true %} -
    -
    - -
    -
    -
    - {{ 'options.chat'|trans }} +
    +
    + +
    +
    +
    + {{ 'options.chat'|trans }} +
    -
    + {% endif %} {% endif %} {% endif %} @@ -76,19 +77,19 @@ {% if getApplicationProperties('LAF_LOOKYLOOKY_FUNCTION') == 1 %} -
    -
    - +
    +
    + -
    -
    - {{ 'options.whiteboard'|trans }} -
    -
    +
    +
    + {{ 'options.whiteboard'|trans }} +
    +
    {% endif %} {% if getApplicationProperties('LAF_ETHERPAD_FUNCTION') == 1 %} @@ -124,7 +125,7 @@ {% endif %} {% block extension %}{% endblock %} {% if not room.server.liveKitServer %} - {% include 'conference_modules/__toggleFilmstripe.html.twig' %} + {% include 'conference_modules/__toggleFilmstripe.html.twig' %} {% endif %} {% if room.server.liveKitServer %} {% include 'conference_modules/__livekit_recording.html.twig' %} diff --git a/templates/form/ja_theme.html.twig b/templates/form/ja_theme.html.twig index e69de29bb..8f8995e50 100644 --- a/templates/form/ja_theme.html.twig +++ b/templates/form/ja_theme.html.twig @@ -0,0 +1,49 @@ +{% block form_row -%} + {%- if compound is defined and compound -%} + {%- set element = 'fieldset' -%} + {%- endif -%} + {%- set widget_attr = {} -%} + {%- if help is not empty -%} + {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} + {%- endif -%} + <{{ element|default('div') }}{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}> + + {{- form_widget(form, widget_attr) -}} + {{- form_help(form) -}} + +{%- endblock form_row %} +{% block text_widget %} +
    + {% set id = form.vars.id %} + {% set attr = attr|merge({'class': (attr.class|default('') ~ ' form-control form-control-lg')|trim}) %} + {{ block('form_widget_simple') }} + +
    +{% endblock %} + +{% block email_widget %} + {{ block('text_widget') }} +{% endblock %} + +{% block number_widget %} + {{ block('text_widget') }} +{% endblock %} + +{# Optional: textarea, password, search, etc. #} +{% block textarea_widget %} +
    + + + +
    +{% endblock %} + +{% block password_widget %} + {{ block('text_widget') }} +{% endblock %} \ No newline at end of file diff --git a/templates/lobby/__lobbyParticipants.html.twig b/templates/lobby/__lobbyParticipants.html.twig index dd0cb8885..a255a493e 100644 --- a/templates/lobby/__lobbyParticipants.html.twig +++ b/templates/lobby/__lobbyParticipants.html.twig @@ -45,15 +45,11 @@
    @@ -62,8 +58,7 @@