mirror of
https://github.com/suitenumerique/meet.git
synced 2026-07-26 11:58:53 +00:00
🚸(addon) switch add button to remove when a link already exists
From the task panel, change the "add" button to "remove" when a meeting link is already present. This will be updated to "update" once the external API supports updating an existing room.
This commit is contained in:
committed by
aleb_the_flash
parent
321cb99f82
commit
09dbb250a7
@@ -42,4 +42,66 @@ function _containsMeetingUrl(text) {
|
||||
return text.includes(BASE_URL);
|
||||
}
|
||||
|
||||
module.exports = { isMeetingAlreadyAdded };
|
||||
function removeMeetingLink(item) {
|
||||
return Promise.all([_removeFromBody(item), _removeFromLocation(item)]);
|
||||
}
|
||||
|
||||
function _removeFromBody(item) {
|
||||
return new Promise((resolve) => {
|
||||
item.body.getAsync(Office.CoercionType.Html, (result) => {
|
||||
if (result.status !== Office.AsyncResultStatus.Succeeded) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const cleaned = _cleanBody(result.value || "");
|
||||
if (cleaned === null) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
item.body.setAsync(cleaned, { coercionType: Office.CoercionType.Html }, () => resolve());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function _removeFromLocation(item) {
|
||||
if (item.itemType !== Office.MailboxEnums.ItemType.Appointment) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
item.location.getAsync((result) => {
|
||||
if (
|
||||
result.status === Office.AsyncResultStatus.Succeeded &&
|
||||
_containsMeetingUrl(result.value)
|
||||
) {
|
||||
item.location.setAsync("", () => resolve());
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const SEPARATOR = /─{10,}/;
|
||||
|
||||
/**
|
||||
* Returns cleaned HTML, or null if no meeting block was found.
|
||||
*/
|
||||
function _cleanBody(html) {
|
||||
const doc = new DOMParser().parseFromString(html, "text/html");
|
||||
|
||||
const hits = [];
|
||||
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
|
||||
while (walker.nextNode()) {
|
||||
if (SEPARATOR.test(walker.currentNode.nodeValue)) hits.push(walker.currentNode);
|
||||
}
|
||||
if (hits.length < 2) return null;
|
||||
|
||||
const range = doc.createRange();
|
||||
range.setStartBefore(hits[0]);
|
||||
range.setEndAfter(hits[hits.length - 1]);
|
||||
range.deleteContents();
|
||||
|
||||
return doc.documentElement.outerHTML;
|
||||
}
|
||||
|
||||
module.exports = { isMeetingAlreadyAdded, removeMeetingLink };
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
"link_inserted": "Besprechungslink erfolgreich eingefügt",
|
||||
"generating": "Wird erstellt...",
|
||||
"add_meeting": "{{app_name}}-Besprechung hinzufügen",
|
||||
"remove_meeting": "{{app_name}}-Besprechung entfernen",
|
||||
"removing": "Wird entfernt...",
|
||||
"error": {
|
||||
"auth": "Ihre Sitzung ist abgelaufen. Bitte versuchen Sie es erneut.",
|
||||
"retry": "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.",
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
"link_inserted": "Meeting link inserted successfully",
|
||||
"generating": "Generating...",
|
||||
"add_meeting": "Add a {{app_name}} meeting",
|
||||
"remove_meeting": "Remove the {{app_name}} meeting",
|
||||
"removing": "Removing...",
|
||||
"error": {
|
||||
"auth": "Your session has expired. Please try again.",
|
||||
"retry": "An error occurred. Please try again.",
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
"link_inserted": "Lien de réunion inséré avec succès",
|
||||
"generating": "Génération...",
|
||||
"add_meeting": "Ajouter une réunion {{app_name}}",
|
||||
"remove_meeting": "Supprimer la réunion {{app_name}}",
|
||||
"removing": "Suppression en cours...",
|
||||
"error": {
|
||||
"auth": "Connexion expirée, veuillez réessayer.",
|
||||
"retry": "Une erreur est survenue, veuillez ré-essayer",
|
||||
|
||||
@@ -115,6 +115,29 @@ button {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* ── Danger button (remove meeting) ── */
|
||||
|
||||
#btn-remove {
|
||||
background-color: #CA3632; /* error.400 */
|
||||
color: #FFFFFF;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#btn-remove:hover {
|
||||
background-color: #EE6A66; /* error.600 */
|
||||
}
|
||||
|
||||
#btn-remove:active {
|
||||
background-color: #F28D8A; /* error.700 */
|
||||
color: #F6AFAD; /* error.200 */
|
||||
}
|
||||
|
||||
#btn-remove:disabled {
|
||||
background-color: #F6AFAD; /* error.800 */
|
||||
color: #FAD2D1; /* error.900 */
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* ── Version ── */
|
||||
|
||||
#version-tag {
|
||||
|
||||
@@ -41,7 +41,10 @@
|
||||
<!-- Authenticated -->
|
||||
<div id="view-auth" style="display:none;">
|
||||
<div id="btn-container">
|
||||
<!-- shown when no meeting is present -->
|
||||
<button id="btn-generate" data-i18n="meeting.add_meeting"></button>
|
||||
<!-- shown when a meeting is already present -->
|
||||
<button id="btn-remove" style="display:none;" data-i18n="meeting.remove_meeting"></button>
|
||||
<button id="btn-disconnect" data-i18n="auth.disconnect"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,24 +1,77 @@
|
||||
/* global Office */
|
||||
const { APP_NAME } = require("../common");
|
||||
|
||||
const { applyAppName } = require("../common/helpers");
|
||||
const { initSession, createRoom } = require("../common/api");
|
||||
const { startPolling } = require("../common/polling");
|
||||
const { openTransitDialog } = require("../common/transitDialog");
|
||||
const { loadSession, saveSession, clearSession } = require("../common/session");
|
||||
|
||||
const { buildMeetingMessage } = require("../common/messageBuilder");
|
||||
const { initI18n, t, translateUI } = require("../common/i18n");
|
||||
const { isMeetingAlreadyAdded, removeMeetingLink } = require("../common/meetingDetector");
|
||||
|
||||
// ── Views ────────────────────────────────────────────────────
|
||||
|
||||
// todo - support loading view while polling
|
||||
// todo - support error view
|
||||
function showView(name) {
|
||||
document.getElementById("view-loading").style.display = "none";
|
||||
document.getElementById("view-unauth").style.display = "none";
|
||||
document.getElementById("view-auth").style.display = "none";
|
||||
document.getElementById(`view-${name}`).style.display = "block";
|
||||
|
||||
if (name === "auth") {
|
||||
_refreshMeetingButtonState();
|
||||
}
|
||||
}
|
||||
|
||||
// ── Button state ─────────────────────────────────────────────
|
||||
|
||||
function _showAddButton() {
|
||||
document.getElementById("btn-generate").style.display = "block";
|
||||
document.getElementById("btn-remove").style.display = "none";
|
||||
}
|
||||
|
||||
function _showRemoveButton() {
|
||||
document.getElementById("btn-generate").style.display = "none";
|
||||
document.getElementById("btn-remove").style.display = "block";
|
||||
}
|
||||
|
||||
function _setButtonLoading() {
|
||||
const btn = document.getElementById("btn-generate");
|
||||
btn.disabled = true;
|
||||
btn.textContent = t("meeting.generating");
|
||||
}
|
||||
|
||||
function _setButtonIdle() {
|
||||
const btn = document.getElementById("btn-generate");
|
||||
btn.disabled = false;
|
||||
btn.textContent = t("meeting.add_meeting", { app_name: APP_NAME });
|
||||
}
|
||||
|
||||
function _setRemoveLoading() {
|
||||
const btn = document.getElementById("btn-remove");
|
||||
btn.disabled = true;
|
||||
btn.textContent = t("meeting.removing");
|
||||
}
|
||||
|
||||
function _setRemoveIdle() {
|
||||
const btn = document.getElementById("btn-remove");
|
||||
btn.disabled = false;
|
||||
btn.textContent = t("meeting.remove_meeting", { app_name: APP_NAME });
|
||||
}
|
||||
|
||||
function _refreshMeetingButtonState() {
|
||||
const item = Office.context.mailbox.item;
|
||||
if (!item) return;
|
||||
isMeetingAlreadyAdded(item).then((alreadyAdded) => {
|
||||
if (alreadyAdded) {
|
||||
_showRemoveButton();
|
||||
} else {
|
||||
_showAddButton();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ── Auth ─────────────────────────────────────────────────────
|
||||
|
||||
function connect() {
|
||||
initSession()
|
||||
.then((data) => {
|
||||
@@ -49,24 +102,11 @@ function disconnect() {
|
||||
clearSession().finally(() => showView("unauth"));
|
||||
}
|
||||
|
||||
function _setButtonLoading() {
|
||||
const btn = document.getElementById("btn-generate");
|
||||
btn.disabled = true;
|
||||
btn.textContent = t("meeting.generating");
|
||||
}
|
||||
|
||||
function _setButtonIdle() {
|
||||
const btn = document.getElementById("btn-generate");
|
||||
btn.disabled = false;
|
||||
btn.textContent = t("meeting.add_meeting", {
|
||||
app_name: APP_NAME,
|
||||
});
|
||||
}
|
||||
// ── Meeting ──────────────────────────────────────────────────
|
||||
|
||||
function generateMeetingLink() {
|
||||
const session = loadSession();
|
||||
if (!session?.access_token) {
|
||||
console.error("Session introuvable. Veuillez vous reconnecter.");
|
||||
showView("unauth");
|
||||
return;
|
||||
}
|
||||
@@ -86,7 +126,6 @@ function generateMeetingLink() {
|
||||
reject(setResult.error);
|
||||
return;
|
||||
}
|
||||
// ─── If calendar event, also set location ──────────────
|
||||
if (item.itemType === Office.MailboxEnums.ItemType.Appointment) {
|
||||
item.location.setAsync(url, () => resolve());
|
||||
return;
|
||||
@@ -95,6 +134,9 @@ function generateMeetingLink() {
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
_showRemoveButton();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
})
|
||||
@@ -103,8 +145,32 @@ function generateMeetingLink() {
|
||||
});
|
||||
}
|
||||
|
||||
Office.onReady(async (info) => {
|
||||
function removeMeetingLinkFromItem() {
|
||||
const session = loadSession();
|
||||
if (!session?.access_token) {
|
||||
showView("unauth");
|
||||
return;
|
||||
}
|
||||
|
||||
_setRemoveLoading();
|
||||
|
||||
const item = Office.context.mailbox.item;
|
||||
|
||||
removeMeetingLink(item)
|
||||
.then(() => {
|
||||
_showAddButton();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
})
|
||||
.finally(() => {
|
||||
_setRemoveIdle();
|
||||
});
|
||||
}
|
||||
|
||||
// ── Init ─────────────────────────────────────────────────────
|
||||
|
||||
Office.onReady(async (info) => {
|
||||
await initI18n();
|
||||
translateUI();
|
||||
|
||||
@@ -115,10 +181,11 @@ Office.onReady(async (info) => {
|
||||
document.getElementById("btn-connect").onclick = connect;
|
||||
document.getElementById("btn-disconnect").onclick = disconnect;
|
||||
document.getElementById("btn-generate").onclick = generateMeetingLink;
|
||||
document.getElementById("btn-remove").onclick = removeMeetingLinkFromItem;
|
||||
|
||||
const session = loadSession();
|
||||
if (session?.state === "authenticated" && session?.access_token) {
|
||||
showView("auth");
|
||||
showView("auth"); // this already calls _refreshMeetingButtonState internally
|
||||
} else {
|
||||
showView("unauth");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user