Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forms - Localization support #185

Draft
wants to merge 37 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6202193
rename type lang
softmarshmallow Sep 1, 2024
ac64146
footer preview
softmarshmallow Sep 1, 2024
6b2c6aa
add stepperize
softmarshmallow Sep 1, 2024
df517ad
sidebar styles
softmarshmallow Sep 1, 2024
5d04c9e
ui
softmarshmallow Sep 1, 2024
d2e2078
wip - language control
softmarshmallow Sep 1, 2024
4a58763
Merge branch 'main' of https://github.com/gridaco/grida into forms
softmarshmallow Sep 2, 2024
f0c572d
mv
softmarshmallow Sep 2, 2024
826b63b
lang state
softmarshmallow Sep 2, 2024
20a0d69
langs add actions
softmarshmallow Sep 2, 2024
1930261
delete confirmation
softmarshmallow Sep 2, 2024
4262790
switch default
softmarshmallow Sep 2, 2024
dc10234
split reducer
softmarshmallow Sep 3, 2024
2bc96ca
rename
softmarshmallow Sep 3, 2024
30e0efe
grid header style
softmarshmallow Sep 3, 2024
e0203b9
issues/new routing
softmarshmallow Sep 3, 2024
726d380
message action
softmarshmallow Sep 3, 2024
077d709
wip translate in panel
softmarshmallow Sep 3, 2024
767311e
translator view
softmarshmallow Sep 3, 2024
d21ef81
clean block
softmarshmallow Sep 7, 2024
1571a1b
Merge branch 'main' of https://github.com/gridaco/grida into forms
softmarshmallow Sep 7, 2024
86caa2d
update state
softmarshmallow Sep 7, 2024
bd76add
init g11n resources
softmarshmallow Sep 7, 2024
feba6ba
translations editor page
softmarshmallow Sep 7, 2024
bc14776
states
softmarshmallow Sep 7, 2024
21d153f
mv supabase client
softmarshmallow Sep 8, 2024
2f3aa46
rename clients
softmarshmallow Sep 8, 2024
ba91b71
types
softmarshmallow Sep 8, 2024
1e1b2f3
fix build
softmarshmallow Sep 8, 2024
920a309
Merge branch 'main' of https://github.com/gridaco/grida into forms
softmarshmallow Sep 8, 2024
dd1803c
Merge branch 'main' of https://github.com/gridaco/grida into forms
softmarshmallow Sep 8, 2024
7372554
g11n service - wip
softmarshmallow Sep 10, 2024
e4600cd
disable feature
softmarshmallow Sep 10, 2024
0754fbf
Merge branch 'main' of https://github.com/gridaco/grida into forms
softmarshmallow Sep 10, 2024
06cf606
rvt mv
softmarshmallow Oct 11, 2024
1296f31
rvt rename
softmarshmallow Oct 11, 2024
ffc06de
rvt
softmarshmallow Oct 12, 2024
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
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the
npx supabase gen types --lang=typescript \
--project-id "$PROJECT_REF" \
--schema public \
--schema grida_g11n \
--schema grida_x_supabase \
--schema grida_sites \
--schema grida_commerce \
Expand Down
2 changes: 1 addition & 1 deletion apps/forms/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ yarn-error.log*
.vercel

# supabase
supabase/.temp
.temp

# typescript
*.tsbuildinfo
Expand Down
4 changes: 2 additions & 2 deletions apps/forms/app/(api)/v1/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import type {
FormMethod,
FormDocument,
Option,
FormsPageLanguage,
LanguageCode,
} from "@/types";
import { Features } from "@/lib/features/scheduling";
import { requesterurl, resolverurl } from "@/services/form/session-storage";
Expand Down Expand Up @@ -201,7 +201,7 @@ export async function GET(
store_connection,
} = data;

