Compare commits

...

10 Commits

Author SHA1 Message Date
lebaudantoine 12e99f8f2a 💄(frontend) adjust font size based on Marianne recent changes
Marianne is bigger than OpenSans, adjust admin side panel style.
2025-03-24 13:38:40 +01:00
lebaudantoine 3358b23edd 🌐(frontend) add missing translation
The admin side panel was translated too quickly.
I forgot a title, fix it.
2025-03-24 13:38:38 +01:00
lebaudantoine 558d844ef3 ✏️(frontend) fix typos in the admin side panel
Based on Users' feedbacks. Also based on Arnaud's one, avoid
having a double negation for the public restriction.
2025-03-24 13:36:03 +01:00
lebaudantoine 94aa828d87 🌐(frontend) add missing dutch content
Oopsi, forgot some dutch content when resolving conflicts
while merging traductions. Fixed.
2025-03-21 16:59:14 +01:00
lebaudantoine 110e062e56 💄(frontend) use official Marianne font
Updated styling system to implement the official French font used across all
La Suite products. This enhances brand consistency and improves the visual
identity alignment with other government digital services.
2025-03-21 16:57:33 +01:00
lebaudantoine f7c2beb30d 🚸(frontend) add screen sharing troubleshooting modal and setup guide
Created modal that appears when users fail to share their entire screen. Also
added documentation helper that explains proper screen sharing setup steps for
different operating systems and browsers.
2025-03-21 15:27:50 +01:00
lebaudantoine 5bf1456200 ⚰️(secrets) remove useless submodule
Secret are not in-use anymore in the project, dead code.
2025-03-21 15:25:37 +01:00
Ikko Eltociear Ashimine 80e5c9bb95 ✏️(frontend) update BackgroundBlurTrackProcessorJsWrapper.ts
accross -> across
2025-03-18 20:07:26 +01:00
Rust Saiargaliev 74164b8498 🗑️(backend) drop obsolete code from the initial boilerplate
Related to 5b1a2b20de
There are no references to the `generate_document.html` template
in the codebase. The same goes for the `INVITATION_VALIDITY_DURATION` setting,
which arrived straigt from https://github.com/suitenumerique/docs

