add option to create an adhoc link

This commit is contained in:
stefan.tollkuehn committed 2026-10-01 00:08:18 +02:00
1 parent a1a9733b8f
commit 143856d51b
1 file changed
+124 -1
+124 -1
View File
@@ -249,6 +249,29 @@
color: #0066cc; color: #0066cc;
} }
.adhoc-result {
margin-top: 24px;
padding: 16px;
border-radius: 8px;
background: #f0fff4;
color: #1a7f37;
}
.adhoc-link {
margin-top: 12px;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
flex-wrap: wrap;
}
.adhoc-link a {
font-family: monospace;
word-break: break-all;
color: #0066cc;
}
@keyframes spin { @keyframes spin {
to { to {
transform: rotate(360deg); transform: rotate(360deg);
@@ -315,6 +338,15 @@
background: #1a3a5a; background: #1a3a5a;
color: #99ccff; color: #99ccff;
} }
:root.dark .adhoc-result {
background: #1c3527;
color: #7ee2a8;
}
:root.dark .adhoc-link a {
color: #99ccff;
}
</style> </style>
</head> </head>
@@ -549,10 +581,21 @@
<button id="createMeetingButton" class="button primary" type="button" data-i18n="creator.createButton"> <button id="createMeetingButton" class="button primary" type="button" data-i18n="creator.createButton">
Create Meeting Create Meeting
</button> </button>
<button id="createAdhocButton" class="button secondary" type="button" data-i18n="creator.adhocButton">
Create Adhoc Link
</button>
<button id="cancelCreateButton" class="button secondary" type="button" data-i18n="creator.cancelButton"> <button id="cancelCreateButton" class="button secondary" type="button" data-i18n="creator.cancelButton">
Cancel Cancel
</button> </button>
</div> </div>
<div id="adhocResult" class="adhoc-result hidden">
<span data-i18n="creator.adhocLinkLabel">Your adhoc meeting link:</span>
<div class="adhoc-link">
<a id="adhocLink" target="_blank" rel="noopener noreferrer"></a>
<button id="copyAdhocLinkButton" class="button secondary" type="button" data-i18n="creator.copyLinkButton">Copy Link</button>
</div>
</div>
<div id="icsSuccess" class="success-message hidden"> <div id="icsSuccess" class="success-message hidden">
<span data-i18n="creator.successMessage">Meeting created! Download your calendar file and open it to import the meeting into your personal calendar.</span> <span data-i18n="creator.successMessage">Meeting created! Download your calendar file and open it to import the meeting into your personal calendar.</span>
@@ -685,6 +728,10 @@
successMessage: "Meeting created! Download your calendar file and open it to import the meeting into your personal calendar.", successMessage: "Meeting created! Download your calendar file and open it to import the meeting into your personal calendar.",
downloadButton: "Download ICS File", downloadButton: "Download ICS File",
createNewButton: "Create New Meeting", createNewButton: "Create New Meeting",
adhocButton: "Create Adhoc Link",
adhocLinkLabel: "Your adhoc meeting link:",
copyLinkButton: "Copy Link",
copiedLabel: "Copied!",
meetingNameRequired: "Please enter a meeting name", meetingNameRequired: "Please enter a meeting name",
meetingNameInvalid: "Meeting name may only contain letters, numbers and hyphens", meetingNameInvalid: "Meeting name may only contain letters, numbers and hyphens",
startTimeRequired: "Please select a start time", startTimeRequired: "Please select a start time",
@@ -775,6 +822,10 @@
successMessage: "Meeting erstellt! Laden Sie Ihre Kalenderdatei herunter und öffnen Sie diese, um das Meeting in Ihren persönlichen Kalender zu importieren.", successMessage: "Meeting erstellt! Laden Sie Ihre Kalenderdatei herunter und öffnen Sie diese, um das Meeting in Ihren persönlichen Kalender zu importieren.",
downloadButton: "ICS-Datei herunterladen", downloadButton: "ICS-Datei herunterladen",
createNewButton: "Neues Meeting erstellen", createNewButton: "Neues Meeting erstellen",
adhocButton: "Adhoc-Link erstellen",
adhocLinkLabel: "Ihr Adhoc-Meeting-Link:",
copyLinkButton: "Link kopieren",
copiedLabel: "Kopiert!",
meetingNameRequired: "Bitte geben Sie einen Meeting-Namen ein", meetingNameRequired: "Bitte geben Sie einen Meeting-Namen ein",
meetingNameInvalid: "Der Meeting-Name darf nur Buchstaben, Zahlen und Bindestriche enthalten", meetingNameInvalid: "Der Meeting-Name darf nur Buchstaben, Zahlen und Bindestriche enthalten",
startTimeRequired: "Bitte wählen Sie eine Startzeit", startTimeRequired: "Bitte wählen Sie eine Startzeit",
@@ -864,6 +915,10 @@
successMessage: "Réunion créée ! Téléchargez votre fichier calendrier et ouvrez-le pour importer la réunion dans votre calendrier personnel.", successMessage: "Réunion créée ! Téléchargez votre fichier calendrier et ouvrez-le pour importer la réunion dans votre calendrier personnel.",
downloadButton: "Télécharger le fichier ICS", downloadButton: "Télécharger le fichier ICS",
createNewButton: "Créer une nouvelle réunion", createNewButton: "Créer une nouvelle réunion",
adhocButton: "Créer un lien adhoc",
adhocLinkLabel: "Votre lien de réunion adhoc :",
copyLinkButton: "Copier le lien",
copiedLabel: "Copié !",
meetingNameRequired: "Veuillez entrer un nom de réunion", meetingNameRequired: "Veuillez entrer un nom de réunion",
meetingNameInvalid: "Le nom de la réunion ne peut contenir que des lettres, des chiffres et des tirets", meetingNameInvalid: "Le nom de la réunion ne peut contenir que des lettres, des chiffres et des tirets",
startTimeRequired: "Veuillez sélectionner une heure de début", startTimeRequired: "Veuillez sélectionner une heure de début",
@@ -947,6 +1002,10 @@
successMessage: "会议已创建!请下载您的日历文件并打开它,将会议导入您的个人日历。", successMessage: "会议已创建!请下载您的日历文件并打开它,将会议导入您的个人日历。",
downloadButton: "下载 ICS 文件", downloadButton: "下载 ICS 文件",
createNewButton: "创建新会议", createNewButton: "创建新会议",
adhocButton: "创建临时链接",
adhocLinkLabel: "您的临时会议链接:",
copyLinkButton: "复制链接",
copiedLabel: "已复制!",
meetingNameRequired: "请输入会议名称", meetingNameRequired: "请输入会议名称",
meetingNameInvalid: "会议名称只能包含字母、数字和连字符", meetingNameInvalid: "会议名称只能包含字母、数字和连字符",
startTimeRequired: "请选择开始时间", startTimeRequired: "请选择开始时间",
@@ -1243,9 +1302,13 @@
const meetingEndInput = document.getElementById("meetingEnd"); const meetingEndInput = document.getElementById("meetingEnd");
const meetingOrganizerInput = document.getElementById("meetingOrganizer"); const meetingOrganizerInput = document.getElementById("meetingOrganizer");
const createMeetingButton = document.getElementById("createMeetingButton"); const createMeetingButton = document.getElementById("createMeetingButton");
const createAdhocButton = document.getElementById("createAdhocButton");
const cancelCreateButton = document.getElementById("cancelCreateButton"); const cancelCreateButton = document.getElementById("cancelCreateButton");
const icsSuccess = document.getElementById("icsSuccess"); const icsSuccess = document.getElementById("icsSuccess");
const downloadIcsLink = document.getElementById("downloadIcsLink"); const downloadIcsLink = document.getElementById("downloadIcsLink");
const adhocResult = document.getElementById("adhocResult");
const adhocLink = document.getElementById("adhocLink");
const copyAdhocLinkButton = document.getElementById("copyAdhocLinkButton");
/* Language menu DOM elements */ /* Language menu DOM elements */
const langMenu = document.getElementById("langMenu"); const langMenu = document.getElementById("langMenu");
@@ -1778,6 +1841,7 @@ END:VCALENDAR`;
meetingEndInput.value = ''; meetingEndInput.value = '';
meetingOrganizerInput.value = ''; meetingOrganizerInput.value = '';
icsSuccess.classList.add("hidden"); icsSuccess.classList.add("hidden");
adhocResult.classList.add("hidden");
/* Set default start and end times */ /* Set default start and end times */
const start = roundMinutes(new Date()); const start = roundMinutes(new Date());
@@ -1843,11 +1907,60 @@ END:VCALENDAR`;
/* Show success message */ /* Show success message */
icsSuccess.classList.remove("hidden"); icsSuccess.classList.remove("hidden");
adhocResult.classList.add("hidden");
/* Scroll to success message */ /* Scroll to success message */
icsSuccess.scrollIntoView({ behavior: 'smooth' }); icsSuccess.scrollIntoView({ behavior: 'smooth' });
} }
/* ============================================================
* ADHOC LINK
* ============================================================
*/
function createAdhocLink() {
const meetingName = meetingNameInput.value.trim();
if (!meetingName) {
alert(getTranslation('creator.meetingNameRequired') || 'Please enter a meeting name');
return;
}
if (!ROOM_PATTERN.test(createRoomName(meetingName))) {
alert(getTranslation('creator.meetingNameInvalid') || 'Meeting name may only contain letters, numbers and hyphens');
return;
}
const roomName = createRoomName(meetingName);
const url = `https://${CONFIG.jitsiLauncher}/launch.html?room=${encodeURIComponent(roomName)}`;
adhocLink.href = url;
adhocLink.textContent = url;
icsSuccess.classList.add("hidden");
adhocResult.classList.remove("hidden");
adhocResult.scrollIntoView({ behavior: 'smooth' });
}
async function copyAdhocLink() {
const url = adhocLink.href;
try {
await navigator.clipboard.writeText(url);
} catch (error) {
const input = document.createElement('textarea');
input.value = url;
document.body.appendChild(input);
input.select();
document.execCommand('copy');
document.body.removeChild(input);
}
copyAdhocLinkButton.textContent = getTranslation('creator.copiedLabel') || 'Copied!';
setTimeout(() => {
copyAdhocLinkButton.textContent = getTranslation('creator.copyLinkButton') || 'Copy Link';
}, 2000);
}
function cancelCreateMeeting() { function cancelCreateMeeting() {
meetingCreator.classList.add("hidden"); meetingCreator.classList.add("hidden");
@@ -1980,6 +2093,16 @@ END:VCALENDAR`;
createMeeting createMeeting
); );
createAdhocButton.addEventListener(
"click",
createAdhocLink
);
copyAdhocLinkButton.addEventListener(
"click",
copyAdhocLink
);
cancelCreateButton.addEventListener( cancelCreateButton.addEventListener(
"click", "click",
cancelCreateMeeting cancelCreateMeeting