Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion echo/directus/sync/collections/permissions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,9 @@
"fields": [
"disable_create_project",
"projects",
"whitelabel_logo"
"whitelabel_logo",
"legal_basis",
"privacy_policy_url"
],
"policy": "37a60e48-dd00-4867-af07-1fb22ac89078",
"_syncId": "25411e4e-fb6c-41e7-be7b-300ca3b503ef"
Expand Down
74 changes: 74 additions & 0 deletions echo/directus/sync/snapshot/fields/directus_users/legal_basis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"collection": "directus_users",
"field": "legal_basis",
"type": "string",
"meta": {
"collection": "directus_users",
"conditions": null,
"display": "labels",
"display_options": {
"choices": [
{
"text": "Client Managed",
"value": "client-managed"
},
{
"text": "Consent",
"value": "consent"
},
{
"text": "dembrane events ",
"value": "dembrane-events"
Comment on lines +20 to +21
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove trailing whitespace in legal basis choice labels

Line 20 and Line 41 use "dembrane events " with a trailing space. This can cause inconsistent rendering/selection text in Directus UI and exports.

Proposed fix
-          "text": "dembrane events ",
+          "text": "dembrane events",
...
-          "text": "dembrane events ",
+          "text": "dembrane events",

Also applies to: 41-42

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@echo/directus/sync/snapshot/fields/directus_users/legal_basis.json` around
lines 20 - 21, The "text" choice entries currently contain a trailing space
("dembrane events ") which causes inconsistent rendering; locate the choice
objects with "text": "dembrane events " (paired with "value": "dembrane-events")
and remove the trailing whitespace so the text becomes "dembrane events" in both
occurrences (the duplicate entry further down the array as well) to ensure
consistent labels in Directus.

}
]
},
"field": "legal_basis",
"group": null,
"hidden": false,
"interface": "select-dropdown",
"note": "GDPR legal basis for processing participant data. Affects consent flows in the participant portal.",
"options": {
"choices": [
{
"text": "Client Managed",
"value": "client-managed"
},
{
"text": "Consent",
"value": "consent"
},
{
"text": "dembrane events ",
"value": "dembrane-events"
}
]
},
"readonly": false,
"required": false,
"searchable": true,
"sort": 6,
"special": null,
"translations": null,
"validation": null,
"validation_message": null,
"width": "full"
},
"schema": {
"name": "legal_basis",
"table": "directus_users",
"data_type": "character varying",
"default_value": "client-managed",
"max_length": 255,
"numeric_precision": null,
"numeric_scale": null,
"is_nullable": true,
"is_unique": false,
"is_indexed": false,
"is_primary_key": false,
"is_generated": false,
"generation_expression": null,
"has_auto_increment": false,
"foreign_key_table": null,
"foreign_key_column": null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"collection": "directus_users",
"field": "privacy_policy_url",
"type": "string",
"meta": {
"collection": "directus_users",
"conditions": null,
"display": null,
"display_options": null,
"field": "privacy_policy_url",
"group": null,
"hidden": false,
"interface": "input",
"note": "URL to the organiser's privacy policy. Shown to participants when Legal Basis is 'Consent'.",
"options": {
"placeholder": "https://example.com/privacy-policy"
},
"readonly": false,
"required": false,
"searchable": true,
"sort": 7,
"special": null,
"translations": null,
"validation": null,
"validation_message": null,
"width": "full"
},
"schema": {
"name": "privacy_policy_url",
"table": "directus_users",
"data_type": "character varying",
"default_value": null,
"max_length": 255,
"numeric_precision": null,
"numeric_scale": null,
"is_nullable": true,
"is_unique": false,
"is_indexed": false,
"is_primary_key": false,
"is_generated": false,
"generation_expression": null,
"has_auto_increment": false,
"foreign_key_table": null,
"foreign_key_column": null
}
}
2 changes: 2 additions & 0 deletions echo/frontend/src/components/auth/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export const useCurrentUser = ({
"disable_create_project",
"tfa_secret",
"whitelabel_logo",
"legal_basis",
"privacy_policy_url",
],
}),
);
Expand Down
4 changes: 2 additions & 2 deletions echo/frontend/src/components/layout/ParticipantHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { DIRECTUS_PUBLIC_URL } from "@/config";
import { useI18nNavigate } from "@/hooks/useI18nNavigate";
import { useWhitelabelLogo } from "@/hooks/useWhitelabelLogo";
import { testId } from "@/lib/testUtils";
import { useParticipantProjectById } from "../participant/hooks";
import { Logo } from "../common/Logo";
import { useParticipantProjectById } from "../participant/hooks";
import { ParticipantSettingsModal } from "../participant/ParticipantSettingsModal";

export const ParticipantHeader = () => {
Expand All @@ -28,7 +28,7 @@ export const ParticipantHeader = () => {
const projectQuery = useParticipantProjectById(projectId ?? "");

useEffect(() => {
const logoFileId = (projectQuery.data as any)?.whitelabel_logo_url;
const logoFileId = projectQuery.data?.whitelabel_logo_url;
if (logoFileId) {
setLogoUrl(`${DIRECTUS_PUBLIC_URL}/assets/${logoFileId}`);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ export interface LanguageCards {
[language: string]: Section[];
}

const ParticipantOnboardingCards = ({ project }: { project: Project }) => {
const ParticipantOnboardingCards = ({
project,
}: {
project: ParticipantProject;
}) => {
const [searchParams] = useSearchParams();
const skipOnboarding = searchParams.get("skipOnboarding");

Expand Down Expand Up @@ -74,10 +78,12 @@ const ParticipantOnboardingCards = ({ project }: { project: Project }) => {
const { getSystemCards } = useOnboardingCards();

const tutorialSlug = project.default_conversation_tutorial_slug ?? "none";
const legalBasis = project.legal_basis ?? "client-managed";
const privacyPolicyUrl = project.privacy_policy_url;

const cards: LanguageCards = {
"de-DE": [
...getSystemCards("de-DE", tutorialSlug),
...getSystemCards("de-DE", tutorialSlug, legalBasis, privacyPolicyUrl),
{
section: "Mikrofon-Check",
slides: [
Expand All @@ -100,7 +106,7 @@ const ParticipantOnboardingCards = ({ project }: { project: Project }) => {
},
],
"en-US": [
...getSystemCards("en-US", tutorialSlug),
...getSystemCards("en-US", tutorialSlug, legalBasis, privacyPolicyUrl),
{
section: "Microphone Check",
slides: [
Expand All @@ -123,7 +129,7 @@ const ParticipantOnboardingCards = ({ project }: { project: Project }) => {
},
],
"es-ES": [
...getSystemCards("es-ES", tutorialSlug),
...getSystemCards("es-ES", tutorialSlug, legalBasis, privacyPolicyUrl),
{
section: "Verificación del Micrófono",
slides: [
Expand All @@ -146,7 +152,7 @@ const ParticipantOnboardingCards = ({ project }: { project: Project }) => {
},
],
"fr-FR": [
...getSystemCards("fr-FR", tutorialSlug),
...getSystemCards("fr-FR", tutorialSlug, legalBasis, privacyPolicyUrl),
{
section: "Vérification du Microphone",
slides: [
Expand All @@ -169,7 +175,7 @@ const ParticipantOnboardingCards = ({ project }: { project: Project }) => {
},
],
"it-IT": [
...getSystemCards("it-IT", tutorialSlug),
...getSystemCards("it-IT", tutorialSlug, legalBasis, privacyPolicyUrl),
{
section: "Controllo Microfono",
slides: [
Expand All @@ -192,7 +198,7 @@ const ParticipantOnboardingCards = ({ project }: { project: Project }) => {
},
],
"nl-NL": [
...getSystemCards("nl-NL", tutorialSlug),
...getSystemCards("nl-NL", tutorialSlug, legalBasis, privacyPolicyUrl),
{
section: "Microfoon Controle",
slides: [
Expand Down Expand Up @@ -330,7 +336,11 @@ const ParticipantOnboardingCards = ({ project }: { project: Project }) => {
)}

{currentCard.extraHelp && (
<Text className="text-sm" ta="left">
<Text
className="text-sm"
ta="left"
style={{ whiteSpace: "pre-line" }}
>
{currentCard.extraHelp}
</Text>
)}
Expand Down Expand Up @@ -371,7 +381,8 @@ const ParticipantOnboardingCards = ({ project }: { project: Project }) => {
label={currentCard.checkbox.label}
classNames={{
body: "items-center",
label: "text-lg text-gray-700",
label:
"text-lg leading-snug pl-4 text-gray-700 text-left pt-0.5",
Comment on lines +384 to +385
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Use theme variable for checkbox label color instead of text-gray-700.

text-gray-700 hardcodes a theme-dependent color. Keep spacing/layout utility classes, but move text color to CSS variables so theme changes propagate.

🎯 Proposed adjustment
 								<Checkbox
@@
 									classNames={{
 										body: "items-center",
-										label:
-											"text-lg leading-snug pl-4 text-gray-700 text-left pt-0.5",
+										label: "text-lg leading-snug pl-4 text-left pt-0.5",
 										root: "items-start",
 									}}
+									styles={{ label: { color: "var(--app-text)" } }}
 									{...testId("portal-onboarding-checkbox")}
 								/>

As per coding guidelines: "Keep static utility classes ... move theme-dependent colors to CSS variables" and "Use var(--app-background) and var(--app-text) instead of hardcoded colors."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@echo/frontend/src/components/participant/ParticipantOnboardingCards.tsx`
around lines 384 - 385, The checkbox label class in ParticipantOnboardingCards
(the label prop string containing "text-lg leading-snug pl-4 text-gray-700
text-left pt-0.5") hardcodes a theme color; replace the theme-dependent
"text-gray-700" with the app CSS variable (e.g. use a utility or inline style
referencing var(--app-text) or a small CSS class that sets color:
var(--app-text)) while preserving the spacing/layout utilities ("text-lg
leading-snug pl-4 text-left pt-0.5") so theme changes propagate correctly.

root: "items-start",
}}
{...testId("portal-onboarding-checkbox")}
Expand Down
Loading
Loading