WeasyPrint is (I believe) not used in the project, so it is a ghost dependency.
2025-03-18 20:05:31 +01:00
Juergen Ehrensberger 82cc2e5d17 📝(helm) correct helm chart repository URL for meet
The URL https://numerique-gouv.github.io/meet/ is not accessible.
The correct URL appears to be https://suitenumerique.github.io/meet/
2025-03-18 20:03:45 +01:00
21 changed files with 247 additions and 52 deletions
-3
View File
@@ -1,3 +0,0 @@
[submodule "secrets"]
path = secrets
url = ../secrets
+1 -1
View File
@@ -212,7 +212,7 @@ POSTGRES_PASSWORD: pass
Now you are ready to deploy Visio without AI. AI required more dependencies (Openai-compliant API, LiveKit Egress, Cold storage and a docs deployment to push resumes). To deploy meet you need to provide all previous information to the helm chart.
```
$ helm repo add meet https://numerique-gouv.github.io/meet/
$ helm repo add meet https://suitenumerique.github.io/meet/
$ helm repo update
$ helm install meet meet/meet -f examples/meet.values.yaml
```
Submodule secrets deleted from 2ba12db71d
@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Generate Document</title>
</head>
<body>
<h2>Generate Document</h2>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Generate PDF</button>
</form>
</body>
</html>
-1
View File
@@ -314,7 +314,6 @@ class Base(Configuration):
EMAIL_FROM = values.Value("from@example.com")
AUTH_USER_MODEL = "core.User"
INVITATION_VALIDITY_DURATION = 604800 # 7 days, in seconds
# CORS
CORS_ALLOW_CREDENTIALS = True
-1
View File
@@ -54,7 +54,6 @@ dependencies = [
"requests==2.32.3",
"sentry-sdk==2.22.0",
"url-normalize==1.4.3",
"WeasyPrint>=60.2",
"whitenoise==6.9.0",
"mozilla-django-oidc==4.0.1",
"livekit-api==0.8.2",
+1
View File
@@ -223,6 +223,7 @@ const config: Config = {
fonts: {
sans: {
value: [
'Marianne',
'Source Sans',
'Source Sans fallback',
'ui-sans-serif',
+10 -3
View File
@@ -1,4 +1,4 @@
import { cva, RecipeVariantProps } from '@/styled-system/css'
import { css, cva, RecipeVariantProps } from '@/styled-system/css'
import React from 'react'
const avatar = cva({
@@ -19,7 +19,8 @@ const avatar = cva({
list: {
width: '32px',
height: '32px',
fontSize: '1.25rem',
fontSize: '1.3rem',
lineHeight: '1rem',
},
placeholder: {
width: '100%',
@@ -60,7 +61,13 @@ export const Avatar = ({
className={avatar({ context, notification })}
{...props}
>
{initial}
<span
className={css({
marginTop: '-0.3rem',
})}
>
{initial}
</span>
</div>
)
}
@@ -25,7 +25,9 @@ export const FeedbackBanner = () => {
})}
>
<RiErrorWarningLine size={20} aria-hidden="true" />
<Text as="p">{t('feedback.context')}</Text>
<Text as="p" variant="sm">
{t('feedback.context')}
</Text>
<div
className={css({
display: 'flex',
@@ -33,7 +35,7 @@ export const FeedbackBanner = () => {
gap: 0.25,
})}
>
<A href={GRIST_FORM} target="_blank">
<A href={GRIST_FORM} target="_blank" size="sm">
{t('feedback.cta')}
</A>
<RiExternalLinkLine size={16} aria-hidden="true" />
@@ -17,12 +17,13 @@ const Heading = styled('h2', {
base: {
width: 'fit-content',
marginBottom: 0,
fontSize: '1.5rem',
fontSize: '1.3rem',
fontWeight: '600',
marginTop: '0.75rem',
lineHeight: '2rem',
maxWidth: '23rem',
textAlign: 'center',
textWrap: 'pretty',
textWrap: 'balance',
},
})
@@ -31,7 +32,7 @@ const Body = styled('p', {
maxWidth: '23rem',
textAlign: 'center',
textWrap: 'pretty',
lineHeight: '1.2rem',
lineHeight: '1.4rem',
fontSize: '1rem',
},
})
@@ -102,7 +103,7 @@ const Slide = styled('div', {
alignItems: 'center',
gap: '0.5rem',
justifyContent: 'start',
minHeight: { base: 'none', xsm: '550px' },
minHeight: { base: 'none', xsm: '580px' },
minWidth: { base: 'none', xsm: '200px' },
width: { base: '100%', xsm: '22.625rem' },
},
@@ -72,8 +72,8 @@ const LeftColumn = ({ children }: { children?: ReactNode }) => {
textAlign: 'left',
alignItems: 'flex-start',
flexShrink: '1',
flexBasis: '36rem',
maxWidth: '36rem',
flexBasis: '40rem',
maxWidth: '40rem',
padding: '1em 3em',
},
})}
@@ -120,14 +120,13 @@ const Separator = styled('div', {
const Heading = styled('h1', {
base: {
fontWeight: '500',
fontWeight: '600',
fontStyle: 'normal',
fontStretch: 'normal',
fontOpticalSizing: 'auto',
marginBottom: 0,
paddingBottom: '0.75rem',
paddingBottom: '1.2rem',
fontSize: '2.3rem',
lineHeight: '2.5rem',
lineHeight: '2.6rem',
letterSpacing: '0',
xsm: {
fontSize: '3rem',
@@ -139,9 +138,9 @@ const Heading = styled('h1', {
const IntroText = styled('div', {
base: {
marginBottom: '3rem',
fontSize: '1.5rem',
lineHeight: '1.8rem',
textWrap: 'pretty',
fontSize: '1.2rem',
lineHeight: '1.5rem',
textWrap: 'balance',
maxWidth: '32rem',
},
})
@@ -37,7 +37,14 @@ export const Admin = () => {
flexDirection="column"
alignItems="start"
>
<Text variant="note" wrap="pretty" margin="md">
<Text
variant="note"
wrap="pretty"
className={css({
textStyle: 'sm',
})}
margin={'md'}
>
{t('description')}
</Text>
<RACSeparator
@@ -68,8 +75,8 @@ export const Admin = () => {
</Text>
<Field
type="radioGroup"
label="Type d'accès à la réunion"
aria-label="Type d'accès à la réunion"
label={t('access.type')}
aria-label={t('access.type')}
labelProps={{
className: css({
fontSize: '1rem',
@@ -0,0 +1,66 @@
import { A, Button, Dialog, P } from '@/primitives'
import { useTranslation } from 'react-i18next'
import { css } from '@/styled-system/css'
// todo - refactor it into a generic system
export const ScreenShareErrorModal = ({
isOpen,
onClose,
}: {
isOpen: boolean
onClose: () => void
}) => {
const { t } = useTranslation('rooms', { keyPrefix: 'error.screenShare' })
const isMac = navigator.userAgent.toLowerCase().indexOf('mac') !== -1
return (
<Dialog
isOpen={isOpen}
role="alertdialog"
title={t('title')}
aria-label={t('ariaLabel')}
onClose={onClose}
>
{({ close }) => {
return (
<>
<P>
{t('message')}{' '}
{isMac && (
<>
{t('macInstructions')}{' '}
<A
href="x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture"
color="primary"
aria-label={t('macSystemPreferences') + '-' + t('newTab')}
>
{t('macSystemPreferences')}
</A>
.{' '}
</>
)}
{t('helpLinkText')}{' '}
<A
href="https://lasuite.crisp.help/fr/article/visio-probleme-de-presentation-1xkf799/"
aria-label={t('helpLinkLabel') + '-' + t('newTab')}
target="_blank"
color="primary"
>
{t('helpLinkLabel')}
</A>
.
</P>
<Button
onPress={close}
size="sm"
variant="primary"
className={css({ marginLeft: 'auto', marginTop: '2rem' })}
>
{t('closeButton')}
</Button>
</>
)
}}
</Dialog>
)
}
@@ -13,7 +13,7 @@ import {
/**
* This is simply a wrapper around track-processor-js Processor
* in order to be compatible with a common interface BackgroundBlurProcessorInterface
* used accross the project.
* used across the project.
*/
export class BackgroundBlurTrackProcessorJsWrapper
implements BackgroundProcessorInterface
@@ -7,7 +7,7 @@ import {
} from '@livekit/components-core'
import { RoomEvent, Track } from 'livekit-client'
import * as React from 'react'
import { useState } from 'react'
import {
CarouselLayout,
ConnectionStateToast,
@@ -29,6 +29,7 @@ import { ParticipantTile } from '../components/ParticipantTile'
import { SidePanel } from '../components/SidePanel'
import { useSidePanel } from '../hooks/useSidePanel'
import { RecordingStateToast } from '../components/RecordingStateToast'
import { ScreenShareErrorModal } from '../components/ScreenShareErrorModal'
const LayoutWrapper = styled(
'div',
@@ -149,6 +150,8 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
const { isSidePanelOpen } = useSidePanel()
const [isShareErrorVisible, setIsShareErrorVisible] = useState(false)
return (
<div
className="lk-video-conference"
@@ -162,6 +165,10 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
value={layoutContext}
// onPinChange={handleFocusStateChange}
>
<ScreenShareErrorModal
isOpen={isShareErrorVisible}
onClose={() => setIsShareErrorVisible(false)}
/>
<div
// todo - extract these magic values into constant
style={{
@@ -207,7 +214,18 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
</LayoutWrapper>
<MainNotificationToast />
</div>
<ControlBar />
<ControlBar
onDeviceError={(e) => {
console.error(e)
if (
e.source == Track.Source.ScreenShare &&
e.error.toString() ==
'NotAllowedError: Permission denied by system'
) {
setIsShareErrorVisible(true)
}
}}
/>
<SidePanel />
</LayoutContextProvider>
)}
+12
View File
@@ -60,6 +60,17 @@
"createRoom": {
"heading": "",
"body": ""
},
"screenShare": {
"title": "",
"ariaLabel": "",
"message": "",
"macInstructions": "",
"macSystemPreferences": "",
"helpLinkText": "",
"helpLinkLabel": "",
"closeButton": "",
"newTab": ""
}
},
"controls": {
@@ -178,6 +189,7 @@
"access": {
"title": "",
"description": "",
"type": "",
"levels": {
"public": {
"label": "",
+12
View File
@@ -61,6 +61,17 @@
"createRoom": {
"heading": "Authentication Required",
"body": "This room has not been created yet. Please authenticate to create it or wait for an authenticated user to do so."
},
"screenShare": {
"title": "Unable to share your screen",
"ariaLabel": "Unable to share your screen",
"message": "Your browser may not be allowed to record the screen on your computer.",
"macInstructions": "Go to your",
"macSystemPreferences": "System Preferences",
"helpLinkText": "To learn more, see",
"helpLinkLabel": "Presentation issue",
"closeButton": "Dismiss",
"newTab": "New window"
}
},
"controls": {
@@ -177,6 +188,7 @@
"access": {
"title": "Room access",
"description": "These settings will also apply to future occurrences of this meeting.",
"type": "Meeting access types",
"levels": {
"public": {
"label": "Open",
+14 -2
View File
@@ -61,6 +61,17 @@
"createRoom": {
"heading": "Authentification requise",
"body": "Cette réunion n'a pas encore été créée. Veuillez vous authentifier pour la créer ou attendre qu'un utilisateur authentifié le fasse."
},
"screenShare": {
"title": "Impossible de partager votre écran",
"ariaLabel": "Impossible de partager votre écran",
"message": "Il se peut que votre navigateur ne soit pas autorisé à enregistrer l'écran sur votre ordinateur.",
"macInstructions": "Accèdez à vos",
"macSystemPreferences": "Préférences système",
"helpLinkText": "Pour en savoir plus, consulter",
"helpLinkLabel": "Problème de présentation",
"closeButton": "Ignorer",
"newTab": "Nouvelle fenêtre"
}
},
"controls": {
@@ -176,11 +187,12 @@
"description": "Ces paramètres organisateur vous permettent de garder le contrôle de votre réunion. Seuls les organisateurs peuvent accéder à ces commandes.",
"access": {
"title": "Accès à la réunion",
"description": "Ces paramètres s'appliqueront également aux futures occurences de cette réunion.",
"description": "Ces paramètres s'appliqueront également aux futures occurrences de cette réunion.",
"type": "Type d'accès à la réunion",
"levels": {
"public": {
"label": "Ouvrir",
"description": "Persone n'a à demander pour rejoindre la réunion."
"description": "Tout le monde peut rejoindre la réunion sans autorisation."
},
"trusted": {
"label": "Ouvrir aux personnes de confiance",
+74 -4
View File
@@ -34,7 +34,19 @@
"usernameEmpty": "Uw naam kan niet leeg zijn"
},
"cameraDisabled": "Camera is uitgeschakeld.",
"cameraStarting": "Camera wordt ingeschakeld."
"cameraStarting": "Camera wordt ingeschakeld.",
"waiting": {
"title": "Verzoek tot deelname...",
"body": "U kunt deelnemen aan dit gesprek wanneer iemand u toestemming geeft"
},
"denied": {
"title": "U kunt niet deelnemen aan dit gesprek",
"body": "Uw verzoek tot deelname is geweigerd."
},
"timeoutInvite": {
"title": "U kunt niet deelnemen aan dit gesprek",
"body": "Niemand heeft gereageerd op uw verzoek om deel te nemen aan het gesprek"
}
},
"leaveRoomPrompt": "Dat zal u de vergadering doen verlaten.",
"shareDialog": {
@@ -49,6 +61,17 @@
"createRoom": {
"heading": "Verificatie vereist",
"body": "Deze ruimte is nog niet gemaakt. Logt u alstublieft in om hem aan te maken, of wacht tot een ingelogde gebruiker dat doet."
},
"screenShare": {
"title": "Kan uw scherm niet delen",
"ariaLabel": "Kan uw scherm niet delen",
"message": "Het is mogelijk dat uw browser geen toestemming heeft om het scherm op uw computer op te nemen.",
"macInstructions": "Ga naar uw",
"macSystemPreferences": "Systeemvoorkeuren",
"helpLinkText": "Meer informatie, zie",
"helpLinkLabel": "Presentatieprobleem",
"closeButton": "Negeren",
"newTab": "Nieuw venster"
}
},
"controls": {
@@ -84,6 +107,10 @@
"open": "Verberg AI-assistent",
"closed": "Toon AI-assistant"
},
"admin": {
"open": "Verberg beheerder",
"closed": "Toon beheerder"
},
"support": "Ondersteuning",
"moreOptions": "Meer opties",
"reactions": {
@@ -129,13 +156,15 @@
"participants": "Deelnemers",
"effects": "Effecten",
"chat": "Berichten in de chat",
"transcript": "AI-assistent"
"transcript": "AI-assistent",
"admin": "Beheerdersbediening"
},
"content": {
"participants": "deelnemers",
"effects": "effecten",
"chat": "berichten",
"transcript": "AI-assistent"
"transcript": "AI-assistent",
"admin": "Beheerdersbediening"
},
"closeButton": "Verberg {{content}}"
},
@@ -154,6 +183,28 @@
"button": "Stop met opname"
}
},
"admin": {
"description": "Deze organisatorinstellingen geven u controle over uw vergadering. Alleen organisatoren hebben toegang tot deze bedieningselementen.",
"access": {
"title": "Toegang tot vergadering",
"description": "Deze instellingen zijn ook van toepassing op toekomstige sessies van deze vergadering.",
"type": "Vergaderings toegangstypen",
"levels": {
"public": {
"label": "Open",
"description": "Niemand hoeft toestemming te vragen om deel te nemen aan de vergadering."
},
"trusted": {
"label": "Open voor vertrouwde personen",
"description": "Geauthenticeerde personen hoeven geen toestemming te vragen om deel te nemen aan de vergadering."
},
"restricted": {
"label": "Beperkt",
"description": "Personen die niet zijn uitgenodigd voor de vergadering moeten vragen om deel te nemen."
}
}
}
},
"rating": {
"submit": "Indienen",
"question": "Wat vindt u van de kwaliteit van het gesprek?",
@@ -172,6 +223,12 @@
"heading": "Bedankt voor uw inzending",
"body": "Ons productteam neemt de tijd om uw feedback zorgvuldig te bekijken. We zullen zo snel mogelijk antwoorden."
},
"authenticationMessage": {
"heading": "Hoe kunnen we contact met u opnemen?",
"placeholder": "Uw e-mail",
"submit": "Verzenden",
"ignore": "Negeren"
},
"participants": {
"subheading": "In de ruimte",
"you": "U",
@@ -190,7 +247,20 @@
},
"raisedHands": "Opgestoken handen",
"lowerParticipantHand": "Laat {{name}}'s hand zakken",
"lowerParticipantsHand": "Laat alle handen zakken"
"lowerParticipantsHand": "Laat alle handen zakken",
"waiting": {
"title": "Wachtkamer",
"accept": {
"button": "Accepteren",
"label": "{{name}} toelaten tot de vergadering",
"all": "Alles accepteren"
},
"deny": {
"button": "Weigeren",
"label": "{{name}} weigeren voor de vergadering",
"all": "Alles weigeren"
}
}
},
"recording": {
"label": "Opnemen"
+7 -1
View File
@@ -75,7 +75,13 @@ export const A = ({
return (
<Link
{...props}
className={link({ size, externalIcon, underline, footer, color })}
className={link({
size,
externalIcon,
underline,
footer,
color,
})}
/>
)
}
+2
View File
@@ -218,8 +218,10 @@ export const Field = <T extends object>({
{item.description && (
<Text
variant="note"
wrap={'pretty'}
className={css({
textStyle: 'sm',
marginBottom: '0.5rem',
})}
>
{item.description}