const lang: FormsPageLanguage =
const lang: LanguageCode =
(default_page as unknown as FormDocument | null)?.lang ?? "en";
const is_powered_by_branding_enabled =
(default_page as unknown as FormDocument | null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ function CurrentPageCanvas() {
const [state, dispatch] = useEditorState();

const {
theme: { lang },
document: { selected_page_id },
} = state;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ function CurrentPageCanvas() {
const [state, dispatch] = useEditorState();

const {
theme: { lang },
document: { selected_page_id },
} = state;

Expand Down
20 changes: 20 additions & 0 deletions apps/forms/app/(workbench)/[org]/[proj]/[id]/form/g11n/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use client";

import Invalid from "@/components/invalid";
import { useEditorState } from "@/scaffolds/editor";
import { I18nEditor } from "@/scaffolds/i18n-editor";

export default function FormI18nPage() {
const [state] = useEditorState();
const { lang, lang_default, langs } = state.document.g11n;

if (langs.length <= 1) {
return <Invalid />;
}

return (
<main className="w-full h-full">
<I18nEditor />
</main>
);
}
6 changes: 1 addition & 5 deletions apps/forms/app/(workbench)/[org]/[proj]/[id]/form/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ import { useEditorState } from "@/scaffolds/editor";
export default function FormDashboard() {
const [state, dispatch] = useEditorState();

const {
form,
theme: { lang },
document: { selected_page_id },
} = state;
const { form } = state;

return (
<main className="max-w-2xl mx-auto">
Expand Down
51 changes: 43 additions & 8 deletions apps/forms/app/(workbench)/[org]/[proj]/[id]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { cookies } from "next/headers";
import {
createRouteHandlerXSBClient,
createServerComponentClient,
createServerComponentG11nClient,
createServerComponentWorkspaceClient,
grida_xsupabase_client,
} from "@/lib/supabase/server";
Expand Down Expand Up @@ -39,6 +40,7 @@ import React from "react";
import { PlayActions } from "@/scaffolds/workbench/play-actions";
import { DontCastJsonProperties } from "@/types/supabase-ext";
import { SupabasePostgRESTOpenApi } from "@/lib/supabase-postgrest";
import EditorRouterProvider from "./router";

export const revalidate = 0;

Expand Down Expand Up @@ -75,8 +77,10 @@ export default async function Layout({
params: GDocEditorRouteParams;
}>) {
const cookieStore = cookies();
const supabase = createServerComponentClient(cookieStore);
const formsclient = createServerComponentClient(cookieStore);
const wsclient = createServerComponentWorkspaceClient(cookieStore);
const g11nclient = createServerComponentG11nClient(cookieStore);

const { id, org, proj } = params;

const { data: project_ref, error: project_ref_err } = await wsclient
Expand Down Expand Up @@ -114,7 +118,7 @@ export default async function Layout({

switch (masterdoc_ref.doctype) {
case "v0_form": {
const { data, error } = await supabase
const { data, error } = await formsclient
.from("form_document")
.select(
`
Expand Down Expand Up @@ -144,7 +148,7 @@ export default async function Layout({
const appearance =
(data.stylesheet as FormStyleSheetV1Schema)?.appearance ?? "system";

const client = new GridaXSupabaseService();
const xsbservice = new GridaXSupabaseService();

const { form: _form } = data;
assert(_form);
Expand All @@ -155,9 +159,33 @@ export default async function Layout({
};

const supabase_connection_state = form.supabase_connection
? await client.getXSBMainTableConnectionState(form.supabase_connection)
? await xsbservice.getXSBMainTableConnectionState(
form.supabase_connection
)
: null;

if (data.g11n_manifest_id) {
const { data: g11n, error: g11n_err } = await g11nclient
.from("manifest")
.select(
`
*,
locales:locale!manifest_id(*),
default_locale:locale(*),
keys:key(*)
`
)
.eq("id", data.g11n_manifest_id)
.single();

// g11n.

if (g11n_err) {
// report and ignore
console.error("g11n_err", g11n_err);
}
}

return (
<Html>
<FormDocumentEditorProvider
Expand All @@ -174,7 +202,6 @@ export default async function Layout({
supabase: supabase_connection_state || undefined,
},
theme: {
lang: data.lang,
is_powered_by_branding_enabled:
data.is_powered_by_branding_enabled,
appearance: appearance,
Expand All @@ -193,6 +220,9 @@ export default async function Layout({
form_id: form.id,
// TODO:
form_title: form.title,
document: {
lang: data.lang,
},
campaign: {
is_scheduling_enabled: form.is_scheduling_enabled,
is_force_closed: form.is_force_closed,
Expand Down Expand Up @@ -258,9 +288,11 @@ export default async function Layout({
theme: {
appearance: "system",
fontFamily: "inter",
lang: "en",
is_powered_by_branding_enabled: true,
},
document: {
lang: "en",
},
}}
>
<BaseLayout
Expand All @@ -280,7 +312,7 @@ export default async function Layout({
);
}
case "v0_schema": {
const { data, error } = await supabase
const { data, error } = await formsclient
.from("schema_document")
.select(
`
Expand Down Expand Up @@ -385,9 +417,11 @@ export default async function Layout({
theme: {
appearance: "system",
fontFamily: "inter",
lang: "en",
is_powered_by_branding_enabled: true,
},
document: {
lang: "en",
},
}}
>
<BaseLayout
Expand Down Expand Up @@ -464,6 +498,7 @@ function BaseLayout({
<div className="w-full h-full overflow-x-hidden">{children}</div>
</div>
</div>
<EditorRouterProvider />
<EditorHelpFab />
<ToasterWithMax position="bottom-center" max={5} />
</ThemeProvider>
Expand Down
28 changes: 28 additions & 0 deletions apps/forms/app/(workbench)/[org]/[proj]/[id]/router.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client";

import { useEditorState } from "@/scaffolds/editor";
import { usePathname } from "next/navigation";
import { useEffect, useMemo } from "react";

export default function EditorRouterProvider() {
const [state, dispatch] = useEditorState();
const pathname = usePathname();

const { params, workbenchpath } = useMemo(() => {
const [org, proj, docid, ...params] = pathname.split("/").filter(Boolean);
const workbenchpath = params.join("/");
return {
org,
proj,
docid,
params,
workbenchpath,
};
}, [pathname]);

useEffect(() => {
dispatch({ type: "workbench/path", path: workbenchpath });
}, [workbenchpath, dispatch]);

return <></>;
}
42 changes: 38 additions & 4 deletions apps/forms/components/delete-confirmation-dialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,42 @@ import {
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Spinner } from "../spinner";
import { useDialogState } from "../hooks/use-dialog-state";

export function DeleteConfirmationAlertDialog({
type UseDeleteConfirmationAlertDialogStateProps<ID> = {
id: ID;
match: string;
title: string;
description?: string;
};

export function useDeleteConfirmationAlertDialogState<
ID extends string = string,
>(name = "alertdialog", config?: { refreshkey?: boolean }) {
const { open, setOpen, openDialog, closeDialog, data, setData, refreshkey } =
useDialogState<UseDeleteConfirmationAlertDialogStateProps<ID>>(
name,
config
);

return {
refreshkey,
open,
setOpen,
onOpenChange: setOpen,
openDialog,
closeDialog,
data: {
id: data?.id as ID,
},
setData,
title: data?.title,
description: data?.description,
match: data?.match,
};
}

export function DeleteConfirmationAlertDialog<ID extends string = string>({
title,
description,
placeholder,
Expand All @@ -26,15 +60,15 @@ export function DeleteConfirmationAlertDialog({
placeholder?: string;
match?: string;
data?: {
id: string;
id: ID;
};
/**
* trigger when the delete button is clicked
* return a promise that resolves to a boolean indicating if the delete was successful
* if the promise resolves to true, the dialog will be closed
*/
onDelete?: (
data: { id: string },
data: { id: ID },
user_confirmation_txt: string
) => Promise<boolean>;
}) {
Expand Down Expand Up @@ -71,7 +105,7 @@ export function DeleteConfirmationAlertDialog({
spellCheck="false"
type="text"
name="comfirmation"
placeholder={placeholder}
placeholder={placeholder ?? match}
value={confirmation}
onChange={(e) => {
setConfirmation(e.target.value);
Expand Down
6 changes: 3 additions & 3 deletions apps/forms/components/formfield/file-upload-field/uploader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createClientFormsClient } from "@/lib/supabase/client";
import { createClientComponentFormsClient } from "@/lib/supabase/client";
import {
GRIDA_FORMS_RESPONSE_BUCKET,
GRIDA_FORMS_RESPONSE_BUCKET_UPLOAD_LIMIT,
Expand Down Expand Up @@ -54,7 +54,7 @@ async function makeSignedUrlUploader({
}: {
signed_urls: { path: string; token: string }[];
}) {
const supabase = createClientFormsClient();
const supabase = createClientComponentFormsClient();

return async (file: File, i: number) => {
const { path, token } = signed_urls[i];
Expand All @@ -70,7 +70,7 @@ async function makeSignedUrlUploader({
}

function makeRequestUrlUploader({ request_url }: { request_url: string }) {
const supabase = createClientFormsClient();
const supabase = createClientComponentFormsClient();

return async (file: File) => {
const res = await fetch(request_url, {
Expand Down
7 changes: 5 additions & 2 deletions apps/forms/components/invalid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ export default function Invalid() {
const { basepath } = state;

return (
<div className="flex w-full flex-col items-center justify-center bg-background px-4 py-12 sm:px-6 lg:px-8">
<div className="flex w-full h-full flex-col items-center justify-center bg-background px-4 py-12 sm:px-6 lg:px-8">
<div className="mx-auto max-w-md text-center">
<div className="mx-auto h-12 w-12 text-primary" />
<h1 className="mt-4 text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
Oops, Not a valid page!
</h1>
<p className="mt-4 text-muted-foreground">
The page you&apos;re looking for doesn&apos;t exist or has been moved.
Don&apos;t worry, we&apos;re here to help.
If you think this is a mistake,{" "}
<Link href={"/issues/new"} className="underline" target="_new">
please file an issue.
</Link>
</p>
<div className="mt-6">
<Link
Expand Down
Loading