Skip to content

Commit

Permalink
feat(forms): emfleshen language version tabs of survey editor
Browse files Browse the repository at this point in the history
  • Loading branch information
japsu committed Feb 13, 2024
1 parent 4399d5a commit ee0a855
Show file tree
Hide file tree
Showing 12 changed files with 331 additions and 62 deletions.
10 changes: 10 additions & 0 deletions frontend/src/__generated__/gql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions frontend/src/__generated__/graphql.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ModalButton from "../dimensions/ModalButton";
import { addLanguageVersion } from "./actions";
import { EditSurveyPageFragment } from "@/__generated__/graphql";
import { Survey } from "./models";
import { Field } from "@/components/forms/models";
import { SchemaForm } from "@/components/forms/SchemaForm";
import ServerTabs, { Tab } from "@/components/ServerTabs";
Expand All @@ -9,7 +9,7 @@ import { Translations } from "@/translations/en";
interface Props {
translations: Translations;
eventSlug: string;
survey: EditSurveyPageFragment;
survey: Survey;
active: string;
}

Expand All @@ -23,35 +23,45 @@ export default function SurveyEditorTabs({
const supportedLanguages: Record<string, string> =
translations.LanguageSwitcher.supportedLanguages;

const url = `/events/${eventSlug}/surveys/${survey.slug}/edit/`;
const tabs: Tab[] = [
{
slug: "properties",
title: t.tabs.properties,
href: "/edit",
href: `${url}`,
},
];

for (const languageVersion of survey.languages) {
// graphql enums are upper case :(
const languageCode = languageVersion.language.toLowerCase();
const languageName =
supportedLanguages[languageCode] ?? languageVersion.language;

tabs.push({
slug: languageCode,
title: supportedLanguages[languageCode] ?? languageVersion.language,
href: `/events/${eventSlug}/surveys/${survey.slug}/edit/${languageCode}`,
title: t.tabs.languageVersion(languageName),
href: `${url}/${languageCode}`,
});
}

// languages that are not yet added to the survey
const potentialLanguages = Object.entries(supportedLanguages).filter(
([languageCode, _]) =>
!survey.languages.find(
(form) => form.language.toLowerCase() === languageCode,
),
);

const addLanguageFields: Field[] = [
{
slug: "language",
type: "SingleSelect",
title: t.addLanguageModal.language,
choices: Object.entries(supportedLanguages).map(
([languageCode, language]) => ({
slug: languageCode,
title: language,
}),
),
choices: potentialLanguages.map(([languageCode, language]) => ({
slug: languageCode,
title: language,
})),
},
];

Expand All @@ -66,6 +76,7 @@ export default function SurveyEditorTabs({
label={`➕ ${t.tabs.addLanguage}…`}
messages={t.addLanguageModal.actions}
action={addLanguageVersion.bind(null, eventSlug, survey.slug)}
disabled={potentialLanguages.length === 0}
>
<SchemaForm
fields={addLanguageFields}
Expand All @@ -75,5 +86,6 @@ export default function SurveyEditorTabs({
);
},
});

return <ServerTabs tabs={tabs} active={active} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Link from "next/link";

import { ReactNode } from "react";
import Card from "react-bootstrap/Card";
import CardBody from "react-bootstrap/CardBody";
import { Survey } from "./models";
import SurveyEditorTabs from "./SurveyEditorTabs";
import ViewContainer from "@/components/ViewContainer";
import ViewHeading from "@/components/ViewHeading";
import { getTranslations } from "@/translations";

interface Props {
params: {
locale: string; // UI language
eventSlug: string;
surveySlug: string;
};

survey: Survey;
activeTab: string;
children: ReactNode;
}

export default function SurveyEditorView({
params,
survey,
activeTab,
children,
}: Props) {
const { locale, eventSlug } = params;
const translations = getTranslations(locale);
const t = translations.Survey;

return (
<ViewContainer>
<Link className="link-subtle" href={`/events/${eventSlug}/surveys`}>
&lt; {t.actions.returnToSurveyList}
</Link>

<ViewHeading>
{t.editSurveyPage.title}
<ViewHeading.Sub>{survey.title}</ViewHeading.Sub>
</ViewHeading>

<SurveyEditorTabs
eventSlug={eventSlug}
survey={survey}
translations={translations}
active={activeTab}
/>
<Card className="mb-2">
<CardBody>{children}</CardBody>
</Card>
</ViewContainer>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"use server";

export async function updateForm(
eventSlug: string,
surveySlug: string,
language: string,
formData: FormData,
) {
console.log("updateForm", {
eventSlug,
surveySlug,
language,
formData: Object.fromEntries(formData),
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import Link from "next/link";
import { notFound } from "next/navigation";

import Card from "react-bootstrap/Card";
import CardBody from "react-bootstrap/CardBody";
import SurveyEditorTabs from "../SurveyEditorTabs";
import SurveyEditorView from "../SurveyEditorView";
import { updateForm } from "./actions";
import { graphql } from "@/__generated__";
import { getClient } from "@/apolloClient";
import { auth } from "@/auth";
import { getPropertiesFormFields } from "@/components/forms/getPropertiesFormFields";
import { Field } from "@/components/forms/models";
import { SchemaForm } from "@/components/forms/SchemaForm";
import SubmitButton from "@/components/forms/SubmitButton";
import SignInRequired from "@/components/SignInRequired";
import ViewContainer from "@/components/ViewContainer";
import ViewHeading from "@/components/ViewHeading";
import getPageTitle from "@/helpers/getPageTitle";
import { getTranslations } from "@/translations";

graphql(`
fragment EditSurveyLanguagePage on SurveyType {
slug
title(lang: $locale)
form(lang: $language) {
title
description
thankYouMessage
fields
}
languages {
language
}
}
`);

const query = graphql(`
query EditSurveyLanguagePageQuery(
$eventSlug: String!
$surveySlug: String!
$language: String!
$locale: String
) {
event(slug: $eventSlug) {
name
forms {
survey(slug: $surveySlug) {
...EditSurveyLanguagePage
}
}
}
}
`);

interface Props {
params: {
locale: string; // UI language
eventSlug: string;
surveySlug: string;
language: string; // language code of form being edited
};
}

export const revalidate = 0;

export async function generateMetadata({ params }: Props) {
const { locale, eventSlug, surveySlug, language } = params;
const translations = getTranslations(locale);

// TODO encap
const session = await auth();
if (!session) {
return translations.SignInRequired.metadata;
}

const t = translations.Survey;

try {
const { data } = await getClient().query({
query,
variables: { locale, eventSlug, surveySlug, language },
});

if (!data.event?.forms?.survey?.form) {
notFound();
}

const title = getPageTitle({
translations,
event: data.event,
subject: data.event.forms.survey.form.title,
viewTitle: t.editSurveyPage.title,
});

return { title };
} catch (e) {
console.log(JSON.stringify(e, null, 2));
}
}

export default async function EditSurveyPage({ params }: Props) {
const { locale, eventSlug, surveySlug, language } = params;
const translations = getTranslations(locale);
const t = translations.Survey;
const session = await auth();

// TODO encap
if (!session) {
return <SignInRequired messages={translations.SignInRequired} />;
}

const { data } = await getClient().query({
query,
variables: { locale, eventSlug, surveySlug, language },
});

if (!data?.event?.forms?.survey?.form) {
notFound();
}

const survey = data.event.forms.survey;
const form = data.event.forms.survey.form;

const fields: Field[] = getPropertiesFormFields(
translations.FormEditor.formPropertiesForm,
);

return (
<SurveyEditorView params={params} survey={survey} activeTab={language}>
<form action={updateForm.bind(null, eventSlug, surveySlug, language)}>
<SchemaForm
fields={fields}
values={form}
messages={translations.SchemaForm}
/>
<SubmitButton>{t.actions.saveProperties}</SubmitButton>
</form>
</SurveyEditorView>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface Survey {
slug: string;
title?: string | null;
languages: {
language: string;
}[];
}
Loading

0 comments on commit ee0a855

Please sign in to comment.