feat: migrate org settings to server components

This commit is contained in:
swve 2023-06-15 19:39:18 +02:00
parent 1bab95b15a
commit 23d5a80966
4 changed files with 156 additions and 117 deletions

View file

@ -0,0 +1,101 @@
"use client";
import React from 'react'
import { Field, Form, Formik } from 'formik';
import { updateOrganization } from '@services/settings/org';
interface OrganizationValues {
name: string;
description: string;
slug: string;
email: string;
}
function OrganizationClient(props: any) {
const org = props.org;
let orgValues: OrganizationValues = {
name: org.name,
description: org.description,
slug: org.slug,
email: org.email
}
const updateOrg = async (values: OrganizationValues) => {
let org_id = org.org_id;
await updateOrganization(org_id, values);
}
return (
<div>
<h1 className='text-3xl font-bold'>Organization Settings</h1>
<br /><br />
<Formik
initialValues={orgValues}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
updateOrg(values)
}, 400);
}}
>
{({ isSubmitting }) => (
<Form>
<label className="block mb-2 font-bold" htmlFor="name">
Name
</label>
<Field
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
type="text"
name="name"
/>
<label className="block mb-2 font-bold" htmlFor="description">
Description
</label>
<Field
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
type="text"
name="description"
/>
<label className="block mb-2 font-bold" htmlFor="slug">
Slug
</label>
<Field
className="w-full px-4 py-2 mb-4 border rounded-lg bg-gray-200 cursor-not-allowed"
disabled
type="text"
name="slug"
/>
<label className="block mb-2 font-bold" htmlFor="email">
Email
</label>
<Field
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
type="email"
name="email"
/>
<button
type="submit"
disabled={isSubmitting}
className="px-6 py-3 text-white bg-black rounded-lg shadow-md hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-black"
>
Submit
</button>
</Form>
)}
</Formik>
</div>
)
}
export default OrganizationClient

View file

@ -1,115 +1,33 @@
"use client"; import { getOrganizationContextInfo } from '@services/organizations/orgs';
import React from 'react' import { Metadata } from 'next';
import useSWR, { mutate } from "swr"; import OrganizationClient from './organization';
import { swrFetcher } from "@services/utils/ts/requests";
import { getAPIUrl } from '@services/config/config';
import { Field, Form, Formik } from 'formik';
import { updateOrganization } from '@services/settings/org';
interface OrganizationValues { type MetadataProps = {
name: string; params: { orgslug: string };
description: string; searchParams: { [key: string]: string | string[] | undefined };
slug: string; };
email: string;
export async function generateMetadata(
{ params }: MetadataProps,
): Promise<Metadata> {
// Get Org context information
const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'] });
return {
title: `Settings: General — ${org.name}`,
description: org.description,
};
} }
function SettingsOrganizationGeneral(params: any) { async function SettingsOrganizationGeneral(params: any) {
const orgslug = params.params.orgslug; const orgslug = params.params.orgslug;
const { data: org, error: error } = useSWR(`${getAPIUrl()}orgs/slug/${orgslug}`, swrFetcher); const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] });
if (org) {
let orgValues: OrganizationValues = {
name: org.name,
description: org.description,
slug: org.slug,
email: org.email
}
const updateOrg = async (values: OrganizationValues) => {
let org_id = org.org_id;
await updateOrganization(org_id, values);
// Sounds good, doesn't work
// TODO: Fix this
mutate(`${getAPIUrl()}orgs/slug/${values.slug}`);
}
return ( return (
<div> <>
<h1 className='text-3xl font-bold'>Oganization Settings</h1> <OrganizationClient org={org} />
<br /><br /> </>
{error && <p>Failed to load</p>}
{!org ? (
<div>Loading...</div>
) : (
<Formik
initialValues={orgValues}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
updateOrg(values)
}, 400);
}}
>
{({ isSubmitting }) => (
<Form>
<label className="block mb-2 font-bold" htmlFor="name">
Name
</label>
<Field
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
type="text"
name="name"
/>
<label className="block mb-2 font-bold" htmlFor="description">
Description
</label>
<Field
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
type="text"
name="description"
/>
<label className="block mb-2 font-bold" htmlFor="slug">
Slug
</label>
<Field
className="w-full px-4 py-2 mb-4 border rounded-lg bg-gray-200 cursor-not-allowed"
disabled
type="text"
name="slug"
/>
<label className="block mb-2 font-bold" htmlFor="email">
Email
</label>
<Field
className="w-full px-4 py-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
type="email"
name="email"
/>
<button
type="submit"
disabled={isSubmitting}
className="px-6 py-3 text-white bg-black rounded-lg shadow-md hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-black"
>
Submit
</button>
</Form>
)}
</Formik>
)}
</div>
) )
}
} }
export default SettingsOrganizationGeneral export default SettingsOrganizationGeneral

View file

@ -1,4 +1,23 @@
import React from 'react' import { getOrganizationContextInfo } from "@services/organizations/orgs";
import { Metadata, ResolvingMetadata } from 'next';
type MetadataProps = {
params: { orgslug: string };
searchParams: { [key: string]: string | string[] | undefined };
};
export async function generateMetadata(
{ params }: MetadataProps,
): Promise<Metadata> {
// Get Org context information
const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'] });
return {
title: `Settings — ${org.name}`,
description: org.description,
};
}
function Settings() { function Settings() {
return ( return (

View file

@ -1,5 +1,7 @@
import json import json
from typing import Optional
from uuid import uuid4 from uuid import uuid4
from click import Option
from pydantic import BaseModel from pydantic import BaseModel
from src.services.users.schemas.users import UserOrganization from src.services.users.schemas.users import UserOrganization
from src.services.users.users import PublicUser from src.services.users.users import PublicUser
@ -14,7 +16,7 @@ class Organization(BaseModel):
description: str description: str
email: str email: str
slug: str slug: str
default: bool default: Optional[bool]
class OrganizationInDB(Organization): class OrganizationInDB(Organization):
@ -106,11 +108,8 @@ async def update_org(request: Request, org_object: Organization, org_id: str, cu
org = await orgs.find_one({"org_id": org_id}) org = await orgs.find_one({"org_id": org_id})
if org: if not org:
org["owners"]
org["admins"]
else:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist") status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
@ -185,12 +184,14 @@ async def verify_org_rights(request: Request, org_id: str, current_user: Public
raise HTTPException( raise HTTPException(
status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist") status_code=status.HTTP_409_CONFLICT, detail="Organization does not exist")
isOwner = current_user.user_id in org["owners"] # check if is owner of org
# todo check if is admin of org
hasRoleRights = await verify_user_rights_with_roles(request, action, current_user.user_id, org_id, org_id) hasRoleRights = await verify_user_rights_with_roles(request, action, current_user.user_id, org_id, org_id)
if not hasRoleRights and not isOwner: # if not hasRoleRights and not isOwner:
raise HTTPException( # raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, detail="You do not have rights to this organization") # status_code=status.HTTP_403_FORBIDDEN, detail="You do not have rights to this organization")
return True return True