mirror of
https://github.com/suitenumerique/meet.git
synced 2026-07-27 20:29:09 +00:00
wip introduce a wip outlook add-in
not production ready
This commit is contained in:
@@ -11,6 +11,12 @@ server {
|
||||
add_header Content-Disposition "attachment; filename=windows-app-web-link";
|
||||
}
|
||||
|
||||
location ~ ^/outlook-addin(/.*)?$ {
|
||||
alias /usr/share/nginx/html/outlook-addin$1;
|
||||
add_header Access-Control-Allow-Origin "*";
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
}
|
||||
|
||||
# Serve static files with caching
|
||||
location ~* ^/assets/.*\.(css|js|json|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 30d;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
|
||||
<script src="common.js" defer></script>
|
||||
<script src="commands.js" defer></script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
/* global Office */
|
||||
|
||||
Office.onReady(() => {});
|
||||
|
||||
function generateMeetingLinkFromCalendar(event) {
|
||||
const session = loadSession();
|
||||
|
||||
if (!session?.access_token) {
|
||||
Office.context.mailbox.item.notificationMessages.replaceAsync("meetNotif", {
|
||||
type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage,
|
||||
message: "Vous n'êtes pas connecté. Ouvrez les paramètres pour vous connecter.",
|
||||
});
|
||||
event.completed();
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`${BASE_URL}/external-api/v1.0/rooms/`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + session.access_token,
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
console.log("Room created:", data);
|
||||
|
||||
const { url, message } = buildMeetingMessage(data);
|
||||
const item = Office.context.mailbox.item;
|
||||
|
||||
item.body.getAsync(Office.CoercionType.Html, (getResult) => {
|
||||
if (getResult.status !== Office.AsyncResultStatus.Succeeded) {
|
||||
item.notificationMessages.replaceAsync("meetNotif", {
|
||||
type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage,
|
||||
message: `Erreur de lecture: ${getResult.error.message}`,
|
||||
});
|
||||
event.completed();
|
||||
return;
|
||||
}
|
||||
|
||||
item.body.setAsync(getResult.value + message, { coercionType: Office.CoercionType.Html }, (setResult) => {
|
||||
if (setResult.status !== Office.AsyncResultStatus.Succeeded) {
|
||||
item.notificationMessages.replaceAsync("meetNotif", {
|
||||
type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage,
|
||||
message: `Erreur d'insertion: ${setResult.error.message}`,
|
||||
});
|
||||
event.completed();
|
||||
return;
|
||||
}
|
||||
|
||||
item.location.setAsync(url, (locationResult) => {
|
||||
if (locationResult.status === Office.AsyncResultStatus.Succeeded) {
|
||||
item.notificationMessages.replaceAsync("meetNotif", {
|
||||
type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,
|
||||
message: "Lien de réunion inséré !",
|
||||
icon: "Icon.80x80",
|
||||
persistent: false,
|
||||
});
|
||||
} else {
|
||||
item.notificationMessages.replaceAsync("meetNotif", {
|
||||
type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage,
|
||||
message: `Erreur de localisation: ${locationResult.error.message}`,
|
||||
});
|
||||
}
|
||||
event.completed();
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
Office.context.mailbox.item.notificationMessages.replaceAsync("meetNotif", {
|
||||
type: Office.MailboxEnums.ItemNotificationMessageType.ErrorMessage,
|
||||
message: `Erreur: ${err.message}`,
|
||||
});
|
||||
event.completed();
|
||||
});
|
||||
}
|
||||
|
||||
Office.actions.associate("generateMeetingLinkFromCalendar", generateMeetingLinkFromCalendar);
|
||||
@@ -0,0 +1,97 @@
|
||||
/* global Office */
|
||||
|
||||
const BASE_URL = "https://meet.127.0.0.1.nip.io";
|
||||
|
||||
// ─── Session Storage ──────────────────────────────────────────────────────
|
||||
|
||||
function saveSession(data) {
|
||||
const expiresAt = data.expires_in
|
||||
? new Date(Date.now() + data.expires_in * 1000).toISOString()
|
||||
: null;
|
||||
|
||||
const payload = JSON.stringify({
|
||||
...data,
|
||||
expiresAt,
|
||||
savedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
localStorage.setItem("meetSession", payload);
|
||||
|
||||
const rs = Office.context.roamingSettings;
|
||||
rs.set("meetSession", payload);
|
||||
rs.saveAsync((result) => {
|
||||
if (result.status !== Office.AsyncResultStatus.Succeeded) {
|
||||
console.error("RoamingSettings save failed:", result.error.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadSession() {
|
||||
let session = null;
|
||||
|
||||
try {
|
||||
const stored = Office.context.roamingSettings.get("meetSession");
|
||||
if (stored) session = JSON.parse(stored);
|
||||
} catch (e) {
|
||||
console.warn("RoamingSettings read failed:", e);
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
try {
|
||||
const stored = localStorage.getItem("meetSession");
|
||||
if (stored) session = JSON.parse(stored);
|
||||
} catch (e) {
|
||||
console.warn("localStorage read failed:", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!session) return null;
|
||||
|
||||
if (session.expiresAt && new Date() > new Date(session.expiresAt)) {
|
||||
console.warn("Token expired, clearing session.");
|
||||
clearSession();
|
||||
return null;
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
function clearSession() {
|
||||
localStorage.removeItem("meetSession");
|
||||
try {
|
||||
const rs = Office.context.roamingSettings;
|
||||
rs.remove("meetSession");
|
||||
rs.saveAsync(() => console.log("RoamingSettings cleared."));
|
||||
} catch (e) {
|
||||
console.warn("Could not clear RoamingSettings:", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Meeting Message Builder ───────────────────────────────────────────────
|
||||
|
||||
function buildMeetingMessage(data) {
|
||||
const url = data.url;
|
||||
const phone = data.telephony?.phone_number;
|
||||
const pin = data.telephony?.pin_code;
|
||||
|
||||
const formattedPin = pin
|
||||
? pin.replace(/(\d{3})(\d{3})(\d{4})/, "$1 $2 $3") + "#"
|
||||
: "";
|
||||
|
||||
const formattedPhone = phone
|
||||
? phone.replace(/^\+33(\d)(\d{2})(\d{2})(\d{2})(\d{2})$/, "+33 $1 $2 $3 $4 $5")
|
||||
: phone;
|
||||
|
||||
const message = `<pre style="font-family:inherit; font-size:inherit; border:none; background:none; margin:16px 0;">
|
||||
────────────────────────────────────────
|
||||
Rejoindre la réunion LaSuite Meet
|
||||
|
||||
<a href="${url}">${url}</a>
|
||||
|
||||
Ou appelez (audio uniquement)
|
||||
(FR) ${formattedPhone}
|
||||
Code : ${formattedPin}
|
||||
────────────────────────────────────────</pre>`;
|
||||
|
||||
return { url, message };
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:mailappor="http://schemas.microsoft.com/office/mailappversionoverrides/1.0" xsi:type="MailApp">
|
||||
<Id>a025f0f6-757a-4790-97f3-99c66c4a5795</Id>
|
||||
<Version>0.0.1.0</Version>
|
||||
<ProviderName>Visio</ProviderName>
|
||||
<DefaultLocale>en-US</DefaultLocale>
|
||||
<DisplayName DefaultValue="Visio"/>
|
||||
<Description DefaultValue="Ajoutez facilement un lien de réunion Visio à vos emails et événements Outlook."/>
|
||||
<IconUrl DefaultValue="https://meet.127.0.0.1.nip.io/outlook-addin/assets/icon-64.png"/>
|
||||
<HighResolutionIconUrl DefaultValue="https://meet.127.0.0.1.nip.io/outlook-addin/assets/icon-128.png"/>
|
||||
<SupportUrl DefaultValue="https://www.contoso.com/help"/>
|
||||
<AppDomains>
|
||||
<AppDomain>https://meet.127.0.0.1.nip.io</AppDomain>
|
||||
</AppDomains>
|
||||
<Hosts>
|
||||
<Host Name="Mailbox"/>
|
||||
</Hosts>
|
||||
<Requirements>
|
||||
<Sets>
|
||||
<Set Name="Mailbox" MinVersion="1.1"/>
|
||||
</Sets>
|
||||
</Requirements>
|
||||
<FormSettings>
|
||||
<Form xsi:type="ItemRead">
|
||||
<DesktopSettings>
|
||||
<SourceLocation DefaultValue="https://meet.127.0.0.1.nip.io/outlook-addin/taskpane.html"/>
|
||||
<RequestedHeight>250</RequestedHeight>
|
||||
</DesktopSettings>
|
||||
</Form>
|
||||
<Form xsi:type="ItemEdit">
|
||||
<DesktopSettings>
|
||||
<SourceLocation DefaultValue="https://meet.127.0.0.1.nip.io/outlook-addin/taskpane.html"/>
|
||||
</DesktopSettings>
|
||||
</Form>
|
||||
</FormSettings>
|
||||
<Permissions>ReadWriteItem</Permissions>
|
||||
<Rule xsi:type="RuleCollection" Mode="Or">
|
||||
<Rule xsi:type="ItemIs" ItemType="Message" FormType="Read"/>
|
||||
<Rule xsi:type="ItemIs" ItemType="Message" FormType="Edit"/>
|
||||
<Rule xsi:type="ItemIs" ItemType="Appointment" FormType="Edit"/>
|
||||
</Rule>
|
||||
<DisableEntityHighlighting>false</DisableEntityHighlighting>
|
||||
<VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides" xsi:type="VersionOverridesV1_0">
|
||||
<Requirements>
|
||||
<bt:Sets DefaultMinVersion="1.3">
|
||||
<bt:Set Name="Mailbox"/>
|
||||
</bt:Sets>
|
||||
</Requirements>
|
||||
<Hosts>
|
||||
<Host xsi:type="MailHost">
|
||||
<DesktopFormFactor>
|
||||
<FunctionFile resid="Commands.Url"/>
|
||||
|
||||
<!-- ─── Mail: Read ─────────────────────────────────────────── -->
|
||||
<ExtensionPoint xsi:type="MessageReadCommandSurface">
|
||||
<OfficeTab id="TabDefault">
|
||||
<Group id="msgReadGroup">
|
||||
<Label resid="GroupLabel"/>
|
||||
<Control xsi:type="Button" id="msgReadOpenPaneButton">
|
||||
<Label resid="TaskpaneButton.Label"/>
|
||||
<Supertip>
|
||||
<Title resid="TaskpaneButton.Label"/>
|
||||
<Description resid="TaskpaneButton.Tooltip"/>
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Action xsi:type="ShowTaskpane">
|
||||
<SourceLocation resid="Taskpane.Url"/>
|
||||
</Action>
|
||||
</Control>
|
||||
</Group>
|
||||
</OfficeTab>
|
||||
</ExtensionPoint>
|
||||
|
||||
<!-- ─── Mail: Compose ─────────────────────────────────────── -->
|
||||
<ExtensionPoint xsi:type="MessageComposeCommandSurface">
|
||||
<OfficeTab id="TabDefault">
|
||||
<Group id="msgComposeGroup">
|
||||
<Label resid="GroupLabel"/>
|
||||
<Control xsi:type="Button" id="msgComposeOpenPaneButton">
|
||||
<Label resid="TaskpaneButton.Label"/>
|
||||
<Supertip>
|
||||
<Title resid="TaskpaneButton.Label"/>
|
||||
<Description resid="TaskpaneButton.Tooltip"/>
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Action xsi:type="ShowTaskpane">
|
||||
<SourceLocation resid="Taskpane.Url"/>
|
||||
</Action>
|
||||
</Control>
|
||||
</Group>
|
||||
</OfficeTab>
|
||||
</ExtensionPoint>
|
||||
|
||||
<!-- ─── Calendar: Compose (New/Edit appointment) ──────────── -->
|
||||
<ExtensionPoint xsi:type="AppointmentOrganizerCommandSurface">
|
||||
<OfficeTab id="TabDefault">
|
||||
<Group id="apptComposeGroup">
|
||||
<Label resid="GroupLabel"/>
|
||||
|
||||
<!-- Button 1: Generate meeting link (function call) -->
|
||||
<Control xsi:type="Button" id="apptGenerateLinkButton">
|
||||
<Label resid="GenerateLink.Label"/>
|
||||
<Supertip>
|
||||
<Title resid="GenerateLink.Label"/>
|
||||
<Description resid="GenerateLink.Tooltip"/>
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Action xsi:type="ExecuteFunction">
|
||||
<FunctionName>generateMeetingLinkFromCalendar</FunctionName>
|
||||
</Action>
|
||||
</Control>
|
||||
|
||||
<!-- Button 2: Open settings taskpane -->
|
||||
<Control xsi:type="Button" id="apptOpenSettingsButton">
|
||||
<Label resid="OpenSettings.Label"/>
|
||||
<Supertip>
|
||||
<Title resid="OpenSettings.Label"/>
|
||||
<Description resid="OpenSettings.Tooltip"/>
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Action xsi:type="ShowTaskpane">
|
||||
<SourceLocation resid="Taskpane.Url"/>
|
||||
</Action>
|
||||
</Control>
|
||||
|
||||
</Group>
|
||||
</OfficeTab>
|
||||
</ExtensionPoint>
|
||||
|
||||
</DesktopFormFactor>
|
||||
</Host>
|
||||
</Hosts>
|
||||
<Resources>
|
||||
<bt:Images>
|
||||
<bt:Image id="Icon.16x16" DefaultValue="https://meet.127.0.0.1.nip.io/outlook-addin/assets/icon-16.png"/>
|
||||
<bt:Image id="Icon.32x32" DefaultValue="https://meet.127.0.0.1.nip.io/outlook-addin/assets/icon-32.png"/>
|
||||
<bt:Image id="Icon.80x80" DefaultValue="https://meet.127.0.0.1.nip.io/outlook-addin/assets/icon-80.png"/>
|
||||
</bt:Images>
|
||||
<bt:Urls>
|
||||
<bt:Url id="Commands.Url" DefaultValue="https://meet.127.0.0.1.nip.io/outlook-addin/commands.html"/>
|
||||
<bt:Url id="Taskpane.Url" DefaultValue="https://meet.127.0.0.1.nip.io/outlook-addin/taskpane.html"/>
|
||||
</bt:Urls>
|
||||
<bt:ShortStrings>
|
||||
<bt:String id="GroupLabel" DefaultValue="Visio"/>
|
||||
<bt:String id="TaskpaneButton.Label" DefaultValue="Ouvrir le panneau"/>
|
||||
<bt:String id="GenerateLink.Label" DefaultValue="Générer un lien de réunion"/>
|
||||
<bt:String id="OpenSettings.Label" DefaultValue="Paramètres"/>
|
||||
</bt:ShortStrings>
|
||||
<bt:LongStrings>
|
||||
<bt:String id="TaskpaneButton.Tooltip" DefaultValue="Ouvre le panneau de connexion Visio."/>
|
||||
<bt:String id="GenerateLink.Tooltip" DefaultValue="Génère un lien de réunion Visio et l'insère dans l'événement."/>
|
||||
<bt:String id="OpenSettings.Tooltip" DefaultValue="Ouvre les paramètres de connexion Visio."/>
|
||||
</bt:LongStrings>
|
||||
</Resources>
|
||||
</VersionOverrides>
|
||||
</OfficeApp>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Visio</title>
|
||||
<link rel="stylesheet" href="taskpane.css" />
|
||||
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
|
||||
<script src="common.js" defer></script>
|
||||
<script src="taskpane.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="sideload-msg">Veuillez charger le complément.</div>
|
||||
|
||||
<div id="app-body">
|
||||
|
||||
<!-- Loading -->
|
||||
<div id="view-loading">
|
||||
<p class="intro-text">Chargement...</p>
|
||||
</div>
|
||||
|
||||
<!-- Unauthenticated -->
|
||||
<div id="view-unauth" style="display:none;">
|
||||
<p class="intro-text">
|
||||
<span>Ajoutez facilement un lien de réunion Visio à vos événements Outlook.</span>
|
||||
<a href="https://meet.numerique.gouv.fr" target="_blank" class="learn-more">En savoir plus</a>
|
||||
</p>
|
||||
|
||||
<hr class="divider" />
|
||||
|
||||
<button class="proconnect-button" id="btn-connect">
|
||||
<span class="proconnect-sr-only">S'identifier avec ProConnect</span>
|
||||
</button>
|
||||
|
||||
<p>
|
||||
<a
|
||||
href="https://www.proconnect.gouv.fr/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="Qu’est-ce que ProConnect ? - nouvelle fenêtre"
|
||||
>
|
||||
Qu’est-ce que ProConnect ?
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Authenticated -->
|
||||
<div id="view-auth" style="display:none;">
|
||||
<div id="btn-container">
|
||||
<button id="btn-generate">Ajouter une réunion Visio</button>
|
||||
<button id="btn-disconnect">Se déconnecter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p id="status"></p>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,193 @@
|
||||
// ─── Views ────────────────────────────────────────────────────────────────
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
function setStatus(msg) {
|
||||
document.getElementById("status").textContent = msg;
|
||||
}
|
||||
|
||||
// ─── Auth Flow ────────────────────────────────────────────────────────────
|
||||
|
||||
function connect() {
|
||||
setStatus("Démarrage de la session...");
|
||||
|
||||
fetch(`${BASE_URL}/api/v1.0/addons/sessions/`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const session_id = data.session_id;
|
||||
setStatus("En attente d'authentification...");
|
||||
|
||||
let dialog = null;
|
||||
let pollInterval = null;
|
||||
let pollCount = 0;
|
||||
|
||||
pollInterval = setInterval(() => {
|
||||
|
||||
// ─── Timeout after 3 minutes ──────────────────────────────
|
||||
if (pollCount++ > 180) {
|
||||
clearInterval(pollInterval);
|
||||
if (dialog) dialog.close();
|
||||
setStatus("Délai d'authentification dépassé. Veuillez réessayer.");
|
||||
showView("unauth");
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`${BASE_URL}/api/v1.0/addons/sessions/${session_id}`, {
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((sessionData) => {
|
||||
console.log("Polling:", sessionData);
|
||||
if (sessionData.state === "authenticated" && sessionData.access_token) {
|
||||
clearInterval(pollInterval);
|
||||
// if (dialog) dialog.close();
|
||||
saveSession(sessionData);
|
||||
setStatus("Connecté !");
|
||||
showView("auth");
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
clearInterval(pollInterval);
|
||||
setStatus(`Erreur de polling: ${err.message}`);
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
// ─── Open transit dialog ──────────────────────────────────────
|
||||
const meetUrl = `${BASE_URL}/addons/transit/?session_id=${session_id}`;
|
||||
Office.context.ui.displayDialogAsync(
|
||||
meetUrl,
|
||||
{ height: 60, width: 50, displayInIframe: false },
|
||||
(asyncResult) => {
|
||||
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
|
||||
clearInterval(pollInterval);
|
||||
setStatus(`Erreur dialog: ${asyncResult.error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
dialog = asyncResult.value;
|
||||
|
||||
dialog.addEventHandler(Office.EventType.DialogMessageReceived, () => {
|
||||
clearInterval(pollInterval);
|
||||
dialog.close();
|
||||
});
|
||||
|
||||
dialog.addEventHandler(Office.EventType.DialogEventReceived, (arg) => {
|
||||
if (arg.error === 12006) {
|
||||
setStatus("Dialog fermé. En attente d'authentification...");
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
setStatus(`Erreur de connexion: ${err.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
clearSession();
|
||||
setStatus("Déconnecté.");
|
||||
showView("unauth");
|
||||
}
|
||||
|
||||
function generateMeetingLink() {
|
||||
const session = loadSession();
|
||||
if (!session?.access_token) {
|
||||
setStatus("Session introuvable. Veuillez vous reconnecter.");
|
||||
showView("unauth");
|
||||
return;
|
||||
}
|
||||
|
||||
const btn = document.getElementById("btn-generate");
|
||||
btn.disabled = true;
|
||||
btn.textContent = "Génération...";
|
||||
|
||||
fetch(`${BASE_URL}/external-api/v1.0/rooms/`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + session.access_token,
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
console.log("Room created:", data);
|
||||
|
||||
const { url, message } = buildMeetingMessage(data);
|
||||
const item = Office.context.mailbox.item;
|
||||
|
||||
item.body.getAsync(Office.CoercionType.Html, (getResult) => {
|
||||
if (getResult.status !== Office.AsyncResultStatus.Succeeded) {
|
||||
setStatus(`Erreur de lecture: ${getResult.error.message}`);
|
||||
btn.disabled = false;
|
||||
btn.textContent = "Ajouter une réunion Visio";
|
||||
return;
|
||||
}
|
||||
|
||||
item.body.setAsync(
|
||||
getResult.value + message,
|
||||
{ coercionType: Office.CoercionType.Html },
|
||||
(setResult) => {
|
||||
if (setResult.status !== Office.AsyncResultStatus.Succeeded) {
|
||||
setStatus(`Erreur d'insertion: ${setResult.error.message}`);
|
||||
btn.disabled = false;
|
||||
btn.textContent = "Ajouter une réunion Visio";
|
||||
return;
|
||||
}
|
||||
|
||||
// ─── If calendar event, also set location ──────────────
|
||||
if (item.itemType === Office.MailboxEnums.ItemType.Appointment) {
|
||||
item.location.setAsync(url, (locationResult) => {
|
||||
btn.disabled = false;
|
||||
btn.textContent = "Ajouter une réunion Visio";
|
||||
if (locationResult.status === Office.AsyncResultStatus.Succeeded) {
|
||||
setStatus("Lien de réunion inséré !");
|
||||
} else {
|
||||
setStatus(`Erreur de localisation: ${locationResult.error.message}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
btn.disabled = false;
|
||||
btn.textContent = "Ajouter une réunion Visio";
|
||||
setStatus("Lien de réunion inséré !");
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
btn.disabled = false;
|
||||
btn.textContent = "Ajouter une réunion Visio";
|
||||
setStatus(`Erreur: ${err.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Init ─────────────────────────────────────────────────────────────────
|
||||
|
||||
Office.onReady((info) => {
|
||||
if (info.host === Office.HostType.Outlook) {
|
||||
document.getElementById("sideload-msg").style.display = "none";
|
||||
document.getElementById("app-body").style.display = "flex";
|
||||
|
||||
document.getElementById("btn-connect").onclick = connect;
|
||||
document.getElementById("btn-disconnect").onclick = disconnect;
|
||||
document.getElementById("btn-generate").onclick = generateMeetingLink;
|
||||
|
||||
const session = loadSession();
|
||||
if (session?.state === "authenticated" && session?.access_token) {
|
||||
setStatus("Connecté.");
|
||||
showView("auth");
|
||||
} else {
|
||||
showView("unauth");
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user