Skip to content

Commit a6adb69

Browse files
committed
Fix bugs and add form switcher to create page
1 parent 8948d60 commit a6adb69

File tree

8 files changed

+79
-27
lines changed

8 files changed

+79
-27
lines changed

Diff for: core/app/c/[communitySlug]/pubs/[pubId]/edit/page.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export async function generateMetadata(props: {
7272

7373
export default async function Page(props: {
7474
params: Promise<{ pubId: PubsId; communitySlug: string }>;
75-
searchParams: Promise<Record<string, string>>;
75+
searchParams: Promise<Record<string, string> & { form: string }>;
7676
}) {
7777
const searchParams = await props.searchParams;
7878
const params = await props.params;
@@ -126,10 +126,11 @@ export default async function Page(props: {
126126
>
127127
<div className="flex justify-center py-10">
128128
<div className="max-w-prose flex-1">
129-
<FormSwitcher forms={availableForms} />
129+
<FormSwitcher defaultFormSlug={searchParams.form} forms={availableForms} />
130130
{/** TODO: Add suspense */}
131131
<PubEditor
132132
searchParams={searchParams}
133+
formSlug={searchParams.form}
133134
pubId={pub.id}
134135
htmlFormId={htmlFormId}
135136
communityId={community.id}

Diff for: core/app/c/[communitySlug]/pubs/[pubId]/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { CreatePubButton } from "~/app/components/pubs/CreatePubButton";
1717
import { RemovePubButton } from "~/app/components/pubs/RemovePubButton";
1818
import { db } from "~/kysely/database";
1919
import { getPageLoginData } from "~/lib/authentication/loginData";
20-
import { getAuthorizedUpdateForms, userCan } from "~/lib/authorization/capabilities";
20+
import { getAuthorizedViewForms, userCan } from "~/lib/authorization/capabilities";
2121
import { getStageActions } from "~/lib/db/queries";
2222
import { getPubByForm, getPubTitle } from "~/lib/pubs";
2323
import { getPubsWithRelatedValues, pubValuesByVal } from "~/lib/server";
@@ -157,7 +157,7 @@ export default async function Page(props: {
157157
{ type: MembershipType.pub, pubId: pub.id },
158158
user.id
159159
),
160-
getAuthorizedUpdateForms(user.id, pub.id).execute(),
160+
getAuthorizedViewForms(user.id, pub.id).execute(),
161161
]);
162162

163163
const pubTypeHasRelatedPubs = pub.pubType.fields.some((field) => field.isRelation);

Diff for: core/app/c/[communitySlug]/pubs/create/page.tsx

+19-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import { notFound, redirect } from "next/navigation";
44

55
import { type PubTypesId } from "db/public";
66
import { Button } from "ui/button";
7+
import { Label } from "ui/label";
78

89
import { ContentLayout } from "~/app/c/[communitySlug]/ContentLayout";
10+
import { FormSwitcher } from "~/app/components/FormSwitcher/FormSwitcher";
911
import { PageTitleWithStatus } from "~/app/components/pubs/PubEditor/PageTitleWithStatus";
1012
import { PubEditor } from "~/app/components/pubs/PubEditor/PubEditor";
1113
import { getPageLoginData } from "~/lib/authentication/loginData";
12-
import { userCanCreatePub } from "~/lib/authorization/capabilities";
14+
import { getAuthorizedCreateForms, userCanCreatePub } from "~/lib/authorization/capabilities";
1315
import { findCommunityBySlug } from "~/lib/server/community";
1416

1517
export async function generateMetadata(props: {
@@ -29,7 +31,7 @@ export async function generateMetadata(props: {
2931

3032
export default async function Page(props: {
3133
params: Promise<{ communitySlug: string }>;
32-
searchParams: Promise<Record<string, string> & { pubTypeId: PubTypesId }>;
34+
searchParams: Promise<Record<string, string> & { pubTypeId: PubTypesId; form?: string }>;
3335
}) {
3436
const searchParams = await props.searchParams;
3537
const params = await props.params;
@@ -57,6 +59,12 @@ export default async function Page(props: {
5759

5860
const htmlFormId = `create-pub`;
5961

62+
const availableForms = await getAuthorizedCreateForms({
63+
userId: user.id,
64+
communityId: community.id,
65+
pubTypeId: searchParams.pubTypeId,
66+
}).execute();
67+
6068
return (
6169
<ContentLayout
6270
left={
@@ -69,10 +77,19 @@ export default async function Page(props: {
6977
>
7078
<div className="flex justify-center py-10">
7179
<div className="max-w-prose flex-1">
80+
<div className="mb-4 flex flex-col gap-3">
81+
<Label htmlFor="create-page-form-switcher">Current form</Label>
82+
<FormSwitcher
83+
htmlId="create-page-form-switcher"
84+
defaultFormSlug={searchParams.form}
85+
forms={availableForms}
86+
/>
87+
</div>
7288
<PubEditor
7389
searchParams={searchParams}
7490
communityId={community.id}
7591
htmlFormId={htmlFormId}
92+
formSlug={searchParams.form}
7693
// PubEditor checks for the existence of the stageId prop
7794
{...(searchParams["stageId"] ? { stageId: searchParams["stageId"] } : {})}
7895
/>

Diff for: core/app/components/FormSwitcher/FormSwitcher.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ export const formSwitcherUrlParam = "form";
1313
export const FormSwitcher = ({
1414
forms,
1515
defaultFormSlug,
16+
htmlId,
1617
}: {
1718
forms: SimpleForm[];
1819
defaultFormSlug?: string;
20+
htmlId?: string;
1921
}) => {
2022
const router = useRouter();
2123
const pathname = usePathname();
@@ -43,7 +45,7 @@ export const FormSwitcher = ({
4345
}}
4446
defaultValue={selectedFormSlug}
4547
>
46-
<SelectTrigger className="">
48+
<SelectTrigger id={htmlId}>
4749
<SelectValue />
4850
</SelectTrigger>
4951
<SelectContent>
@@ -54,7 +56,9 @@ export const FormSwitcher = ({
5456
))}
5557
</SelectContent>
5658
</Select>
57-
<Button onClick={switchForms}>Switch forms</Button>
59+
<Button disabled={forms.length < 2} onClick={switchForms}>
60+
Switch forms
61+
</Button>
5862
</div>
5963
);
6064
};

Diff for: core/app/components/pubs/PubEditor/PubEditor.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ const getRelatedPubData = async ({
103103
};
104104

105105
export type PubEditorProps = {
106-
searchParams: { relatedPubId?: PubsId; slug?: string; pubTypeId?: PubTypesId };
106+
searchParams: { relatedPubId?: PubsId; slug?: string; pubTypeId?: PubTypesId; form?: string };
107107
htmlFormId?: string;
108108
formSlug?: string;
109109
} & (

Diff for: core/lib/authorization/capabilities.ts

+30-2
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,6 @@ export const getAuthorizedCreateForms = ({
302302
eb("membership_capabilities.capability", "in", [
303303
Capabilities.createPubWithAnyForm,
304304
Capabilities.createPubWithForm,
305-
Capabilities.createPubWithDefaultForm,
306305
]),
307306
])
308307
)
@@ -389,7 +388,7 @@ export const getAuthorizedUpdateForms = (userId: UsersId, pubId: PubsId) =>
389388
)
390389
.selectFrom("forms")
391390
.innerJoin("community", "community.communityId", "forms.communityId")
392-
.where("forms.pubTypeId", "=", (eb) => eb.selectFrom("pubtype").select("pubTypeId"))
391+
.whereRef("forms.pubTypeId", "=", (eb) => eb.selectFrom("pubtype").select("id"))
393392
.where((eb) =>
394393
eb.or([
395394
eb(
@@ -422,3 +421,32 @@ export const getAuthorizedUpdateForms = (userId: UsersId, pubId: PubsId) =>
422421
.orderBy("forms.isDefault desc")
423422
.orderBy("forms.updatedAt desc")
424423
);
424+
425+
export const getAuthorizedViewForms = (userId: UsersId, pubId: PubsId) =>
426+
autoCache(
427+
getAuthorizedUpdateForms(userId, pubId)
428+
.qb.clearWhere()
429+
.where((eb) =>
430+
eb.or([
431+
eb(
432+
eb.val(Capabilities.editPubWithAnyForm),
433+
"in",
434+
eb.selectFrom("capabilities").select("capability")
435+
),
436+
eb.and([
437+
eb(
438+
eb.val(Capabilities.editPubWithForm),
439+
"in",
440+
eb.selectFrom("capabilities").select("capability")
441+
),
442+
eb.or([
443+
eb("forms.id", "in", eb.selectFrom("pub_ms").select("formId")),
444+
eb("forms.id", "in", eb.selectFrom("stage_ms").select("formId")),
445+
]),
446+
]),
447+
// Always include the default form (otherwise these conditions are identical to update)
448+
eb("forms.isDefault", "is", true),
449+
])
450+
)
451+
.whereRef("forms.pubTypeId", "=", (eb) => eb.selectFrom("pubtype").select("id"))
452+
);

Diff for: core/prisma/migrations/20250420212706_update_capabilities/migration.sql

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ VALUES
7070
('community'::"MembershipType", 'admin'::"MemberRole", 'editPubField'::"Capabilities"),
7171
('community'::"MembershipType", 'admin'::"MemberRole", 'editPubType'::"Capabilities"),
7272
('community'::"MembershipType", 'admin'::"MemberRole", 'editPubWithForm'::"Capabilities"),
73+
('community'::"MembershipType", 'admin'::"MemberRole", 'editPubWithAnyForm'::"Capabilities"),
7374
('community'::"MembershipType", 'admin'::"MemberRole", 'manageMemberGroups'::"Capabilities"),
7475
('community'::"MembershipType", 'admin'::"MemberRole", 'manageStage'::"Capabilities"),
7576
('community'::"MembershipType", 'admin'::"MemberRole", 'movePub'::"Capabilities"),
@@ -87,6 +88,7 @@ VALUES
8788
('community'::"MembershipType", 'editor'::"MemberRole", 'createRelatedPub'::"Capabilities"),
8889
('community'::"MembershipType", 'editor'::"MemberRole", 'deletePub'::"Capabilities"),
8990
('community'::"MembershipType", 'editor'::"MemberRole", 'editPubWithForm'::"Capabilities"),
91+
('community'::"MembershipType", 'editor'::"MemberRole", 'editPubWithAnyForm'::"Capabilities"),
9092
('community'::"MembershipType", 'editor'::"MemberRole", 'movePub'::"Capabilities"),
9193
('community'::"MembershipType", 'editor'::"MemberRole", 'runAction'::"Capabilities"),
9294
('community'::"MembershipType", 'editor'::"MemberRole", 'seeExtraPubValues'::"Capabilities"),

Diff for: packages/db/src/public/PublicSchema.ts

+16-16
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ import type { StagesTable } from "./Stages";
3333
import type { UsersTable } from "./Users";
3434

3535
export interface PublicSchema {
36+
form_elements: FormElementsTable;
37+
38+
sessions: SessionsTable;
39+
40+
community_memberships: CommunityMembershipsTable;
41+
42+
pub_memberships: PubMembershipsTable;
43+
44+
stage_memberships: StageMembershipsTable;
45+
46+
membership_capabilities: MembershipCapabilitiesTable;
47+
48+
pub_values_history: PubValuesHistoryTable;
49+
50+
_FormElementToPubType: FormElementToPubTypeTable;
51+
3652
_prisma_migrations: PrismaMigrationsTable;
3753

3854
users: UsersTable;
@@ -76,20 +92,4 @@ export interface PublicSchema {
7692
api_access_logs: ApiAccessLogsTable;
7793

7894
api_access_permissions: ApiAccessPermissionsTable;
79-
80-
form_elements: FormElementsTable;
81-
82-
sessions: SessionsTable;
83-
84-
community_memberships: CommunityMembershipsTable;
85-
86-
pub_memberships: PubMembershipsTable;
87-
88-
stage_memberships: StageMembershipsTable;
89-
90-
membership_capabilities: MembershipCapabilitiesTable;
91-
92-
pub_values_history: PubValuesHistoryTable;
93-
94-
_FormElementToPubType: FormElementToPubTypeTable;
9595
}

0 commit comments

Comments
 (0)