diff --git a/app/components/content-mdx-provider.tsx b/app/components/content-mdx-provider.tsx index 3e8997dd1..80ec1977a 100644 --- a/app/components/content-mdx-provider.tsx +++ b/app/components/content-mdx-provider.tsx @@ -3,7 +3,16 @@ import { Box } from "@mui/material"; import { ReactNode } from "react"; import { ContentLayout, StaticContentLayout } from "@/components/layout"; -import { Contribute, Examples, Intro, Tutorial } from "@/homepage"; +import { + BugReport, + Contribute, + Examples, + Intro, + Newsletter, + Tutorial, +} from "@/homepage"; +import { FeatureRequest } from "@/homepage/feature-request"; +import { Section } from "@/homepage/section"; const castContentId = (contentId: unknown) => { if (typeof contentId === "string") { @@ -35,6 +44,10 @@ const defaultMDXComponents = { Tutorial, Examples, Contribute, + Newsletter, + BugReport, + Section, + FeatureRequest, }; export const ContentMDXProvider = ({ children }: { children: ReactNode }) => { diff --git a/app/docs/homepage.docs.mdx b/app/docs/homepage.docs.mdx index 65a5fc793..4f054848d 100644 --- a/app/docs/homepage.docs.mdx +++ b/app/docs/homepage.docs.mdx @@ -1,25 +1,38 @@ import { Box } from "@mui/material"; import { ReactSpecimen } from "./catalog"; -import { Contribute, Examples, Intro, Tutorial } from "@/homepage"; -import { Canvas, Meta } from '@storybook/blocks'; -import * as HomepageStories from './homepage.stories'; +import { + BugReport, + Contribute, + Examples, + Intro, + Newsletter, + Tutorial, +} from "@/homepage"; +import { bugReportTemplates } from "@/templates/email/bug-report"; +import { OWNER_ORGANIZATION_EMAIL } from "@/templates/email/config"; +import { featureRequestTemplates } from "@/templates/email/feature-request"; +import { Canvas, Meta } from "@storybook/blocks"; +import { createMailtoLink } from "../../app/templates/email"; +import * as HomepageStories from "./homepage.stories"; > The Homepage is the main page you see when you enter the Visualize app. -It consists of 4 different components: Intro, Tutorial, Examples and Contribute. In order to compose a complete Homepage, you have to use them all in the correct order. +It consists of 7 different components: Intro, Tutorial, Examples, Newsletter, +Bug Reporting, Feature Requesting and Contribute. In order to compose a complete +Homepage, you have to use them all in the correct order. -You can either import them directly to JSX files or create a separate MDX file and use a MDXProvider to render the page (see ContentMDXProvider component). +You can either import them directly to JSX files or create a separate MDX file +and use a MDXProvider to render the page (see ContentMDXProvider component). - ## How to use ```jsx -import { Contribute, Examples, Intro, Tutorial } from "../homepage"; +import { Contribute, Examples, Intro, Tutorial, Newsletter, BugReport, FeatureRequest } from "../homepage"; + + + -``` \ No newline at end of file +``` diff --git a/app/docs/homepage.stories.tsx b/app/docs/homepage.stories.tsx index ad3cb8480..ccd8ec845 100644 --- a/app/docs/homepage.stories.tsx +++ b/app/docs/homepage.stories.tsx @@ -1,7 +1,21 @@ import { Box } from "@mui/material"; import { Meta } from "@storybook/react"; -import { Contribute, Examples, Intro, Tutorial } from "@/homepage"; +import { + BugReport, + Contribute, + Examples, + Intro, + Newsletter, + Tutorial, +} from "@/homepage"; +import { FeatureRequest } from "@/homepage/feature-request"; +import { Section } from "@/homepage/section"; +import { bugReportTemplates } from "@/templates/email/bug-report"; +import { OWNER_ORGANIZATION_EMAIL } from "@/templates/email/config"; +import { featureRequestTemplates } from "@/templates/email/feature-request"; + +import { createMailtoLink } from "../../app/templates/email"; import { ReactSpecimen } from "./catalog"; @@ -33,12 +47,55 @@ const HomepageStory = { example2Headline="Use powerful customizations" example2Description="With the help of custom filters and data segmentation, even complex issues can be visualized." /> - +
+ +
+ +
+ +
+ +
+ +
), diff --git a/app/homepage/bug-report.tsx b/app/homepage/bug-report.tsx new file mode 100644 index 000000000..2c5ab05a5 --- /dev/null +++ b/app/homepage/bug-report.tsx @@ -0,0 +1,70 @@ +import { Button, Link, Typography } from "@mui/material"; + +import Flex from "@/components/flex"; + +export const BugReport = ({ + headline, + description, + buttonLabel, + buttonUrl, +}: { + headline: string; + description: string; + buttonLabel: string; + buttonUrl: string; +}) => { + return ( + + + + {headline} + + + {description} + + + + + + + ); +}; diff --git a/app/homepage/contribute.tsx b/app/homepage/contribute.tsx index 696344da7..fa797f4e3 100644 --- a/app/homepage/contribute.tsx +++ b/app/homepage/contribute.tsx @@ -1,5 +1,4 @@ -import { Box, Button, Link, Typography } from "@mui/material"; -import * as React from "react"; +import { Button, Link, Typography } from "@mui/material"; import Flex from "@/components/flex"; @@ -15,50 +14,57 @@ export const Contribute = ({ buttonUrl: string; }) => { return ( - - - - - - {headline} - - - {description} - - - - - - - - + + + + {headline} + + + {description} + + + + + + ); }; diff --git a/app/homepage/feature-request.tsx b/app/homepage/feature-request.tsx new file mode 100644 index 000000000..d06c5d058 --- /dev/null +++ b/app/homepage/feature-request.tsx @@ -0,0 +1,69 @@ +import { Button, Link, Typography } from "@mui/material"; + +import Flex from "@/components/flex"; + +export const FeatureRequest = ({ + headline, + description, + buttonLabel, + buttonUrl, +}: { + headline: string; + description: string; + buttonLabel: string; + buttonUrl: string; +}) => { + return ( + + + + {headline} + + + {description} + + + + + + + ); +}; diff --git a/app/homepage/index.ts b/app/homepage/index.ts index b227d2c40..7ad20a2e9 100644 --- a/app/homepage/index.ts +++ b/app/homepage/index.ts @@ -1,4 +1,6 @@ +export * from "./bug-report"; +export * from "./contribute"; +export * from "./examples"; export * from "./intro"; +export * from "./newsletter"; export * from "./tutorial"; -export * from "./examples"; -export * from "./contribute"; diff --git a/app/homepage/newsletter.tsx b/app/homepage/newsletter.tsx new file mode 100644 index 000000000..51f6daba8 --- /dev/null +++ b/app/homepage/newsletter.tsx @@ -0,0 +1,69 @@ +import { Button, Link, Typography } from "@mui/material"; + +import Flex from "@/components/flex"; + +export const Newsletter = ({ + headline, + description, + buttonLabel, + buttonUrl, +}: { + headline: string; + description: string; + buttonLabel: string; + buttonUrl: string; +}) => { + return ( + + + + {headline} + + + {description} + + + + + + + ); +}; diff --git a/app/homepage/section.tsx b/app/homepage/section.tsx new file mode 100644 index 000000000..6563eb761 --- /dev/null +++ b/app/homepage/section.tsx @@ -0,0 +1,30 @@ +import { Box, SxProps } from "@mui/material"; +import { Theme } from "@mui/material/styles"; + +import Flex from "@/components/flex"; + +export const Section = ({ + children, + sx = { backgroundColor: "primary.main", color: "grey.100", width: "100%" }, +}: { + children: React.ReactNode; + sx?: SxProps; +}) => { + return ( + + + + {children} + + + + ); +}; diff --git a/app/static-pages/de/index.mdx b/app/static-pages/de/index.mdx index 475dc5664..0fd448f5b 100644 --- a/app/static-pages/de/index.mdx +++ b/app/static-pages/de/index.mdx @@ -1,3 +1,12 @@ +import { bugReportTemplates } from "@/templates/email/bug-report"; +import { featureRequestTemplates } from "@/templates/email/feature-request"; +import { Divider } from "@mui/material"; +import { createMailtoLink } from "../../../app/templates/email"; +import { + OWNER_ORGANIZATION_EMAIL, + SUPPORT_EMAIL, +} from "../../../app/templates/email/config"; + export const contentId = "home"; - +
+ + + +
+
+ + + +
diff --git a/app/static-pages/en/index.mdx b/app/static-pages/en/index.mdx index 380ab047b..c3600380b 100644 --- a/app/static-pages/en/index.mdx +++ b/app/static-pages/en/index.mdx @@ -1,3 +1,12 @@ +import { bugReportTemplates } from "@/templates/email/bug-report"; +import { featureRequestTemplates } from "@/templates/email/feature-request"; +import { Divider } from "@mui/material"; +import { createMailtoLink } from "../../../app/templates/email"; +import { + OWNER_ORGANIZATION_EMAIL, + SUPPORT_EMAIL, +} from "../../../app/templates/email/config"; + export const contentId = "home"; - +
+ + + +
+
+ + + +
diff --git a/app/static-pages/fr/index.mdx b/app/static-pages/fr/index.mdx index 35e80c5d9..8f66dbaf4 100644 --- a/app/static-pages/fr/index.mdx +++ b/app/static-pages/fr/index.mdx @@ -1,3 +1,12 @@ +import { bugReportTemplates } from "@/templates/email/bug-report"; +import { featureRequestTemplates } from "@/templates/email/feature-request"; +import { Divider } from "@mui/material"; +import { createMailtoLink } from "../../../app/templates/email"; +import { + OWNER_ORGANIZATION_EMAIL, + SUPPORT_EMAIL, +} from "../../../app/templates/email/config"; + export const contentId = "home"; - +
+ + + +
+
+ + + +
diff --git a/app/static-pages/it/index.mdx b/app/static-pages/it/index.mdx index 347b4fa35..fae06cbdf 100644 --- a/app/static-pages/it/index.mdx +++ b/app/static-pages/it/index.mdx @@ -1,3 +1,13 @@ +import { bugReportTemplates } from "@/templates/email/bug-report"; +import { featureRequestTemplates } from "@/templates/email/feature-request"; +import { Divider } from "@mui/material"; + +import { createMailtoLink } from "../../../app/templates/email"; +import { + OWNER_ORGANIZATION_EMAIL, + SUPPORT_EMAIL, +} from "../../../app/templates/email/config"; + export const contentId = "home"; - +
+ + + +
+
+ + + +
diff --git a/app/templates/email/bug-report.ts b/app/templates/email/bug-report.ts new file mode 100644 index 000000000..695f198dd --- /dev/null +++ b/app/templates/email/bug-report.ts @@ -0,0 +1,146 @@ +export const bugReportTemplates = { + en: ` +Bug Report + +Describe the bug +A clear and concise description of what the bug is. If it seems connected to some data problem (missing values, wrong parsing), please first check the cube in Cube Validator (https://cube-validator.lindas.admin.ch/select) to see if everything is fine there. +Please describe... + +---------------------------------------------- +To Reproduce +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '...' +3. Scroll down to '...' +4. See error + +---------------------------------------------- +Expected behavior +A clear and concise description of what you expected to happen. +Please describe... + +---------------------------------------------- +Screenshots or video +If applicable, add screenshots or a short video to help put your problem into a context. + +---------------------------------------------- +Environment +Please complete the following information. +- Visualize environment and version: [e.g., INT v4.9.4] +- Browser and version [e.g., Chrome 107] + +---------------------------------------------- +Additional context +Add any other context about the problem here. +Please describe... +`, + + de: ` +Fehlermeldung + +---------------------------------------------- +Beschreiben Sie den Fehler +Eine klare und präzise Beschreibung des Fehlers. Wenn es mit einem Datenproblem zusammenhängt (fehlende Werte, falsche Analyse), überprüfen Sie bitte zuerst den Cube im Cube Validator (https://cube-validator.lindas.admin.ch/select), um sicherzustellen, dass dort alles in Ordnung ist. +Bitte beschreiben Sie... + +---------------------------------------------- +Zum Reproduzieren +Schritte zum Reproduzieren des Verhaltens: +1. Gehen Sie zu '...' +2. Klicken Sie auf '...' +3. Scrollen Sie nach unten zu '...' +4. Fehlermeldung erscheint + +---------------------------------------------- +Erwartetes Verhalten +Eine klare und präzise Beschreibung dessen, was Sie erwartet haben. +Bitte beschreiben Sie... + +---------------------------------------------- +Screenshots oder Video +Falls zutreffend, fügen Sie Screenshots oder ein kurzes Video hinzu, um Ihr Problem in einen Kontext zu setzen. + +---------------------------------------------- +Umgebung +Bitte vervollständigen Sie die folgenden Informationen. +- Visualize-Umgebung und Version: [z.B., INT v4.9.4] +- Browser und Version [z.B., Chrome 107] + +---------------------------------------------- +Zusätzlicher Kontext +Fügen Sie hier weitere Kontextinformationen zum Problem hinzu. +Bitte beschreiben Sie... +`, + + fr: ` +Rapport de bug + +Description du bug +Une description claire et concise du bug. S'il semble lié à un problème de données (valeurs manquantes, analyse incorrecte), veuillez d'abord vérifier le cube dans le Cube Validator (https://cube-validator.lindas.admin.ch/select) pour vous assurer que tout y est correct. +Veuillez décrire... + +---------------------------------------------- +Pour reproduire +Étapes pour reproduire le comportement : +1. Aller à '...' +2. Cliquer sur '...' +3. Faire défiler jusqu'à '...' +4. Voir l'erreur + +---------------------------------------------- +Comportement attendu +Une description claire et concise de ce que vous attendiez. +Veuillez décrire... + +---------------------------------------------- +Captures d'écran ou vidéo +Le cas échéant, ajoutez des captures d'écran ou une courte vidéo pour mettre votre problème en contexte. + +---------------------------------------------- +Environnement +Veuillez compléter les informations suivantes. +- Environnement et version Visualize : [ex. INT v4.9.4] +- Navigateur et version [ex. Chrome 107] + +---------------------------------------------- +Contexte supplémentaire +Ajoutez ici tout autre contexte concernant le problème. +Veuillez décrire... +`, + + it: ` +Segnalazione di bug + +Descrizione del bug +Una descrizione chiara e concisa del bug. Se sembra collegato a un problema di dati (valori mancanti, analisi errata), controllare prima il cubo nel Cube Validator (https://cube-validator.lindas.admin.ch/select) per assicurarsi che tutto sia a posto. +Si prega di descrivere... + +---------------------------------------------- +Per riprodurre +Passaggi per riprodurre il comportamento: +1. Andare a '...' +2. Cliccare su '...' +3. Scorrere fino a '...' +4. Vedere l'errore + +---------------------------------------------- +Comportamento previsto +Una descrizione chiara e concisa di ciò che ci si aspettava. +Si prega di descrivere... + +---------------------------------------------- +Screenshot o video +Se applicabile, aggiungere screenshot o un breve video per contestualizzare il problema. + +---------------------------------------------- +Ambiente +Si prega di completare le seguenti informazioni. +- Ambiente e versione Visualize: [es. INT v4.9.4] +- Browser e versione [es. Chrome 107] + +---------------------------------------------- +Contesto aggiuntivo +Aggiungere qui qualsiasi altro contesto sul problema. +Si prega di descrivere... +`, +}; diff --git a/app/templates/email/config.ts b/app/templates/email/config.ts new file mode 100644 index 000000000..9e6151b9d --- /dev/null +++ b/app/templates/email/config.ts @@ -0,0 +1,2 @@ +export const OWNER_ORGANIZATION_EMAIL = "visualize@bafu.admin.ch"; +export const SUPPORT_EMAIL = "support@interactivethings.com"; diff --git a/app/templates/email/feature-request.ts b/app/templates/email/feature-request.ts new file mode 100644 index 000000000..285256df4 --- /dev/null +++ b/app/templates/email/feature-request.ts @@ -0,0 +1,113 @@ +export const featureRequestTemplates = { + en: ` +New Feature + +Is your feature request related to a problem? +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] +Please describe... + +---------------------------------------------- +Describe the solution you'd like +A clear and concise description of what you want to happen. +Please describe... + +---------------------------------------------- +Describe alternatives you've considered +A clear and concise description of any alternative solutions or features you've considered. +Please describe... + +---------------------------------------------- +Use cases and impact +Examples of how the feature would be beneficial and an estimation of how much impact it would have. +Please describe... + +---------------------------------------------- +Additional context +Add any other context or screenshots about the feature request here. +Please describe... +`, + + de: ` +Neue Funktion + +Bezieht sich Ihre Feature-Anfrage auf ein Problem? +Eine klare und präzise Beschreibung des Problems. Z.B. Es frustriert mich immer, wenn [...] +Bitte beschreiben Sie... + +---------------------------------------------- +Beschreiben Sie die gewünschte Lösung +Eine klare und präzise Beschreibung dessen, was passieren soll. +Bitte beschreiben Sie... + +---------------------------------------------- +Beschreiben Sie Alternativen, die Sie in Betracht gezogen haben +Eine klare und präzise Beschreibung aller alternativen Lösungen oder Funktionen, die Sie in Betracht gezogen haben. +Bitte beschreiben Sie... + +---------------------------------------------- +Anwendungsfälle und Auswirkungen +Beispiele dafür, wie die Funktion nützlich wäre und eine Einschätzung der Auswirkungen. +Bitte beschreiben Sie... + +---------------------------------------------- +Zusätzlicher Kontext +Fügen Sie hier weitere Kontextinformationen oder Screenshots zur Feature-Anfrage hinzu. +Bitte beschreiben Sie... +`, + + fr: ` +Nouvelle fonctionnalité + +Votre demande de fonctionnalité est-elle liée à un problème ? +Une description claire et concise du problème. Ex. Je suis toujours frustré quand [...] +Veuillez décrire... + +---------------------------------------------- +Décrivez la solution que vous souhaitez +Une description claire et concise de ce que vous voulez qu'il se passe. +Veuillez décrire... + +---------------------------------------------- +Décrivez les alternatives que vous avez envisagées +Une description claire et concise des solutions ou fonctionnalités alternatives que vous avez envisagées. +Veuillez décrire... + +---------------------------------------------- +Cas d'utilisation et impact +Exemples de l'utilité de la fonctionnalité et estimation de son impact. +Veuillez décrire... + +---------------------------------------------- +Contexte supplémentaire +Ajoutez ici tout autre contexte ou captures d'écran concernant la demande de fonctionnalité. +Veuillez décrire... +`, + + it: ` +Nuova funzionalità + +La sua richiesta di funzionalità è legata a un problema? +Una descrizione chiara e concisa del problema. Es. Sono sempre frustrato quando [...] +Si prega di descrivere... + +---------------------------------- +Descriva la soluzione che vorrebbe +Una descrizione chiara e concisa di ciò che vuole che accada. +Si prega di descrivere... + +---------------------------------------------- +Descriva le alternative considerate +Una descrizione chiara e concisa di eventuali soluzioni o funzionalità alternative che ha considerato. +Si prega di descrivere... + +---------------------------------------------- +Casi d'uso e impatto +Esempi di come la funzionalità sarebbe utile e una stima del suo impatto. +Si prega di descrivere... + +---------------------------------------------- +Contesto aggiuntivo +Aggiunga qui qualsiasi altro contesto o screenshot sulla richiesta di funzionalità. +Si prega di descrivere... +`, +}; diff --git a/app/templates/email/index.ts b/app/templates/email/index.ts new file mode 100644 index 000000000..a1726e278 --- /dev/null +++ b/app/templates/email/index.ts @@ -0,0 +1,22 @@ +import { bugReportTemplates } from "./bug-report"; + +type EmailRecipients = { + to: string; + cc: string; +}; + +export const createMailtoLink = ( + lang: keyof typeof bugReportTemplates, + options: { + recipients: EmailRecipients; + template: typeof bugReportTemplates; + subject: string; + } +) => { + const template = options.template[lang]; + return `mailto:${options.recipients.to}?cc=${ + options.recipients.cc + }&subject=${encodeURIComponent(options.subject)}&body=${encodeURIComponent( + template + )}`; +};