✨(front) add video conference link generation in event modal
Implement the visio conference feature in the event modal: - Add NEXT_PUBLIC_VISIO_BASE_URL env var for configurable base URL - Create generateVisioRoomId() utility (xxx-xxxx-xxx format, a-z) - Refactor VideoConferenceSection: button to create, link + remove when URL exists - Hide visio pill when env var is not configured (feature flag) - Add removeVisio i18n key in EN/FR/NL The visio URL is stored via the standard ICS URL property, which is already wired through useEventForm.toIcsEvent() and CalDavService. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
NEXT_PUBLIC_API_ORIGIN=
|
NEXT_PUBLIC_API_ORIGIN=
|
||||||
|
NEXT_PUBLIC_VISIO_BASE_URL=https://visio.suite.anct.gouv.fr
|
||||||
@@ -1 +1,2 @@
|
|||||||
NEXT_PUBLIC_API_ORIGIN=http://localhost:8921
|
NEXT_PUBLIC_API_ORIGIN=http://localhost:8921
|
||||||
|
NEXT_PUBLIC_VISIO_BASE_URL=https://visio.suite.anct.gouv.fr
|
||||||
|
|||||||
@@ -119,13 +119,19 @@ export const EventModal = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const visioBaseUrl = process.env.NEXT_PUBLIC_VISIO_BASE_URL;
|
||||||
|
|
||||||
const pills = useMemo(
|
const pills = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
...(visioBaseUrl
|
||||||
id: "videoConference" as const,
|
? [
|
||||||
icon: "videocam",
|
{
|
||||||
label: t("calendar.event.sections.addVideoConference"),
|
id: "videoConference" as const,
|
||||||
},
|
icon: "videocam",
|
||||||
|
label: t("calendar.event.sections.addVideoConference"),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
{
|
{
|
||||||
id: "location" as const,
|
id: "location" as const,
|
||||||
icon: "place",
|
icon: "place",
|
||||||
@@ -147,7 +153,7 @@ export const EventModal = ({
|
|||||||
label: t("calendar.event.attendees"),
|
label: t("calendar.event.attendees"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[t],
|
[t, visioBaseUrl],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Button } from "@gouvfr-lasuite/cunningham-react";
|
import { Button } from "@gouvfr-lasuite/cunningham-react";
|
||||||
import { SectionRow } from "./SectionRow";
|
import { SectionRow } from "./SectionRow";
|
||||||
|
import { generateVisioRoomId } from "./generateVisioRoomId";
|
||||||
|
|
||||||
interface VideoConferenceSectionProps {
|
interface VideoConferenceSectionProps {
|
||||||
url: string;
|
url: string;
|
||||||
@@ -19,14 +19,12 @@ export const VideoConferenceSection = ({
|
|||||||
onToggle,
|
onToggle,
|
||||||
}: VideoConferenceSectionProps) => {
|
}: VideoConferenceSectionProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [isCreating, setIsCreating] = useState(false);
|
|
||||||
|
|
||||||
const handleCreateVisio = () => {
|
const handleCreateVisio = () => {
|
||||||
// Inert for now - will integrate with La Suite API in the future
|
const baseUrl = process.env.NEXT_PUBLIC_VISIO_BASE_URL;
|
||||||
setIsCreating(true);
|
if (!baseUrl) return;
|
||||||
setTimeout(() => {
|
const roomId = generateVisioRoomId();
|
||||||
setIsCreating(false);
|
onChange(`${baseUrl}/${roomId}`);
|
||||||
}, 500);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemove = () => {
|
const handleRemove = () => {
|
||||||
@@ -42,15 +40,35 @@ export const VideoConferenceSection = ({
|
|||||||
isExpanded={isExpanded}
|
isExpanded={isExpanded}
|
||||||
onToggle={onToggle}
|
onToggle={onToggle}
|
||||||
>
|
>
|
||||||
<Button
|
{url ? (
|
||||||
size="small"
|
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||||
color="neutral"
|
<a
|
||||||
variant="tertiary"
|
href={url}
|
||||||
onClick={handleCreateVisio}
|
target="_blank"
|
||||||
disabled={isCreating}
|
rel="noopener noreferrer"
|
||||||
>
|
style={{ wordBreak: "break-all" }}
|
||||||
{t("calendar.event.sections.createVisio")}
|
>
|
||||||
</Button>
|
{url}
|
||||||
|
</a>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
color="neutral"
|
||||||
|
variant="tertiary"
|
||||||
|
icon={<span className="material-icons">close</span>}
|
||||||
|
onClick={handleRemove}
|
||||||
|
aria-label={t("calendar.event.sections.removeVisio")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
color="neutral"
|
||||||
|
variant="tertiary"
|
||||||
|
onClick={handleCreateVisio}
|
||||||
|
>
|
||||||
|
{t("calendar.event.sections.createVisio")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</SectionRow>
|
</SectionRow>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
const randomLetters = (n: number): string =>
|
||||||
|
Array.from({ length: n }, () =>
|
||||||
|
String.fromCharCode(97 + Math.floor(Math.random() * 26)),
|
||||||
|
).join("");
|
||||||
|
|
||||||
|
export const generateVisioRoomId = (): string =>
|
||||||
|
`${randomLetters(3)}-${randomLetters(4)}-${randomLetters(3)}`;
|
||||||
@@ -137,6 +137,7 @@
|
|||||||
"addLocation": "Add location",
|
"addLocation": "Add location",
|
||||||
"addVideoConference": "Visio",
|
"addVideoConference": "Visio",
|
||||||
"createVisio": "Add video conference",
|
"createVisio": "Add video conference",
|
||||||
|
"removeVisio": "Remove video conference",
|
||||||
"videoLink": "Video conference link",
|
"videoLink": "Video conference link",
|
||||||
"addAttendees": "Add participants",
|
"addAttendees": "Add participants",
|
||||||
"addDescription": "Add description",
|
"addDescription": "Add description",
|
||||||
@@ -747,6 +748,7 @@
|
|||||||
"addLocation": "Ajouter un lieu",
|
"addLocation": "Ajouter un lieu",
|
||||||
"addVideoConference": "Visio",
|
"addVideoConference": "Visio",
|
||||||
"createVisio": "Ajouter une visioconférence",
|
"createVisio": "Ajouter une visioconférence",
|
||||||
|
"removeVisio": "Supprimer la visioconférence",
|
||||||
"videoLink": "Lien de visioconférence",
|
"videoLink": "Lien de visioconférence",
|
||||||
"addAttendees": "Ajouter des participants",
|
"addAttendees": "Ajouter des participants",
|
||||||
"addDescription": "Ajouter une description",
|
"addDescription": "Ajouter une description",
|
||||||
@@ -1104,6 +1106,7 @@
|
|||||||
"addLocation": "Locatie toevoegen",
|
"addLocation": "Locatie toevoegen",
|
||||||
"addVideoConference": "Visio",
|
"addVideoConference": "Visio",
|
||||||
"createVisio": "Add video conference",
|
"createVisio": "Add video conference",
|
||||||
|
"removeVisio": "Videoconferentie verwijderen",
|
||||||
"videoLink": "Videoconferentie link",
|
"videoLink": "Videoconferentie link",
|
||||||
"addAttendees": "Deelnemers toevoegen",
|
"addAttendees": "Deelnemers toevoegen",
|
||||||
"addDescription": "Beschrijving toevoegen",
|
"addDescription": "Beschrijving toevoegen",
|
||||||
|
|||||||
Reference in New Issue
Block a user