diff --git a/.npmrc b/.npmrc index 4343c8ca..90ed8716 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ -shared-workspace-lockfile=false \ No newline at end of file +shared-workspace-lockfile=false +package-manager-strict=false \ No newline at end of file diff --git a/apps/api/src/routers/auth.py b/apps/api/src/routers/auth.py index 535ebe74..f13bc033 100644 --- a/apps/api/src/routers/auth.py +++ b/apps/api/src/routers/auth.py @@ -1,11 +1,14 @@ from datetime import timedelta +from typing import Literal, Optional from fastapi import Depends, APIRouter, HTTPException, Response, status, Request from fastapi.security import OAuth2PasswordRequestForm +from pydantic import BaseModel, EmailStr from sqlmodel import Session -from src.db.users import UserRead +from src.db.users import AnonymousUser, UserRead from src.core.events.database import get_db_session from config.config import get_learnhouse_config -from src.security.auth import AuthJWT, authenticate_user +from src.security.auth import AuthJWT, authenticate_user, get_current_user +from src.services.auth.utils import signWithGoogle router = APIRouter() @@ -74,6 +77,58 @@ async def login( return result +class ThirdPartyLogin(BaseModel): + email: EmailStr + provider: Literal["google"] + access_token: str + + +@router.post("/oauth") +async def third_party_login( + request: Request, + response: Response, + body: ThirdPartyLogin, + org_id: Optional[int] = None, + current_user: AnonymousUser = Depends(get_current_user), + db_session: Session = Depends(get_db_session), + Authorize: AuthJWT = Depends(), +): + # Google + if body.provider == "google": + + user = await signWithGoogle( + request, body.access_token, body.email, org_id, current_user, db_session + ) + + if not user: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Incorrect Email or password", + headers={"WWW-Authenticate": "Bearer"}, + ) + + access_token = Authorize.create_access_token(subject=user.email) + refresh_token = Authorize.create_refresh_token(subject=user.email) + Authorize.set_refresh_cookies(refresh_token) + + # set cookies using fastapi + response.set_cookie( + key="access_token_cookie", + value=access_token, + httponly=False, + domain=get_learnhouse_config().hosting_config.cookie_config.domain, + expires=int(timedelta(hours=8).total_seconds()), + ) + + user = UserRead.model_validate(user) + + result = { + "user": user, + "tokens": {"access_token": access_token, "refresh_token": refresh_token}, + } + return result + + @router.delete("/logout") def logout(Authorize: AuthJWT = Depends()): """ diff --git a/apps/api/src/routers/orgs.py b/apps/api/src/routers/orgs.py index cd7f7d9b..ad345649 100644 --- a/apps/api/src/routers/orgs.py +++ b/apps/api/src/routers/orgs.py @@ -8,6 +8,7 @@ from src.services.orgs.invites import ( get_invite_code, get_invite_codes, ) +from src.services.orgs.join import JoinOrg, join_org from src.services.orgs.users import ( get_list_of_invited_users, get_organization_users, @@ -99,6 +100,19 @@ async def api_get_org_users( return await get_organization_users(request, org_id, db_session, current_user) +@router.post("/join") +async def api_join_an_org( + request: Request, + args: JoinOrg, + current_user: PublicUser = Depends(get_current_user), + db_session: Session = Depends(get_db_session), +): + """ + Get single Org by ID + """ + return await join_org(request, args, current_user, db_session) + + @router.put("/{org_id}/users/{user_id}/role/{role_uuid}") async def api_update_user_role( request: Request, diff --git a/apps/api/src/routers/users.py b/apps/api/src/routers/users.py index 5dc621f3..98cb25aa 100644 --- a/apps/api/src/routers/users.py +++ b/apps/api/src/routers/users.py @@ -85,7 +85,6 @@ async def api_create_user_with_orgid( """ Create User with Org ID """ - print(await get_org_join_mechanism(request, org_id, current_user, db_session)) # TODO(fix) : This is temporary, logic should be moved to service if ( diff --git a/apps/api/src/services/auth/utils.py b/apps/api/src/services/auth/utils.py new file mode 100644 index 00000000..aa6b0d17 --- /dev/null +++ b/apps/api/src/services/auth/utils.py @@ -0,0 +1,70 @@ +import random +from typing import Optional +from fastapi import Depends, HTTPException, Request +import httpx +from sqlmodel import Session, select +from src.core.events.database import get_db_session +from src.db.users import User, UserCreate, UserRead +from src.security.auth import get_current_user +from src.services.users.users import create_user, create_user_without_org + + +async def get_google_user_info(access_token: str): + url = "https://www.googleapis.com/oauth2/v3/userinfo" + headers = {"Authorization": f"Bearer {access_token}"} + async with httpx.AsyncClient() as client: + response = await client.get(url, headers=headers) + + if response.status_code != 200: + raise HTTPException( + status_code=response.status_code, + detail="Failed to fetch user info from Google", + ) + + return response.json() + + +async def signWithGoogle( + request: Request, + access_token: str, + email: str, + org_id: Optional[int] = None, + current_user=Depends(get_current_user), + db_session: Session = Depends(get_db_session), +): + # Google + google_user = await get_google_user_info(access_token) + + user = db_session.exec( + select(User).where(User.email == google_user["email"]) + ).first() + + if not user: + username = ( + google_user["given_name"] + + google_user["family_name"] + + str(random.randint(10, 99)) + ) + user_object = UserCreate( + email=google_user["email"], + username=username, + password="", + first_name=google_user["given_name"], + last_name=google_user["family_name"], + avatar_image=google_user["picture"], + ) + + if org_id is not None: + user = await create_user( + request, db_session, current_user, user_object, org_id + ) + + return user + else: + user = await create_user_without_org( + request, db_session, current_user, user_object + ) + + return user + + return UserRead.model_validate(user) diff --git a/apps/api/src/services/orgs/join.py b/apps/api/src/services/orgs/join.py new file mode 100644 index 00000000..177cc04e --- /dev/null +++ b/apps/api/src/services/orgs/join.py @@ -0,0 +1,119 @@ +from datetime import datetime +from typing import Optional +from fastapi import HTTPException, Request +from pydantic import BaseModel +from sqlmodel import Session, select +from src.db.organizations import Organization +from src.db.user_organizations import UserOrganization +from src.db.users import AnonymousUser, PublicUser, User +from src.services.orgs.invites import get_invite_code +from src.services.orgs.orgs import get_org_join_mechanism + + +class JoinOrg(BaseModel): + org_id: int + user_id: str + invite_code: Optional[str] + + +async def join_org( + request: Request, + args: JoinOrg, + current_user: PublicUser | AnonymousUser, + db_session: Session, +): + statement = select(Organization).where(Organization.id == args.org_id) + result = db_session.exec(statement) + + org = result.first() + + if not org: + raise HTTPException( + status_code=404, + detail="Organization not found", + ) + + join_method = await get_org_join_mechanism( + request, args.org_id, current_user, db_session + ) + + # Get User + statement = select(User).where(User.id == args.user_id) + result = db_session.exec(statement) + + user = result.first() + + # Check if User isn't already part of the org + statement = select(UserOrganization).where( + UserOrganization.user_id == args.user_id, UserOrganization.org_id == args.org_id + ) + result = db_session.exec(statement) + + userorg = result.first() + + if userorg: + raise HTTPException( + status_code=400, detail="User is already part of that organization" + ) + + if join_method == "inviteOnly" and user and org and args.invite_code: + if user.id is not None and org.id is not None: + + # Check if invite code exists + inviteCode = await get_invite_code( + request, org.id, args.invite_code, current_user, db_session + ) + + if not inviteCode: + raise HTTPException( + status_code=400, + detail="Invite code is incorrect", + ) + + # Link user and organization + user_organization = UserOrganization( + user_id=user.id, + org_id=org.id, + role_id=3, + creation_date=str(datetime.now()), + update_date=str(datetime.now()), + ) + + db_session.add(user_organization) + db_session.commit() + + return "Great, You're part of the Organization" + + else: + raise HTTPException( + status_code=403, + detail="Something wrong, try later.", + ) + + if join_method == "open" and user and org: + if user.id is not None and org.id is not None: + # Link user and organization + user_organization = UserOrganization( + user_id=user.id, + org_id=org.id, + role_id=3, + creation_date=str(datetime.now()), + update_date=str(datetime.now()), + ) + + db_session.add(user_organization) + db_session.commit() + + return "Great, You're part of the Organization" + + else: + raise HTTPException( + status_code=403, + detail="Something wrong, try later.", + ) + + else: + raise HTTPException( + status_code=403, + detail="Something wrong, try later.", + ) diff --git a/apps/api/src/services/orgs/orgs.py b/apps/api/src/services/orgs/orgs.py index bd96d22b..d7923ae9 100644 --- a/apps/api/src/services/orgs/orgs.py +++ b/apps/api/src/services/orgs/orgs.py @@ -436,8 +436,7 @@ async def get_orgs_by_user( orgs = result.all() - return orgs - + return orgs #type:ignore # Config related async def update_org_signup_mechanism( diff --git a/apps/api/src/services/users/emails.py b/apps/api/src/services/users/emails.py index 95ab0a15..6e20e704 100644 --- a/apps/api/src/services/users/emails.py +++ b/apps/api/src/services/users/emails.py @@ -17,7 +17,7 @@ def send_account_creation_email(

Hello {user.username}

Welcome to LearnHouse! , get started by creating your own organization or join a one.

-

Need some help to get started ? LearnHouse Academy

+

Need some help to get started ? LearnHouse Academy

""", diff --git a/apps/collaboration/pnpm-lock.yaml b/apps/collaboration/pnpm-lock.yaml index 867e9b80..924c19f5 100644 --- a/apps/collaboration/pnpm-lock.yaml +++ b/apps/collaboration/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@hocuspocus/server': specifier: ^2.11.3 - version: 2.11.3(y-protocols@1.0.6)(yjs@13.6.14) + version: 2.11.3(y-protocols@1.0.6(yjs@13.6.14))(yjs@13.6.14) bun: specifier: ^1.0.36 version: 1.1.1 @@ -80,7 +80,6 @@ packages: bun@1.1.1: resolution: {integrity: sha512-gV90TkJgHvI50X9BoKQ3zVpPEY6YP0vqOww2uZmsOyckZSRlcFYWhXZwFj6PV8KCFINYs8VZ65m59U2RuFYfWw==} - cpu: [arm64, x64] os: [darwin, linux, win32] hasBin: true @@ -133,7 +132,7 @@ snapshots: dependencies: lib0: 0.2.93 - '@hocuspocus/server@2.11.3(y-protocols@1.0.6)(yjs@13.6.14)': + '@hocuspocus/server@2.11.3(y-protocols@1.0.6(yjs@13.6.14))(yjs@13.6.14)': dependencies: '@hocuspocus/common': 2.11.3 async-lock: 1.4.1 diff --git a/apps/web/.eslintrc b/apps/web/.eslintrc index e562b59a..38fc69f2 100644 --- a/apps/web/.eslintrc +++ b/apps/web/.eslintrc @@ -4,7 +4,8 @@ "react/no-unescaped-entities": "off", "@next/next/no-page-custom-font": "off", "@next/next/no-img-element": "off", - "unused-imports/no-unused-imports": "warn" + "unused-imports/no-unused-imports": "warn", + "no-console": "warn" }, "plugins": ["unused-imports"] } diff --git a/apps/web/.gitignore b/apps/web/.gitignore index e1753567..59d3e5b9 100644 --- a/apps/web/.gitignore +++ b/apps/web/.gitignore @@ -43,3 +43,5 @@ next.config.original.js # Sentry Config File .sentryclirc + +certificates \ No newline at end of file diff --git a/apps/web/app/api/auth/[...nextauth]/route.ts b/apps/web/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 00000000..d187f4a9 --- /dev/null +++ b/apps/web/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1,6 @@ +import NextAuth from 'next-auth' +import { nextAuthOptions } from 'app/auth/options' + +const handler = NextAuth(nextAuthOptions) + +export { handler as GET, handler as POST } diff --git a/apps/web/app/orgs/[orgslug]/forgot/forgot.tsx b/apps/web/app/auth/forgot/forgot.tsx similarity index 100% rename from apps/web/app/orgs/[orgslug]/forgot/forgot.tsx rename to apps/web/app/auth/forgot/forgot.tsx diff --git a/apps/web/app/orgs/[orgslug]/forgot/page.tsx b/apps/web/app/auth/forgot/page.tsx similarity index 100% rename from apps/web/app/orgs/[orgslug]/forgot/page.tsx rename to apps/web/app/auth/forgot/page.tsx diff --git a/apps/web/app/auth/layout.tsx b/apps/web/app/auth/layout.tsx new file mode 100644 index 00000000..37fbd3a3 --- /dev/null +++ b/apps/web/app/auth/layout.tsx @@ -0,0 +1,19 @@ +'use client' +import { OrgProvider } from '@components/Contexts/OrgContext' +import ErrorUI from '@components/StyledElements/Error/Error' +import { useSearchParams } from 'next/navigation' + + +export default function AuthLayout({ + children, +}: { + children: React.ReactNode +}) { + const searchParams = useSearchParams() + const orgslug = searchParams.get('orgslug') + if (orgslug) { + return {children} + } else { + return + } +} \ No newline at end of file diff --git a/apps/web/app/orgs/[orgslug]/login/login.tsx b/apps/web/app/auth/login/login.tsx similarity index 73% rename from apps/web/app/orgs/[orgslug]/login/login.tsx rename to apps/web/app/auth/login/login.tsx index 603c93a4..e766cf51 100644 --- a/apps/web/app/orgs/[orgslug]/login/login.tsx +++ b/apps/web/app/auth/login/login.tsx @@ -10,11 +10,12 @@ import * as Form from '@radix-ui/react-form' import { useFormik } from 'formik' import { getOrgLogoMediaDirectory } from '@services/media/media' import React from 'react' -import { loginAndGetToken } from '@services/auth/auth' -import { AlertTriangle } from 'lucide-react' +import { AlertTriangle, UserRoundPlus } from 'lucide-react' import { useRouter } from 'next/navigation' import Link from 'next/link' -import { getUriWithOrg } from '@services/config/config' +import { signIn } from "next-auth/react" +import { getUriWithOrg, getUriWithoutOrg } from '@services/config/config' +import { useLHSession } from '@components/Contexts/LHSessionContext' interface LoginClientProps { org: any @@ -40,7 +41,9 @@ const validate = (values: any) => { const LoginClient = (props: LoginClientProps) => { const [isSubmitting, setIsSubmitting] = React.useState(false) - const router = useRouter() + const router = useRouter(); + const session = useLHSession() as any; + const [error, setError] = React.useState('') const formik = useFormik({ initialValues: { @@ -50,25 +53,25 @@ const LoginClient = (props: LoginClientProps) => { validate, onSubmit: async (values) => { setIsSubmitting(true) - let res = await loginAndGetToken(values.email, values.password) - let message = await res.json() - if (res.status == 200) { - router.push(`/`) - setIsSubmitting(false) - } else if ( - res.status == 401 || - res.status == 400 || - res.status == 404 || - res.status == 409 - ) { - setError(message.detail) - setIsSubmitting(false) + const res = await signIn('credentials', { + redirect: false, + email: values.email, + password: values.password, + callbackUrl: '/redirect_from_auth' + }); + if (res && res.error) { + setError("Wrong Email or password"); + setIsSubmitting(false); } else { - setError('Something went wrong') - setIsSubmitting(false) + await signIn('credentials', { + email: values.email, + password: values.password, + callbackUrl: '/redirect_from_auth' + }); } }, }) + return (
{ Forgot password?
-
+
+
OR
+
+ + + Sign up + + +
diff --git a/apps/web/app/orgs/[orgslug]/login/page.tsx b/apps/web/app/auth/login/page.tsx similarity index 69% rename from apps/web/app/orgs/[orgslug]/login/page.tsx rename to apps/web/app/auth/login/page.tsx index dce15e8b..9baf1cc7 100644 --- a/apps/web/app/orgs/[orgslug]/login/page.tsx +++ b/apps/web/app/auth/login/page.tsx @@ -3,14 +3,14 @@ import LoginClient from './login' import { Metadata } from 'next' type MetadataProps = { - params: { orgslug: string; courseid: string } + params: { orgslug: string } searchParams: { [key: string]: string | string[] | undefined } } -export async function generateMetadata({ - params, -}: MetadataProps): Promise { - const orgslug = params.orgslug +export async function generateMetadata(params: MetadataProps): Promise { + const orgslug = params.searchParams.orgslug + + //const orgslug = params.orgslug // Get Org context information const org = await getOrganizationContextInfo(orgslug, { revalidate: 0, @@ -22,8 +22,8 @@ export async function generateMetadata({ } } -const Login = async (params: any) => { - const orgslug = params.params.orgslug +const Login = async (params: MetadataProps) => { + const orgslug = params.searchParams.orgslug const org = await getOrganizationContextInfo(orgslug, { revalidate: 0, tags: ['organizations'], diff --git a/apps/web/app/auth/options.ts b/apps/web/app/auth/options.ts new file mode 100644 index 00000000..04553622 --- /dev/null +++ b/apps/web/app/auth/options.ts @@ -0,0 +1,114 @@ +import { + getNewAccessTokenUsingRefreshTokenServer, + getUserSession, + loginAndGetToken, + loginWithOAuthToken, +} from '@services/auth/auth' +import { LEARNHOUSE_TOP_DOMAIN, getUriWithOrg } from '@services/config/config' +import { getResponseMetadata } from '@services/utils/ts/requests' +import CredentialsProvider from 'next-auth/providers/credentials' +import GoogleProvider from 'next-auth/providers/google' + +const isDevEnv = LEARNHOUSE_TOP_DOMAIN == 'localhost' ? true : false + +export const nextAuthOptions = { + debug: true, + providers: [ + CredentialsProvider({ + // The name to display on the sign in form (e.g. 'Sign in with...') + name: 'Credentials', + // The credentials is used to generate a suitable form on the sign in page. + // You can specify whatever fields you are expecting to be submitted. + // e.g. domain, username, password, 2FA token, etc. + // You can pass any HTML attribute to the tag through the object. + credentials: { + email: { label: 'Email', type: 'text', placeholder: 'jsmith' }, + password: { label: 'Password', type: 'password' }, + }, + async authorize(credentials, req) { + // logic to verify if user exists + let unsanitized_req = await loginAndGetToken( + credentials?.email, + credentials?.password + ) + let res = await getResponseMetadata(unsanitized_req) + if (res.success) { + // If login failed, then this is the place you could do a registration + return res.data + } else { + return null + } + }, + }), + GoogleProvider({ + clientId: process.env.LEARNHOUSE_GOOGLE_CLIENT_ID || '', + clientSecret: process.env.LEARNHOUSE_GOOGLE_CLIENT_SECRET || '', + }), + ], + pages: { + signIn: getUriWithOrg('auth', '/'), + verifyRequest: getUriWithOrg('auth', '/'), + error: getUriWithOrg('auth', '/'), // Error code passed in query string as ?error= + }, + cookies: { + sessionToken: { + name: `${!isDevEnv ? '__Secure-' : ''}next-auth.session-token`, + options: { + httpOnly: true, + sameSite: 'lax', + path: '/', + // When working on localhost, the cookie domain must be omitted entirely (https://stackoverflow.com/a/1188145) + domain: `.${LEARNHOUSE_TOP_DOMAIN}`, + secure: !isDevEnv, + }, + }, + }, + callbacks: { + async jwt({ token, user, account }: any) { + // First sign in with Credentials provider + if (account?.provider == 'credentials' && user) { + token.user = user + } + + // Sign up with Google + if (account?.provider == 'google' && user) { + let unsanitized_req = await loginWithOAuthToken( + user.email, + 'google', + account.access_token + ) + let userFromOAuth = await getResponseMetadata(unsanitized_req) + token.user = userFromOAuth.data + } + + // Refresh token + // TODO : Improve this implementation + if (token?.user?.tokens) { + const RefreshedToken = await getNewAccessTokenUsingRefreshTokenServer( + token?.user?.tokens?.refresh_token + ) + token = { + ...token, + user: { + ...token.user, + tokens: { + ...token.user.tokens, + access_token: RefreshedToken.access_token, + }, + }, + } + } + return token + }, + async session({ session, token }: any) { + // Include user information in the session + if (token.user) { + let api_SESSION = await getUserSession(token.user.tokens.access_token) + session.user = api_SESSION.user + session.roles = api_SESSION.roles + session.tokens = token.user.tokens + } + return session + }, + }, +} diff --git a/apps/web/app/orgs/[orgslug]/reset/page.tsx b/apps/web/app/auth/reset/page.tsx similarity index 100% rename from apps/web/app/orgs/[orgslug]/reset/page.tsx rename to apps/web/app/auth/reset/page.tsx diff --git a/apps/web/app/orgs/[orgslug]/reset/reset.tsx b/apps/web/app/auth/reset/reset.tsx similarity index 99% rename from apps/web/app/orgs/[orgslug]/reset/reset.tsx rename to apps/web/app/auth/reset/reset.tsx index f29d9a36..c275f98f 100644 --- a/apps/web/app/orgs/[orgslug]/reset/reset.tsx +++ b/apps/web/app/auth/reset/reset.tsx @@ -15,7 +15,7 @@ import { getUriWithOrg } from '@services/config/config' import { useOrg } from '@components/Contexts/OrgContext' import { useRouter, useSearchParams } from 'next/navigation' import { useFormik } from 'formik' -import { resetPassword, sendResetLink } from '@services/auth/auth' +import { resetPassword } from '@services/auth/auth' const validate = (values: any) => { const errors: any = {} diff --git a/apps/web/app/orgs/[orgslug]/signup/InviteOnlySignUp.tsx b/apps/web/app/auth/signup/InviteOnlySignUp.tsx similarity index 90% rename from apps/web/app/orgs/[orgslug]/signup/InviteOnlySignUp.tsx rename to apps/web/app/auth/signup/InviteOnlySignUp.tsx index 6827fc20..0ffa7952 100644 --- a/apps/web/app/orgs/[orgslug]/signup/InviteOnlySignUp.tsx +++ b/apps/web/app/auth/signup/InviteOnlySignUp.tsx @@ -13,6 +13,7 @@ import { AlertTriangle, Check, User } from 'lucide-react' import Link from 'next/link' import { signUpWithInviteCode } from '@services/auth/auth' import { useOrg } from '@components/Contexts/OrgContext' +import { signIn } from 'next-auth/react' const validate = (values: any) => { const errors: any = {} @@ -92,7 +93,7 @@ function InviteOnlySignUpComponent(props: InviteOnlySignUpProps) { }, }) - useEffect(() => {}, [org]) + useEffect(() => { }, [org]) return (
@@ -180,6 +181,13 @@ function InviteOnlySignUpComponent(props: InviteOnlySignUpProps) {
+
+
+ +
) } diff --git a/apps/web/app/orgs/[orgslug]/signup/OpenSignup.tsx b/apps/web/app/auth/signup/OpenSignup.tsx similarity index 90% rename from apps/web/app/orgs/[orgslug]/signup/OpenSignup.tsx rename to apps/web/app/auth/signup/OpenSignup.tsx index 9c4bbc4d..36a2e821 100644 --- a/apps/web/app/orgs/[orgslug]/signup/OpenSignup.tsx +++ b/apps/web/app/auth/signup/OpenSignup.tsx @@ -13,6 +13,7 @@ import { AlertTriangle, Check, User } from 'lucide-react' import Link from 'next/link' import { signup } from '@services/auth/auth' import { useOrg } from '@components/Contexts/OrgContext' +import { signIn } from 'next-auth/react' const validate = (values: any) => { const errors: any = {} @@ -88,7 +89,7 @@ function OpenSignUpComponent() { }, }) - useEffect(() => {}, [org]) + useEffect(() => { }, [org]) return (
@@ -176,6 +177,13 @@ function OpenSignUpComponent() {
+
+
+ +
) } diff --git a/apps/web/app/orgs/[orgslug]/signup/page.tsx b/apps/web/app/auth/signup/page.tsx similarity index 82% rename from apps/web/app/orgs/[orgslug]/signup/page.tsx rename to apps/web/app/auth/signup/page.tsx index 9a9b48e4..babc3203 100644 --- a/apps/web/app/orgs/[orgslug]/signup/page.tsx +++ b/apps/web/app/auth/signup/page.tsx @@ -9,10 +9,10 @@ type MetadataProps = { searchParams: { [key: string]: string | string[] | undefined } } -export async function generateMetadata({ - params, -}: MetadataProps): Promise { - const orgslug = params.orgslug +export async function generateMetadata( + params + : MetadataProps): Promise { + const orgslug = params.searchParams.orgslug // Get Org context information const org = await getOrganizationContextInfo(orgslug, { revalidate: 0, @@ -25,7 +25,7 @@ export async function generateMetadata({ } const SignUp = async (params: any) => { - const orgslug = params.params.orgslug + const orgslug = params.searchParams.orgslug const org = await getOrganizationContextInfo(orgslug, { revalidate: 0, tags: ['organizations'], diff --git a/apps/web/app/orgs/[orgslug]/signup/signup.tsx b/apps/web/app/auth/signup/signup.tsx similarity index 77% rename from apps/web/app/orgs/[orgslug]/signup/signup.tsx rename to apps/web/app/auth/signup/signup.tsx index 77091406..5174fc7f 100644 --- a/apps/web/app/orgs/[orgslug]/signup/signup.tsx +++ b/apps/web/app/auth/signup/signup.tsx @@ -4,9 +4,9 @@ import Image from 'next/image' import { getOrgLogoMediaDirectory } from '@services/media/media' import Link from 'next/link' import { getUriWithOrg } from '@services/config/config' -import { useSession } from '@components/Contexts/SessionContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' import React, { useEffect } from 'react' -import { MailWarning, Shield, Ticket, UserPlus } from 'lucide-react' +import { MailWarning, Ticket, UserPlus } from 'lucide-react' import { useOrg } from '@components/Contexts/OrgContext' import UserAvatar from '@components/Objects/UserAvatar' import OpenSignUpComponent from './OpenSignup' @@ -16,13 +16,15 @@ import { validateInviteCode } from '@services/organizations/invites' import PageLoading from '@components/Objects/Loaders/PageLoading' import Toast from '@components/StyledElements/Toast/Toast' import toast from 'react-hot-toast' +import { BarLoader } from 'react-spinners' +import { joinOrg } from '@services/organizations/orgs' interface SignUpClientProps { org: any } function SignUpClient(props: SignUpClientProps) { - const session = useSession() as any + const session = useLHSession() as any const [joinMethod, setJoinMethod] = React.useState('open') const [inviteCode, setInviteCode] = React.useState('') const searchParams = useSearchParams() @@ -33,9 +35,6 @@ function SignUpClient(props: SignUpClientProps) { setJoinMethod( props.org?.config?.config?.GeneralConfig.users.signup_mechanism ) - console.log( - props.org?.config?.config?.GeneralConfig.users.signup_mechanism - ) } if (inviteCodeParam) { setInviteCode(inviteCodeParam) @@ -72,7 +71,7 @@ function SignUpClient(props: SignUpClientProps) { props.org.org_uuid, props.org?.logo_image )}`} - alt="Learnhouse" + alt="LearnHouse" style={{ width: 'auto', height: 70 }} className="rounded-xl shadow-xl inset-0 ring-1 ring-inset ring-black/10 bg-white" /> @@ -92,15 +91,15 @@ function SignUpClient(props: SignUpClientProps) {
{joinMethod == 'open' && - (session.isAuthenticated ? ( + (session.status == 'authenticated' ? ( ) : ( ))} {joinMethod == 'inviteOnly' && (inviteCode ? ( - session.isAuthenticated ? ( - + session.status == 'authenticated' ? ( + ) : ( ) @@ -113,9 +112,32 @@ function SignUpClient(props: SignUpClientProps) { } const LoggedInJoinScreen = (props: any) => { - const session = useSession() as any + const session = useLHSession() as any const org = useOrg() as any + const invite_code = props.inviteCode const [isLoading, setIsLoading] = React.useState(true) + const [isSumbitting, setIsSubmitting] = React.useState(false) + const router = useRouter() + + const join = async () => { + setIsSubmitting(true) + const res = await joinOrg({ org_id: org.id, user_id: session?.data?.user?.id, invite_code: props.inviteCode }, null, session.data?.tokens?.access_token) + //wait for 1s + if (res.success) { + toast.success( + res.data + ) + setTimeout(() => { + router.push(getUriWithOrg(org.slug,'/')) + }, 2000) + setIsSubmitting(false) + } else { + toast.error(res.data.detail) + setIsLoading(false) + setIsSubmitting(false) + } + + } useEffect(() => { if (session && org) { @@ -125,18 +147,23 @@ const LoggedInJoinScreen = (props: any) => { return (
+

Hi - {session.user.username}, + {session.data.username}, join {org?.name} ?

-
@@ -144,7 +171,7 @@ const LoggedInJoinScreen = (props: any) => { } const NoTokenScreen = (props: any) => { - const session = useSession() as any + const session = useLHSession() as any const org = useOrg() as any const router = useRouter() const [isLoading, setIsLoading] = React.useState(true) @@ -157,14 +184,14 @@ const NoTokenScreen = (props: any) => { const validateCode = async () => { setIsLoading(true) - let res = await validateInviteCode(org?.id, inviteCode) + let res = await validateInviteCode(org?.id, inviteCode, session?.user?.tokens.access_token) //wait for 1s if (res.success) { toast.success( "Invite code is valid, you'll be redirected to the signup page in a few seconds" ) setTimeout(() => { - router.push(`/signup?inviteCode=${inviteCode}`) + router.push(`/signup?inviteCode=${inviteCode}&orgslug=${org.slug}`) }, 2000) } else { toast.error('Invite code is invalid') diff --git a/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/loading.tsx b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/loading.tsx index 3da44848..a6338cbf 100644 --- a/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/loading.tsx +++ b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/loading.tsx @@ -3,4 +3,4 @@ import PageLoading from '@components/Objects/Loaders/PageLoading' export default function Loading() { // Or a custom loading skeleton component return -} +} \ No newline at end of file diff --git a/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx index 0b7c113e..72183f3a 100644 --- a/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx +++ b/apps/web/app/editor/course/[courseid]/activity/[activityuuid]/edit/page.tsx @@ -1,14 +1,13 @@ import { default as React } from 'react' import dynamic from 'next/dynamic' -import { getCourseMetadataWithAuthHeader } from '@services/courses/courses' -import { cookies } from 'next/headers' +import { getCourseMetadata } from '@services/courses/courses' import { Metadata } from 'next' import { getActivityWithAuthHeader } from '@services/courses/activities' -import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth' import { getOrganizationContextInfoWithId } from '@services/organizations/orgs' -import SessionProvider from '@components/Contexts/SessionContext' import EditorOptionsProvider from '@components/Contexts/Editor/EditorContext' import AIEditorProvider from '@components/Contexts/AI/AIEditorContext' +import { nextAuthOptions } from 'app/auth/options' +import { getServerSession } from 'next-auth' const EditorWrapper = dynamic(() => import('@components/Objects/Editor/EditorWrapper'), { ssr: false }) @@ -20,10 +19,10 @@ type MetadataProps = { export async function generateMetadata({ params, }: MetadataProps): Promise { - const cookieStore = cookies() - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token // Get Org context information - const course_meta = await getCourseMetadataWithAuthHeader( + const course_meta = await getCourseMetadata( params.courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null @@ -36,11 +35,11 @@ export async function generateMetadata({ } const EditActivity = async (params: any) => { - const cookieStore = cookies() - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token const activityuuid = params.params.activityuuid const courseid = params.params.courseid - const courseInfo = await getCourseMetadataWithAuthHeader( + const courseInfo = await getCourseMetadata( courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null @@ -53,19 +52,17 @@ const EditActivity = async (params: any) => { const org = await getOrganizationContextInfoWithId(courseInfo.org_id, { revalidate: 180, tags: ['organizations'], - }) + }, access_token) return ( - - - + ) diff --git a/apps/web/app/home/home.tsx b/apps/web/app/home/home.tsx new file mode 100644 index 00000000..6c5c83ae --- /dev/null +++ b/apps/web/app/home/home.tsx @@ -0,0 +1,57 @@ +'use client' +import { useLHSession } from '@components/Contexts/LHSessionContext' +import UserAvatar from '@components/Objects/UserAvatar'; +import { getAPIUrl, getUriWithOrg, getUriWithoutOrg } from '@services/config/config'; +import { swrFetcher } from '@services/utils/ts/requests'; +import { ArrowRightCircle, Info } from 'lucide-react'; +import { signOut } from 'next-auth/react'; +import Image from 'next/image'; +import Link from 'next/link'; +import learnhouseIcon from 'public/learnhouse_bigicon_1.png' +import React, { useEffect } from 'react' +import useSWR from 'swr'; + +function HomeClient() { + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; + const { data: orgs } = useSWR(`${getAPIUrl()}orgs/user/page/1/limit/10`, (url) => swrFetcher(url, access_token)) + + useEffect(() => { + console.log(orgs) + + + }, [session, orgs]) + return ( +
+ +
+ +
+ +
Hello, {session?.data?.user.first_name} {session?.data?.user.last_name}
+
Your Organizations
+ {orgs && orgs.length == 0 &&
+ + It seems you're not part of an organization yet, join one to be able to see it here +
} +
+ {orgs && orgs.map((org: any) => ( + +
{org.name}
+ + + ))} +
+
signOut({ redirect: true, callbackUrl: getUriWithoutOrg('/') })}>Sign out
+ +
+ ) +} + +export default HomeClient \ No newline at end of file diff --git a/apps/web/app/home/page.tsx b/apps/web/app/home/page.tsx new file mode 100644 index 00000000..2dd1b5ef --- /dev/null +++ b/apps/web/app/home/page.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import HomeClient from './home' +import type { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'Home', +} +function Home() { + return ( +
+ +
+ ) +} + +export default Home \ No newline at end of file diff --git a/apps/web/app/install/steps/account_creation.tsx b/apps/web/app/install/steps/account_creation.tsx index 98cc1760..1a8d8531 100644 --- a/apps/web/app/install/steps/account_creation.tsx +++ b/apps/web/app/install/steps/account_creation.tsx @@ -10,6 +10,7 @@ import { getAPIUrl } from '@services/config/config' import { createNewUserInstall, updateInstall } from '@services/install/install' import { swrFetcher } from '@services/utils/ts/requests' import { useFormik } from 'formik' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useRouter } from 'next/navigation' import React from 'react' import { BarLoader } from 'react-spinners' @@ -47,11 +48,13 @@ const validate = (values: any) => { function AccountCreation() { const [isSubmitting, setIsSubmitting] = React.useState(false) + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const { data: install, error: error, isLoading, - } = useSWR(`${getAPIUrl()}install/latest`, swrFetcher) + } = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token)) const router = useRouter() const formik = useFormik({ initialValues: { diff --git a/apps/web/app/install/steps/default_elements.tsx b/apps/web/app/install/steps/default_elements.tsx index 53b19190..b5f54bb6 100644 --- a/apps/web/app/install/steps/default_elements.tsx +++ b/apps/web/app/install/steps/default_elements.tsx @@ -1,16 +1,19 @@ import { getAPIUrl } from '@services/config/config' import { createDefaultElements, updateInstall } from '@services/install/install' import { swrFetcher } from '@services/utils/ts/requests' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useRouter } from 'next/navigation' import React from 'react' import useSWR from 'swr' function DefaultElements() { + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const { data: install, error: error, isLoading, - } = useSWR(`${getAPIUrl()}install/latest`, swrFetcher) + } = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token)) const [isSubmitting, setIsSubmitting] = React.useState(false) const [isSubmitted, setIsSubmitted] = React.useState(false) const router = useRouter() diff --git a/apps/web/app/install/steps/finish.tsx b/apps/web/app/install/steps/finish.tsx index 8bb09fe3..853908ec 100644 --- a/apps/web/app/install/steps/finish.tsx +++ b/apps/web/app/install/steps/finish.tsx @@ -2,16 +2,19 @@ import { getAPIUrl } from '@services/config/config' import { updateInstall } from '@services/install/install' import { swrFetcher } from '@services/utils/ts/requests' import { Check } from 'lucide-react' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useRouter } from 'next/navigation' import React from 'react' import useSWR from 'swr' const Finish = () => { + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const { data: install, error: error, isLoading, - } = useSWR(`${getAPIUrl()}install/latest`, swrFetcher) + } = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token)) const router = useRouter() async function finishInstall() { diff --git a/apps/web/app/install/steps/get_started.tsx b/apps/web/app/install/steps/get_started.tsx index 1c247b97..75483613 100644 --- a/apps/web/app/install/steps/get_started.tsx +++ b/apps/web/app/install/steps/get_started.tsx @@ -1,16 +1,19 @@ import PageLoading from '@components/Objects/Loaders/PageLoading' import { getAPIUrl } from '@services/config/config' import { swrFetcher } from '@services/utils/ts/requests' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useRouter } from 'next/navigation' import React, { useEffect } from 'react' import useSWR, { mutate } from 'swr' function GetStarted() { + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const { data: install, error: error, isLoading, - } = useSWR(`${getAPIUrl()}install/latest`, swrFetcher) + } = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token)) const router = useRouter() async function startInstallation() { diff --git a/apps/web/app/install/steps/org_creation.tsx b/apps/web/app/install/steps/org_creation.tsx index 11ac9810..5efd2c93 100644 --- a/apps/web/app/install/steps/org_creation.tsx +++ b/apps/web/app/install/steps/org_creation.tsx @@ -14,6 +14,7 @@ import useSWR from 'swr' import { createNewOrgInstall, updateInstall } from '@services/install/install' import { useRouter } from 'next/navigation' import { Check } from 'lucide-react' +import { useLHSession } from '@components/Contexts/LHSessionContext' const validate = (values: any) => { const errors: any = {} @@ -40,11 +41,13 @@ const validate = (values: any) => { } function OrgCreation() { + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const { data: install, error: error, isLoading, - } = useSWR(`${getAPIUrl()}install/latest`, swrFetcher) + } = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token)) const [isSubmitting, setIsSubmitting] = React.useState(false) const [isSubmitted, setIsSubmitted] = React.useState(false) const router = useRouter() diff --git a/apps/web/app/install/steps/sample_data.tsx b/apps/web/app/install/steps/sample_data.tsx index 7a174283..217cc547 100644 --- a/apps/web/app/install/steps/sample_data.tsx +++ b/apps/web/app/install/steps/sample_data.tsx @@ -4,16 +4,19 @@ import { updateInstall, } from '@services/install/install' import { swrFetcher } from '@services/utils/ts/requests' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useRouter } from 'next/navigation' import React from 'react' import useSWR from 'swr' function SampleData() { + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const { data: install, error: error, isLoading, - } = useSWR(`${getAPIUrl()}install/latest`, swrFetcher) + } = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token)) const router = useRouter() function createSampleData() { diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx index aedda02e..93dcdc2d 100644 --- a/apps/web/app/layout.tsx +++ b/apps/web/app/layout.tsx @@ -1,8 +1,9 @@ 'use client' import '../styles/globals.css' import StyledComponentsRegistry from '../components/Utils/libs/styled-registry' - import { motion } from 'framer-motion' +import { SessionProvider } from 'next-auth/react' +import LHSessionProvider from '@components/Contexts/LHSessionContext' export default function RootLayout({ children, @@ -18,18 +19,22 @@ export default function RootLayout({ - - - {children} - - + + + + + {children} + + + + ) diff --git a/apps/web/app/organizations/new/page.tsx b/apps/web/app/organizations/new/page.tsx deleted file mode 100644 index 800bc838..00000000 --- a/apps/web/app/organizations/new/page.tsx +++ /dev/null @@ -1,58 +0,0 @@ -'use client' -import React from 'react' -import { createNewOrganization } from '../../../services/organizations/orgs' - -const Organizations = () => { - const [name, setName] = React.useState('') - const [description, setDescription] = React.useState('') - const [email, setEmail] = React.useState('') - const [slug, setSlug] = React.useState('') - - const handleNameChange = (e: any) => { - setName(e.target.value) - } - - const handleDescriptionChange = (e: any) => { - setDescription(e.target.value) - } - - const handleEmailChange = (e: any) => { - setEmail(e.target.value) - } - - const handleSlugChange = (e: any) => { - setSlug(e.target.value) - } - - const handleSubmit = async (e: any) => { - e.preventDefault() - - let logo = '' - const status = await createNewOrganization({ - name, - description, - email, - logo, - slug, - default: false, - }) - alert(JSON.stringify(status)) - } - - return ( -
-
New Organization
- Name: -
- Description: -
- Slug: -
- Email Address: -
- -
- ) -} - -export default Organizations diff --git a/apps/web/app/organizations/page.tsx b/apps/web/app/organizations/page.tsx deleted file mode 100644 index ae2b9e18..00000000 --- a/apps/web/app/organizations/page.tsx +++ /dev/null @@ -1,65 +0,0 @@ -'use client' //todo: use server components -import Link from 'next/link' -import React from 'react' -import { deleteOrganizationFromBackend } from '@services/organizations/orgs' -import useSWR, { mutate } from 'swr' -import { swrFetcher } from '@services/utils/ts/requests' -import { getAPIUrl, getUriWithOrg } from '@services/config/config' - -const Organizations = () => { - const { data: organizations, error } = useSWR( - `${getAPIUrl()}orgs/user/page/1/limit/10`, - swrFetcher - ) - - async function deleteOrganization(org_id: any) { - const response = await deleteOrganizationFromBackend(org_id) - response && - mutate( - `${getAPIUrl()}orgs/user/page/1/limit/10`, - organizations.filter((org: any) => org.org_id !== org_id) - ) - } - - return ( - <> -
- Your Organizations{' '} - - - -
-
- - {error &&

Failed to load

} - {!organizations ? ( -

Loading...

- ) : ( -
- {organizations.map((org: any) => ( -
- -

- {org.name} -

- - -
- ))} -
- )} - - ) -} - -export default Organizations diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/collection/[collectionid]/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/collection/[collectionid]/page.tsx index a93d57d9..523ca9bd 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/collection/[collectionid]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/collection/[collectionid]/page.tsx @@ -1,11 +1,11 @@ import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper' -import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth' import { getUriWithOrg } from '@services/config/config' -import { getCollectionByIdWithAuthHeader } from '@services/courses/collections' +import { getCollectionById } from '@services/courses/collections' import { getCourseThumbnailMediaDirectory } from '@services/media/media' import { getOrganizationContextInfo } from '@services/organizations/orgs' +import { nextAuthOptions } from 'app/auth/options' import { Metadata } from 'next' -import { cookies } from 'next/headers' +import { getServerSession } from 'next-auth' import Link from 'next/link' type MetadataProps = { @@ -16,15 +16,15 @@ type MetadataProps = { export async function generateMetadata({ params, }: MetadataProps): Promise { - const cookieStore = cookies() - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'], }) - const col = await getCollectionByIdWithAuthHeader( + const col = await getCollectionById( params.collectionid, access_token ? access_token : null, { revalidate: 0, tags: ['collections'] } @@ -53,14 +53,14 @@ export async function generateMetadata({ } const CollectionPage = async (params: any) => { - const cookieStore = cookies() - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token const org = await getOrganizationContextInfo(params.params.orgslug, { revalidate: 1800, tags: ['organizations'], }) const orgslug = params.params.orgslug - const col = await getCollectionByIdWithAuthHeader( + const col = await getCollectionById( params.params.collectionid, access_token ? access_token : null, { revalidate: 0, tags: ['collections'] } diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/collections/new/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/collections/new/page.tsx index 77708f79..be8cbd01 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/collections/new/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/collections/new/page.tsx @@ -6,9 +6,12 @@ import useSWR from 'swr' import { getAPIUrl, getUriWithOrg } from '@services/config/config' import { revalidateTags, swrFetcher } from '@services/utils/ts/requests' import { useOrg } from '@components/Contexts/OrgContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' function NewCollection(params: any) { const org = useOrg() as any + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const orgslug = params.params.orgslug const [name, setName] = React.useState('') const [description, setDescription] = React.useState('') @@ -16,7 +19,7 @@ function NewCollection(params: any) { const router = useRouter() const { data: courses, error: error } = useSWR( `${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`, - swrFetcher + (url) => swrFetcher(url, access_token) ) const [isPublic, setIsPublic] = useState('true') @@ -44,7 +47,7 @@ function NewCollection(params: any) { public: isPublic, org_id: org.id, } - await createCollection(collection) + await createCollection(collection, session.data?.tokens?.access_token) await revalidateTags(['collections'], org.slug) // reload the page router.refresh() diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/collections/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/collections/page.tsx index aaed61cf..9ff96216 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/collections/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/collections/page.tsx @@ -2,15 +2,15 @@ import AuthenticatedClientElement from '@components/Security/AuthenticatedClient import TypeOfContentTitle from '@components/StyledElements/Titles/TypeOfContentTitle' import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper' import { getUriWithOrg } from '@services/config/config' -import { getOrgCollectionsWithAuthHeader } from '@services/courses/collections' import { getOrganizationContextInfo } from '@services/organizations/orgs' import { Metadata } from 'next' -import { cookies } from 'next/headers' import Link from 'next/link' -import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth' import CollectionThumbnail from '@components/Objects/Thumbnails/CollectionThumbnail' import NewCollectionButton from '@components/StyledElements/Buttons/NewCollectionButton' import ContentPlaceHolderIfUserIsNotAdmin from '@components/ContentPlaceHolder' +import { nextAuthOptions } from 'app/auth/options' +import { getServerSession } from 'next-auth' +import { getOrgCollections } from '@services/courses/collections' type MetadataProps = { params: { orgslug: string; courseid: string } @@ -49,15 +49,15 @@ export async function generateMetadata({ } const CollectionsPage = async (params: any) => { - const cookieStore = cookies() - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token const orgslug = params.params.orgslug const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'], }) const org_id = org.id - const collections = await getOrgCollectionsWithAuthHeader( + const collections = await getOrgCollections( org_id, access_token ? access_token : null, { revalidate: 0, tags: ['collections'] } diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/activity.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/activity.tsx index f7c91833..9bc369cd 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/activity.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/activity.tsx @@ -15,6 +15,7 @@ import { useOrg } from '@components/Contexts/OrgContext' import { CourseProvider } from '@components/Contexts/CourseContext' import AIActivityAsk from '@components/Objects/Activities/AI/AIActivityAsk' import AIChatBotProvider from '@components/Contexts/AI/AIChatBotContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' interface ActivityClientProps { activityid: string @@ -106,11 +107,10 @@ function ActivityClient(props: ActivityClientProps) { {activity ? (
{activity.activity_type == 'TYPE_DYNAMIC' && ( @@ -147,13 +147,14 @@ export function MarkStatus(props: { orgslug: string }) { const router = useRouter() - console.log(props.course.trail) + const session = useLHSession() as any; async function markActivityAsCompleteFront() { const trail = await markActivityAsComplete( props.orgslug, props.course.course_uuid, - 'activity_' + props.activityid + 'activity_' + props.activityid, + session.data?.tokens?.access_token ) router.refresh() } @@ -169,8 +170,6 @@ export function MarkStatus(props: { } } - console.log('isActivityCompleted', isActivityCompleted()) - return ( <> {isActivityCompleted() ? ( diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx index 1cf87b7f..9f4b0935 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/activity/[activityid]/page.tsx @@ -1,10 +1,10 @@ import { getActivityWithAuthHeader } from '@services/courses/activities' -import { getCourseMetadataWithAuthHeader } from '@services/courses/courses' -import { cookies } from 'next/headers' +import { getCourseMetadata } from '@services/courses/courses' import ActivityClient from './activity' import { getOrganizationContextInfo } from '@services/organizations/orgs' import { Metadata } from 'next' -import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth' +import { getServerSession } from 'next-auth' +import { nextAuthOptions } from 'app/auth/options' type MetadataProps = { params: { orgslug: string; courseuuid: string; activityid: string } @@ -14,15 +14,15 @@ type MetadataProps = { export async function generateMetadata({ params, }: MetadataProps): Promise { - const cookieStore = cookies() - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'], }) - const course_meta = await getCourseMetadataWithAuthHeader( + const course_meta = await getCourseMetadata( params.courseuuid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null @@ -58,13 +58,13 @@ export async function generateMetadata({ } const ActivityPage = async (params: any) => { - const cookieStore = cookies() - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token const activityid = params.params.activityid const courseuuid = params.params.courseuuid const orgslug = params.params.orgslug - const course_meta = await getCourseMetadataWithAuthHeader( + const course_meta = await getCourseMetadata( courseuuid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/course.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/course.tsx index fd58842b..26a23c5c 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/course.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/course.tsx @@ -17,10 +17,12 @@ import { useOrg } from '@components/Contexts/OrgContext' import UserAvatar from '@components/Objects/UserAvatar' import CourseUpdates from '@components/Objects/CourseUpdates/CourseUpdates' import { CourseProvider } from '@components/Contexts/CourseContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' const CourseClient = (props: any) => { const [user, setUser] = useState({}) const [learnings, setLearnings] = useState([]) + const session = useLHSession() as any; const courseuuid = props.courseuuid const orgslug = props.orgslug const course = props.course @@ -35,7 +37,7 @@ const CourseClient = (props: any) => { async function startCourseUI() { // Create activity - await startCourse('course_' + courseuuid, orgslug) + await startCourse('course_' + courseuuid, orgslug, session.data?.tokens?.access_token) await revalidateTags(['courses'], orgslug) router.refresh() @@ -54,7 +56,7 @@ const CourseClient = (props: any) => { async function quitCourse() { // Close activity - let activity = await removeCourse('course_' + courseuuid, orgslug) + let activity = await removeCourse('course_' + courseuuid, orgslug, session.data?.tokens?.access_token) // Mutate course await revalidateTags(['courses'], orgslug) router.refresh() @@ -277,7 +279,7 @@ const CourseClient = (props: any) => {
diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/error.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/error.tsx index d5320406..1e0708da 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/error.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/error.tsx @@ -1,6 +1,5 @@ 'use client' // Error components must be Client Components -import ErrorUI from '@components/StyledElements/Error/Error' import { useEffect } from 'react' export default function Error({ @@ -17,7 +16,7 @@ export default function Error({ return (
- +
) } diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/loading.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/loading.tsx deleted file mode 100644 index 3da44848..00000000 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/loading.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import PageLoading from '@components/Objects/Loaders/PageLoading' - -export default function Loading() { - // Or a custom loading skeleton component - return -} diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/page.tsx index f26b7caa..ca4180d6 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/course/[courseuuid]/page.tsx @@ -1,11 +1,11 @@ import React from 'react' import CourseClient from './course' -import { cookies } from 'next/headers' -import { getCourseMetadataWithAuthHeader } from '@services/courses/courses' +import { getCourseMetadata } from '@services/courses/courses' import { getOrganizationContextInfo } from '@services/organizations/orgs' import { Metadata } from 'next' -import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth' import { getCourseThumbnailMediaDirectory } from '@services/media/media' +import { nextAuthOptions } from 'app/auth/options' +import { getServerSession } from 'next-auth' type MetadataProps = { params: { orgslug: string; courseuuid: string } @@ -15,15 +15,15 @@ type MetadataProps = { export async function generateMetadata({ params, }: MetadataProps): Promise { - const cookieStore = cookies() - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'], }) - const course_meta = await getCourseMetadataWithAuthHeader( + const course_meta = await getCourseMetadata( params.courseuuid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null @@ -67,11 +67,11 @@ export async function generateMetadata({ } const CoursePage = async (params: any) => { - const cookieStore = cookies() const courseuuid = params.params.courseuuid const orgslug = params.params.orgslug - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) - const course_meta = await getCourseMetadataWithAuthHeader( + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token + const course_meta = await getCourseMetadata( courseuuid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/courses/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/courses/page.tsx index d7c8baca..a339cd02 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/courses/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/courses/page.tsx @@ -1,10 +1,10 @@ import React from 'react' import Courses from './courses' -import { getOrgCoursesWithAuthHeader } from '@services/courses/courses' import { Metadata } from 'next' import { getOrganizationContextInfo } from '@services/organizations/orgs' -import { cookies } from 'next/headers' -import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth' +import { nextAuthOptions } from 'app/auth/options' +import { getServerSession } from 'next-auth' +import { getOrgCourses } from '@services/courses/courses' type MetadataProps = { params: { orgslug: string } @@ -49,9 +49,10 @@ const CoursesPage = async (params: any) => { revalidate: 1800, tags: ['organizations'], }) - const cookieStore = cookies() - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) - const courses = await getOrgCoursesWithAuthHeader( + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token + + const courses = await getOrgCourses( orgslug, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/layout.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/layout.tsx index 00ca27ac..152aa846 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/layout.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/layout.tsx @@ -1,6 +1,7 @@ +'use client' import '@styles/globals.css' import { Menu } from '@components/Objects/Menu/Menu' -import SessionProvider from '@components/Contexts/SessionContext' +import { SessionProvider } from 'next-auth/react' export default function RootLayout({ children, diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/page.tsx index b8bc5d0a..5718bb98 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/page.tsx @@ -1,20 +1,20 @@ export const dynamic = 'force-dynamic' import { Metadata } from 'next' import { getUriWithOrg } from '@services/config/config' -import { getOrgCoursesWithAuthHeader } from '@services/courses/courses' +import { getOrgCourses } from '@services/courses/courses' import Link from 'next/link' -import { getOrgCollectionsWithAuthHeader } from '@services/courses/collections' import { getOrganizationContextInfo } from '@services/organizations/orgs' -import { cookies } from 'next/headers' import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper' import TypeOfContentTitle from '@components/StyledElements/Titles/TypeOfContentTitle' -import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth' import CourseThumbnail from '@components/Objects/Thumbnails/CourseThumbnail' import CollectionThumbnail from '@components/Objects/Thumbnails/CollectionThumbnail' import AuthenticatedClientElement from '@components/Security/AuthenticatedClientElement' import NewCourseButton from '@components/StyledElements/Buttons/NewCourseButton' import NewCollectionButton from '@components/StyledElements/Buttons/NewCollectionButton' import ContentPlaceHolderIfUserIsNotAdmin from '@components/ContentPlaceHolder' +import { getOrgCollections } from '@services/courses/collections' +import { getServerSession } from 'next-auth' +import { nextAuthOptions } from 'app/auth/options' type MetadataProps = { params: { orgslug: string } @@ -54,10 +54,9 @@ export async function generateMetadata({ const OrgHomePage = async (params: any) => { const orgslug = params.params.orgslug - const cookieStore = cookies() - - const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) - const courses = await getOrgCoursesWithAuthHeader( + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token + const courses = await getOrgCourses( orgslug, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null @@ -67,7 +66,7 @@ const OrgHomePage = async (params: any) => { tags: ['organizations'], }) const org_id = org.id - const collections = await getOrgCollectionsWithAuthHeader( + const collections = await getOrgCollections( org.id, access_token ? access_token : null, { revalidate: 0, tags: ['courses'] } diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/trail/page.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/trail/page.tsx index 2a327ddd..637156d7 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/trail/page.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/trail/page.tsx @@ -2,6 +2,8 @@ import React from 'react' import { Metadata } from 'next' import { getOrganizationContextInfo } from '@services/organizations/orgs' import Trail from './trail' +import { getServerSession } from 'next-auth' +import { nextAuthOptions } from 'app/auth/options' type MetadataProps = { params: { orgslug: string } @@ -11,11 +13,13 @@ type MetadataProps = { export async function generateMetadata({ params, }: MetadataProps): Promise { + const session = await getServerSession(nextAuthOptions) + const access_token = session?.tokens?.access_token // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'], - }) + }, access_token) return { title: 'Trail — ' + org.name, description: diff --git a/apps/web/app/orgs/[orgslug]/(withmenu)/trail/trail.tsx b/apps/web/app/orgs/[orgslug]/(withmenu)/trail/trail.tsx index 8cbfcf93..b562c0d2 100644 --- a/apps/web/app/orgs/[orgslug]/(withmenu)/trail/trail.tsx +++ b/apps/web/app/orgs/[orgslug]/(withmenu)/trail/trail.tsx @@ -1,4 +1,5 @@ 'use client' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useOrg } from '@components/Contexts/OrgContext' import PageLoading from '@components/Objects/Loaders/PageLoading' import TrailCourseElement from '@components/Pages/Trail/TrailCourseElement' @@ -11,14 +12,16 @@ import useSWR from 'swr' function Trail(params: any) { let orgslug = params.orgslug + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const org = useOrg() as any const orgID = org?.id const { data: trail, error: error } = useSWR( `${getAPIUrl()}trail/org/${orgID}/trail`, - swrFetcher + (url) => swrFetcher(url, access_token) ) - useEffect(() => {}, [trail, org]) + useEffect(() => { }, [trail, org]) return ( diff --git a/apps/web/app/orgs/[orgslug]/dash/ClientAdminLayout.tsx b/apps/web/app/orgs/[orgslug]/dash/ClientAdminLayout.tsx new file mode 100644 index 00000000..32778e18 --- /dev/null +++ b/apps/web/app/orgs/[orgslug]/dash/ClientAdminLayout.tsx @@ -0,0 +1,26 @@ +'use client'; +import LeftMenu from '@components/Dashboard/UI/LeftMenu' +import AdminAuthorization from '@components/Security/AdminAuthorization' +import { SessionProvider } from 'next-auth/react' +import React from 'react' + +function ClientAdminLayout({ + children, + params, +}: { + children: React.ReactNode + params: any +}) { + return ( + + +
+ +
{children}
+
+
+
+ ) +} + +export default ClientAdminLayout \ No newline at end of file diff --git a/apps/web/app/orgs/[orgslug]/dash/courses/client.tsx b/apps/web/app/orgs/[orgslug]/dash/courses/client.tsx index cce3a585..31ae5ce3 100644 --- a/apps/web/app/orgs/[orgslug]/dash/courses/client.tsx +++ b/apps/web/app/orgs/[orgslug]/dash/courses/client.tsx @@ -30,7 +30,6 @@ function CoursesHome(params: CourseProps) {
-
Courses
- - -
- -
{children}
-
-
-
+ + {children} + ) } diff --git a/apps/web/app/orgs/[orgslug]/dash/user-account/settings/[subpage]/page.tsx b/apps/web/app/orgs/[orgslug]/dash/user-account/settings/[subpage]/page.tsx index 5a8d0d72..6162f70e 100644 --- a/apps/web/app/orgs/[orgslug]/dash/user-account/settings/[subpage]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/dash/user-account/settings/[subpage]/page.tsx @@ -7,7 +7,7 @@ import Link from 'next/link' import { getUriWithOrg } from '@services/config/config' import { Info, Lock } from 'lucide-react' import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs' -import { useSession } from '@components/Contexts/SessionContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' export type SettingsParams = { subpage: string @@ -15,7 +15,7 @@ export type SettingsParams = { } function SettingsPage({ params }: { params: SettingsParams }) { - const session = useSession() as any + const session = useLHSession() as any useEffect(() => {}, [session]) diff --git a/apps/web/app/orgs/[orgslug]/dash/users/settings/[subpage]/page.tsx b/apps/web/app/orgs/[orgslug]/dash/users/settings/[subpage]/page.tsx index 8d364a22..995c3a68 100644 --- a/apps/web/app/orgs/[orgslug]/dash/users/settings/[subpage]/page.tsx +++ b/apps/web/app/orgs/[orgslug]/dash/users/settings/[subpage]/page.tsx @@ -5,7 +5,7 @@ import Link from 'next/link' import { getUriWithOrg } from '@services/config/config' import { ScanEye, SquareUserRound, UserPlus, Users } from 'lucide-react' import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs' -import { useSession } from '@components/Contexts/SessionContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useOrg } from '@components/Contexts/OrgContext' import OrgUsers from '@components/Dashboard/Users/OrgUsers/OrgUsers' import OrgAccess from '@components/Dashboard/Users/OrgAccess/OrgAccess' @@ -18,7 +18,7 @@ export type SettingsParams = { } function UsersSettingsPage({ params }: { params: SettingsParams }) { - const session = useSession() as any + const session = useLHSession() as any const org = useOrg() as any const [H1Label, setH1Label] = React.useState('') const [H2Label, setH2Label] = React.useState('') diff --git a/apps/web/app/orgs/[orgslug]/layout.tsx b/apps/web/app/orgs/[orgslug]/layout.tsx index 97ccd9fa..d722fb9f 100644 --- a/apps/web/app/orgs/[orgslug]/layout.tsx +++ b/apps/web/app/orgs/[orgslug]/layout.tsx @@ -1,6 +1,5 @@ 'use client' import { OrgProvider } from '@components/Contexts/OrgContext' -import SessionProvider from '@components/Contexts/SessionContext' import Toast from '@components/StyledElements/Toast/Toast' import '@styles/globals.css' @@ -13,9 +12,9 @@ export default function RootLayout({ }) { return (
- - {children} + + {children}
) diff --git a/apps/web/components/AI/Hooks/useGetAIFeatures.tsx b/apps/web/components/AI/Hooks/useGetAIFeatures.tsx index 19702019..e7c0afb5 100644 --- a/apps/web/components/AI/Hooks/useGetAIFeatures.tsx +++ b/apps/web/components/AI/Hooks/useGetAIFeatures.tsx @@ -13,17 +13,14 @@ function useGetAIFeatures(props: UseGetAIFeatures) { const config = org?.config?.config?.AIConfig if (!config) { - console.log('AI or Organization config is not defined.') return false } if (!config.enabled) { - console.log('AI is not enabled for this Organization.') return false } if (!config.features[feature]) { - console.log(`Feature ${feature} is not enabled for this Organization.`) return false } diff --git a/apps/web/components/ContentPlaceHolder.tsx b/apps/web/components/ContentPlaceHolder.tsx index 1937a408..68c5aa18 100644 --- a/apps/web/components/ContentPlaceHolder.tsx +++ b/apps/web/components/ContentPlaceHolder.tsx @@ -7,7 +7,7 @@ import useAdminStatus from './Hooks/useAdminStatus' function ContentPlaceHolderIfUserIsNotAdmin({ text }: { text: string }) { const isUserAdmin = useAdminStatus() as any return ( -
{isUserAdmin ? text : 'No content yet'}
+ {isUserAdmin ? text : 'No content yet'} ) } diff --git a/apps/web/components/Contexts/CourseContext.tsx b/apps/web/components/Contexts/CourseContext.tsx index aed51150..a2f9f161 100644 --- a/apps/web/components/Contexts/CourseContext.tsx +++ b/apps/web/components/Contexts/CourseContext.tsx @@ -1,9 +1,9 @@ 'use client' -import PageLoading from '@components/Objects/Loaders/PageLoading' import { getAPIUrl } from '@services/config/config' import { swrFetcher } from '@services/utils/ts/requests' import React, { createContext, useContext, useEffect, useReducer } from 'react' import useSWR from 'swr' +import { useLHSession } from '@components/Contexts/LHSessionContext' export const CourseContext = createContext(null) as any export const CourseDispatchContext = createContext(null) as any @@ -15,9 +15,11 @@ export function CourseProvider({ children: React.ReactNode courseuuid: string }) { + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const { data: courseStructureData } = useSWR( `${getAPIUrl()}courses/${courseuuid}/meta`, - swrFetcher + (url) => swrFetcher(url, access_token) ) const [courseStructure, dispatchCourseStructure] = useReducer(courseReducer, { courseStructure: courseStructureData ? courseStructureData : {}, @@ -33,9 +35,9 @@ export function CourseProvider({ payload: courseStructureData, }) } - }, [courseStructureData]) + }, [courseStructureData,session]) - if (!courseStructureData) return + if (!courseStructureData) return return ( diff --git a/apps/web/components/Contexts/LHSessionContext.tsx b/apps/web/components/Contexts/LHSessionContext.tsx new file mode 100644 index 00000000..90acb9d8 --- /dev/null +++ b/apps/web/components/Contexts/LHSessionContext.tsx @@ -0,0 +1,32 @@ +'use client' +import PageLoading from '@components/Objects/Loaders/PageLoading'; +import { useSession } from 'next-auth/react'; +import React, { useContext, createContext, useEffect } from 'react' + +export const SessionContext = createContext({}) as any + +function LHSessionProvider({ children }: { children: React.ReactNode }) { + const session = useSession(); + + useEffect(() => { + }, []) + + + if (session && session.status == 'loading') { + return + } + + else if (session) { + return ( + + {children} + + ) + } +} + +export function useLHSession() { + return useContext(SessionContext) +} + +export default LHSessionProvider \ No newline at end of file diff --git a/apps/web/components/Contexts/OrgContext.tsx b/apps/web/components/Contexts/OrgContext.tsx index 1362cb45..f434b3f1 100644 --- a/apps/web/components/Contexts/OrgContext.tsx +++ b/apps/web/components/Contexts/OrgContext.tsx @@ -1,32 +1,46 @@ 'use client' -import { getAPIUrl } from '@services/config/config' +import { getAPIUrl, getUriWithoutOrg } from '@services/config/config' import { swrFetcher } from '@services/utils/ts/requests' -import React, { useContext, useEffect } from 'react' +import React, { createContext, useContext, useMemo } from 'react' import useSWR from 'swr' -import { createContext } from 'react' -import { useRouter } from 'next/navigation' +import { useLHSession } from '@components/Contexts/LHSessionContext' +import ErrorUI from '@components/StyledElements/Error/Error' +import InfoUI from '@components/StyledElements/Info/Info' +import { usePathname } from 'next/navigation' -export const OrgContext = createContext({}) as any +export const OrgContext = createContext(null) -export function OrgProvider({ - children, - orgslug, -}: { - children: React.ReactNode - orgslug: string -}) { - const { data: org } = useSWR(`${getAPIUrl()}orgs/slug/${orgslug}`, swrFetcher) - const router = useRouter() - // Check if Org is Active - const verifyIfOrgIsActive = () => { - if (org && org?.config.config.GeneralConfig.active === false) { - router.push('/404') - } +export function OrgProvider({ children, orgslug }: { children: React.ReactNode, orgslug: string }) { + const session = useLHSession() as any + const pathname = usePathname() + const accessToken = session?.data?.tokens?.access_token + const isAllowedPathname = ['/login', '/signup'].includes(pathname); + const { data: org, error: orgError } = useSWR( + `${getAPIUrl()}orgs/slug/${orgslug}`, + (url) => swrFetcher(url, accessToken) + ) + const { data: orgs, error: orgsError } = useSWR( + `${getAPIUrl()}orgs/user/page/1/limit/10`, + (url) => swrFetcher(url, accessToken) + ) + + + const isOrgActive = useMemo(() => org?.config?.config?.GeneralConfig?.active !== false, [org]) + const isUserPartOfTheOrg = useMemo(() => orgs?.some((userOrg: any) => userOrg.id === org?.id), [orgs, org?.id]) + + if (orgError || orgsError) return + if (!org || !orgs || !session) return
Loading...
+ if (!isOrgActive) return + if (!isUserPartOfTheOrg && session.status == 'authenticated' && !isAllowedPathname) { + return ( + + ) } - useEffect(() => { - verifyIfOrgIsActive() - }, [org]) return {children} } diff --git a/apps/web/components/Contexts/SessionContext.tsx b/apps/web/components/Contexts/SessionContext.tsx deleted file mode 100644 index b2d5ea94..00000000 --- a/apps/web/components/Contexts/SessionContext.tsx +++ /dev/null @@ -1,77 +0,0 @@ -'use client' -import { - getNewAccessTokenUsingRefreshToken, - getUserSession, -} from '@services/auth/auth' -import React, { useContext, createContext, useEffect } from 'react' - -export const SessionContext = createContext({}) as any - -type Session = { - access_token: string - user: any - roles: any - isLoading: boolean - isAuthenticated: boolean -} - -function SessionProvider({ children }: { children: React.ReactNode }) { - const [session, setSession] = React.useState({ - access_token: '', - user: {}, - roles: {}, - isLoading: true, - isAuthenticated: false, - }) - - async function getNewAccessTokenUsingRefreshTokenUI() { - let data = await getNewAccessTokenUsingRefreshToken() - return data.access_token - } - - async function checkSession() { - // Get new access token using refresh token - const access_token = await getNewAccessTokenUsingRefreshTokenUI() - - if (access_token) { - // Get user session info - const user_session = await getUserSession(access_token) - - // Set session - setSession({ - access_token: access_token, - user: user_session.user, - roles: user_session.roles, - isLoading: false, - isAuthenticated: true, - }) - } - - if (!access_token) { - setSession({ - access_token: '', - user: {}, - roles: {}, - isLoading: false, - isAuthenticated: false, - }) - } - } - - useEffect(() => { - // Check session - checkSession() - }, []) - - return ( - - {children} - - ) -} - -export function useSession() { - return useContext(SessionContext) -} - -export default SessionProvider diff --git a/apps/web/components/Dashboard/Course/EditCourseAccess/EditCourseAccess.tsx b/apps/web/components/Dashboard/Course/EditCourseAccess/EditCourseAccess.tsx index 9fa1abc3..6cb3ab10 100644 --- a/apps/web/components/Dashboard/Course/EditCourseAccess/EditCourseAccess.tsx +++ b/apps/web/components/Dashboard/Course/EditCourseAccess/EditCourseAccess.tsx @@ -5,7 +5,8 @@ import Modal from '@components/StyledElements/Modal/Modal' import { getAPIUrl } from '@services/config/config' import { unLinkResourcesToUserGroup } from '@services/usergroups/usergroups' import { swrFetcher } from '@services/utils/ts/requests' -import { Globe, SquareUserRound, Users, UsersRound, X } from 'lucide-react' +import { Globe, SquareUserRound, Users, X } from 'lucide-react' +import { useLHSession } from '@components/Contexts/LHSessionContext' import React from 'react' import toast from 'react-hot-toast' import useSWR, { mutate } from 'swr' @@ -17,13 +18,15 @@ type EditCourseAccessProps = { function EditCourseAccess(props: EditCourseAccessProps) { const [error, setError] = React.useState('') + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const course = useCourse() as any const dispatchCourse = useCourseDispatch() as any const courseStructure = course.courseStructure const { data: usergroups } = useSWR( courseStructure ? `${getAPIUrl()}usergroups/resource/${courseStructure.course_uuid}` : null, - swrFetcher + (url) => swrFetcher(url, access_token) ) const [isPublic, setIsPublic] = React.useState(courseStructure.public) @@ -109,7 +112,7 @@ function EditCourseAccess(props: EditCourseAccessProps) { status="info" >
- {!isPublic ? ( ) : null} + {!isPublic ? () : null}
) @@ -119,9 +122,11 @@ function EditCourseAccess(props: EditCourseAccessProps) { function UserGroupsSection({ usergroups }: { usergroups: any[] }) { const course = useCourse() as any const [userGroupModal, setUserGroupModal] = React.useState(false) + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const removeUserGroupLink = async (usergroup_id: number) => { - const res = await unLinkResourcesToUserGroup(usergroup_id, course.courseStructure.course_uuid) + const res = await unLinkResourcesToUserGroup(usergroup_id, course.courseStructure.course_uuid,access_token) if (res.status === 200) { toast.success('Successfully unliked from usergroup') mutate(`${getAPIUrl()}usergroups/resource/${course.courseStructure.course_uuid}`) diff --git a/apps/web/components/Dashboard/Course/EditCourseGeneral/EditCourseGeneral.tsx b/apps/web/components/Dashboard/Course/EditCourseGeneral/EditCourseGeneral.tsx index 84129421..1f6d5ddc 100644 --- a/apps/web/components/Dashboard/Course/EditCourseGeneral/EditCourseGeneral.tsx +++ b/apps/web/components/Dashboard/Course/EditCourseGeneral/EditCourseGeneral.tsx @@ -6,7 +6,6 @@ import FormLayout, { } from '@components/StyledElements/Form/Form' import { useFormik } from 'formik' import { AlertTriangle } from 'lucide-react' -import * as Switch from '@radix-ui/react-switch' import * as Form from '@radix-ui/react-form' import React from 'react' import { useCourse, useCourseDispatch } from '../../../Contexts/CourseContext' diff --git a/apps/web/components/Dashboard/Course/EditCourseGeneral/ThumbnailUpdate.tsx b/apps/web/components/Dashboard/Course/EditCourseGeneral/ThumbnailUpdate.tsx index 2a3fce58..980fd6bb 100644 --- a/apps/web/components/Dashboard/Course/EditCourseGeneral/ThumbnailUpdate.tsx +++ b/apps/web/components/Dashboard/Course/EditCourseGeneral/ThumbnailUpdate.tsx @@ -4,11 +4,13 @@ import { getAPIUrl } from '@services/config/config' import { updateCourseThumbnail } from '@services/courses/courses' import { getCourseThumbnailMediaDirectory } from '@services/media/media' import { ArrowBigUpDash, UploadCloud } from 'lucide-react' +import { useLHSession } from '@components/Contexts/LHSessionContext' import React from 'react' import { mutate } from 'swr' function ThumbnailUpdate() { const course = useCourse() as any + const session = useLHSession() as any; const org = useOrg() as any const [localThumbnail, setLocalThumbnail] = React.useState(null) as any const [isLoading, setIsLoading] = React.useState(false) as any @@ -20,7 +22,8 @@ function ThumbnailUpdate() { setIsLoading(true) const res = await updateCourseThumbnail( course.courseStructure.course_uuid, - file + file, + session.data?.tokens?.access_token ) mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`) // wait for 1 second to show loading animation diff --git a/apps/web/components/Dashboard/Course/EditCourseStructure/Buttons/NewActivityButton.tsx b/apps/web/components/Dashboard/Course/EditCourseStructure/Buttons/NewActivityButton.tsx index 0926d669..afa30d9a 100644 --- a/apps/web/components/Dashboard/Course/EditCourseStructure/Buttons/NewActivityButton.tsx +++ b/apps/web/components/Dashboard/Course/EditCourseStructure/Buttons/NewActivityButton.tsx @@ -10,6 +10,7 @@ import { import { getOrganizationContextInfoWithoutCredentials } from '@services/organizations/orgs' import { revalidateTags } from '@services/utils/ts/requests' import { Layers } from 'lucide-react' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useRouter } from 'next/navigation' import React, { useEffect } from 'react' import { mutate } from 'swr' @@ -23,6 +24,8 @@ function NewActivityButton(props: NewActivityButtonProps) { const [newActivityModal, setNewActivityModal] = React.useState(false) const router = useRouter() const course = useCourse() as any + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const openNewActivityModal = async (chapterId: any) => { setNewActivityModal(true) @@ -38,7 +41,7 @@ function NewActivityButton(props: NewActivityButtonProps) { props.orgslug, { revalidate: 1800 } ) - await createActivity(activity, props.chapterId, org.org_id) + await createActivity(activity, props.chapterId, org.org_id, access_token) mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`) setNewActivityModal(false) await revalidateTags(['courses'], props.orgslug) @@ -52,7 +55,7 @@ function NewActivityButton(props: NewActivityButtonProps) { activity: any, chapterId: string ) => { - await createFileActivity(file, type, activity, chapterId) + await createFileActivity(file, type, activity, chapterId, access_token) mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`) setNewActivityModal(false) await revalidateTags(['courses'], props.orgslug) @@ -68,7 +71,7 @@ function NewActivityButton(props: NewActivityButtonProps) { await createExternalVideoActivity( external_video_data, activity, - props.chapterId + props.chapterId, access_token ) mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`) setNewActivityModal(false) @@ -76,7 +79,7 @@ function NewActivityButton(props: NewActivityButtonProps) { router.refresh() } - useEffect(() => {}, [course]) + useEffect(() => { }, [course]) return (
diff --git a/apps/web/components/Dashboard/Course/EditCourseStructure/DraggableElements/ActivityElement.tsx b/apps/web/components/Dashboard/Course/EditCourseStructure/DraggableElements/ActivityElement.tsx index 4b182c7e..d001fa06 100644 --- a/apps/web/components/Dashboard/Course/EditCourseStructure/DraggableElements/ActivityElement.tsx +++ b/apps/web/components/Dashboard/Course/EditCourseStructure/DraggableElements/ActivityElement.tsx @@ -12,6 +12,7 @@ import { Video, X, } from 'lucide-react' +import { useLHSession } from '@components/Contexts/LHSessionContext' import Link from 'next/link' import { useRouter } from 'next/navigation' import React from 'react' @@ -32,6 +33,8 @@ interface ModifiedActivityInterface { function ActivityElement(props: ActivitiyElementProps) { const router = useRouter() + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const [modifiedActivity, setModifiedActivity] = React.useState< ModifiedActivityInterface | undefined >(undefined) @@ -41,7 +44,7 @@ function ActivityElement(props: ActivitiyElementProps) { const activityUUID = props.activity.activity_uuid async function deleteActivityUI() { - await deleteActivity(props.activity.activity_uuid) + await deleteActivity(props.activity.activity_uuid,access_token) mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`) await revalidateTags(['courses'], props.orgslug) router.refresh() @@ -60,7 +63,7 @@ function ActivityElement(props: ActivitiyElementProps) { content: props.activity.content, } - await updateActivity(modifiedActivityCopy, activityUUID) + await updateActivity(modifiedActivityCopy, activityUUID,access_token) mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`) await revalidateTags(['courses'], props.orgslug) router.refresh() diff --git a/apps/web/components/Dashboard/Course/EditCourseStructure/DraggableElements/ChapterElement.tsx b/apps/web/components/Dashboard/Course/EditCourseStructure/DraggableElements/ChapterElement.tsx index ac96b86b..092dd5e7 100644 --- a/apps/web/components/Dashboard/Course/EditCourseStructure/DraggableElements/ChapterElement.tsx +++ b/apps/web/components/Dashboard/Course/EditCourseStructure/DraggableElements/ChapterElement.tsx @@ -16,6 +16,7 @@ import { revalidateTags } from '@services/utils/ts/requests' import { useRouter } from 'next/navigation' import { getAPIUrl } from '@services/config/config' import { mutate } from 'swr' +import { useLHSession } from '@components/Contexts/LHSessionContext' type ChapterElementProps = { chapter: any @@ -31,6 +32,8 @@ interface ModifiedChapterInterface { function ChapterElement(props: ChapterElementProps) { const activities = props.chapter.activities || [] + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const [modifiedChapter, setModifiedChapter] = React.useState< ModifiedChapterInterface | undefined >(undefined) @@ -41,7 +44,7 @@ function ChapterElement(props: ChapterElementProps) { const router = useRouter() const deleteChapterUI = async () => { - await deleteChapter(props.chapter.id) + await deleteChapter(props.chapter.id, access_token) mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`) await revalidateTags(['courses'], props.orgslug) router.refresh() @@ -53,7 +56,7 @@ function ChapterElement(props: ChapterElementProps) { let modifiedChapterCopy = { name: modifiedChapter.chapterName, } - await updateChapter(chapterId, modifiedChapterCopy) + await updateChapter(chapterId, modifiedChapterCopy, access_token) mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`) await revalidateTags(['courses'], props.orgslug) router.refresh() diff --git a/apps/web/components/Dashboard/Course/EditCourseStructure/EditCourseStructure.tsx b/apps/web/components/Dashboard/Course/EditCourseStructure/EditCourseStructure.tsx index bb81597b..f9b5b24a 100644 --- a/apps/web/components/Dashboard/Course/EditCourseStructure/EditCourseStructure.tsx +++ b/apps/web/components/Dashboard/Course/EditCourseStructure/EditCourseStructure.tsx @@ -15,6 +15,7 @@ import { import { Hexagon } from 'lucide-react' import Modal from '@components/StyledElements/Modal/Modal' import NewChapterModal from '@components/Objects/Modals/Chapters/NewChapter' +import { useLHSession } from '@components/Contexts/LHSessionContext' type EditCourseStructureProps = { orgslug: string @@ -38,6 +39,8 @@ export type OrderPayload = const EditCourseStructure = (props: EditCourseStructureProps) => { const router = useRouter() + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; // Check window availability const [winReady, setwinReady] = useState(false) @@ -57,7 +60,7 @@ const EditCourseStructure = (props: EditCourseStructureProps) => { // Submit new chapter const submitChapter = async (chapter: any) => { - await createChapter(chapter) + await createChapter(chapter,access_token) mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`) await revalidateTags(['courses'], props.orgslug) router.refresh() diff --git a/apps/web/components/Dashboard/Org/OrgEditGeneral/OrgEditGeneral.tsx b/apps/web/components/Dashboard/Org/OrgEditGeneral/OrgEditGeneral.tsx index 82fa7e5a..118eec41 100644 --- a/apps/web/components/Dashboard/Org/OrgEditGeneral/OrgEditGeneral.tsx +++ b/apps/web/components/Dashboard/Org/OrgEditGeneral/OrgEditGeneral.tsx @@ -9,6 +9,7 @@ import { UploadCloud } from 'lucide-react' import { revalidateTags } from '@services/utils/ts/requests' import { useRouter } from 'next/navigation' import { useOrg } from '@components/Contexts/OrgContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' interface OrganizationValues { name: string @@ -20,7 +21,9 @@ interface OrganizationValues { function OrgEditGeneral(props: any) { const [selectedFile, setSelectedFile] = useState(null) - const router = useRouter() + const router = useRouter(); + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const org = useOrg() as any // ... @@ -34,7 +37,7 @@ function OrgEditGeneral(props: any) { const uploadLogo = async () => { if (selectedFile) { let org_id = org.id - await uploadOrganizationLogo(org_id, selectedFile) + await uploadOrganizationLogo(org_id, selectedFile, access_token) setSelectedFile(null) // Reset the selected file await revalidateTags(['organizations'], org.slug) router.refresh() @@ -51,14 +54,14 @@ function OrgEditGeneral(props: any) { const updateOrg = async (values: OrganizationValues) => { let org_id = org.id - await updateOrganization(org_id, values) + await updateOrganization(org_id, values, access_token) // Mutate the org await revalidateTags(['organizations'], org.slug) router.refresh() } - useEffect(() => {}, [org]) + useEffect(() => { }, [org]) return (
diff --git a/apps/web/components/Dashboard/UI/LeftMenu.tsx b/apps/web/components/Dashboard/UI/LeftMenu.tsx index 67387646..9f695bbc 100644 --- a/apps/web/components/Dashboard/UI/LeftMenu.tsx +++ b/apps/web/components/Dashboard/UI/LeftMenu.tsx @@ -1,22 +1,21 @@ 'use client' import { useOrg } from '@components/Contexts/OrgContext' -import { useSession } from '@components/Contexts/SessionContext' +import { signOut } from 'next-auth/react' import ToolTip from '@components/StyledElements/Tooltip/Tooltip' import LearnHouseDashboardLogo from '@public/dashLogo.png' -import { logout } from '@services/auth/auth' import { BookCopy, Home, LogOut, School, Settings, Users } from 'lucide-react' import Image from 'next/image' import Link from 'next/link' -import { useRouter } from 'next/navigation' import React, { useEffect } from 'react' import UserAvatar from '../../Objects/UserAvatar' import AdminAuthorization from '@components/Security/AdminAuthorization' +import { useLHSession } from '@components/Contexts/LHSessionContext' +import { getUriWithOrg, getUriWithoutOrg } from '@services/config/config' function LeftMenu() { const org = useOrg() as any - const session = useSession() as any + const session = useLHSession() as any const [loading, setLoading] = React.useState(true) - const route = useRouter() function waitForEverythingToLoad() { if (org && session) { @@ -26,9 +25,9 @@ function LeftMenu() { } async function logOutUI() { - const res = await logout() + const res = await signOut({ redirect: true, callbackUrl: getUriWithoutOrg('/login?orgslug=' + org.slug) }) if (res) { - route.push('/login') + getUriWithOrg(org.slug, '/') } } @@ -123,7 +122,7 @@ function LeftMenu() {
setTimeout(r, 1500)) if (res.success === false) { @@ -35,24 +37,24 @@ function UserEditGeneral() { } } - useEffect(() => {}, [session, session.user]) + useEffect(() => { }, [session, session.data]) return (
- {session.user && ( + {session.data.user && ( { setTimeout(() => { setSubmitting(false) - updateProfile(values, session.user.id) + updateProfile(values, session.data.user.id, access_token) }, 400) }} > diff --git a/apps/web/components/Dashboard/UserAccount/UserEditPassword/UserEditPassword.tsx b/apps/web/components/Dashboard/UserAccount/UserEditPassword/UserEditPassword.tsx index de1ec79f..3f8a80b4 100644 --- a/apps/web/components/Dashboard/UserAccount/UserEditPassword/UserEditPassword.tsx +++ b/apps/web/components/Dashboard/UserAccount/UserEditPassword/UserEditPassword.tsx @@ -1,17 +1,18 @@ -import { useSession } from '@components/Contexts/SessionContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { updatePassword } from '@services/settings/password' import { Formik, Form, Field } from 'formik' import React, { useEffect } from 'react' function UserEditPassword() { - const session = useSession() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const updatePasswordUI = async (values: any) => { - let user_id = session.user.id - await updatePassword(user_id, values) + let user_id = session.data.user.id + await updatePassword(user_id, values, access_token) } - useEffect(() => {}, [session]) + useEffect(() => { }, [session]) return (
diff --git a/apps/web/components/Dashboard/Users/OrgAccess/OrgAccess.tsx b/apps/web/components/Dashboard/Users/OrgAccess/OrgAccess.tsx index 82273e35..fd5a86b6 100644 --- a/apps/web/components/Dashboard/Users/OrgAccess/OrgAccess.tsx +++ b/apps/web/components/Dashboard/Users/OrgAccess/OrgAccess.tsx @@ -3,27 +3,28 @@ import PageLoading from '@components/Objects/Loaders/PageLoading' import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal' import { getAPIUrl, getUriWithOrg } from '@services/config/config' import { swrFetcher } from '@services/utils/ts/requests' -import { Globe, Shield, Ticket, User, UserSquare, Users, X } from 'lucide-react' +import { Globe, Ticket, UserSquare, Users, X } from 'lucide-react' import Link from 'next/link' import React, { useEffect } from 'react' import useSWR, { mutate } from 'swr' import dayjs from 'dayjs' import { changeSignupMechanism, - createInviteCode, deleteInviteCode, } from '@services/organizations/invites' -import Toast from '@components/StyledElements/Toast/Toast' import toast from 'react-hot-toast' import { useRouter } from 'next/navigation' import Modal from '@components/StyledElements/Modal/Modal' import OrgInviteCodeGenerate from '@components/Objects/Modals/Dash/OrgAccess/OrgInviteCodeGenerate' +import { useLHSession } from '@components/Contexts/LHSessionContext' function OrgAccess() { const org = useOrg() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const { data: invites } = useSWR( org ? `${getAPIUrl()}orgs/${org?.id}/invites` : null, - swrFetcher + (url) => swrFetcher(url, access_token) ) const [isLoading, setIsLoading] = React.useState(false) const [joinMethod, setJoinMethod] = React.useState('closed') @@ -40,10 +41,8 @@ function OrgAccess() { } } - - async function deleteInvite(invite: any) { - let res = await deleteInviteCode(org.id, invite.invite_code_uuid) + let res = await deleteInviteCode(org.id, invite.invite_code_uuid, access_token) if (res.status == 200) { mutate(`${getAPIUrl()}orgs/${org.id}/invites`) } else { @@ -52,7 +51,7 @@ function OrgAccess() { } async function changeJoinMethod(method: 'open' | 'inviteOnly') { - let res = await changeSignupMechanism(org.id, method) + let res = await changeSignupMechanism(org.id, method, access_token) if (res.status == 200) { router.refresh() mutate(`${getAPIUrl()}orgs/slug/${org?.slug}`) diff --git a/apps/web/components/Dashboard/Users/OrgUserGroups/OrgUserGroups.tsx b/apps/web/components/Dashboard/Users/OrgUserGroups/OrgUserGroups.tsx index 8a874b95..4d357dd4 100644 --- a/apps/web/components/Dashboard/Users/OrgUserGroups/OrgUserGroups.tsx +++ b/apps/web/components/Dashboard/Users/OrgUserGroups/OrgUserGroups.tsx @@ -1,4 +1,5 @@ 'use client' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useOrg } from '@components/Contexts/OrgContext' import AddUserGroup from '@components/Objects/Modals/Dash/OrgUserGroups/AddUserGroup' import ManageUsers from '@components/Objects/Modals/Dash/OrgUserGroups/ManageUsers' @@ -14,17 +15,19 @@ import useSWR, { mutate } from 'swr' function OrgUserGroups() { const org = useOrg() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const [userGroupManagementModal, setUserGroupManagementModal] = React.useState(false) const [createUserGroupModal, setCreateUserGroupModal] = React.useState(false) const [selectedUserGroup, setSelectedUserGroup] = React.useState(null) as any const { data: usergroups } = useSWR( org ? `${getAPIUrl()}usergroups/org/${org.id}` : null, - swrFetcher + (url) => swrFetcher(url, access_token) ) const deleteUserGroupUI = async (usergroup_id: any) => { - const res = await deleteUserGroup(usergroup_id) + const res = await deleteUserGroup(usergroup_id, access_token) if (res.status == 200) { mutate(`${getAPIUrl()}usergroups/org/${org.id}`) } diff --git a/apps/web/components/Dashboard/Users/OrgUsers/OrgUsers.tsx b/apps/web/components/Dashboard/Users/OrgUsers/OrgUsers.tsx index 1b394e36..6048816d 100644 --- a/apps/web/components/Dashboard/Users/OrgUsers/OrgUsers.tsx +++ b/apps/web/components/Dashboard/Users/OrgUsers/OrgUsers.tsx @@ -1,3 +1,4 @@ +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useOrg } from '@components/Contexts/OrgContext' import PageLoading from '@components/Objects/Loaders/PageLoading' import RolesUpdate from '@components/Objects/Modals/Dash/OrgUsers/RolesUpdate' @@ -14,9 +15,11 @@ import useSWR, { mutate } from 'swr' function OrgUsers() { const org = useOrg() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const { data: orgUsers } = useSWR( org ? `${getAPIUrl()}orgs/${org?.id}/users` : null, - swrFetcher + (url) => swrFetcher(url, access_token) ) const [rolesModal, setRolesModal] = React.useState(false) const [selectedUser, setSelectedUser] = React.useState(null) as any @@ -28,7 +31,7 @@ function OrgUsers() { } const handleRemoveUser = async (user_id: any) => { - const res = await removeUserFromOrg(org.id, user_id) + const res = await removeUserFromOrg(org.id, user_id,access_token) if (res.status === 200) { await mutate(`${getAPIUrl()}orgs/${org.id}/users`) } else { @@ -39,7 +42,6 @@ function OrgUsers() { useEffect(() => { if (orgUsers) { setIsLoading(false) - console.log(orgUsers) } }, [org, orgUsers]) diff --git a/apps/web/components/Dashboard/Users/OrgUsersAdd/OrgUsersAdd.tsx b/apps/web/components/Dashboard/Users/OrgUsersAdd/OrgUsersAdd.tsx index d0217849..08bac53b 100644 --- a/apps/web/components/Dashboard/Users/OrgUsersAdd/OrgUsersAdd.tsx +++ b/apps/web/components/Dashboard/Users/OrgUsersAdd/OrgUsersAdd.tsx @@ -1,3 +1,4 @@ +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useOrg } from '@components/Contexts/OrgContext' import PageLoading from '@components/Objects/Loaders/PageLoading' import Toast from '@components/StyledElements/Toast/Toast' @@ -5,20 +6,22 @@ import ToolTip from '@components/StyledElements/Tooltip/Tooltip' import { getAPIUrl } from '@services/config/config' import { inviteBatchUsers } from '@services/organizations/invites' import { swrFetcher } from '@services/utils/ts/requests' -import { Info, Shield, UserPlus } from 'lucide-react' +import { Info, UserPlus } from 'lucide-react' import React, { useEffect } from 'react' import toast from 'react-hot-toast' import useSWR, { mutate } from 'swr' function OrgUsersAdd() { const org = useOrg() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const [isLoading, setIsLoading] = React.useState(false) const [invitedUsers, setInvitedUsers] = React.useState(''); const [selectedInviteCode, setSelectedInviteCode] = React.useState(''); async function sendInvites() { setIsLoading(true) - let res = await inviteBatchUsers(org.id, invitedUsers, selectedInviteCode) + let res = await inviteBatchUsers(org.id, invitedUsers, selectedInviteCode,access_token) if (res.status == 200) { mutate(`${getAPIUrl()}orgs/${org?.id}/invites/users`) setIsLoading(false) @@ -31,18 +34,17 @@ function OrgUsersAdd() { const { data: invites } = useSWR( org ? `${getAPIUrl()}orgs/${org?.id}/invites` : null, - swrFetcher + (url) => swrFetcher(url, access_token) ) const { data: invited_users } = useSWR( org ? `${getAPIUrl()}orgs/${org?.id}/invites/users` : null, - swrFetcher + (url) => swrFetcher(url, access_token) ) useEffect(() => { if (invites) { setSelectedInviteCode(invites?.[0]?.invite_code_uuid) } - console.log('dev,',selectedInviteCode) } , [invites, invited_users]) diff --git a/apps/web/components/Hooks/useAdminStatus.tsx b/apps/web/components/Hooks/useAdminStatus.tsx index 9fe343a9..93ae93d0 100644 --- a/apps/web/components/Hooks/useAdminStatus.tsx +++ b/apps/web/components/Hooks/useAdminStatus.tsx @@ -1,40 +1,43 @@ -import { useOrg } from '@components/Contexts/OrgContext' -import { useSession } from '@components/Contexts/SessionContext' -import { useEffect } from 'react' - -function useAdminStatus() { - const session = useSession() as any - const org = useOrg() as any - - // If session is not loaded, redirect to login - - useEffect(() => { - if (session.isLoading) { - return - } - - } - , [session]) - - const isUserAdmin = () => { - if (session.isAuthenticated) { - const isAdmin = session.roles.some((role: any) => { - return ( - role.org.id === org.id && - (role.role.id === 1 || - role.role.id === 2 || - role.role.role_uuid === 'role_global_admin' || - role.role.role_uuid === 'role_global_maintainer') - ) - }) - return isAdmin - } - return false - } - - // Return the user admin status - return isUserAdmin() +import { useOrg } from '@components/Contexts/OrgContext'; +import { useLHSession } from '@components/Contexts/LHSessionContext'; +import { useEffect, useState, useMemo } from 'react'; +interface Role { + org: { id: number }; + role: { id: number; role_uuid: string }; } -export default useAdminStatus \ No newline at end of file +function useAdminStatus() { + const session = useLHSession() as any; + const org = useOrg() as any; + const [isAdmin, setIsAdmin] = useState(null); + const [loading, setLoading] = useState(true); + + const userRoles = useMemo(() => session?.data?.roles || [], [session?.data?.roles]); + + useEffect(() => { + if (session.status === 'authenticated' && org?.id) { + const isAdminVar = userRoles.some((role: Role) => { + return ( + role.org.id === org.id && + ( + role.role.id === 1 || + role.role.id === 2 || + role.role.role_uuid === 'role_global_admin' || + role.role.role_uuid === 'role_global_maintainer' + ) + ); + }); + setIsAdmin(isAdminVar); + setLoading(false); // Set loading to false once the status is determined + } else { + setIsAdmin(false); + setLoading(false); // Set loading to false if not authenticated or org not found + } + }, [session.status, userRoles, org.id]); + + return { isAdmin, loading }; +} + +export default useAdminStatus; + diff --git a/apps/web/components/Objects/Activities/AI/AIActivityAsk.tsx b/apps/web/components/Objects/Activities/AI/AIActivityAsk.tsx index 3d4c1dbc..a0a00582 100644 --- a/apps/web/components/Objects/Activities/AI/AIActivityAsk.tsx +++ b/apps/web/components/Objects/Activities/AI/AIActivityAsk.tsx @@ -1,4 +1,4 @@ -import { useSession } from '@components/Contexts/SessionContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { sendActivityAIChatMessage, startActivityAIChatSession, @@ -74,7 +74,8 @@ type ActivityChatMessageBoxProps = { } function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) { - const session = useSession() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const aiChatBotState = useAIChatBot() as AIChatBotStateTypes const dispatchAIChatBot = useAIChatBotDispatch() as any @@ -115,7 +116,8 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) { const response = await sendActivityAIChatMessage( message, aiChatBotState.aichat_uuid, - props.activity.activity_uuid + props.activity.activity_uuid, + access_token ) if (response.success == false) { await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' }) @@ -143,8 +145,9 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) { }) await dispatchAIChatBot({ type: 'setIsWaitingForResponse' }) const response = await startActivityAIChatSession( - message, + message,access_token, props.activity.activity_uuid + ) if (response.success == false) { await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' }) @@ -219,14 +222,12 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) { />
{aiChatBotState.messages.length > 0 && - !aiChatBotState.error.isError ? ( + !aiChatBotState.error.isError ? (
{aiChatBotState.messages.map( (message: AIMessage, index: number) => { @@ -328,7 +328,7 @@ type AIMessageProps = { } function AIMessage(props: AIMessageProps) { - const session = useSession() as any + const session = useLHSession() as any const words = props.message.message.split(' ') @@ -378,7 +378,7 @@ const AIMessagePlaceHolder = (props: { activity_uuid: string sendMessage: any }) => { - const session = useSession() as any + const session = useLHSession() as any const [feedbackModal, setFeedbackModal] = React.useState(false) const aiChatBotState = useAIChatBot() as AIChatBotStateTypes @@ -409,7 +409,7 @@ const AIMessagePlaceHolder = (props: { Hello - {session.user.username}, + {session.data.user.username}, how can we help today ?

diff --git a/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx b/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx index 2dc84193..0e753369 100644 --- a/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx +++ b/apps/web/components/Objects/Activities/DocumentPdf/DocumentPdf.tsx @@ -12,7 +12,6 @@ function DocumentPdfActivity({ const org = useOrg() as any React.useEffect(() => { - console.log(activity) }, [activity, org]) return ( diff --git a/apps/web/components/Objects/Activities/DynamicCanva/AI/AICanvaToolkit.tsx b/apps/web/components/Objects/Activities/DynamicCanva/AI/AICanvaToolkit.tsx index 040041a5..7792e1ee 100644 --- a/apps/web/components/Objects/Activities/DynamicCanva/AI/AICanvaToolkit.tsx +++ b/apps/web/components/Objects/Activities/DynamicCanva/AI/AICanvaToolkit.tsx @@ -15,6 +15,7 @@ import { startActivityAIChatSession, } from '@services/ai/ai' import useGetAIFeatures from '../../../../AI/Hooks/useGetAIFeatures' +import { useLHSession } from '@components/Contexts/LHSessionContext' type AICanvaToolkitProps = { editor: Editor @@ -92,6 +93,8 @@ function AIActionButton(props: { label: string activity: any }) { + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const dispatchAIChatBot = useAIChatBotDispatch() as any const aiChatBotState = useAIChatBot() as AIChatBotStateTypes @@ -132,7 +135,7 @@ function AIActionButton(props: { const response = await sendActivityAIChatMessage( message, aiChatBotState.aichat_uuid, - props.activity.activity_uuid + props.activity.activity_uuid, access_token ) if (response.success == false) { await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' }) @@ -160,8 +163,7 @@ function AIActionButton(props: { }) await dispatchAIChatBot({ type: 'setIsWaitingForResponse' }) const response = await startActivityAIChatSession( - message, - props.activity.activity_uuid + message, access_token ) if (response.success == false) { await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' }) @@ -193,10 +195,10 @@ function AIActionButton(props: { props.label === 'Explain' ? 'Explain a word or a sentence with AI' : props.label === 'Summarize' - ? 'Summarize a long paragraph or text with AI' - : props.label === 'Translate' - ? 'Translate to different languages with AI' - : 'Give examples to understand better with AI' + ? 'Summarize a long paragraph or text with AI' + : props.label === 'Translate' + ? 'Translate to different languages with AI' + : 'Give examples to understand better with AI' return (
diff --git a/apps/web/components/Objects/Activities/Video/Video.tsx b/apps/web/components/Objects/Activities/Video/Video.tsx index f2d205d8..e523f43b 100644 --- a/apps/web/components/Objects/Activities/Video/Video.tsx +++ b/apps/web/components/Objects/Activities/Video/Video.tsx @@ -7,22 +7,6 @@ function VideoActivity({ activity, course }: { activity: any; course: any }) { const org = useOrg() as any const [videoId, setVideoId] = React.useState('') - function getYouTubeEmbed(url: any) { - // Extract video ID from the YouTube URL - var videoId = url.match( - /(?:\?v=|\/embed\/|\/\d\/|\/vi\/|\/v\/|https?:\/\/(?:www\.)?youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([^#\&\?\/]+)/ - )[1] - - // Create the embed object - var embedObject = { - videoId: videoId, - width: 560, - height: 315, - } - - return embedObject - } - React.useEffect(() => { if (activity && activity.content && activity.content.uri) { var getYouTubeID = require('get-youtube-id'); diff --git a/apps/web/components/Objects/CourseUpdates/CourseUpdates.tsx b/apps/web/components/Objects/CourseUpdates/CourseUpdates.tsx index 2b173eff..62085e29 100644 --- a/apps/web/components/Objects/CourseUpdates/CourseUpdates.tsx +++ b/apps/web/components/Objects/CourseUpdates/CourseUpdates.tsx @@ -20,12 +20,15 @@ import toast from 'react-hot-toast' import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal' import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; +import { useLHSession } from '@components/Contexts/LHSessionContext' dayjs.extend(relativeTime); function CourseUpdates() { const course = useCourse() as any; - const { data: updates } = useSWR(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`, swrFetcher) + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; + const { data: updates } = useSWR(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`, (url) => swrFetcher(url, access_token)) const [isModelOpen, setIsModelOpen] = React.useState(false) function handleModelOpen() { @@ -35,7 +38,6 @@ function CourseUpdates() { // if user clicks outside the model, close the model React.useLayoutEffect(() => { function handleClickOutside(event: any) { - console.log(event.target.id) if (event.target.closest('.bg-white') || event.target.id === 'delete-update-button') return; setIsModelOpen(false); } @@ -71,7 +73,7 @@ function CourseUpdates() { const UpdatesSection = () => { const [selectedView, setSelectedView] = React.useState('list') - const isAdmin = useAdminStatus() as boolean; + const adminStatus = useAdminStatus() ; return (
@@ -80,7 +82,7 @@ const UpdatesSection = () => { Updates
- {isAdmin &&
setSelectedView('new')} className='py-2 px-4 space-x-2 items-center flex cursor-pointer text-xs font-medium hover:bg-gray-200 bg-gray-100 outline outline-1 outline-neutral-200/40'> @@ -98,6 +100,7 @@ const UpdatesSection = () => { const NewUpdateForm = ({ setSelectedView }: any) => { const org = useOrg() as any; const course = useCourse() as any; + const session = useLHSession() as any; const validate = (values: any) => { const errors: any = {} @@ -124,7 +127,7 @@ const NewUpdateForm = ({ setSelectedView }: any) => { course_uuid: course.courseStructure.course_uuid, org_id: org.id } - const res = await createCourseUpdate(body) + const res = await createCourseUpdate(body, session.data?.tokens?.access_token) if (res.status === 200) { toast.success('Update added successfully') setSelectedView('list') @@ -192,23 +195,25 @@ const NewUpdateForm = ({ setSelectedView }: any) => { const UpdatesListView = () => { const course = useCourse() as any; - const isAdmin = useAdminStatus() as boolean; - const { data: updates } = useSWR(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`, swrFetcher) + const adminStatus = useAdminStatus() ; + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; + const { data: updates } = useSWR(`${getAPIUrl()}courses/${course?.courseStructure?.course_uuid}/updates`, (url) => swrFetcher(url, access_token)) return (
- {updates && updates.map((update: any) => ( + {updates && !adminStatus.loading && updates.map((update: any) => (
{update.title} - - {dayjs(update.creation_date).fromNow()} + + {dayjs(update.creation_date).fromNow()}
- {isAdmin && }
+ {adminStatus.isAdmin && !adminStatus.loading && }
{update.content}
))} @@ -223,11 +228,12 @@ const UpdatesListView = () => { } const DeleteUpdateButton = ({ update }: any) => { + const session = useLHSession() as any; const course = useCourse() as any; const org = useOrg() as any; const handleDelete = async () => { - const res = await deleteCourseUpdate(course.courseStructure.course_uuid, update.courseupdate_uuid) + const res = await deleteCourseUpdate(course.courseStructure.course_uuid, update.courseupdate_uuid, session.data?.tokens?.access_token) if (res.status === 200) { toast.success('Update deleted successfully') mutate(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`) diff --git a/apps/web/components/Objects/Editor/AI/AIEditorToolkit.tsx b/apps/web/components/Objects/Editor/AI/AIEditorToolkit.tsx index 1807c4ab..fd287fe0 100644 --- a/apps/web/components/Objects/Editor/AI/AIEditorToolkit.tsx +++ b/apps/web/components/Objects/Editor/AI/AIEditorToolkit.tsx @@ -24,6 +24,7 @@ import { startActivityAIChatSession, } from '@services/ai/ai' import useGetAIFeatures from '@components/AI/Hooks/useGetAIFeatures' +import { useLHSession } from '@components/Contexts/LHSessionContext' type AIEditorToolkitProps = { editor: Editor @@ -32,11 +33,11 @@ type AIEditorToolkitProps = { type AIPromptsLabels = { label: - | 'Writer' - | 'ContinueWriting' - | 'MakeLonger' - | 'GenerateQuiz' - | 'Translate' + | 'Writer' + | 'ContinueWriting' + | 'MakeLonger' + | 'GenerateQuiz' + | 'Translate' selection: string } @@ -141,6 +142,8 @@ function AIEditorToolkit(props: AIEditorToolkitProps) { const UserFeedbackModal = (props: AIEditorToolkitProps) => { const dispatchAIEditor = useAIEditorDispatch() as any const aiEditorState = useAIEditor() as AIEditorStateTypes + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const handleChange = async (event: React.ChangeEvent) => { await dispatchAIEditor({ @@ -159,7 +162,7 @@ const UserFeedbackModal = (props: AIEditorToolkitProps) => { const response = await sendActivityAIChatMessage( message, aiEditorState.aichat_uuid, - props.activity.activity_uuid + props.activity.activity_uuid, access_token ) if (response.success === false) { await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' }) @@ -191,7 +194,7 @@ const UserFeedbackModal = (props: AIEditorToolkitProps) => { }) await dispatchAIEditor({ type: 'setIsWaitingForResponse' }) const response = await startActivityAIChatSession( - message, + message, access_token, props.activity.activity_uuid ) if (response.success === false) { diff --git a/apps/web/components/Objects/Editor/ActiveAvatars.tsx b/apps/web/components/Objects/Editor/ActiveAvatars.tsx index db84a79f..ddab6d8a 100644 --- a/apps/web/components/Objects/Editor/ActiveAvatars.tsx +++ b/apps/web/components/Objects/Editor/ActiveAvatars.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react' import UserAvatar from '../UserAvatar' -import { useSession } from '@components/Contexts/SessionContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { getUserAvatarMediaDirectory } from '@services/media/media'; import { getCollaborationServerUrl } from '@services/config/config'; import { useOrg } from '@components/Contexts/OrgContext'; @@ -11,7 +11,7 @@ type ActiveAvatarsProps = { } function ActiveAvatars(props: ActiveAvatarsProps) { - const session = useSession() as any; + const session = useLHSession() as any; const org = useOrg() as any; const [activeUsers, setActiveUsers] = useState({} as any); @@ -27,11 +27,11 @@ function ActiveAvatars(props: ActiveAvatarsProps) { }); // Remove the current user from the list - delete users[session.user.user_uuid]; + delete users[session.data.user.user_uuid]; setActiveUsers(users); } - , [props.mouseMovements, session.user, org]); + , [props.mouseMovements, session.data.user, org]); return ( @@ -50,7 +50,7 @@ function ActiveAvatars(props: ActiveAvatarsProps) {
))} - {session.isAuthenticated && ( + {session.status && (
(null); const [thisPageColor, setThisPageColor] = useState(randomColor({ luminosity: 'light' }) as string) @@ -57,7 +58,7 @@ function EditorWrapper(props: EditorWrapperProps): JSX.Element { document.addEventListener("mousemove", (event) => { // Share any information you like provider?.setAwarenessField("userMouseMovement", { - user: session.user, + user: session.data.user, mouseX: event.clientX, mouseY: event.clientY, color: thisPageColor, @@ -72,14 +73,14 @@ function EditorWrapper(props: EditorWrapperProps): JSX.Element { provider?.setAwarenessField("savings_states", { - [session.user.user_uuid]: { + [session.data.user.user_uuid]: { status: 'action_save', timestamp: new Date().toISOString(), - user: session.user + user: session.data.user } }); - toast.promise(updateActivity(activity, activity.activity_uuid), { + toast.promise(updateActivity(activity, activity.activity_uuid,access_token), { loading: 'Saving...', success: Activity saved!, error: Could not save., diff --git a/apps/web/components/Objects/Editor/Extensions/Image/ImageBlockComponent.tsx b/apps/web/components/Objects/Editor/Extensions/Image/ImageBlockComponent.tsx index 426dcfdb..1f1beca7 100644 --- a/apps/web/components/Objects/Editor/Extensions/Image/ImageBlockComponent.tsx +++ b/apps/web/components/Objects/Editor/Extensions/Image/ImageBlockComponent.tsx @@ -9,11 +9,14 @@ import { getActivityBlockMediaDirectory } from '@services/media/media' import { useOrg } from '@components/Contexts/OrgContext' import { useCourse } from '@components/Contexts/CourseContext' import { useEditorProvider } from '@components/Contexts/Editor/EditorContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' function ImageBlockComponent(props: any) { const org = useOrg() as any const course = useCourse() as any const editorState = useEditorProvider() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const isEditable = editorState.isEditable const [image, setImage] = React.useState(null) @@ -36,7 +39,7 @@ function ImageBlockComponent(props: any) { setIsLoading(true) let object = await uploadNewImageFile( image, - props.extension.options.activity.activity_uuid + props.extension.options.activity.activity_uuid,access_token ) setIsLoading(false) setblockObject(object) diff --git a/apps/web/components/Objects/Editor/Extensions/PDF/PDFBlockComponent.tsx b/apps/web/components/Objects/Editor/Extensions/PDF/PDFBlockComponent.tsx index c0e11903..c6c61fbe 100644 --- a/apps/web/components/Objects/Editor/Extensions/PDF/PDFBlockComponent.tsx +++ b/apps/web/components/Objects/Editor/Extensions/PDF/PDFBlockComponent.tsx @@ -8,10 +8,13 @@ import { getActivityBlockMediaDirectory } from '@services/media/media' import { useOrg } from '@components/Contexts/OrgContext' import { useCourse } from '@components/Contexts/CourseContext' import { useEditorProvider } from '@components/Contexts/Editor/EditorContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' function PDFBlockComponent(props: any) { const org = useOrg() as any const course = useCourse() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const [pdf, setPDF] = React.useState(null) const [isLoading, setIsLoading] = React.useState(false) const [blockObject, setblockObject] = React.useState( @@ -32,7 +35,7 @@ function PDFBlockComponent(props: any) { setIsLoading(true) let object = await uploadNewPDFFile( pdf, - props.extension.options.activity.activity_uuid + props.extension.options.activity.activity_uuid, access_token ) setIsLoading(false) setblockObject(object) @@ -41,7 +44,7 @@ function PDFBlockComponent(props: any) { }) } - useEffect(() => {}, [course, org]) + useEffect(() => { }, [course, org]) return ( diff --git a/apps/web/components/Objects/Editor/Extensions/Quiz/QuizBlockComponent.tsx b/apps/web/components/Objects/Editor/Extensions/Quiz/QuizBlockComponent.tsx index 26d0dfa4..a33aab0e 100644 --- a/apps/web/components/Objects/Editor/Extensions/Quiz/QuizBlockComponent.tsx +++ b/apps/web/components/Objects/Editor/Extensions/Quiz/QuizBlockComponent.tsx @@ -86,10 +86,8 @@ function QuizBlockComponent(props: any) { if (allCorrect) { setSubmissionMessage('All answers are correct!') - console.log('All answers are correct!') } else { setSubmissionMessage('Some answers are incorrect!') - console.log('Some answers are incorrect!') } } diff --git a/apps/web/components/Objects/Editor/Extensions/Video/VideoBlockComponent.tsx b/apps/web/components/Objects/Editor/Extensions/Video/VideoBlockComponent.tsx index 42063263..f90923bd 100644 --- a/apps/web/components/Objects/Editor/Extensions/Video/VideoBlockComponent.tsx +++ b/apps/web/components/Objects/Editor/Extensions/Video/VideoBlockComponent.tsx @@ -8,6 +8,7 @@ import { UploadIcon } from '@radix-ui/react-icons' import { useOrg } from '@components/Contexts/OrgContext' import { useCourse } from '@components/Contexts/CourseContext' import { useEditorProvider } from '@components/Contexts/Editor/EditorContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' function VideoBlockComponents(props: any) { const org = useOrg() as any @@ -15,6 +16,8 @@ function VideoBlockComponents(props: any) { const editorState = useEditorProvider() as any const isEditable = editorState.isEditable const [video, setVideo] = React.useState(null) + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const [isLoading, setIsLoading] = React.useState(false) const [blockObject, setblockObject] = React.useState( props.node.attrs.blockObject @@ -32,7 +35,7 @@ function VideoBlockComponents(props: any) { setIsLoading(true) let object = await uploadNewVideoFile( video, - props.extension.options.activity.activity_uuid + props.extension.options.activity.activity_uuid, access_token ) setIsLoading(false) setblockObject(object) @@ -41,7 +44,7 @@ function VideoBlockComponents(props: any) { }) } - useEffect(() => {}, [course, org]) + useEffect(() => { }, [course, org]) return ( @@ -98,7 +101,7 @@ function VideoBlockComponents(props: any) { ) } const BlockVideoWrapper = styled.div` - //border: ${(props) => + border: ${(props) => props.contentEditable ? '2px dashed #713f1117' : 'none'}; // center diff --git a/apps/web/components/Objects/Menu/Menu.tsx b/apps/web/components/Objects/Menu/Menu.tsx index 212d2b6c..1b77a619 100644 --- a/apps/web/components/Objects/Menu/Menu.tsx +++ b/apps/web/components/Objects/Menu/Menu.tsx @@ -1,21 +1,19 @@ 'use client' import React from 'react' import Link from 'next/link' -import { getAPIUrl, getUriWithOrg } from '@services/config/config' +import { getUriWithOrg } from '@services/config/config' import { HeaderProfileBox } from '@components/Security/HeaderProfileBox' import MenuLinks from './MenuLinks' import { getOrgLogoMediaDirectory } from '@services/media/media' -import useSWR from 'swr' -import { swrFetcher } from '@services/utils/ts/requests' +import { useLHSession } from '@components/Contexts/LHSessionContext' +import { useOrg } from '@components/Contexts/OrgContext' export const Menu = (props: any) => { const orgslug = props.orgslug + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const [feedbackModal, setFeedbackModal] = React.useState(false) - const { - data: org, - error: error, - isLoading, - } = useSWR(`${getAPIUrl()}orgs/slug/${orgslug}`, swrFetcher) + const org = useOrg() as any; function closeFeedbackModal() { setFeedbackModal(false) diff --git a/apps/web/components/Objects/Modals/Course/Create/CreateCourse.tsx b/apps/web/components/Objects/Modals/Course/Create/CreateCourse.tsx index 13fd3ce5..51bfe5f5 100644 --- a/apps/web/components/Objects/Modals/Course/Create/CreateCourse.tsx +++ b/apps/web/components/Objects/Modals/Course/Create/CreateCourse.tsx @@ -15,9 +15,11 @@ import React, { useState } from 'react' import { BarLoader } from 'react-spinners' import { revalidateTags } from '@services/utils/ts/requests' import { useRouter } from 'next/navigation' +import { useLHSession } from '@components/Contexts/LHSessionContext' function CreateCourseModal({ closeModal, orgslug }: any) { const [isSubmitting, setIsSubmitting] = useState(false) + const session = useLHSession() as any; const [name, setName] = React.useState('') const [description, setDescription] = React.useState('') const [learnings, setLearnings] = React.useState('') @@ -53,7 +55,6 @@ function CreateCourseModal({ closeModal, orgslug }: any) { const handleVisibilityChange = (event: React.ChangeEvent) => { setVisibility(event.target.value) - console.log(visibility) } const handleTagsChange = (event: React.ChangeEvent) => { @@ -71,7 +72,8 @@ function CreateCourseModal({ closeModal, orgslug }: any) { let status = await createNewCourse( orgId, { name, description, tags, visibility }, - thumbnail + thumbnail, + session.data?.tokens?.access_token ) await revalidateTags(['courses'], orgslug) setIsSubmitting(false) @@ -80,9 +82,6 @@ function CreateCourseModal({ closeModal, orgslug }: any) { closeModal() router.refresh() await revalidateTags(['courses'], orgslug) - - // refresh page (FIX for Next.js BUG) - // window.location.reload(); } else { alert('Error creating course, please see console logs') } diff --git a/apps/web/components/Objects/Modals/Dash/EditCourseAccess/LinkToUserGroup.tsx b/apps/web/components/Objects/Modals/Dash/EditCourseAccess/LinkToUserGroup.tsx index 56976fba..6cefeeda 100644 --- a/apps/web/components/Objects/Modals/Dash/EditCourseAccess/LinkToUserGroup.tsx +++ b/apps/web/components/Objects/Modals/Dash/EditCourseAccess/LinkToUserGroup.tsx @@ -1,10 +1,11 @@ 'use client'; import { useCourse } from '@components/Contexts/CourseContext'; +import { useLHSession } from '@components/Contexts/LHSessionContext'; import { useOrg } from '@components/Contexts/OrgContext'; import { getAPIUrl } from '@services/config/config'; import { linkResourcesToUserGroup } from '@services/usergroups/usergroups'; import { swrFetcher } from '@services/utils/ts/requests'; -import { AlertTriangle, Info } from 'lucide-react'; +import { Info } from 'lucide-react'; import React, { useEffect } from 'react' import toast from 'react-hot-toast'; import useSWR, { mutate } from 'swr' @@ -17,6 +18,8 @@ type LinkToUserGroupProps = { function LinkToUserGroup(props: LinkToUserGroupProps) { const course = useCourse() as any const org = useOrg() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const courseStructure = course.courseStructure const { data: usergroups } = useSWR( @@ -27,8 +30,7 @@ function LinkToUserGroup(props: LinkToUserGroupProps) { const handleLink = async () => { - console.log('selectedUserGroup', selectedUserGroup) - const res = await linkResourcesToUserGroup(selectedUserGroup, courseStructure.course_uuid) + const res = await linkResourcesToUserGroup(selectedUserGroup, courseStructure.course_uuid, access_token) if (res.status === 200) { props.setUserGroupModal(false) toast.success('Successfully linked to usergroup') @@ -37,7 +39,6 @@ function LinkToUserGroup(props: LinkToUserGroupProps) { else { toast.error('Error ' + res.status + ': ' + res.data.detail) } - } useEffect(() => { @@ -54,25 +55,25 @@ function LinkToUserGroup(props: LinkToUserGroupProps) {

Users that are not part of the UserGroup will no longer have access to this course

- -
- UserGroup Name - -
-
- +
+ UserGroup Name + +
+
+ +
-
- + ) } diff --git a/apps/web/components/Objects/Modals/Dash/OrgAccess/OrgInviteCodeGenerate.tsx b/apps/web/components/Objects/Modals/Dash/OrgAccess/OrgInviteCodeGenerate.tsx index bd63fd8d..06834009 100644 --- a/apps/web/components/Objects/Modals/Dash/OrgAccess/OrgInviteCodeGenerate.tsx +++ b/apps/web/components/Objects/Modals/Dash/OrgAccess/OrgInviteCodeGenerate.tsx @@ -2,7 +2,8 @@ import { useOrg } from '@components/Contexts/OrgContext' import { getAPIUrl } from '@services/config/config' import { createInviteCode, createInviteCodeWithUserGroup } from '@services/organizations/invites' import { swrFetcher } from '@services/utils/ts/requests' -import { Shield, Ticket } from 'lucide-react' +import { Ticket } from 'lucide-react' +import { useLHSession } from '@components/Contexts/LHSessionContext' import React, { useEffect } from 'react' import toast from 'react-hot-toast' import useSWR, { mutate } from 'swr' @@ -13,6 +14,8 @@ type OrgInviteCodeGenerateProps = { function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) { const org = useOrg() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const [usergroup_id, setUsergroup_id] = React.useState(0); const { data: usergroups } = useSWR( org ? `${getAPIUrl()}usergroups/org/${org.id}` : null, @@ -20,7 +23,7 @@ function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) { ) async function createInviteWithUserGroup() { - let res = await createInviteCodeWithUserGroup(org.id, usergroup_id) + let res = await createInviteCodeWithUserGroup(org.id, usergroup_id, session.data?.tokens?.access_token) if (res.status == 200) { mutate(`${getAPIUrl()}orgs/${org.id}/invites`) props.setInvitesModal(false) @@ -30,7 +33,7 @@ function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) { } async function createInvite() { - let res = await createInviteCode(org.id) + let res = await createInviteCode(org.id, session.data?.tokens?.access_token) if (res.status == 200) { mutate(`${getAPIUrl()}orgs/${org.id}/invites`) props.setInvitesModal(false) diff --git a/apps/web/components/Objects/Modals/Dash/OrgUserGroups/AddUserGroup.tsx b/apps/web/components/Objects/Modals/Dash/OrgUserGroups/AddUserGroup.tsx index e7e4f28b..df4677bd 100644 --- a/apps/web/components/Objects/Modals/Dash/OrgUserGroups/AddUserGroup.tsx +++ b/apps/web/components/Objects/Modals/Dash/OrgUserGroups/AddUserGroup.tsx @@ -14,13 +14,16 @@ import { BarLoader } from 'react-spinners' import { createUserGroup } from '@services/usergroups/usergroups' import { mutate } from 'swr' import { getAPIUrl } from '@services/config/config' +import { useLHSession } from '@components/Contexts/LHSessionContext' type AddUserGroupProps = { setCreateUserGroupModal: any } function AddUserGroup(props: AddUserGroupProps) { - const org = useOrg() as any + const org = useOrg() as any; + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const [userGroupName, setUserGroupName] = React.useState('') const [userGroupDescription, setUserGroupDescription] = React.useState('') const [isSubmitting, setIsSubmitting] = React.useState(false) @@ -42,7 +45,7 @@ function AddUserGroup(props: AddUserGroupProps) { description: userGroupDescription, org_id: org.id } - const res = await createUserGroup(obj) + const res = await createUserGroup(obj, access_token) if (res.status == 200) { setIsSubmitting(false) mutate(`${getAPIUrl()}usergroups/org/${org.id}`) diff --git a/apps/web/components/Objects/Modals/Dash/OrgUserGroups/ManageUsers.tsx b/apps/web/components/Objects/Modals/Dash/OrgUserGroups/ManageUsers.tsx index ce7d35e2..71eb8390 100644 --- a/apps/web/components/Objects/Modals/Dash/OrgUserGroups/ManageUsers.tsx +++ b/apps/web/components/Objects/Modals/Dash/OrgUserGroups/ManageUsers.tsx @@ -1,3 +1,4 @@ +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useOrg } from '@components/Contexts/OrgContext' import { getAPIUrl } from '@services/config/config' import { linkUserToUserGroup, unLinkUserToUserGroup } from '@services/usergroups/usergroups' @@ -14,6 +15,8 @@ type ManageUsersProps = { function ManageUsers(props: ManageUsersProps) { const org = useOrg() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const { data: OrgUsers } = useSWR( org ? `${getAPIUrl()}orgs/${org.id}/users` : null, swrFetcher @@ -31,7 +34,7 @@ function ManageUsers(props: ManageUsersProps) { } const handleLinkUser = async (user_id: any) => { - const res = await linkUserToUserGroup(props.usergroup_id, user_id) + const res = await linkUserToUserGroup(props.usergroup_id, user_id,access_token) if (res.status === 200) { toast.success('User linked successfully') mutate(`${getAPIUrl()}usergroups/${props.usergroup_id}/users`) @@ -41,7 +44,7 @@ function ManageUsers(props: ManageUsersProps) { } const handleUnlinkUser = async (user_id: any) => { - const res = await unLinkUserToUserGroup(props.usergroup_id, user_id) + const res = await unLinkUserToUserGroup(props.usergroup_id, user_id,access_token) if (res.status === 200) { toast.success('User unlinked successfully') mutate(`${getAPIUrl()}usergroups/${props.usergroup_id}/users`) diff --git a/apps/web/components/Objects/Modals/Dash/OrgUsers/RolesUpdate.tsx b/apps/web/components/Objects/Modals/Dash/OrgUsers/RolesUpdate.tsx index 3ee7e6ef..1712ab19 100644 --- a/apps/web/components/Objects/Modals/Dash/OrgUsers/RolesUpdate.tsx +++ b/apps/web/components/Objects/Modals/Dash/OrgUsers/RolesUpdate.tsx @@ -1,4 +1,5 @@ 'use client' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useOrg } from '@components/Contexts/OrgContext' import FormLayout, { ButtonBlack, @@ -22,6 +23,8 @@ interface Props { function RolesUpdate(props: Props) { const org = useOrg() as any + const session = useLHSession() as any + const access_token = session.data.tokens.access_token; const [isSubmitting, setIsSubmitting] = React.useState(false) const [assignedRole, setAssignedRole] = React.useState( props.alreadyAssignedRole @@ -36,7 +39,7 @@ function RolesUpdate(props: Props) { const handleSubmit = async (e: any) => { e.preventDefault() setIsSubmitting(true) - const res = await updateUserRole(org.id, props.user.user.id, assignedRole) + const res = await updateUserRole(org.id, props.user.user.id, assignedRole,access_token) if (res.status === 200) { await mutate(`${getAPIUrl()}orgs/${org.id}/users`) diff --git a/apps/web/components/Objects/Thumbnails/CollectionThumbnail.tsx b/apps/web/components/Objects/Thumbnails/CollectionThumbnail.tsx index 034a87a5..df27f05a 100644 --- a/apps/web/components/Objects/Thumbnails/CollectionThumbnail.tsx +++ b/apps/web/components/Objects/Thumbnails/CollectionThumbnail.tsx @@ -7,6 +7,7 @@ import { deleteCollection } from '@services/courses/collections' import { getCourseThumbnailMediaDirectory } from '@services/media/media' import { revalidateTags } from '@services/utils/ts/requests' import { X } from 'lucide-react' +import { useLHSession } from '@components/Contexts/LHSessionContext' import Link from 'next/link' import { useRouter } from 'next/navigation' import React from 'react' @@ -33,7 +34,7 @@ function CollectionThumbnail(props: PropsType) { href={getUriWithOrg( props.orgslug, '/collection/' + - removeCollectionPrefix(props.collection.collection_uuid) + removeCollectionPrefix(props.collection.collection_uuid) )} >

@@ -74,9 +75,10 @@ function CollectionThumbnail(props: PropsType) { const CollectionAdminEditsArea = (props: any) => { const router = useRouter() + const session = useLHSession() as any; const deleteCollectionUI = async (collectionId: number) => { - await deleteCollection(collectionId) + await deleteCollection(collectionId, session.data?.tokens?.access_token) await revalidateTags(['collections'], props.orgslug) // reload the page router.refresh() diff --git a/apps/web/components/Objects/Thumbnails/CourseThumbnail.tsx b/apps/web/components/Objects/Thumbnails/CourseThumbnail.tsx index 4899e131..174b63ae 100644 --- a/apps/web/components/Objects/Thumbnails/CourseThumbnail.tsx +++ b/apps/web/components/Objects/Thumbnails/CourseThumbnail.tsx @@ -7,6 +7,7 @@ import { deleteCourseFromBackend } from '@services/courses/courses' import { getCourseThumbnailMediaDirectory } from '@services/media/media' import { revalidateTags } from '@services/utils/ts/requests' import { Settings, X } from 'lucide-react' +import { useLHSession } from '@components/Contexts/LHSessionContext' import Link from 'next/link' import { useRouter } from 'next/navigation' import React, { useEffect } from 'react' @@ -24,15 +25,16 @@ function removeCoursePrefix(course_uuid: string) { function CourseThumbnail(props: PropsType) { const router = useRouter() const org = useOrg() as any + const session = useLHSession() as any; async function deleteCourses(course_uuid: any) { - await deleteCourseFromBackend(course_uuid) + await deleteCourseFromBackend(course_uuid, session.data?.tokens?.access_token) await revalidateTags(['courses'], props.orgslug) router.refresh() } - useEffect(() => {}, [org]) + useEffect(() => { }, [org]) return (
@@ -92,8 +94,8 @@ const AdminEditsArea = (props: { href={getUriWithOrg( props.orgSlug, '/dash/courses/course/' + - removeCoursePrefix(props.courseId) + - '/general' + removeCoursePrefix(props.courseId) + + '/general' )} >
{ if (props.predefined_avatar === 'ai') { return getUriWithOrg(params.orgslug, '/ai_avatar.png') @@ -35,10 +39,10 @@ function UserAvatar(props: UserAvatarProps) { const predefinedAvatar = predefinedAvatarFunc() const emptyAvatar = getUriWithOrg(params.orgslug, '/empty_avatar.png') as any - const uploadedAvatar = getUserAvatarMediaDirectory( - session.user.user_uuid, - session.user.avatar_image - ) as any + const uploadedAvatar = (session.status == 'authenticated') && (checkUrlProtocol(session?.data?.user?.avatar_image)) ? session?.data?.user?.avatar_image : getUserAvatarMediaDirectory( + session?.data?.user?.user_uuid, + session?.data?.user?.avatar_image + ) const useAvatar = () => { if (props.predefined_avatar) { @@ -47,7 +51,7 @@ function UserAvatar(props: UserAvatarProps) { if (props.avatar_url) { return props.avatar_url } else { - if (session.user.avatar_image) { + if (session?.data?.user?.avatar_image) { return uploadedAvatar } else { return emptyAvatar @@ -57,8 +61,10 @@ function UserAvatar(props: UserAvatarProps) { } useEffect(() => { + - }, [session]) + + }, [session.status]) return ( ) } diff --git a/apps/web/components/Pages/CourseEdit/Draggables/Activity.tsx b/apps/web/components/Pages/CourseEdit/Draggables/Activity.tsx index 62a9d20b..ed3ed13d 100644 --- a/apps/web/components/Pages/CourseEdit/Draggables/Activity.tsx +++ b/apps/web/components/Pages/CourseEdit/Draggables/Activity.tsx @@ -17,6 +17,7 @@ import { revalidateTags } from '@services/utils/ts/requests' import { useRouter } from 'next/navigation' import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal' import { deleteActivity, updateActivity } from '@services/courses/activities' +import { useLHSession } from '@components/Contexts/LHSessionContext' interface ModifiedActivityInterface { activityId: string @@ -25,6 +26,7 @@ interface ModifiedActivityInterface { function Activity(props: any) { const router = useRouter() + const session = useLHSession() as any; const [modifiedActivity, setModifiedActivity] = React.useState< ModifiedActivityInterface | undefined >(undefined) @@ -33,7 +35,7 @@ function Activity(props: any) { >(undefined) async function removeActivity() { - await deleteActivity(props.activity.id) + await deleteActivity(props.activity.id, session.data?.tokens?.access_token) mutate(`${getAPIUrl()}chapters/meta/course_${props.courseid}`) await revalidateTags(['courses'], props.orgslug) router.refresh() @@ -52,7 +54,7 @@ function Activity(props: any) { content: props.activity.content, } - await updateActivity(modifiedActivityCopy, activityId) + await updateActivity(modifiedActivityCopy, activityId, session.data?.tokens?.access_token) await mutate(`${getAPIUrl()}chapters/meta/course_${props.courseid}`) await revalidateTags(['courses'], props.orgslug) router.refresh() diff --git a/apps/web/components/Pages/CourseEdit/Draggables/Chapter.tsx b/apps/web/components/Pages/CourseEdit/Draggables/Chapter.tsx index f0fe7bf5..121eb838 100644 --- a/apps/web/components/Pages/CourseEdit/Draggables/Chapter.tsx +++ b/apps/web/components/Pages/CourseEdit/Draggables/Chapter.tsx @@ -9,6 +9,7 @@ import { updateChapter } from '@services/courses/chapters' import { mutate } from 'swr' import { getAPIUrl } from '@services/config/config' import { revalidateTags } from '@services/utils/ts/requests' +import { useLHSession } from '@components/Contexts/LHSessionContext' interface ModifiedChapterInterface { chapterId: string @@ -17,6 +18,7 @@ interface ModifiedChapterInterface { function Chapter(props: any) { const router = useRouter() + const session = useLHSession() as any; const [modifiedChapter, setModifiedChapter] = React.useState< ModifiedChapterInterface | undefined >(undefined) @@ -30,7 +32,7 @@ function Chapter(props: any) { let modifiedChapterCopy = { name: modifiedChapter.chapterName, } - await updateChapter(chapterId, modifiedChapterCopy) + await updateChapter(chapterId, modifiedChapterCopy, session.data?.tokens?.access_token) await mutate(`${getAPIUrl()}chapters/course/${props.course_uuid}/meta`) await revalidateTags(['courses'], props.orgslug) router.refresh() diff --git a/apps/web/components/Pages/Trail/TrailCourseElement.tsx b/apps/web/components/Pages/Trail/TrailCourseElement.tsx index 4303e458..dfbcd456 100644 --- a/apps/web/components/Pages/Trail/TrailCourseElement.tsx +++ b/apps/web/components/Pages/Trail/TrailCourseElement.tsx @@ -4,6 +4,7 @@ import { getAPIUrl, getUriWithOrg } from '@services/config/config' import { removeCourse } from '@services/courses/activity' import { getCourseThumbnailMediaDirectory } from '@services/media/media' import { revalidateTags } from '@services/utils/ts/requests' +import { useLHSession } from '@components/Contexts/LHSessionContext' import Link from 'next/link' import { useRouter } from 'next/navigation' import { useEffect } from 'react' @@ -17,6 +18,8 @@ interface TrailCourseElementProps { function TrailCourseElement(props: TrailCourseElementProps) { const org = useOrg() as any + const session = useLHSession() as any; + const access_token = session?.data?.tokens?.access_token; const courseid = props.course.course_uuid.replace('course_', '') const course = props.course const router = useRouter() @@ -29,7 +32,7 @@ function TrailCourseElement(props: TrailCourseElementProps) { async function quitCourse(course_uuid: string) { // Close activity - let activity = await removeCourse(course_uuid, props.orgslug) + let activity = await removeCourse(course_uuid, props.orgslug,access_token) // Mutate course await revalidateTags(['courses'], props.orgslug) router.refresh() diff --git a/apps/web/components/Security/AdminAuthorization.tsx b/apps/web/components/Security/AdminAuthorization.tsx index ff8158ad..7840317f 100644 --- a/apps/web/components/Security/AdminAuthorization.tsx +++ b/apps/web/components/Security/AdminAuthorization.tsx @@ -1,15 +1,14 @@ -'use client' -import { useOrg } from '@components/Contexts/OrgContext' -import { useSession } from '@components/Contexts/SessionContext' -import useAdminStatus from '@components/Hooks/useAdminStatus' -import { usePathname, useRouter } from 'next/navigation' -import React from 'react' +'use client'; +import React, { useEffect, useState, useCallback, useMemo } from 'react'; +import { useLHSession } from '@components/Contexts/LHSessionContext'; +import useAdminStatus from '@components/Hooks/useAdminStatus'; +import { usePathname, useRouter } from 'next/navigation'; +import PageLoading from '@components/Objects/Loaders/PageLoading'; type AuthorizationProps = { - children: React.ReactNode - // Authorize components rendering or page rendering - authorizationMode: 'component' | 'page' -} + children: React.ReactNode; + authorizationMode: 'component' | 'page'; +}; const ADMIN_PATHS = [ '/dash/org/*', @@ -19,107 +18,80 @@ const ADMIN_PATHS = [ '/dash/courses/*', '/dash/courses', '/dash/org/settings/general', -] +]; -function AdminAuthorization(props: AuthorizationProps) { - const session = useSession() as any - const org = useOrg() as any - const pathname = usePathname() - const router = useRouter() +const AdminAuthorization: React.FC = ({ children, authorizationMode }) => { + const session = useLHSession() as any; + const pathname = usePathname(); + const router = useRouter(); + const { isAdmin, loading } = useAdminStatus() as any + const [isAuthorized, setIsAuthorized] = useState(false); - // States - const [isLoading, setIsLoading] = React.useState(true) - const [isAuthorized, setIsAuthorized] = React.useState(false) + const isUserAuthenticated = useMemo(() => session.status === 'authenticated', [session.status]); - // Verify if the user is authenticated - const isUserAuthenticated = () => { - if (session.isAuthenticated === true) { - return true - } else { - return false + const checkPathname = useCallback((pattern: string, pathname: string) => { + // Ensure the inputs are strings + if (typeof pattern !== 'string' || typeof pathname !== 'string') { + return false; } - } - // Verify if the user is an Admin (1), Maintainer (2) or Member (3) of the organization - const isUserAdmin = useAdminStatus() + // Convert pattern to a regex pattern + const regexPattern = new RegExp(`^${pattern.replace(/[\/.*+?^${}()|[\]\\]/g, '\\$&').replace(/\\\*/g, '.*')}$`); - function checkPathname(pattern: string, pathname: string) { - // Escape special characters in the pattern and replace '*' with a regex pattern - const regexPattern = new RegExp( - `^${pattern.replace(/\//g, '\\/').replace(/\*/g, '.*')}$` - ) + // Test the pathname against the regex pattern + return regexPattern.test(pathname); + }, []); - // Test if the pathname matches the regex pattern - const isMatch = regexPattern.test(pathname) - return isMatch - } + const isAdminPath = useMemo(() => ADMIN_PATHS.some(path => checkPathname(path, pathname)), [pathname, checkPathname]); - const Authorize = () => { - if (props.authorizationMode === 'page') { - // Check if user is in an admin path - if (ADMIN_PATHS.some((path) => checkPathname(path, pathname))) { - console.log('Admin path') - if (isUserAuthenticated()) { - // Check if the user is an Admin - if (isUserAdmin) { - setIsAuthorized(true) - } else { - setIsAuthorized(false) - router.push('/dash') - } + const authorizeUser = useCallback(() => { + if (loading) { + return; // Wait until the admin status is determined + } + + if (!isUserAuthenticated) { + router.push('/login'); + return; + } + + if (authorizationMode === 'page') { + if (isAdminPath) { + if (isAdmin) { + setIsAuthorized(true); } else { - router.push('/login') + setIsAuthorized(false); + router.push('/dash'); } } else { - if (isUserAuthenticated()) { - setIsAuthorized(true) - } else { - setIsAuthorized(false) - router.push('/login') - } + setIsAuthorized(true); } + } else if (authorizationMode === 'component') { + setIsAuthorized(isAdmin); } + }, [loading, isUserAuthenticated, isAdmin, isAdminPath, authorizationMode, router]); - if (props.authorizationMode === 'component') { - // Component mode - if (isUserAuthenticated() && isUserAdmin) { - setIsAuthorized(true) - } else { - setIsAuthorized(false) - } - } + useEffect(() => { + authorizeUser(); + }, [authorizeUser]); + + if (loading) { + return ( +
+ +
+ ); } - React.useEffect(() => { - if (session.isLoading) { - return - } + if (authorizationMode === 'page' && !isAuthorized) { + return ( +
+

You are not authorized to access this page

+
+ ); + } - Authorize() - setIsLoading(false) - }, [session, org, pathname]) + return <>{isAuthorized && children}; +}; - return ( - <> - {props.authorizationMode === 'component' && - isAuthorized === true && - props.children} - {props.authorizationMode === 'page' && - isAuthorized === true && - !isLoading && - props.children} - {props.authorizationMode === 'page' && - isAuthorized === false && - !isLoading && ( -
-

- You are not authorized to access this page -

-
- )} - - ) -} - -export default AdminAuthorization +export default AdminAuthorization; diff --git a/apps/web/components/Security/AuthenticatedClientElement.tsx b/apps/web/components/Security/AuthenticatedClientElement.tsx index ec17c363..ec65e5b3 100644 --- a/apps/web/components/Security/AuthenticatedClientElement.tsx +++ b/apps/web/components/Security/AuthenticatedClientElement.tsx @@ -1,6 +1,6 @@ 'use client' import React from 'react' -import { useSession } from '@components/Contexts/SessionContext' +import { useLHSession } from '@components/Contexts/LHSessionContext' import { useOrg } from '@components/Contexts/OrgContext' interface AuthenticatedClientElementProps { @@ -8,11 +8,11 @@ interface AuthenticatedClientElementProps { checkMethod: 'authentication' | 'roles' orgId?: string ressourceType?: - | 'collections' - | 'courses' - | 'activities' - | 'users' - | 'organizations' + | 'collections' + | 'courses' + | 'activities' + | 'users' + | 'organizations' action?: 'create' | 'update' | 'delete' | 'read' } @@ -20,7 +20,7 @@ export const AuthenticatedClientElement = ( props: AuthenticatedClientElementProps ) => { const [isAllowed, setIsAllowed] = React.useState(false) - const session = useSession() as any + const session = useLHSession() as any const org = useOrg() as any function isUserAllowed( @@ -49,19 +49,19 @@ export const AuthenticatedClientElement = ( } function check() { - if (session.isAuthenticated === false) { + if (session.status == 'unauthenticated') { setIsAllowed(false) return } else { if (props.checkMethod === 'authentication') { - setIsAllowed(session.isAuthenticated) - } else if (props.checkMethod === 'roles') { + setIsAllowed(session.status == 'authenticated') + } else if (props.checkMethod === 'roles' ) { return setIsAllowed( isUserAllowed( - session.roles, + session?.data?.roles, props.action!, props.ressourceType!, - org.org_uuid + org?.org_uuid ) ) } @@ -69,12 +69,12 @@ export const AuthenticatedClientElement = ( } React.useEffect(() => { - if (session.isLoading) { + if (session.status == 'loading') { return } check() - }, [session, org]) + }, [session.data, org]) return <>{isAllowed && props.children} } diff --git a/apps/web/components/Security/HeaderProfileBox.tsx b/apps/web/components/Security/HeaderProfileBox.tsx index b9e490aa..ca0b9c50 100644 --- a/apps/web/components/Security/HeaderProfileBox.tsx +++ b/apps/web/components/Security/HeaderProfileBox.tsx @@ -3,38 +3,41 @@ import React, { useEffect } from 'react' import styled from 'styled-components' import Link from 'next/link' import { Settings } from 'lucide-react' -import { useSession } from '@components/Contexts/SessionContext' import UserAvatar from '@components/Objects/UserAvatar' import useAdminStatus from '@components/Hooks/useAdminStatus' +import { useLHSession } from '@components/Contexts/LHSessionContext' +import { useOrg } from '@components/Contexts/OrgContext' +import { getUriWithoutOrg } from '@services/config/config' export const HeaderProfileBox = () => { - const session = useSession() as any - const isUserAdmin = useAdminStatus() as any + const session = useLHSession() as any + const isUserAdmin = useAdminStatus() + const org = useOrg() as any - useEffect(() => { - } - , [session]) + useEffect(() => { } + , [session]) return ( - {!session.isAuthenticated && ( + {session.status == 'unauthenticated' && (
  • - Login + Login
  • - Sign up + Sign up
)} - {session.isAuthenticated && ( + {session.status == 'authenticated' && (
-

{session.user.username}

- {isUserAdmin &&
ADMIN
} +

{session.data.user.username}

+ {isUserAdmin.isAdmin &&
ADMIN
}
diff --git a/apps/web/components/StyledElements/Error/Error.tsx b/apps/web/components/StyledElements/Error/Error.tsx index ead83f1f..ee1b0812 100644 --- a/apps/web/components/StyledElements/Error/Error.tsx +++ b/apps/web/components/StyledElements/Error/Error.tsx @@ -1,9 +1,11 @@ 'use client' -import { AlertTriangle, RefreshCcw } from 'lucide-react' +import { getUriWithoutOrg } from '@services/config/config' +import { AlertTriangle, HomeIcon, RefreshCcw } from 'lucide-react' +import Link from 'next/link' import { useRouter } from 'next/navigation' import React from 'react' -function ErrorUI() { +function ErrorUI(params: { message?: string, submessage?: string }) { const router = useRouter() function reloadPage() { @@ -15,9 +17,12 @@ function ErrorUI() {
-

Something went wrong

+
+

{params.message ? params.message : 'Something went wrong'}

+

{params.submessage ? params.submessage : ''}

+
-
+
+ + + Home +
) diff --git a/apps/web/components/StyledElements/Info/Info.tsx b/apps/web/components/StyledElements/Info/Info.tsx new file mode 100644 index 00000000..a117783a --- /dev/null +++ b/apps/web/components/StyledElements/Info/Info.tsx @@ -0,0 +1,37 @@ +'use client' +import { getUriWithoutOrg } from '@services/config/config' +import { Diamond, Home, PersonStanding } from 'lucide-react' +import Link from 'next/link' +import React from 'react' + +function InfoUI(params: { message?: string, submessage?: string, cta?: string, href: string }) { + return ( +
+
+ +
+

{params.message ? params.message : 'Something went wrong'}

+

{params.submessage ? params.submessage : ''}

+
+
+ {params.cta &&
+ + + {params.cta} + + + + Home + +
} +
+ ) +} + +export default InfoUI diff --git a/apps/web/middleware.ts b/apps/web/middleware.ts index 0d799d26..2234ca51 100644 --- a/apps/web/middleware.ts +++ b/apps/web/middleware.ts @@ -1,7 +1,9 @@ import { isInstallModeEnabled } from '@services/install/install' import { LEARNHOUSE_DOMAIN, + LEARNHOUSE_TOP_DOMAIN, getDefaultOrg, + getUriWithOrg, isMultiOrgModeEnabled, } from './services/config/config' import { NextResponse } from 'next/server' @@ -25,15 +27,31 @@ export default async function middleware(req: NextRequest) { // Get initial data const hosting_mode = isMultiOrgModeEnabled() ? 'multi' : 'single' const default_org = getDefaultOrg() - const pathname = req.nextUrl.pathname + const { pathname, search } = req.nextUrl const fullhost = req.headers ? req.headers.get('host') : '' + const cookie_orgslug = req.cookies.get('learnhouse_current_orgslug')?.value + const orgslug = fullhost + ? fullhost.replace(`.${LEARNHOUSE_DOMAIN}`, '') + : (default_org as string) - // Organizations & Global settings - if (pathname.startsWith('/organizations')) { - return NextResponse.rewrite(new URL(pathname, req.url)) + // Out of orgslug paths & rewrite + const standard_paths = ['/home'] + const auth_paths = ['/login', '/signup', '/reset'] + if (standard_paths.includes(pathname)) { + // Redirect to the same pathname with the original search params + return NextResponse.rewrite(new URL(`${pathname}${search}`, req.url)) + } + if (auth_paths.includes(pathname)) { + // Redirect to the same pathname with the original search params + return NextResponse.rewrite(new URL(`/auth${pathname}${search}`, req.url)) } - // Install Page + // Login + if (orgslug == 'auth' || pathname.startsWith('/login')) { + return NextResponse.rewrite(new URL(`/login${search}`, req.url)) + } + + // Install Page (depreceated) if (pathname.startsWith('/install')) { // Check if install mode is enabled const install_mode = await isInstallModeEnabled() @@ -49,19 +67,62 @@ export default async function middleware(req: NextRequest) { return NextResponse.rewrite(new URL(`/editor${pathname}`, req.url)) } + // Auth Redirects + if (pathname == '/redirect_from_auth') { + if (cookie_orgslug) { + const searchParams = req.nextUrl.searchParams + const queryString = searchParams.toString() + const redirectPathname = '/' + const redirectUrl = new URL( + getUriWithOrg(cookie_orgslug, redirectPathname), + req.url + ) + + if (queryString) { + redirectUrl.search = queryString + } + return NextResponse.redirect(redirectUrl) + } else { + } + } + // Multi Organization Mode if (hosting_mode === 'multi') { // Get the organization slug from the URL const orgslug = fullhost ? fullhost.replace(`.${LEARNHOUSE_DOMAIN}`, '') - : default_org - return NextResponse.rewrite(new URL(`/orgs/${orgslug}${pathname}`, req.url)) + : (default_org as string) + const response = NextResponse.rewrite( + new URL(`/orgs/${orgslug}${pathname}`, req.url) + ) + + // Set the cookie with the orgslug value + response.cookies.set({ + name: 'learnhouse_current_orgslug', + value: orgslug, + domain: LEARNHOUSE_TOP_DOMAIN == 'localhost' ? '' : LEARNHOUSE_TOP_DOMAIN, + path: '/', + }) + + return response } // Single Organization Mode if (hosting_mode === 'single') { // Get the default organization slug - const orgslug = default_org - return NextResponse.rewrite(new URL(`/orgs/${orgslug}${pathname}`, req.url)) + const orgslug = default_org as string + const response = NextResponse.rewrite( + new URL(`/orgs/${orgslug}${pathname}`, req.url) + ) + + // Set the cookie with the orgslug value + response.cookies.set({ + name: 'learnhouse_current_orgslug', + value: orgslug, + domain: LEARNHOUSE_TOP_DOMAIN == 'localhost' ? '' : LEARNHOUSE_TOP_DOMAIN, + path: '/', + }) + + return response } } diff --git a/apps/web/package.json b/apps/web/package.json index 867ddd4b..b7815d2e 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "dev": "next dev", + "dev-https" : "next dev --experimental-https -p 443", "build": "next build", "start": "next start", "lint": "next lint", @@ -39,6 +40,7 @@ "lowlight": "^3.1.0", "lucide-react": "^0.363.0", "next": "14.2.3", + "next-auth": "^4.24.7", "prosemirror-state": "^1.4.3", "randomcolor": "^0.6.2", "re-resizable": "^6.9.11", diff --git a/apps/web/pnpm-lock.yaml b/apps/web/pnpm-lock.yaml index 8c3367d8..55c9d56d 100644 --- a/apps/web/pnpm-lock.yaml +++ b/apps/web/pnpm-lock.yaml @@ -10,73 +10,73 @@ importers: dependencies: '@hocuspocus/provider': specifier: ^2.11.3 - version: 2.11.3(y-protocols@1.0.6)(yjs@13.6.14) + version: 2.13.0(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15) '@radix-ui/colors': specifier: ^0.1.9 version: 0.1.9 '@radix-ui/react-aspect-ratio': specifier: ^1.0.3 - version: 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dialog': specifier: ^1.0.5 - version: 1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-form': specifier: ^0.0.3 - version: 0.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + version: 0.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-icons': specifier: ^1.3.0 - version: 1.3.0(react@18.2.0) + version: 1.3.0(react@18.3.1) '@radix-ui/react-switch': specifier: ^1.0.3 - version: 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tooltip': specifier: ^1.0.7 - version: 1.0.7(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.7(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@stitches/react': specifier: ^1.2.8 - version: 1.2.8(react@18.2.0) + version: 1.2.8(react@18.3.1) '@tiptap/core': specifier: ^2.2.4 - version: 2.2.4(@tiptap/pm@2.2.4) + version: 2.4.0(@tiptap/pm@2.4.0) '@tiptap/extension-code-block-lowlight': specifier: ^2.2.4 - version: 2.2.4(@tiptap/core@2.2.4)(@tiptap/extension-code-block@2.2.4)(@tiptap/pm@2.2.4) + version: 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/extension-code-block@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) '@tiptap/extension-collaboration': specifier: ^2.2.4 - version: 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)(y-prosemirror@1.2.3) + version: 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)(y-prosemirror@1.2.5(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7)(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15)) '@tiptap/extension-collaboration-cursor': specifier: ^2.2.4 - version: 2.2.4(@tiptap/core@2.2.4)(y-prosemirror@1.2.3) + version: 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(y-prosemirror@1.2.5(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7)(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15)) '@tiptap/extension-youtube': specifier: ^2.2.4 - version: 2.2.4(@tiptap/core@2.2.4) + version: 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) '@tiptap/html': specifier: ^2.2.4 - version: 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) + version: 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) '@tiptap/pm': specifier: ^2.2.4 - version: 2.2.4 + version: 2.4.0 '@tiptap/react': specifier: ^2.2.4 - version: 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)(react-dom@18.2.0)(react@18.2.0) + version: 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tiptap/starter-kit': specifier: ^2.2.4 - version: 2.2.4(@tiptap/pm@2.2.4) + version: 2.4.0(@tiptap/pm@2.4.0) '@types/randomcolor': specifier: ^0.5.9 version: 0.5.9 avvvatars-react: specifier: ^0.4.2 - version: 0.4.2(csstype@3.1.3)(react-dom@18.2.0)(react@18.2.0) + version: 0.4.2(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) dayjs: specifier: ^1.11.10 - version: 1.11.10 + version: 1.11.11 formik: specifier: ^2.4.5 - version: 2.4.5(react@18.2.0) + version: 2.4.6(react@18.3.1) framer-motion: specifier: ^10.18.0 - version: 10.18.0(react-dom@18.2.0)(react@18.2.0) + version: 10.18.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) get-youtube-id: specifier: ^1.0.1 version: 1.0.1 @@ -91,10 +91,13 @@ importers: version: 3.1.0 lucide-react: specifier: ^0.363.0 - version: 0.363.0(react@18.2.0) + version: 0.363.0(react@18.3.1) next: specifier: 14.2.3 - version: 14.2.3(react-dom@18.2.0)(react@18.2.0) + version: 14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-auth: + specifier: ^4.24.7 + version: 4.24.7(next@14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) prosemirror-state: specifier: ^1.4.3 version: 1.4.3 @@ -103,61 +106,61 @@ importers: version: 0.6.2 re-resizable: specifier: ^6.9.11 - version: 6.9.11(react-dom@18.2.0)(react@18.2.0) + version: 6.9.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.2.0 - version: 18.2.0 + version: 18.3.1 react-beautiful-dnd: specifier: ^13.1.1 - version: 13.1.1(react-dom@18.2.0)(react@18.2.0) + version: 13.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-confetti: specifier: ^6.1.0 - version: 6.1.0(react@18.2.0) + version: 6.1.0(react@18.3.1) react-dom: specifier: ^18.2.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) react-hot-toast: specifier: ^2.4.1 - version: 2.4.1(csstype@3.1.3)(react-dom@18.2.0)(react@18.2.0) + version: 2.4.1(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-katex: specifier: ^3.0.1 - version: 3.0.1(prop-types@15.8.1)(react@18.2.0) + version: 3.0.1(prop-types@15.8.1)(react@18.3.1) react-spinners: specifier: ^0.13.8 - version: 0.13.8(react-dom@18.2.0)(react@18.2.0) + version: 0.13.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-youtube: specifier: ^10.1.0 - version: 10.1.0(react@18.2.0) + version: 10.1.0(react@18.3.1) sharp: specifier: ^0.33.3 - version: 0.33.3 + version: 0.33.4 styled-components: specifier: ^6.1.8 - version: 6.1.8(react-dom@18.2.0)(react@18.2.0) + version: 6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) swr: specifier: ^2.2.5 - version: 2.2.5(react@18.2.0) + version: 2.2.5(react@18.3.1) tailwind-merge: specifier: ^2.2.2 - version: 2.2.2 + version: 2.3.0 tailwind-scrollbar: specifier: ^3.1.0 - version: 3.1.0(tailwindcss@3.4.3) + version: 3.1.0(tailwindcss@3.4.4) uuid: specifier: ^9.0.1 version: 9.0.1 y-indexeddb: specifier: ^9.0.12 - version: 9.0.12(yjs@13.6.14) + version: 9.0.12(yjs@13.6.15) y-prosemirror: specifier: ^1.2.3 - version: 1.2.3(prosemirror-model@1.19.4)(prosemirror-state@1.4.3)(prosemirror-view@1.33.3)(y-protocols@1.0.6)(yjs@13.6.14) + version: 1.2.5(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7)(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15) y-webrtc: specifier: ^10.3.0 - version: 10.3.0(yjs@13.6.14) + version: 10.3.0(yjs@13.6.15) yjs: specifier: ^13.6.14 - version: 13.6.14 + version: 13.6.15 devDependencies: '@types/node': specifier: 20.12.2 @@ -191,42 +194,38 @@ importers: version: 8.57.0 eslint-config-next: specifier: ^14.1.4 - version: 14.1.4(eslint@8.57.0)(typescript@5.4.4) + version: 14.2.3(eslint@8.57.0)(typescript@5.4.4) eslint-plugin-unused-imports: specifier: ^3.1.0 - version: 3.1.0(eslint@8.57.0) + version: 3.2.0(eslint@8.57.0) postcss: specifier: ^8.4.38 version: 8.4.38 tailwindcss: specifier: ^3.4.3 - version: 3.4.3 + version: 3.4.4 typescript: specifier: 5.4.4 version: 5.4.4 packages: - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - '@babel/runtime@7.24.4': - resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} + '@babel/runtime@7.24.7': + resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==} engines: {node: '>=6.9.0'} - '@emnapi/runtime@1.1.1': - resolution: {integrity: sha512-3bfqkzuR1KLx57nZfjr2NLnFOobvyS0aTszaEGCGqmYMVDRaGvgIZbjGSV/MHSSmLgQ/b9JFHQ5xm5WRZYd+XQ==} + '@emnapi/runtime@1.2.0': + resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==} '@emotion/is-prop-valid@0.8.8': resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} - '@emotion/is-prop-valid@1.2.1': - resolution: {integrity: sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==} + '@emotion/is-prop-valid@1.2.2': + resolution: {integrity: sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==} '@emotion/memoize@0.7.4': resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} @@ -234,8 +233,8 @@ packages: '@emotion/memoize@0.8.1': resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} - '@emotion/unitless@0.8.0': - resolution: {integrity: sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==} + '@emotion/unitless@0.8.1': + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} @@ -243,8 +242,8 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + '@eslint-community/regexpp@4.10.1': + resolution: {integrity: sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} '@eslint/eslintrc@2.1.4': @@ -255,26 +254,26 @@ packages: resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@floating-ui/core@1.6.0': - resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} + '@floating-ui/core@1.6.2': + resolution: {integrity: sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==} - '@floating-ui/dom@1.6.3': - resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==} + '@floating-ui/dom@1.6.5': + resolution: {integrity: sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==} - '@floating-ui/react-dom@2.0.8': - resolution: {integrity: sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==} + '@floating-ui/react-dom@2.1.0': + resolution: {integrity: sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' - '@floating-ui/utils@0.2.1': - resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + '@floating-ui/utils@0.2.2': + resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==} - '@hocuspocus/common@2.11.3': - resolution: {integrity: sha512-w3UZpW6ZVYIHPEFzZJV3yn1d3EZaXf2m2zU53pwj0AyTBmVD7kB9ZiD6twc9A7NNB1dkqD8c58PbD42+pnNiKQ==} + '@hocuspocus/common@2.13.0': + resolution: {integrity: sha512-gyuUZ/7Jlht/cokGSTYWmG2+ZR1amBkV7gZgY6Bw8ko0OkUbEFsRdzWaB6RVcYNv+ZvYcsbkM8JU6rPsNykMrg==} - '@hocuspocus/provider@2.11.3': - resolution: {integrity: sha512-MvwA6TUrh7aXK4TwzJVkq60+iYkEkLIGjSOaGTxZfyDrgE70awmDiE4QlZ0e5lGc+T6/c6ct+asduP7nc3NHXw==} + '@hocuspocus/provider@2.13.0': + resolution: {integrity: sha512-xWRcyjW3koQajBCTEK3X2PrwaadUpaABsbYGKMWlr6I86pfknLJR8QIjEw1xgump9EbXjwtoXP6V6wuBkN4wkQ==} peerDependencies: y-protocols: ^1.0.6 yjs: ^13.6.8 @@ -290,14 +289,14 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - '@img/sharp-darwin-arm64@0.33.3': - resolution: {integrity: sha512-FaNiGX1MrOuJ3hxuNzWgsT/mg5OHG/Izh59WW2mk1UwYHUwtfbhk5QNKYZgxf0pLOhx9ctGiGa2OykD71vOnSw==} + '@img/sharp-darwin-arm64@0.33.4': + resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.33.3': - resolution: {integrity: sha512-2QeSl7QDK9ru//YBT4sQkoq7L0EAJZA3rtV+v9p8xTKl4U1bUqTIaCnoC7Ctx2kCjQgwFXDasOtPTCT8eCTXvw==} + '@img/sharp-darwin-x64@0.33.4': + resolution: {integrity: sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [darwin] @@ -350,55 +349,55 @@ packages: cpu: [x64] os: [linux] - '@img/sharp-linux-arm64@0.33.3': - resolution: {integrity: sha512-Zf+sF1jHZJKA6Gor9hoYG2ljr4wo9cY4twaxgFDvlG0Xz9V7sinsPp8pFd1XtlhTzYo0IhDbl3rK7P6MzHpnYA==} + '@img/sharp-linux-arm64@0.33.4': + resolution: {integrity: sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] - '@img/sharp-linux-arm@0.33.3': - resolution: {integrity: sha512-Q7Ee3fFSC9P7vUSqVEF0zccJsZ8GiiCJYGWDdhEjdlOeS9/jdkyJ6sUSPj+bL8VuOYFSbofrW0t/86ceVhx32w==} + '@img/sharp-linux-arm@0.33.4': + resolution: {integrity: sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==} engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm] os: [linux] - '@img/sharp-linux-s390x@0.33.3': - resolution: {integrity: sha512-vFk441DKRFepjhTEH20oBlFrHcLjPfI8B0pMIxGm3+yilKyYeHEVvrZhYFdqIseSclIqbQ3SnZMwEMWonY5XFA==} - engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + '@img/sharp-linux-s390x@0.33.4': + resolution: {integrity: sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==} + engines: {glibc: '>=2.31', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [s390x] os: [linux] - '@img/sharp-linux-x64@0.33.3': - resolution: {integrity: sha512-Q4I++herIJxJi+qmbySd072oDPRkCg/SClLEIDh5IL9h1zjhqjv82H0Seupd+q2m0yOfD+/fJnjSoDFtKiHu2g==} + '@img/sharp-linux-x64@0.33.4': + resolution: {integrity: sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] - '@img/sharp-linuxmusl-arm64@0.33.3': - resolution: {integrity: sha512-qnDccehRDXadhM9PM5hLvcPRYqyFCBN31kq+ErBSZtZlsAc1U4Z85xf/RXv1qolkdu+ibw64fUDaRdktxTNP9A==} + '@img/sharp-linuxmusl-arm64@0.33.4': + resolution: {integrity: sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] - '@img/sharp-linuxmusl-x64@0.33.3': - resolution: {integrity: sha512-Jhchim8kHWIU/GZ+9poHMWRcefeaxFIs9EBqf9KtcC14Ojk6qua7ghKiPs0sbeLbLj/2IGBtDcxHyjCdYWkk2w==} + '@img/sharp-linuxmusl-x64@0.33.4': + resolution: {integrity: sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] - '@img/sharp-wasm32@0.33.3': - resolution: {integrity: sha512-68zivsdJ0koE96stdUfM+gmyaK/NcoSZK5dV5CAjES0FUXS9lchYt8LAB5rTbM7nlWtxaU/2GON0HVN6/ZYJAQ==} + '@img/sharp-wasm32@0.33.4': + resolution: {integrity: sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [wasm32] - '@img/sharp-win32-ia32@0.33.3': - resolution: {integrity: sha512-CyimAduT2whQD8ER4Ux7exKrtfoaUiVr7HG0zZvO0XTFn2idUWljjxv58GxNTkFb8/J9Ub9AqITGkJD6ZginxQ==} + '@img/sharp-win32-ia32@0.33.4': + resolution: {integrity: sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.33.3': - resolution: {integrity: sha512-viT4fUIDKnli3IfOephGnolMzhz5VaTvDRkYqtZxOMIoMQ4MrAziO7pT1nVnOt2FAm7qW5aa+CCc13aEY6Le0g==} + '@img/sharp-win32-x64@0.33.4': + resolution: {integrity: sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [win32] @@ -431,8 +430,8 @@ packages: '@next/env@14.2.3': resolution: {integrity: sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==} - '@next/eslint-plugin-next@14.1.4': - resolution: {integrity: sha512-n4zYNLSyCo0Ln5b7qxqQeQ34OZKXwgbdcx6kmkQbywr+0k6M3Vinft0T72R6CDAcDrne2IAgSud4uWCzFgc5HA==} + '@next/eslint-plugin-next@14.2.3': + resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==} '@next/swc-darwin-arm64@14.2.3': resolution: {integrity: sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==} @@ -500,6 +499,9 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@panva/hkdf@1.1.1': + resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -814,8 +816,8 @@ packages: '@remirror/core-constants@2.0.2': resolution: {integrity: sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==} - '@rushstack/eslint-patch@1.10.1': - resolution: {integrity: sha512-S3Kq8e7LqxkA9s7HKLqXGTGck1uwis5vAXan3FnU5yw1Ec5hsSGnq4s/UCaSqABPOnOTg7zASLyst7+ohgWexg==} + '@rushstack/eslint-patch@1.10.3': + resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==} '@stitches/react@1.2.8': resolution: {integrity: sha512-9g9dWI4gsSVe8bNLlb+lMkBYsnIKCZTmvqvDG+Avnn69XfmHZKiaMrx7cgTaddq7aTPPmXiTsbFcUy0xgI4+wA==} @@ -828,162 +830,162 @@ packages: '@swc/helpers@0.5.5': resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} - '@tiptap/core@2.2.4': - resolution: {integrity: sha512-cRrI8IlLIhCE1hacBQzXIC8dsRvGq6a4lYWQK/BaHuZg21CG7szp3Vd8Ix+ra1f5v0xPOT+Hy+QFNQooRMKMCw==} + '@tiptap/core@2.4.0': + resolution: {integrity: sha512-YJSahk8pkxpCs8SflCZfTnJpE7IPyUWIylfgXM2DefjRQa5DZ+c6sNY0s/zbxKYFQ6AuHVX40r9pCfcqHChGxQ==} peerDependencies: '@tiptap/pm': ^2.0.0 - '@tiptap/extension-blockquote@2.2.4': - resolution: {integrity: sha512-FrfPnn0VgVrUwWLwja1afX99JGLp6PE9ThVcmri+tLwUZQvTTVcCvHoCdOakav3/nge1+aV4iE3tQdyq1tWI9Q==} + '@tiptap/extension-blockquote@2.4.0': + resolution: {integrity: sha512-nJJy4KsPgQqWTTDOWzFRdjCfG5+QExfZj44dulgDFNh+E66xhamnbM70PklllXJgEcge7xmT5oKM0gKls5XgFw==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-bold@2.2.4': - resolution: {integrity: sha512-v3tTLc8YESFZPOGj5ByFr8VbmQ/PTo49T1vsK50VubxIN/5r9cXlKH8kb3dZlZxCxJa3FrXNO/M8rdGBSWQvSg==} + '@tiptap/extension-bold@2.4.0': + resolution: {integrity: sha512-csnW6hMDEHoRfxcPRLSqeJn+j35Lgtt1YRiOwn7DlS66sAECGRuoGfCvQSPij0TCDp4VCR9if5Sf8EymhnQumQ==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-bubble-menu@2.2.4': - resolution: {integrity: sha512-Nx1fS9jcFlhxaTDYlnayz2UulhK6CMaePc36+7PQIVI+u20RhgTCRNr25zKNemvsiM0RPZZVUjlHkxC0l5as1Q==} + '@tiptap/extension-bubble-menu@2.4.0': + resolution: {integrity: sha512-s99HmttUtpW3rScWq8rqk4+CGCwergNZbHLTkF6Rp6TSboMwfp+rwL5Q/JkcAG9KGLso1vGyXKbt1xHOvm8zMw==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 - '@tiptap/extension-bullet-list@2.2.4': - resolution: {integrity: sha512-z/MPmW8bhRougMuorl6MAQBXeK4rhlP+jBWlNwT+CT8h5IkXqPnDbM1sZeagp2nYfVV6Yc4RWpzimqHHtGnYTA==} + '@tiptap/extension-bullet-list@2.4.0': + resolution: {integrity: sha512-9S5DLIvFRBoExvmZ+/ErpTvs4Wf1yOEs8WXlKYUCcZssK7brTFj99XDwpHFA29HKDwma5q9UHhr2OB2o0JYAdw==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-code-block-lowlight@2.2.4': - resolution: {integrity: sha512-FxrpY2Lj6kV6pu5LcaeccE3lqOqvOyFSfMGRV6x1OGOMV9TIFJKIVEIcEhqoiqEnuJZzSmQSx7QZqzOvquZo+A==} + '@tiptap/extension-code-block-lowlight@2.4.0': + resolution: {integrity: sha512-j0SdFq66A97Cn7bQOMqFYBaYsmOltZZ6o4uDZH6fdTvEFbfXTdtTYs2awsNSbW+w/DtivKZCvAX1FRLR3/g/5A==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/extension-code-block': ^2.0.0 '@tiptap/pm': ^2.0.0 - '@tiptap/extension-code-block@2.2.4': - resolution: {integrity: sha512-h6WV9TmaBEZmvqe1ezMR83DhCPUap6P2mSR5pwVk0WVq6rvZjfgU0iF3EetBJOeDgPlz7cNe2NMDfVb1nGTM/g==} + '@tiptap/extension-code-block@2.4.0': + resolution: {integrity: sha512-QWGdv1D56TBGbbJSj2cIiXGJEKguPiAl9ONzJ/Ql1ZksiQsYwx0YHriXX6TOC//T4VIf6NSClHEtwtxWBQ/Csg==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 - '@tiptap/extension-code@2.2.4': - resolution: {integrity: sha512-JB4SJ2mUU/9qXFUf+K5K9szvovnN9AIcCb0f0UlcVBuddKHSqCl3wO3QJgYt44BfQTLMNuyzr+zVqfFd6BNt/g==} + '@tiptap/extension-code@2.4.0': + resolution: {integrity: sha512-wjhBukuiyJMq4cTcK3RBTzUPV24k5n1eEPlpmzku6ThwwkMdwynnMGMAmSF3fErh3AOyOUPoTTjgMYN2d10SJA==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-collaboration-cursor@2.2.4': - resolution: {integrity: sha512-G0j08yGwFaq3AiaNHR+CUVCqLQv0fZhmwy9V1ByE7YkIgiDs9icCuKo1cbY2riW/Sn874rIHEctMxA8hVsNttw==} + '@tiptap/extension-collaboration-cursor@2.4.0': + resolution: {integrity: sha512-BTVy9FCTGdHxYieJ4lteVLrRY5qAPQyfunhMwakVf1NT3iU9quE6CaeaIwt6wEDJPMPPKzOHg1/ltSz9nIDe4A==} peerDependencies: '@tiptap/core': ^2.0.0 - y-prosemirror: ^1.2.1 + y-prosemirror: ^1.2.5 - '@tiptap/extension-collaboration@2.2.4': - resolution: {integrity: sha512-Q9DnGeTYhB8TDud9B2zbRZqbNdBi0C/zzTYora2bFRRXnUzQUJgvV7HeIcHajj2wdKe8HXGwXjrCzORUtwUFgA==} + '@tiptap/extension-collaboration@2.4.0': + resolution: {integrity: sha512-achU+GU9tqxn3zsU61CbwWrCausf0U23MJIpo8vnywOIx6E955by6okHEHoUazLIGVFXVc5DBzBP7bf+Snzk0Q==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 - y-prosemirror: ^1.2.1 + y-prosemirror: ^1.2.5 - '@tiptap/extension-document@2.2.4': - resolution: {integrity: sha512-z+05xGK0OFoXV1GL+/8bzcZuWMdMA3+EKwk5c+iziG60VZcvGTF7jBRsZidlu9Oaj0cDwWHCeeo6L9SgSh6i2A==} + '@tiptap/extension-document@2.4.0': + resolution: {integrity: sha512-3jRodQJZDGbXlRPERaloS+IERg/VwzpC1IO6YSJR9jVIsBO6xC29P3cKTQlg1XO7p6ZH/0ksK73VC5BzzTwoHg==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-dropcursor@2.2.4': - resolution: {integrity: sha512-IHwkEKmqpqXyJi16h7871NrcIqeyN7I6XRE2qdqi+MhGigVWI8nWHoYbjRKa7K/1uhs5zeRYyDlq5EuZyL6mgA==} + '@tiptap/extension-dropcursor@2.4.0': + resolution: {integrity: sha512-c46HoG2PEEpSZv5rmS5UX/lJ6/kP1iVO0Ax+6JrNfLEIiDULUoi20NqdjolEa38La2VhWvs+o20OviiTOKEE9g==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 - '@tiptap/extension-floating-menu@2.2.4': - resolution: {integrity: sha512-U25l7PEzOmlAPugNRl8t8lqyhQZS6W/+3f92+FdwW9qXju3i62iX/3OGCC3Gv+vybmQ4fbZmMjvl+VDfenNi3A==} + '@tiptap/extension-floating-menu@2.4.0': + resolution: {integrity: sha512-vLb9v+htbHhXyty0oaXjT3VC8St4xuGSHWUB9GuAJAQ+NajIO6rBPbLUmm9qM0Eh2zico5mpSD1Qtn5FM6xYzg==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 - '@tiptap/extension-gapcursor@2.2.4': - resolution: {integrity: sha512-Y6htT/RDSqkQ1UwG2Ia+rNVRvxrKPOs3RbqKHPaWr3vbFWwhHyKhMCvi/FqfI3d5pViVHOZQ7jhb5hT/a0BmNw==} + '@tiptap/extension-gapcursor@2.4.0': + resolution: {integrity: sha512-F4y/0J2lseohkFUw9P2OpKhrJ6dHz69ZScABUvcHxjznJLd6+0Zt7014Lw5PA8/m2d/w0fX8LZQ88pZr4quZPQ==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 - '@tiptap/extension-hard-break@2.2.4': - resolution: {integrity: sha512-FPvS57GcqHIeLbPKGJa3gnH30Xw+YB1PXXnAWG2MpnMtc2Vtj1l5xaYYBZB+ADdXLAlU0YMbKhFLQO4+pg1Isg==} + '@tiptap/extension-hard-break@2.4.0': + resolution: {integrity: sha512-3+Z6zxevtHza5IsDBZ4lZqvNR3Kvdqwxq/QKCKu9UhJN1DUjsg/l1Jn2NilSQ3NYkBYh2yJjT8CMo9pQIu776g==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-heading@2.2.4': - resolution: {integrity: sha512-gkq7Ns2FcrOCRq7Q+VRYt5saMt2R9g4REAtWy/jEevJ5UV5vA2AiGnYDmxwAkHutoYU0sAUkjqx37wE0wpamNw==} + '@tiptap/extension-heading@2.4.0': + resolution: {integrity: sha512-fYkyP/VMo7YHO76YVrUjd95Qeo0cubWn/Spavmwm1gLTHH/q7xMtbod2Z/F0wd6QHnc7+HGhO7XAjjKWDjldaw==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-history@2.2.4': - resolution: {integrity: sha512-FDM32XYF5NU4mzh+fJ8w2CyUqv0l2Nl15sd6fOhQkVxSj8t57z+DUXc9ZR3zkH+1RAagYJo/2Gu3e99KpMr0tg==} + '@tiptap/extension-history@2.4.0': + resolution: {integrity: sha512-gr5qsKAXEVGr1Lyk1598F7drTaEtAxqZiuuSwTCzZzkiwgEQsWMWTWc9F8FlneCEaqe1aIYg6WKWlmYPaFwr0w==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 - '@tiptap/extension-horizontal-rule@2.2.4': - resolution: {integrity: sha512-iCRHjFQQHApWg3R4fkKkJQhWEOdu1Fdc4YEAukdOXPSg3fg36IwjvsMXjt9SYBtVZ+iio3rORCZGXyMvgCH9uw==} + '@tiptap/extension-horizontal-rule@2.4.0': + resolution: {integrity: sha512-yDgxy+YxagcEsBbdWvbQiXYxsv3noS1VTuGwc9G7ZK9xPmBHJ5y0agOkB7HskwsZvJHoaSqNRsh7oZTkf0VR3g==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 - '@tiptap/extension-italic@2.2.4': - resolution: {integrity: sha512-qIhGNvWnsQswSgEMRA8jQQjxfkOGNAuNWKEVQX9DPoqAUgknT41hQcAMP8L2+OdACpb2jbVMOO5Cy5Dof2L8/w==} + '@tiptap/extension-italic@2.4.0': + resolution: {integrity: sha512-aaW/L9q+KNHHK+X73MPloHeIsT191n3VLd3xm6uUcFDnUNvzYJ/q65/1ZicdtCaOLvTutxdrEvhbkrVREX6a8g==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-list-item@2.2.4': - resolution: {integrity: sha512-lPLKGKsHpM9ClUa8n7GEUn8pG6HCYU0vFruIy3l2t6jZdHkrgBnYtVGMZ13K8UDnj/hlAlccxku0D0P4mA1Vrg==} + '@tiptap/extension-list-item@2.4.0': + resolution: {integrity: sha512-reUVUx+2cI2NIAqMZhlJ9uK/+zvRzm1GTmlU2Wvzwc7AwLN4yemj6mBDsmBLEXAKPvitfLh6EkeHaruOGymQtg==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-ordered-list@2.2.4': - resolution: {integrity: sha512-TpFy140O9Af1JciXt+xwqYUXxcJ6YG8zi/B5UDJujp+FH5sCmlYYBBnWxiFMhVaj6yEmA2eafu1qUkic/1X5Aw==} + '@tiptap/extension-ordered-list@2.4.0': + resolution: {integrity: sha512-Zo0c9M0aowv+2+jExZiAvhCB83GZMjZsxywmuOrdUbq5EGYKb7q8hDyN3hkrktVHr9UPXdPAYTmLAHztTOHYRA==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-paragraph@2.2.4': - resolution: {integrity: sha512-m1KwyvTNJxsq7StbspbcOhxO4Wk4YpElDbqOouWi+H4c8azdpI5Pn96ZqhFeE9bSyjByg6OcB/wqoJsLbeFWdQ==} + '@tiptap/extension-paragraph@2.4.0': + resolution: {integrity: sha512-+yse0Ow67IRwcACd9K/CzBcxlpr9OFnmf0x9uqpaWt1eHck1sJnti6jrw5DVVkyEBHDh/cnkkV49gvctT/NyCw==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-strike@2.2.4': - resolution: {integrity: sha512-/a2EwQgA+PpG17V2tVRspcrIY0SN3blwcgM7lxdW4aucGkqSKnf7+91dkhQEwCZ//o8kv9mBCyRoCUcGy6S5Xg==} + '@tiptap/extension-strike@2.4.0': + resolution: {integrity: sha512-pE1uN/fQPOMS3i+zxPYMmPmI3keubnR6ivwM+KdXWOMnBiHl9N4cNpJgq1n2eUUGKLurC2qrQHpnVyGAwBS6Vg==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-text@2.2.4': - resolution: {integrity: sha512-NlKHMPnRJXB+0AGtDlU0P2Pg+SdesA2lMMd7JzDUgJgL7pX2jOb8eUqSeOjFKuSzFSqYfH6C3o6mQiNhuQMv+g==} + '@tiptap/extension-text@2.4.0': + resolution: {integrity: sha512-LV0bvE+VowE8IgLca7pM8ll7quNH+AgEHRbSrsI3SHKDCYB9gTHMjWaAkgkUVaO1u0IfCrjnCLym/PqFKa+vvg==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/extension-youtube@2.2.4': - resolution: {integrity: sha512-OM8YVWF2febaErLGUzHGKAo3HkfX1RmXDxcsV2lChhxQUUuaQkv4oBFBNRNi/fcjnA/dMVe/2DfGMI5EGZmLrg==} + '@tiptap/extension-youtube@2.4.0': + resolution: {integrity: sha512-Ew6Oik9DaqP0xgQSUIWwozqeToJVOY4nqjRoKExGRuLdzgZeS+SmEA22ITBMcnZSJj8XBMgGBLcCWi+A7x1KAg==} peerDependencies: '@tiptap/core': ^2.0.0 - '@tiptap/html@2.2.4': - resolution: {integrity: sha512-a6ORgv+X5CExUOdLVjAd4uIPPTrETLylyed/4vhaPIhe3fZKc+2oJrj87lxfUGasY4LV7Gpn+s08XM5fXyB61g==} + '@tiptap/html@2.4.0': + resolution: {integrity: sha512-iM0sa6t0Hb5GTXnjdKvMDtD3KZgA4Mwx3QADeqfR10EjfPNlkh/BHU83oIhss/2JVRBXiUUDnNxW9cfpHX37/g==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 - '@tiptap/pm@2.2.4': - resolution: {integrity: sha512-Po0klR165zgtinhVp1nwMubjyKx6gAY9kH3IzcniYLCkqhPgiqnAcCr61TBpp4hfK8YURBS4ihvCB1dyfCyY8A==} + '@tiptap/pm@2.4.0': + resolution: {integrity: sha512-B1HMEqGS4MzIVXnpgRZDLm30mxDWj51LkBT/if1XD+hj5gm8B9Q0c84bhvODX6KIs+c6z+zsY9VkVu8w9Yfgxg==} - '@tiptap/react@2.2.4': - resolution: {integrity: sha512-HkYmMZWcETPZn3KpzdDg/ns2TKeFh54TvtCEInA4ljYtWGLoZc/A+KaiEtMIgVs+Mo1XwrhuoNGjL9c0OK2HJw==} + '@tiptap/react@2.4.0': + resolution: {integrity: sha512-baxnIr6Dy+5iGagOEIKFeHzdl1ZRa6Cg+SJ3GDL/BVLpO6KiCM3Mm5ymB726UKP1w7icrBiQD2fGY3Bx8KaiSA==} peerDependencies: '@tiptap/core': ^2.0.0 '@tiptap/pm': ^2.0.0 react: ^17.0.0 || ^18.0.0 react-dom: ^17.0.0 || ^18.0.0 - '@tiptap/starter-kit@2.2.4': - resolution: {integrity: sha512-Kbk7qUfIZg3+bNa3e/wBeDQt4jJB46uQgM+xy5NSY6H8NZP6gdmmap3aIrn9S/W/hGpxJl4RcXAeaT0CQji9XA==} + '@tiptap/starter-kit@2.4.0': + resolution: {integrity: sha512-DYYzMZdTEnRn9oZhKOeRCcB+TjhNz5icLlvJKoHoOGL9kCbuUyEf8WRR2OSPckI0+KUIPJL3oHRqO4SqSdTjfg==} '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -1024,8 +1026,8 @@ packages: '@types/styled-components@5.1.34': resolution: {integrity: sha512-mmiVvwpYklFIv9E8qfxuPyIt/OuyIrn6gMOAMOFUO3WJfSrSE+sGUoa4PiZj77Ut7bKZpaa6o1fBKS/4TOEvnA==} - '@types/stylis@4.2.0': - resolution: {integrity: sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw==} + '@types/stylis@4.2.5': + resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==} '@types/unist@3.0.2': resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} @@ -1033,26 +1035,26 @@ packages: '@types/uuid@9.0.8': resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} - '@typescript-eslint/parser@6.21.0': - resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} + '@typescript-eslint/parser@7.2.0': + resolution: {integrity: sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/scope-manager@6.21.0': - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + '@typescript-eslint/scope-manager@7.2.0': + resolution: {integrity: sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/types@6.21.0': - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + '@typescript-eslint/types@7.2.0': + resolution: {integrity: sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/typescript-estree@6.21.0': - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + '@typescript-eslint/typescript-estree@7.2.0': + resolution: {integrity: sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1060,8 +1062,8 @@ packages: typescript: optional: true - '@typescript-eslint/visitor-keys@6.21.0': - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + '@typescript-eslint/visitor-keys@7.2.0': + resolution: {integrity: sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==} engines: {node: ^16.0.0 || >=18.0.0} '@ungap/structured-clone@1.2.0': @@ -1147,8 +1149,9 @@ packages: array.prototype.toreversed@1.1.2: resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} - array.prototype.tosorted@1.1.3: - resolution: {integrity: sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==} + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} arraybuffer.prototype.slice@1.0.3: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} @@ -1197,8 +1200,8 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} browserslist@4.23.0: @@ -1228,8 +1231,8 @@ packages: camelize@1.0.1: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} - caniuse-lite@1.0.30001606: - resolution: {integrity: sha512-LPbwnW4vfpJId225pwjZJOgX1m9sGfbw/RKJvw/t0QhYOOaTXHvkjVGFGPpvwEzufrjvTlsULnVTxdy4/6cqkg==} + caniuse-lite@1.0.30001629: + resolution: {integrity: sha512-c3dl911slnQhmxUIT4HhYzT7wnBK/XYpGnYLOj4nJBaRiw52Ibe7YxlDaAeRECvA786zCuExhxIUJ2K7nHMrBw==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -1267,6 +1270,10 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + crelt@1.0.6: resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} @@ -1293,9 +1300,6 @@ packages: engines: {node: '>=4'} hasBin: true - csstype@3.1.2: - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -1314,8 +1318,8 @@ packages: resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} engines: {node: '>= 0.4'} - dayjs@1.11.10: - resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + dayjs@1.11.11: + resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -1333,8 +1337,8 @@ packages: supports-color: optional: true - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1392,8 +1396,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.4.728: - resolution: {integrity: sha512-Ud1v7hJJYIqehlUJGqR6PF1Ek8l80zWwxA6nGxigBsGJ9f9M2fciHyrIiNMerSHSH3p+0/Ia7jIlnDkt41h5cw==} + electron-to-chromium@1.4.792: + resolution: {integrity: sha512-rkg5/N3L+Y844JyfgPUyuKK0Hk0efo3JNxUDKvz3HgP6EmN4rNGhr2D8boLsfTV/hGo7ZGAL8djw+jlg99zQyA==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1401,8 +1405,8 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - enhanced-resolve@5.16.0: - resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} + enhanced-resolve@5.17.0: + resolution: {integrity: sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==} engines: {node: '>=10.13.0'} entities@4.5.0: @@ -1424,8 +1428,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-iterator-helpers@1.0.18: - resolution: {integrity: sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==} + es-iterator-helpers@1.0.19: + resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} engines: {node: '>= 0.4'} es-object-atoms@1.0.0: @@ -1451,8 +1455,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-config-next@14.1.4: - resolution: {integrity: sha512-cihIahbhYAWwXJwZkAaRPpUi5t9aOi/HdfWXOjZeUOqNWXHD8X22kd1KG58Dc3MVaRx3HoR/oMGk2ltcrqDn8g==} + eslint-config-next@14.2.3: + resolution: {integrity: sha512-ZkNztm3Q7hjqvB1rRlOX8P9E/cXRL9ajRcs8jufEtwMfTVYRqnmtnaSu57QqHyBlovMuiB8LEzfLBkh5RYV6Fg==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 typescript: '>=3.3.1' @@ -1507,20 +1511,20 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - eslint-plugin-react-hooks@4.6.0: - resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + eslint-plugin-react-hooks@4.6.2: + resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - eslint-plugin-react@7.34.1: - resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==} + eslint-plugin-react@7.34.2: + resolution: {integrity: sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - eslint-plugin-unused-imports@3.1.0: - resolution: {integrity: sha512-9l1YFCzXKkw1qtAru1RWUtG2EVDZY0a0eChKXcL+EZ5jitG7qxdctu4RnvhOJHv4xfmUf7h+JJPINlVpGhZMrw==} + eslint-plugin-unused-imports@3.2.0: + resolution: {integrity: sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': 6 - 7 @@ -1586,8 +1590,8 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} find-up@5.0.0: @@ -1608,8 +1612,8 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} - formik@2.4.5: - resolution: {integrity: sha512-Gxlht0TD3vVdzMDHwkiNZqJ7Mvg77xQNfmBRrNtvzcHZs72TJppSTDKHpImCMJZwcWPBJ8jSQQ95GJzXFf1nAQ==} + formik@2.4.6: + resolution: {integrity: sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==} peerDependencies: react: '>=16.8.0' @@ -1660,8 +1664,8 @@ packages: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} - get-tsconfig@4.7.3: - resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} + get-tsconfig@4.7.5: + resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} get-youtube-id@1.0.1: resolution: {integrity: sha512-5yidLzoLXbtw82a/Wb7LrajkGn29BM6JuLWeHyNfzOGp1weGyW4+7eMz6cP23+etqj27VlOFtq8fFFDMLq/FXQ==} @@ -1679,20 +1683,21 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true - glob@10.3.12: - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} - engines: {node: '>=16 || 14 >=14.17'} + glob@10.4.1: + resolution: {integrity: sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==} + engines: {node: '>=16 || 14 >=14.18'} hasBin: true glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} - globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} globby@11.1.0: @@ -1763,6 +1768,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -1901,10 +1907,17 @@ packages: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} + jackspeak@3.4.0: + resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} + engines: {node: '>=14'} + jiti@1.21.0: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true + jose@4.15.5: + resolution: {integrity: sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1936,8 +1949,8 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} language-tags@1.0.9: resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} @@ -1947,8 +1960,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lib0@0.2.93: - resolution: {integrity: sha512-M5IKsiFJYulS+8Eal8f+zAqf5ckm1vffW0fFDxfgxJ+uiVopvDdd3PxJmz0GsVi3YNO7QCFSq0nAsiDmNhLj9Q==} + lib0@0.2.94: + resolution: {integrity: sha512-hZ3p54jL4Wpu7IOg26uC7dnEWiMyNlUrb9KoG7+xYs45WkQwpVvKFndVq2+pqLYKe1u8Fp3+zAfZHVvTK34PvQ==} engines: {node: '>=16'} hasBin: true @@ -1989,8 +2002,8 @@ packages: lowlight@3.1.0: resolution: {integrity: sha512-CEbNVoSikAxwDMDPjXlqlFYiZLkDJHwyGu/MfOsJnF3d7f3tds5J3z8s/l9TMXhzfsJCCJEAsD78842mwmg0PQ==} - lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} + lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} engines: {node: 14 || >=16.14} lru-cache@6.0.0: @@ -2016,8 +2029,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} minimatch@3.1.2: @@ -2034,8 +2047,8 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} ms@2.0.0: @@ -2058,6 +2071,17 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + next-auth@4.24.7: + resolution: {integrity: sha512-iChjE8ov/1K/z98gdKbn2Jw+2vLgJtVV39X+rCP5SGnVQuco7QOr19FRNGMIrD8d3LYhHWV9j9sKLzq1aDWWQQ==} + peerDependencies: + next: ^12.2.5 || ^13 || ^14 + nodemailer: ^6.6.5 + react: ^17.0.2 || ^18 + react-dom: ^17.0.2 || ^18 + peerDependenciesMeta: + nodemailer: + optional: true + next@14.2.3: resolution: {integrity: sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==} engines: {node: '>=18.17.0'} @@ -2087,10 +2111,17 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} + oauth@0.9.15: + resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + object-hash@2.2.0: + resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} + engines: {node: '>= 6'} + object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} @@ -2126,11 +2157,18 @@ packages: resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} engines: {node: '>= 0.4'} + oidc-token-hash@5.0.3: + resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==} + engines: {node: ^10.13.0 || >=12.0.0} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + openid-client@5.6.5: + resolution: {integrity: sha512-5P4qO9nGJzB5PI0LFlhj4Dzg3m4odt0qsJTfyEtZyOlkgpILwEioOhVVJOrS1iVH494S4Ee5OCjjg6Bf5WOj3w==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} orderedmap@2.1.1: @@ -2163,16 +2201,16 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -2220,8 +2258,8 @@ packages: peerDependencies: postcss: ^8.2.14 - postcss-selector-parser@6.0.16: - resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} + postcss-selector-parser@6.1.0: + resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==} engines: {node: '>=4'} postcss-value-parser@4.2.0: @@ -2235,10 +2273,21 @@ packages: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} + preact-render-to-string@5.2.6: + resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} + peerDependencies: + preact: '>=10' + + preact@10.22.0: + resolution: {integrity: sha512-RRurnSjJPj4rp5K6XoP45Ui33ncb7e4H7WiOHVpjbkvqvA3U+N8Z6Qbo0AE6leGYBV66n8EhEaFixvIu3SkxFw==} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + pretty-format@3.8.0: + resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -2266,14 +2315,14 @@ packages: prosemirror-keymap@1.2.2: resolution: {integrity: sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==} - prosemirror-markdown@1.12.0: - resolution: {integrity: sha512-6F5HS8Z0HDYiS2VQDZzfZP6A0s/I0gbkJy8NCzzDMtcsz3qrfqyroMMeoSjAmOhDITyon11NbXSzztfKi+frSQ==} + prosemirror-markdown@1.13.0: + resolution: {integrity: sha512-UziddX3ZYSYibgx8042hfGKmukq5Aljp2qoBiJRejD/8MH70siQNz5RB1TrdTPheqLMy4aCe4GYNF10/3lQS5g==} prosemirror-menu@1.2.4: resolution: {integrity: sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==} - prosemirror-model@1.19.4: - resolution: {integrity: sha512-RPmVXxUfOhyFdayHawjuZCxiROsm9L4FCUA6pWI+l7n2yCBsWy9VpdE1hpDHUS8Vad661YLY9AzqfjLhAKQ4iQ==} + prosemirror-model@1.21.1: + resolution: {integrity: sha512-IVBAuMqOfltTr7yPypwpfdGT+6rGAteVOw2FO6GEvCGGa1ZwxLseqC1Eax/EChDvG/xGquB2d/hLdgh3THpsYg==} prosemirror-schema-basic@1.2.2: resolution: {integrity: sha512-/dT4JFEGyO7QnNTe9UaKUhjDXbTNkiWTq/N4VpKaF79bBjSExVV2NXmJpcM7z/gD7mbqNjxbmWW5nf1iNSSGnw==} @@ -2294,11 +2343,11 @@ packages: prosemirror-state: ^1.4.2 prosemirror-view: ^1.31.2 - prosemirror-transform@1.8.0: - resolution: {integrity: sha512-BaSBsIMv52F1BVVMvOmp1yzD3u65uC3HTzCBQV1WDPqJRQ2LuHKcyfn0jwqodo8sR9vVzMzZyI+Dal5W9E6a9A==} + prosemirror-transform@1.9.0: + resolution: {integrity: sha512-5UXkr1LIRx3jmpXXNKDhv8OyAOeLTGuXNwdVfg8x27uASna/wQkr9p6fD3eupGOi4PLJfbezxTyi/7fSJypXHg==} - prosemirror-view@1.33.3: - resolution: {integrity: sha512-P4Ao/bc4OrU/2yLIf8dL4lJaEtjLR3QjIvQHgJYp2jUS7kYM4bSR6okbBjkqzOs/FwUon6UGjTLdKMnPL1MZqw==} + prosemirror-view@1.33.7: + resolution: {integrity: sha512-jo6eMQCtPRwcrA2jISBCnm0Dd2B+szS08BU1Ay+XGiozHo5EZMHfLQE8R5nO4vb1spTH2RW1woZIYXRiQsuP8g==} punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} @@ -2320,8 +2369,8 @@ packages: randomcolor@0.6.2: resolution: {integrity: sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==} - re-resizable@6.9.11: - resolution: {integrity: sha512-a3hiLWck/NkmyLvGWUuvkAmN1VhwAz4yOhS6FdMTaxCUVN9joIWkT11wsO68coG/iEYuwn+p/7qAmfQzRhiPLQ==} + re-resizable@6.9.17: + resolution: {integrity: sha512-OBqd1BwVXpEJJn/yYROG+CbeqIDBWIp6wathlpB0kzZWWZIY1gPTsgK2yJEui5hOvkCdC2mcexF2V3DZVfLq2g==} peerDependencies: react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 @@ -2338,10 +2387,10 @@ packages: peerDependencies: react: ^16.3.0 || ^17.0.1 || ^18.0.0 - react-dom@18.2.0: - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: - react: ^18.2.0 + react: ^18.3.1 react-fast-compare@2.0.4: resolution: {integrity: sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==} @@ -2419,8 +2468,8 @@ packages: peerDependencies: react: '>=0.14.1' - react@18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} read-cache@1.0.0: @@ -2469,6 +2518,7 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rope-sequence@1.3.4: @@ -2488,15 +2538,15 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} - scheduler@0.23.0: - resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} hasBin: true @@ -2511,8 +2561,8 @@ packages: shallowequal@1.1.0: resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - sharp@0.33.3: - resolution: {integrity: sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A==} + sharp@0.33.4: + resolution: {integrity: sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==} engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: @@ -2594,8 +2644,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - styled-components@6.1.8: - resolution: {integrity: sha512-PQ6Dn+QxlWyEGCKDS71NGsXoVLKfE1c3vApkvDYS5KAK+V8fNWGhbSUEo9Gg2iaID2tjLXegEW3bZDUGpofRWw==} + styled-components@6.1.11: + resolution: {integrity: sha512-Ui0jXPzbp1phYij90h12ksljKGqF8ncGx+pjrNPsSPhbUUjWT2tD1FwGo2LF6USCnbrsIhNngDfodhxbegfEOA==} engines: {node: '>= 16'} peerDependencies: react: '>= 16.8.0' @@ -2614,8 +2664,8 @@ packages: babel-plugin-macros: optional: true - stylis@4.3.1: - resolution: {integrity: sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==} + stylis@4.3.2: + resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==} sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} @@ -2635,8 +2685,8 @@ packages: peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 - tailwind-merge@2.2.2: - resolution: {integrity: sha512-tWANXsnmJzgw6mQ07nE3aCDkCK4QdT3ThPMCzawoYA2Pws7vSTCvz3Vrjg61jVUGfFZPJzxEP+NimbcW+EdaDw==} + tailwind-merge@2.3.0: + resolution: {integrity: sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==} tailwind-scrollbar@3.1.0: resolution: {integrity: sha512-pmrtDIZeHyu2idTejfV59SbaJyvp1VRjYxAjZBH0jnyrPRo6HL1kD5Glz8VPagasqr6oAx6M05+Tuw429Z8jxg==} @@ -2644,8 +2694,8 @@ packages: peerDependencies: tailwindcss: 3.x - tailwindcss@3.4.3: - resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} + tailwindcss@3.4.4: + resolution: {integrity: sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==} engines: {node: '>=14.0.0'} hasBin: true @@ -2688,12 +2738,12 @@ packages: tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - tslib@2.5.0: - resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} - tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tween-functions@1.2.0: resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==} @@ -2735,8 +2785,8 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - update-browserslist-db@1.0.13: - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + update-browserslist-db@1.0.16: + resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -2769,14 +2819,18 @@ packages: '@types/react': optional: true - use-sync-external-store@1.2.0: - resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + use-sync-external-store@1.2.2: + resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true @@ -2804,6 +2858,10 @@ packages: engines: {node: '>= 8'} hasBin: true + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -2815,8 +2873,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.16.0: - resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + ws@8.17.0: + resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -2833,8 +2891,8 @@ packages: peerDependencies: yjs: ^13.0.0 - y-prosemirror@1.2.3: - resolution: {integrity: sha512-0e9QB78hcAT3l+ml26x+f7K9xmP1tqHGzbKTfe+JuPpKFBLpr2NUwH7D+J7uKhtMAmOhHUMFtd7Zd2mNKyP2+A==} + y-prosemirror@1.2.5: + resolution: {integrity: sha512-T/JATxC8P2Dbvq/dAiaiztD1a8KEwRP8oLRlT8YlaZdNlLGE1Ea0IJ8If25UlDYmk+4+uqLbqT/S+dzUmwwgbA==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} peerDependencies: prosemirror-model: ^1.7.1 @@ -2859,13 +2917,13 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yaml@2.4.1: - resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} + yaml@2.4.3: + resolution: {integrity: sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg==} engines: {node: '>= 14'} hasBin: true - yjs@13.6.14: - resolution: {integrity: sha512-D+7KcUr0j+vBCUSKXXEWfA+bG4UQBviAwP3gYBhkstkgwy5+8diOPMx0iqLIOxNo/HxaREUimZRxqHGAHCL2BQ==} + yjs@13.6.15: + resolution: {integrity: sha512-moFv4uNYhp8BFxIk3AkpoAnnjts7gwdpiG8RtyFiKbMtxKCS0zVZ5wPaaGpwC3V2N/K8TK8MwtSI3+WO9CHWjQ==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} yocto-queue@0.1.0: @@ -2881,17 +2939,15 @@ packages: snapshots: - '@aashutoshrathi/word-wrap@1.2.6': {} - '@alloc/quick-lru@5.2.0': {} - '@babel/runtime@7.24.4': + '@babel/runtime@7.24.7': dependencies: regenerator-runtime: 0.14.1 - '@emnapi/runtime@1.1.1': + '@emnapi/runtime@1.2.0': dependencies: - tslib: 2.6.2 + tslib: 2.6.3 optional: true '@emotion/is-prop-valid@0.8.8': @@ -2899,7 +2955,7 @@ snapshots: '@emotion/memoize': 0.7.4 optional: true - '@emotion/is-prop-valid@1.2.1': + '@emotion/is-prop-valid@1.2.2': dependencies: '@emotion/memoize': 0.8.1 @@ -2908,19 +2964,19 @@ snapshots: '@emotion/memoize@0.8.1': {} - '@emotion/unitless@0.8.0': {} + '@emotion/unitless@0.8.1': {} '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.10.0': {} + '@eslint-community/regexpp@4.10.1': {} '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.5 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -2933,35 +2989,35 @@ snapshots: '@eslint/js@8.57.0': {} - '@floating-ui/core@1.6.0': + '@floating-ui/core@1.6.2': dependencies: - '@floating-ui/utils': 0.2.1 + '@floating-ui/utils': 0.2.2 - '@floating-ui/dom@1.6.3': + '@floating-ui/dom@1.6.5': dependencies: - '@floating-ui/core': 1.6.0 - '@floating-ui/utils': 0.2.1 + '@floating-ui/core': 1.6.2 + '@floating-ui/utils': 0.2.2 - '@floating-ui/react-dom@2.0.8(react-dom@18.2.0)(react@18.2.0)': + '@floating-ui/react-dom@2.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/dom': 1.6.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@floating-ui/dom': 1.6.5 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - '@floating-ui/utils@0.2.1': {} + '@floating-ui/utils@0.2.2': {} - '@hocuspocus/common@2.11.3': + '@hocuspocus/common@2.13.0': dependencies: - lib0: 0.2.93 + lib0: 0.2.94 - '@hocuspocus/provider@2.11.3(y-protocols@1.0.6)(yjs@13.6.14)': + '@hocuspocus/provider@2.13.0(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15)': dependencies: - '@hocuspocus/common': 2.11.3 + '@hocuspocus/common': 2.13.0 '@lifeomic/attempt': 3.1.0 - lib0: 0.2.93 - ws: 8.16.0 - y-protocols: 1.0.6(yjs@13.6.14) - yjs: 13.6.14 + lib0: 0.2.94 + ws: 8.17.0 + y-protocols: 1.0.6(yjs@13.6.15) + yjs: 13.6.15 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -2969,7 +3025,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4 + debug: 4.3.5 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -2978,12 +3034,12 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} - '@img/sharp-darwin-arm64@0.33.3': + '@img/sharp-darwin-arm64@0.33.4': optionalDependencies: '@img/sharp-libvips-darwin-arm64': 1.0.2 optional: true - '@img/sharp-darwin-x64@0.33.3': + '@img/sharp-darwin-x64@0.33.4': optionalDependencies: '@img/sharp-libvips-darwin-x64': 1.0.2 optional: true @@ -3012,45 +3068,45 @@ snapshots: '@img/sharp-libvips-linuxmusl-x64@1.0.2': optional: true - '@img/sharp-linux-arm64@0.33.3': + '@img/sharp-linux-arm64@0.33.4': optionalDependencies: '@img/sharp-libvips-linux-arm64': 1.0.2 optional: true - '@img/sharp-linux-arm@0.33.3': + '@img/sharp-linux-arm@0.33.4': optionalDependencies: '@img/sharp-libvips-linux-arm': 1.0.2 optional: true - '@img/sharp-linux-s390x@0.33.3': + '@img/sharp-linux-s390x@0.33.4': optionalDependencies: '@img/sharp-libvips-linux-s390x': 1.0.2 optional: true - '@img/sharp-linux-x64@0.33.3': + '@img/sharp-linux-x64@0.33.4': optionalDependencies: '@img/sharp-libvips-linux-x64': 1.0.2 optional: true - '@img/sharp-linuxmusl-arm64@0.33.3': + '@img/sharp-linuxmusl-arm64@0.33.4': optionalDependencies: '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 optional: true - '@img/sharp-linuxmusl-x64@0.33.3': + '@img/sharp-linuxmusl-x64@0.33.4': optionalDependencies: '@img/sharp-libvips-linuxmusl-x64': 1.0.2 optional: true - '@img/sharp-wasm32@0.33.3': + '@img/sharp-wasm32@0.33.4': dependencies: - '@emnapi/runtime': 1.1.1 + '@emnapi/runtime': 1.2.0 optional: true - '@img/sharp-win32-ia32@0.33.3': + '@img/sharp-win32-ia32@0.33.4': optional: true - '@img/sharp-win32-x64@0.33.3': + '@img/sharp-win32-x64@0.33.4': optional: true '@isaacs/cliui@8.0.2': @@ -3083,7 +3139,7 @@ snapshots: '@next/env@14.2.3': {} - '@next/eslint-plugin-next@14.1.4': + '@next/eslint-plugin-next@14.2.3': dependencies: glob: 10.3.10 @@ -3126,6 +3182,8 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@panva/hkdf@1.1.1': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -3135,407 +3193,433 @@ snapshots: '@radix-ui/primitive@1.0.1': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 - '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-aspect-ratio@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-aspect-ratio@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-context@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-context@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@types/react': 18.2.74 - '@types/react-dom': 18.2.23 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.3.1) aria-hidden: 1.2.4 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.5(@types/react@18.2.74)(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.5.5(@types/react@18.2.74)(react@18.3.1) + optionalDependencies: + '@types/react': 18.2.74 + '@types/react-dom': 18.2.23 - '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-form@0.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-form@0.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-label': 2.0.2(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-label': 2.0.2(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-icons@1.3.0(react@18.2.0)': + '@radix-ui/react-icons@1.3.0(react@18.3.1)': dependencies: - react: 18.2.0 + react: 18.3.1 - '@radix-ui/react-id@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-id@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-label@2.0.2(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-label@2.0.2(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@floating-ui/react-dom': 2.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.74)(react@18.3.1) '@radix-ui/rect': 1.0.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.74)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-slot@1.0.2(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-slot@1.0.2(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-switch@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-switch@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-tooltip@1.0.7(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-tooltip@1.0.7(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.2.0) - '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.74)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-use-previous@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-use-previous@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-use-rect@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-use-rect@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 '@radix-ui/rect': 1.0.1 + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-use-size@1.0.1(@types/react@18.2.74)(react@18.2.0)': + '@radix-ui/react-use-size@1.0.1(@types/react@18.2.74)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.74)(react@18.3.1) + react: 18.3.1 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - '@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0)': + '@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.4 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@babel/runtime': 7.24.7 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.23)(@types/react@18.2.74)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 '@types/react-dom': 18.2.23 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) '@radix-ui/rect@1.0.1': dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 '@remirror/core-constants@2.0.2': {} - '@rushstack/eslint-patch@1.10.1': {} + '@rushstack/eslint-patch@1.10.3': {} - '@stitches/react@1.2.8(react@18.2.0)': + '@stitches/react@1.2.8(react@18.3.1)': dependencies: - react: 18.2.0 + react: 18.3.1 '@swc/counter@0.1.3': {} '@swc/helpers@0.5.5': dependencies: '@swc/counter': 0.1.3 - tslib: 2.6.2 + tslib: 2.6.3 - '@tiptap/core@2.2.4(@tiptap/pm@2.2.4)': + '@tiptap/core@2.4.0(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/pm': 2.2.4 + '@tiptap/pm': 2.4.0 - '@tiptap/extension-blockquote@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-blockquote@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-bold@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-bold@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-bubble-menu@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)': + '@tiptap/extension-bubble-menu@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 tippy.js: 6.3.7 - '@tiptap/extension-bullet-list@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-bullet-list@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-code-block-lowlight@2.2.4(@tiptap/core@2.2.4)(@tiptap/extension-code-block@2.2.4)(@tiptap/pm@2.2.4)': + '@tiptap/extension-code-block-lowlight@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/extension-code-block@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/extension-code-block': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/extension-code-block': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 - '@tiptap/extension-code-block@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)': + '@tiptap/extension-code-block@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 - '@tiptap/extension-code@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-code@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-collaboration-cursor@2.2.4(@tiptap/core@2.2.4)(y-prosemirror@1.2.3)': + '@tiptap/extension-collaboration-cursor@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(y-prosemirror@1.2.5(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7)(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - y-prosemirror: 1.2.3(prosemirror-model@1.19.4)(prosemirror-state@1.4.3)(prosemirror-view@1.33.3)(y-protocols@1.0.6)(yjs@13.6.14) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + y-prosemirror: 1.2.5(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7)(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15) - '@tiptap/extension-collaboration@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)(y-prosemirror@1.2.3)': + '@tiptap/extension-collaboration@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)(y-prosemirror@1.2.5(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7)(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 - y-prosemirror: 1.2.3(prosemirror-model@1.19.4)(prosemirror-state@1.4.3)(prosemirror-view@1.33.3)(y-protocols@1.0.6)(yjs@13.6.14) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 + y-prosemirror: 1.2.5(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7)(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15) - '@tiptap/extension-document@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-document@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-dropcursor@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)': + '@tiptap/extension-dropcursor@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 - '@tiptap/extension-floating-menu@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)': + '@tiptap/extension-floating-menu@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 tippy.js: 6.3.7 - '@tiptap/extension-gapcursor@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)': + '@tiptap/extension-gapcursor@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 - '@tiptap/extension-hard-break@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-hard-break@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-heading@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-heading@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-history@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)': + '@tiptap/extension-history@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 - '@tiptap/extension-horizontal-rule@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)': + '@tiptap/extension-horizontal-rule@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 - '@tiptap/extension-italic@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-italic@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-list-item@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-list-item@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-ordered-list@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-ordered-list@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-paragraph@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-paragraph@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-strike@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-strike@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-text@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-text@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/extension-youtube@2.2.4(@tiptap/core@2.2.4)': + '@tiptap/extension-youtube@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) - '@tiptap/html@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)': + '@tiptap/html@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 zeed-dom: 0.10.11 - '@tiptap/pm@2.2.4': + '@tiptap/pm@2.4.0': dependencies: prosemirror-changeset: 2.2.1 prosemirror-collab: 1.3.1 @@ -3545,47 +3629,47 @@ snapshots: prosemirror-history: 1.4.0 prosemirror-inputrules: 1.4.0 prosemirror-keymap: 1.2.2 - prosemirror-markdown: 1.12.0 + prosemirror-markdown: 1.13.0 prosemirror-menu: 1.2.4 - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 prosemirror-schema-basic: 1.2.2 prosemirror-schema-list: 1.3.0 prosemirror-state: 1.4.3 prosemirror-tables: 1.3.7 - prosemirror-trailing-node: 2.0.8(prosemirror-model@1.19.4)(prosemirror-state@1.4.3)(prosemirror-view@1.33.3) - prosemirror-transform: 1.8.0 - prosemirror-view: 1.33.3 + prosemirror-trailing-node: 2.0.8(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7) + prosemirror-transform: 1.9.0 + prosemirror-view: 1.33.7 - '@tiptap/react@2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4)(react-dom@18.2.0)(react@18.2.0)': + '@tiptap/react@2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/extension-bubble-menu': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) - '@tiptap/extension-floating-menu': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) - '@tiptap/pm': 2.2.4 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/extension-bubble-menu': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) + '@tiptap/extension-floating-menu': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) + '@tiptap/pm': 2.4.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - '@tiptap/starter-kit@2.2.4(@tiptap/pm@2.2.4)': + '@tiptap/starter-kit@2.4.0(@tiptap/pm@2.4.0)': dependencies: - '@tiptap/core': 2.2.4(@tiptap/pm@2.2.4) - '@tiptap/extension-blockquote': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-bold': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-bullet-list': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-code': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-code-block': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) - '@tiptap/extension-document': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-dropcursor': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) - '@tiptap/extension-gapcursor': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) - '@tiptap/extension-hard-break': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-heading': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-history': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) - '@tiptap/extension-horizontal-rule': 2.2.4(@tiptap/core@2.2.4)(@tiptap/pm@2.2.4) - '@tiptap/extension-italic': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-list-item': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-ordered-list': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-paragraph': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-strike': 2.2.4(@tiptap/core@2.2.4) - '@tiptap/extension-text': 2.2.4(@tiptap/core@2.2.4) + '@tiptap/core': 2.4.0(@tiptap/pm@2.4.0) + '@tiptap/extension-blockquote': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-bold': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-bullet-list': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-code': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-code-block': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) + '@tiptap/extension-document': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-dropcursor': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) + '@tiptap/extension-gapcursor': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) + '@tiptap/extension-hard-break': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-heading': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-history': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) + '@tiptap/extension-horizontal-rule': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0))(@tiptap/pm@2.4.0) + '@tiptap/extension-italic': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-list-item': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-ordered-list': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-paragraph': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-strike': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) + '@tiptap/extension-text': 2.4.0(@tiptap/core@2.4.0(@tiptap/pm@2.4.0)) transitivePeerDependencies: - '@tiptap/pm' @@ -3642,48 +3726,50 @@ snapshots: '@types/react': 18.2.74 csstype: 3.1.3 - '@types/stylis@4.2.0': {} + '@types/stylis@4.2.5': {} '@types/unist@3.0.2': {} '@types/uuid@9.0.8': {} - '@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.4)': + '@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4)': dependencies: - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.4) - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4 + '@typescript-eslint/scope-manager': 7.2.0 + '@typescript-eslint/types': 7.2.0 + '@typescript-eslint/typescript-estree': 7.2.0(typescript@5.4.4) + '@typescript-eslint/visitor-keys': 7.2.0 + debug: 4.3.5 eslint: 8.57.0 + optionalDependencies: typescript: 5.4.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@6.21.0': + '@typescript-eslint/scope-manager@7.2.0': dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 + '@typescript-eslint/types': 7.2.0 + '@typescript-eslint/visitor-keys': 7.2.0 - '@typescript-eslint/types@6.21.0': {} + '@typescript-eslint/types@7.2.0': {} - '@typescript-eslint/typescript-estree@6.21.0(typescript@5.4.4)': + '@typescript-eslint/typescript-estree@7.2.0(typescript@5.4.4)': dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4 + '@typescript-eslint/types': 7.2.0 + '@typescript-eslint/visitor-keys': 7.2.0 + debug: 4.3.5 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 - semver: 7.6.0 + semver: 7.6.2 ts-api-utils: 1.3.0(typescript@5.4.4) + optionalDependencies: typescript: 5.4.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@6.21.0': + '@typescript-eslint/visitor-keys@7.2.0': dependencies: - '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/types': 7.2.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} @@ -3724,7 +3810,7 @@ snapshots: aria-hidden@1.2.4: dependencies: - tslib: 2.6.2 + tslib: 2.6.3 aria-query@5.3.0: dependencies: @@ -3785,7 +3871,7 @@ snapshots: es-abstract: 1.23.3 es-shim-unscopables: 1.0.2 - array.prototype.tosorted@1.1.3: + array.prototype.tosorted@1.1.4: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 @@ -3809,10 +3895,10 @@ snapshots: autoprefixer@10.4.19(postcss@8.4.38): dependencies: browserslist: 4.23.0 - caniuse-lite: 1.0.30001606 + caniuse-lite: 1.0.30001629 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.0 + picocolors: 1.0.1 postcss: 8.4.38 postcss-value-parser: 4.2.0 @@ -3820,11 +3906,11 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 - avvvatars-react@0.4.2(csstype@3.1.3)(react-dom@18.2.0)(react@18.2.0): + avvvatars-react@0.4.2(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: goober: 2.1.14(csstype@3.1.3) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: - csstype @@ -3849,16 +3935,16 @@ snapshots: dependencies: balanced-match: 1.0.2 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 browserslist@4.23.0: dependencies: - caniuse-lite: 1.0.30001606 - electron-to-chromium: 1.4.728 + caniuse-lite: 1.0.30001629 + electron-to-chromium: 1.4.792 node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) + update-browserslist-db: 1.0.16(browserslist@4.23.0) buffer@6.0.3: dependencies: @@ -3883,7 +3969,7 @@ snapshots: camelize@1.0.1: {} - caniuse-lite@1.0.30001606: {} + caniuse-lite@1.0.30001629: {} chalk@4.1.2: dependencies: @@ -3893,7 +3979,7 @@ snapshots: chokidar@3.6.0: dependencies: anymatch: 3.1.3 - braces: 3.0.2 + braces: 3.0.3 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 @@ -3926,6 +4012,8 @@ snapshots: concat-map@0.0.1: {} + cookie@0.5.0: {} + crelt@1.0.6: {} cross-spawn@7.0.3: @@ -3950,8 +4038,6 @@ snapshots: cssesc@3.0.0: {} - csstype@3.1.2: {} - csstype@3.1.3: {} damerau-levenshtein@1.0.8: {} @@ -3974,7 +4060,7 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.1 - dayjs@1.11.10: {} + dayjs@1.11.11: {} debug@2.6.9: dependencies: @@ -3984,7 +4070,7 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.3.4: + debug@4.3.5: dependencies: ms: 2.1.2 @@ -4032,13 +4118,13 @@ snapshots: eastasianwidth@0.2.0: {} - electron-to-chromium@1.4.728: {} + electron-to-chromium@1.4.792: {} emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} - enhanced-resolve@5.16.0: + enhanced-resolve@5.17.0: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 @@ -4064,7 +4150,7 @@ snapshots: function.prototype.name: 1.1.6 get-intrinsic: 1.2.4 get-symbol-description: 1.0.2 - globalthis: 1.0.3 + globalthis: 1.0.4 gopd: 1.0.1 has-property-descriptors: 1.0.2 has-proto: 1.0.3 @@ -4102,7 +4188,7 @@ snapshots: es-errors@1.3.0: {} - es-iterator-helpers@1.0.18: + es-iterator-helpers@1.0.19: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 @@ -4111,7 +4197,7 @@ snapshots: es-set-tostringtag: 2.0.3 function-bind: 1.1.2 get-intrinsic: 1.2.4 - globalthis: 1.0.3 + globalthis: 1.0.4 has-property-descriptors: 1.0.2 has-proto: 1.0.3 has-symbols: 1.0.3 @@ -4143,18 +4229,19 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-next@14.1.4(eslint@8.57.0)(typescript@5.4.4): + eslint-config-next@14.2.3(eslint@8.57.0)(typescript@5.4.4): dependencies: - '@next/eslint-plugin-next': 14.1.4 - '@rushstack/eslint-patch': 1.10.1 - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.4) + '@next/eslint-plugin-next': 14.2.3 + '@rushstack/eslint-patch': 1.10.3 + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.4) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) - eslint-plugin-react: 7.34.1(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) + eslint-plugin-react: 7.34.2(eslint@8.57.0) + eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) + optionalDependencies: typescript: 5.4.4 transitivePeerDependencies: - eslint-import-resolver-webpack @@ -4168,15 +4255,15 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0): dependencies: - debug: 4.3.4 - enhanced-resolve: 5.16.0 + debug: 4.3.5 + enhanced-resolve: 5.17.0 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) fast-glob: 3.3.2 - get-tsconfig: 4.7.3 + get-tsconfig: 4.7.5 is-core-module: 2.13.1 is-glob: 4.0.3 transitivePeerDependencies: @@ -4185,19 +4272,19 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.4) debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.4) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.4) array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 @@ -4206,7 +4293,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -4216,6 +4303,8 @@ snapshots: object.values: 1.2.0 semver: 6.3.1 tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.4) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -4223,7 +4312,7 @@ snapshots: eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 aria-query: 5.3.0 array-includes: 3.1.8 array.prototype.flatmap: 1.3.2 @@ -4232,7 +4321,7 @@ snapshots: axobject-query: 3.2.1 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - es-iterator-helpers: 1.0.18 + es-iterator-helpers: 1.0.19 eslint: 8.57.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -4241,19 +4330,19 @@ snapshots: object.entries: 1.1.8 object.fromentries: 2.0.8 - eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): + eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): dependencies: eslint: 8.57.0 - eslint-plugin-react@7.34.1(eslint@8.57.0): + eslint-plugin-react@7.34.2(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 array.prototype.flatmap: 1.3.2 array.prototype.toreversed: 1.1.2 - array.prototype.tosorted: 1.1.3 + array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 - es-iterator-helpers: 1.0.18 + es-iterator-helpers: 1.0.19 eslint: 8.57.0 estraverse: 5.3.0 jsx-ast-utils: 3.3.5 @@ -4267,7 +4356,7 @@ snapshots: semver: 6.3.1 string.prototype.matchall: 4.0.11 - eslint-plugin-unused-imports@3.1.0(eslint@8.57.0): + eslint-plugin-unused-imports@3.2.0(eslint@8.57.0): dependencies: eslint: 8.57.0 eslint-rule-composer: 0.3.0 @@ -4284,7 +4373,7 @@ snapshots: eslint@8.57.0: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 + '@eslint-community/regexpp': 4.10.1 '@eslint/eslintrc': 2.1.4 '@eslint/js': 8.57.0 '@humanwhocodes/config-array': 0.11.14 @@ -4294,7 +4383,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.5 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -4318,7 +4407,7 @@ snapshots: lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 - optionator: 0.9.3 + optionator: 0.9.4 strip-ansi: 6.0.1 text-table: 0.2.0 transitivePeerDependencies: @@ -4350,7 +4439,7 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 fast-json-stable-stringify@2.1.0: {} @@ -4364,7 +4453,7 @@ snapshots: dependencies: flat-cache: 3.2.0 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -4390,27 +4479,27 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formik@2.4.5(react@18.2.0): + formik@2.4.6(react@18.3.1): dependencies: '@types/hoist-non-react-statics': 3.3.5 deepmerge: 2.2.1 hoist-non-react-statics: 3.3.2 lodash: 4.17.21 lodash-es: 4.17.21 - react: 18.2.0 + react: 18.3.1 react-fast-compare: 2.0.4 tiny-warning: 1.0.3 - tslib: 2.6.2 + tslib: 2.6.3 fraction.js@4.3.7: {} - framer-motion@10.18.0(react-dom@18.2.0)(react@18.2.0): + framer-motion@10.18.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - tslib: 2.6.2 + tslib: 2.6.3 optionalDependencies: '@emotion/is-prop-valid': 0.8.8 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) fs.realpath@1.0.0: {} @@ -4446,7 +4535,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 - get-tsconfig@4.7.3: + get-tsconfig@4.7.5: dependencies: resolve-pkg-maps: 1.0.0 @@ -4465,16 +4554,16 @@ snapshots: foreground-child: 3.1.1 jackspeak: 2.3.6 minimatch: 9.0.4 - minipass: 7.0.4 - path-scurry: 1.10.2 + minipass: 7.1.2 + path-scurry: 1.11.1 - glob@10.3.12: + glob@10.4.1: dependencies: foreground-child: 3.1.1 - jackspeak: 2.3.6 + jackspeak: 3.4.0 minimatch: 9.0.4 - minipass: 7.0.4 - path-scurry: 1.10.2 + minipass: 7.1.2 + path-scurry: 1.11.1 glob@7.2.3: dependencies: @@ -4489,9 +4578,10 @@ snapshots: dependencies: type-fest: 0.20.2 - globalthis@1.0.3: + globalthis@1.0.4: dependencies: define-properties: 1.2.1 + gopd: 1.0.1 globby@11.1.0: dependencies: @@ -4688,8 +4778,16 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jackspeak@3.4.0: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jiti@1.21.0: {} + jose@4.15.5: {} + js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -4721,18 +4819,18 @@ snapshots: dependencies: json-buffer: 3.0.1 - language-subtag-registry@0.3.22: {} + language-subtag-registry@0.3.23: {} language-tags@1.0.9: dependencies: - language-subtag-registry: 0.3.22 + language-subtag-registry: 0.3.23 levn@0.4.1: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - lib0@0.2.93: + lib0@0.2.94: dependencies: isomorphic.js: 0.2.5 @@ -4768,15 +4866,15 @@ snapshots: devlop: 1.1.0 highlight.js: 11.9.0 - lru-cache@10.2.0: {} + lru-cache@10.2.2: {} lru-cache@6.0.0: dependencies: yallist: 4.0.0 - lucide-react@0.363.0(react@18.2.0): + lucide-react@0.363.0(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 markdown-it@14.1.0: dependencies: @@ -4793,9 +4891,9 @@ snapshots: merge2@1.4.1: {} - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 minimatch@3.1.2: @@ -4812,7 +4910,7 @@ snapshots: minimist@1.2.8: {} - minipass@7.0.4: {} + minipass@7.1.2: {} ms@2.0.0: {} @@ -4830,17 +4928,32 @@ snapshots: natural-compare@1.4.0: {} - next@14.2.3(react-dom@18.2.0)(react@18.2.0): + next-auth@4.24.7(next@14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/runtime': 7.24.7 + '@panva/hkdf': 1.1.1 + cookie: 0.5.0 + jose: 4.15.5 + next: 14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + oauth: 0.9.15 + openid-client: 5.6.5 + preact: 10.22.0 + preact-render-to-string: 5.2.6(preact@10.22.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + uuid: 8.3.2 + + next@14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.2.3 '@swc/helpers': 0.5.5 busboy: 1.6.0 - caniuse-lite: 1.0.30001606 + caniuse-lite: 1.0.30001629 graceful-fs: 4.2.11 postcss: 8.4.31 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.1(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.1(react@18.3.1) optionalDependencies: '@next/swc-darwin-arm64': 14.2.3 '@next/swc-darwin-x64': 14.2.3 @@ -4861,8 +4974,12 @@ snapshots: normalize-range@0.1.2: {} + oauth@0.9.15: {} + object-assign@4.1.1: {} + object-hash@2.2.0: {} + object-hash@3.0.0: {} object-inspect@1.13.1: {} @@ -4907,18 +5024,27 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 + oidc-token-hash@5.0.3: {} + once@1.4.0: dependencies: wrappy: 1.0.2 - optionator@0.9.3: + openid-client@5.6.5: + dependencies: + jose: 4.15.5 + lru-cache: 6.0.0 + object-hash: 2.2.0 + oidc-token-hash: 5.0.3 + + optionator@0.9.4: dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 + word-wrap: 1.2.5 orderedmap@2.1.1: {} @@ -4942,14 +5068,14 @@ snapshots: path-parse@1.0.7: {} - path-scurry@1.10.2: + path-scurry@1.11.1: dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 + lru-cache: 10.2.2 + minipass: 7.1.2 path-type@4.0.0: {} - picocolors@1.0.0: {} + picocolors@1.0.1: {} picomatch@2.3.1: {} @@ -4974,15 +5100,16 @@ snapshots: postcss-load-config@4.0.2(postcss@8.4.38): dependencies: lilconfig: 3.1.1 + yaml: 2.4.3 + optionalDependencies: postcss: 8.4.38 - yaml: 2.4.1 postcss-nested@6.0.1(postcss@8.4.38): dependencies: postcss: 8.4.38 - postcss-selector-parser: 6.0.16 + postcss-selector-parser: 6.1.0 - postcss-selector-parser@6.0.16: + postcss-selector-parser@6.1.0: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 @@ -4992,17 +5119,26 @@ snapshots: postcss@8.4.31: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 + picocolors: 1.0.1 source-map-js: 1.2.0 postcss@8.4.38: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 + picocolors: 1.0.1 source-map-js: 1.2.0 + preact-render-to-string@5.2.6(preact@10.22.0): + dependencies: + preact: 10.22.0 + pretty-format: 3.8.0 + + preact@10.22.0: {} + prelude-ls@1.2.1: {} + pretty-format@3.8.0: {} + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -5011,7 +5147,7 @@ snapshots: prosemirror-changeset@2.2.1: dependencies: - prosemirror-transform: 1.8.0 + prosemirror-transform: 1.9.0 prosemirror-collab@1.3.1: dependencies: @@ -5019,44 +5155,44 @@ snapshots: prosemirror-commands@1.5.2: dependencies: - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 + prosemirror-transform: 1.9.0 prosemirror-dropcursor@1.8.1: dependencies: prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 - prosemirror-view: 1.33.3 + prosemirror-transform: 1.9.0 + prosemirror-view: 1.33.7 prosemirror-gapcursor@1.3.2: dependencies: prosemirror-keymap: 1.2.2 - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 prosemirror-state: 1.4.3 - prosemirror-view: 1.33.3 + prosemirror-view: 1.33.7 prosemirror-history@1.4.0: dependencies: prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 - prosemirror-view: 1.33.3 + prosemirror-transform: 1.9.0 + prosemirror-view: 1.33.7 rope-sequence: 1.3.4 prosemirror-inputrules@1.4.0: dependencies: prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 + prosemirror-transform: 1.9.0 prosemirror-keymap@1.2.2: dependencies: prosemirror-state: 1.4.3 w3c-keyname: 2.2.8 - prosemirror-markdown@1.12.0: + prosemirror-markdown@1.13.0: dependencies: markdown-it: 14.1.0 - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 prosemirror-menu@1.2.4: dependencies: @@ -5065,51 +5201,51 @@ snapshots: prosemirror-history: 1.4.0 prosemirror-state: 1.4.3 - prosemirror-model@1.19.4: + prosemirror-model@1.21.1: dependencies: orderedmap: 2.1.1 prosemirror-schema-basic@1.2.2: dependencies: - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 prosemirror-schema-list@1.3.0: dependencies: - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 + prosemirror-transform: 1.9.0 prosemirror-state@1.4.3: dependencies: - prosemirror-model: 1.19.4 - prosemirror-transform: 1.8.0 - prosemirror-view: 1.33.3 + prosemirror-model: 1.21.1 + prosemirror-transform: 1.9.0 + prosemirror-view: 1.33.7 prosemirror-tables@1.3.7: dependencies: prosemirror-keymap: 1.2.2 - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 - prosemirror-view: 1.33.3 + prosemirror-transform: 1.9.0 + prosemirror-view: 1.33.7 - prosemirror-trailing-node@2.0.8(prosemirror-model@1.19.4)(prosemirror-state@1.4.3)(prosemirror-view@1.33.3): + prosemirror-trailing-node@2.0.8(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7): dependencies: '@remirror/core-constants': 2.0.2 escape-string-regexp: 4.0.0 - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 prosemirror-state: 1.4.3 - prosemirror-view: 1.33.3 + prosemirror-view: 1.33.7 - prosemirror-transform@1.8.0: + prosemirror-transform@1.9.0: dependencies: - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 - prosemirror-view@1.33.3: + prosemirror-view@1.33.7: dependencies: - prosemirror-model: 1.19.4 + prosemirror-model: 1.21.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 + prosemirror-transform: 1.9.0 punycode.js@2.3.1: {} @@ -5125,43 +5261,43 @@ snapshots: randomcolor@0.6.2: {} - re-resizable@6.9.11(react-dom@18.2.0)(react@18.2.0): + re-resizable@6.9.17(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-beautiful-dnd@13.1.1(react-dom@18.2.0)(react@18.2.0): + react-beautiful-dnd@13.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 css-box-model: 1.2.1 memoize-one: 5.2.1 raf-schd: 4.0.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-redux: 7.2.9(react-dom@18.2.0)(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-redux: 7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) redux: 4.2.1 - use-memo-one: 1.1.3(react@18.2.0) + use-memo-one: 1.1.3(react@18.3.1) transitivePeerDependencies: - react-native - react-confetti@6.1.0(react@18.2.0): + react-confetti@6.1.0(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 tween-functions: 1.2.0 - react-dom@18.2.0(react@18.2.0): + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 + react: 18.3.1 + scheduler: 0.23.2 react-fast-compare@2.0.4: {} - react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@18.2.0)(react@18.2.0): + react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: goober: 2.1.14(csstype@3.1.3) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: - csstype @@ -5169,63 +5305,67 @@ snapshots: react-is@17.0.2: {} - react-katex@3.0.1(prop-types@15.8.1)(react@18.2.0): + react-katex@3.0.1(prop-types@15.8.1)(react@18.3.1): dependencies: katex: 0.16.10 prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 - react-redux@7.2.9(react-dom@18.2.0)(react@18.2.0): + react-redux@7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 '@types/react-redux': 7.1.33 hoist-non-react-statics: 3.3.2 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 react-is: 17.0.2 + optionalDependencies: + react-dom: 18.3.1(react@18.3.1) - react-remove-scroll-bar@2.3.6(@types/react@18.2.74)(react@18.2.0): + react-remove-scroll-bar@2.3.6(@types/react@18.2.74)(react@18.3.1): dependencies: + react: 18.3.1 + react-style-singleton: 2.2.1(@types/react@18.2.74)(react@18.3.1) + tslib: 2.6.3 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - react-style-singleton: 2.2.1(@types/react@18.2.74)(react@18.2.0) - tslib: 2.6.2 - react-remove-scroll@2.5.5(@types/react@18.2.74)(react@18.2.0): + react-remove-scroll@2.5.5(@types/react@18.2.74)(react@18.3.1): dependencies: + react: 18.3.1 + react-remove-scroll-bar: 2.3.6(@types/react@18.2.74)(react@18.3.1) + react-style-singleton: 2.2.1(@types/react@18.2.74)(react@18.3.1) + tslib: 2.6.3 + use-callback-ref: 1.3.2(@types/react@18.2.74)(react@18.3.1) + use-sidecar: 1.1.2(@types/react@18.2.74)(react@18.3.1) + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - react-remove-scroll-bar: 2.3.6(@types/react@18.2.74)(react@18.2.0) - react-style-singleton: 2.2.1(@types/react@18.2.74)(react@18.2.0) - tslib: 2.6.2 - use-callback-ref: 1.3.2(@types/react@18.2.74)(react@18.2.0) - use-sidecar: 1.1.2(@types/react@18.2.74)(react@18.2.0) - react-spinners@0.13.8(react-dom@18.2.0)(react@18.2.0): + react-spinners@0.13.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-style-singleton@2.2.1(@types/react@18.2.74)(react@18.2.0): + react-style-singleton@2.2.1(@types/react@18.2.74)(react@18.3.1): dependencies: - '@types/react': 18.2.74 get-nonce: 1.0.1 invariant: 2.2.4 - react: 18.2.0 - tslib: 2.6.2 + react: 18.3.1 + tslib: 2.6.3 + optionalDependencies: + '@types/react': 18.2.74 - react-youtube@10.1.0(react@18.2.0): + react-youtube@10.1.0(react@18.3.1): dependencies: fast-deep-equal: 3.1.3 prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 youtube-player: 5.5.2 transitivePeerDependencies: - supports-color - react@18.2.0: + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -5245,7 +5385,7 @@ snapshots: redux@4.2.1: dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 reflect.getprototypeof@1.0.6: dependencies: @@ -5254,7 +5394,7 @@ snapshots: es-abstract: 1.23.3 es-errors: 1.3.0 get-intrinsic: 1.2.4 - globalthis: 1.0.3 + globalthis: 1.0.4 which-builtin-type: 1.1.3 regenerator-runtime@0.14.1: {} @@ -5309,15 +5449,13 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 - scheduler@0.23.0: + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 semver@6.3.1: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.6.2: {} set-function-length@1.2.2: dependencies: @@ -5337,14 +5475,14 @@ snapshots: shallowequal@1.1.0: {} - sharp@0.33.3: + sharp@0.33.4: dependencies: color: 4.2.3 detect-libc: 2.0.3 - semver: 7.6.0 + semver: 7.6.2 optionalDependencies: - '@img/sharp-darwin-arm64': 0.33.3 - '@img/sharp-darwin-x64': 0.33.3 + '@img/sharp-darwin-arm64': 0.33.4 + '@img/sharp-darwin-x64': 0.33.4 '@img/sharp-libvips-darwin-arm64': 1.0.2 '@img/sharp-libvips-darwin-x64': 1.0.2 '@img/sharp-libvips-linux-arm': 1.0.2 @@ -5353,15 +5491,15 @@ snapshots: '@img/sharp-libvips-linux-x64': 1.0.2 '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 '@img/sharp-libvips-linuxmusl-x64': 1.0.2 - '@img/sharp-linux-arm': 0.33.3 - '@img/sharp-linux-arm64': 0.33.3 - '@img/sharp-linux-s390x': 0.33.3 - '@img/sharp-linux-x64': 0.33.3 - '@img/sharp-linuxmusl-arm64': 0.33.3 - '@img/sharp-linuxmusl-x64': 0.33.3 - '@img/sharp-wasm32': 0.33.3 - '@img/sharp-win32-ia32': 0.33.3 - '@img/sharp-win32-x64': 0.33.3 + '@img/sharp-linux-arm': 0.33.4 + '@img/sharp-linux-arm64': 0.33.4 + '@img/sharp-linux-s390x': 0.33.4 + '@img/sharp-linux-x64': 0.33.4 + '@img/sharp-linuxmusl-arm64': 0.33.4 + '@img/sharp-linuxmusl-x64': 0.33.4 + '@img/sharp-wasm32': 0.33.4 + '@img/sharp-win32-ia32': 0.33.4 + '@img/sharp-win32-x64': 0.33.4 shebang-command@2.0.0: dependencies: @@ -5381,7 +5519,7 @@ snapshots: simple-peer@9.11.1: dependencies: buffer: 6.0.3 - debug: 4.3.4 + debug: 4.3.5 err-code: 3.0.1 get-browser-rtc: 1.1.0 queue-microtask: 1.2.3 @@ -5464,32 +5602,32 @@ snapshots: strip-json-comments@3.1.1: {} - styled-components@6.1.8(react-dom@18.2.0)(react@18.2.0): + styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@emotion/is-prop-valid': 1.2.1 - '@emotion/unitless': 0.8.0 - '@types/stylis': 4.2.0 + '@emotion/is-prop-valid': 1.2.2 + '@emotion/unitless': 0.8.1 + '@types/stylis': 4.2.5 css-to-react-native: 3.2.0 - csstype: 3.1.2 - postcss: 8.4.31 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + csstype: 3.1.3 + postcss: 8.4.38 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) shallowequal: 1.1.0 - stylis: 4.3.1 - tslib: 2.5.0 + stylis: 4.3.2 + tslib: 2.6.2 - styled-jsx@5.1.1(react@18.2.0): + styled-jsx@5.1.1(react@18.3.1): dependencies: client-only: 0.0.1 - react: 18.2.0 + react: 18.3.1 - stylis@4.3.1: {} + stylis@4.3.2: {} sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.5 commander: 4.1.1 - glob: 10.3.12 + glob: 10.4.1 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.6 @@ -5501,21 +5639,21 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - swr@2.2.5(react@18.2.0): + swr@2.2.5(react@18.3.1): dependencies: client-only: 0.0.1 - react: 18.2.0 - use-sync-external-store: 1.2.0(react@18.2.0) + react: 18.3.1 + use-sync-external-store: 1.2.2(react@18.3.1) - tailwind-merge@2.2.2: + tailwind-merge@2.3.0: dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.7 - tailwind-scrollbar@3.1.0(tailwindcss@3.4.3): + tailwind-scrollbar@3.1.0(tailwindcss@3.4.4): dependencies: - tailwindcss: 3.4.3 + tailwindcss: 3.4.4 - tailwindcss@3.4.3: + tailwindcss@3.4.4: dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -5527,16 +5665,16 @@ snapshots: is-glob: 4.0.3 jiti: 1.21.0 lilconfig: 2.1.0 - micromatch: 4.0.5 + micromatch: 4.0.7 normalize-path: 3.0.0 object-hash: 3.0.0 - picocolors: 1.0.0 + picocolors: 1.0.1 postcss: 8.4.38 postcss-import: 15.1.0(postcss@8.4.38) postcss-js: 4.0.1(postcss@8.4.38) postcss-load-config: 4.0.2(postcss@8.4.38) postcss-nested: 6.0.1(postcss@8.4.38) - postcss-selector-parser: 6.0.16 + postcss-selector-parser: 6.1.0 resolve: 1.22.8 sucrase: 3.35.0 transitivePeerDependencies: @@ -5579,10 +5717,10 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 - tslib@2.5.0: {} - tslib@2.6.2: {} + tslib@2.6.3: {} + tween-functions@1.2.0: {} type-check@0.4.0: @@ -5636,39 +5774,43 @@ snapshots: undici-types@5.26.5: {} - update-browserslist-db@1.0.13(browserslist@4.23.0): + update-browserslist-db@1.0.16(browserslist@4.23.0): dependencies: browserslist: 4.23.0 escalade: 3.1.2 - picocolors: 1.0.0 + picocolors: 1.0.1 uri-js@4.4.1: dependencies: punycode: 2.3.1 - use-callback-ref@1.3.2(@types/react@18.2.74)(react@18.2.0): + use-callback-ref@1.3.2(@types/react@18.2.74)(react@18.3.1): dependencies: + react: 18.3.1 + tslib: 2.6.3 + optionalDependencies: '@types/react': 18.2.74 - react: 18.2.0 - tslib: 2.6.2 - use-memo-one@1.1.3(react@18.2.0): + use-memo-one@1.1.3(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 - use-sidecar@1.1.2(@types/react@18.2.74)(react@18.2.0): + use-sidecar@1.1.2(@types/react@18.2.74)(react@18.3.1): dependencies: - '@types/react': 18.2.74 detect-node-es: 1.1.0 - react: 18.2.0 - tslib: 2.6.2 + react: 18.3.1 + tslib: 2.6.3 + optionalDependencies: + '@types/react': 18.2.74 - use-sync-external-store@1.2.0(react@18.2.0): + use-sync-external-store@1.2.2(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 util-deprecate@1.0.2: {} + uuid@8.3.2: {} + uuid@9.0.1: {} w3c-keyname@2.2.8: {} @@ -5715,6 +5857,8 @@ snapshots: dependencies: isexe: 2.0.0 + word-wrap@1.2.5: {} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -5729,35 +5873,35 @@ snapshots: wrappy@1.0.2: {} - ws@8.16.0: {} + ws@8.17.0: {} - y-indexeddb@9.0.12(yjs@13.6.14): + y-indexeddb@9.0.12(yjs@13.6.15): dependencies: - lib0: 0.2.93 - yjs: 13.6.14 + lib0: 0.2.94 + yjs: 13.6.15 - y-prosemirror@1.2.3(prosemirror-model@1.19.4)(prosemirror-state@1.4.3)(prosemirror-view@1.33.3)(y-protocols@1.0.6)(yjs@13.6.14): + y-prosemirror@1.2.5(prosemirror-model@1.21.1)(prosemirror-state@1.4.3)(prosemirror-view@1.33.7)(y-protocols@1.0.6(yjs@13.6.15))(yjs@13.6.15): dependencies: - lib0: 0.2.93 - prosemirror-model: 1.19.4 + lib0: 0.2.94 + prosemirror-model: 1.21.1 prosemirror-state: 1.4.3 - prosemirror-view: 1.33.3 - y-protocols: 1.0.6(yjs@13.6.14) - yjs: 13.6.14 + prosemirror-view: 1.33.7 + y-protocols: 1.0.6(yjs@13.6.15) + yjs: 13.6.15 - y-protocols@1.0.6(yjs@13.6.14): + y-protocols@1.0.6(yjs@13.6.15): dependencies: - lib0: 0.2.93 - yjs: 13.6.14 + lib0: 0.2.94 + yjs: 13.6.15 - y-webrtc@10.3.0(yjs@13.6.14): + y-webrtc@10.3.0(yjs@13.6.15): dependencies: - lib0: 0.2.93 + lib0: 0.2.94 simple-peer: 9.11.1 - y-protocols: 1.0.6(yjs@13.6.14) - yjs: 13.6.14 + y-protocols: 1.0.6(yjs@13.6.15) + yjs: 13.6.15 optionalDependencies: - ws: 8.16.0 + ws: 8.17.0 transitivePeerDependencies: - bufferutil - supports-color @@ -5765,11 +5909,11 @@ snapshots: yallist@4.0.0: {} - yaml@2.4.1: {} + yaml@2.4.3: {} - yjs@13.6.14: + yjs@13.6.15: dependencies: - lib0: 0.2.93 + lib0: 0.2.94 yocto-queue@0.1.0: {} diff --git a/apps/web/services/ai/ai.ts b/apps/web/services/ai/ai.ts index 4d1542ce..e9707f6e 100644 --- a/apps/web/services/ai/ai.ts +++ b/apps/web/services/ai/ai.ts @@ -1,9 +1,10 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody } from '@services/utils/ts/requests' +import { RequestBodyWithAuthHeader } from '@services/utils/ts/requests' export async function startActivityAIChatSession( message: string, - activity_uuid: string + access_token: string, + activity_uuid?: string ) { const data = { message, @@ -11,7 +12,7 @@ export async function startActivityAIChatSession( } const result = await fetch( `${getAPIUrl()}ai/start/activity_chat_session`, - RequestBody('POST', data, null) + RequestBodyWithAuthHeader('POST', data, null, access_token) ) const json = await result.json() if (result.status === 200) { @@ -34,7 +35,8 @@ export async function startActivityAIChatSession( export async function sendActivityAIChatMessage( message: string, aichat_uuid: string, - activity_uuid: string + activity_uuid: string, + access_token: string ) { const data = { aichat_uuid, @@ -43,7 +45,7 @@ export async function sendActivityAIChatMessage( } const result = await fetch( `${getAPIUrl()}ai/send/activity_chat_message`, - RequestBody('POST', data, null) + RequestBodyWithAuthHeader('POST', data, null, access_token) ) const json = await result.json() diff --git a/apps/web/services/auth/auth.ts b/apps/web/services/auth/auth.ts index bb3e6ef0..5e181fac 100644 --- a/apps/web/services/auth/auth.ts +++ b/apps/web/services/auth/auth.ts @@ -10,8 +10,8 @@ interface LoginAndGetTokenResponse { // TODO : everything in this file need to be refactored including security issues fix export async function loginAndGetToken( - username: string, - password: string + username: any, + password: any ): Promise { // Request Config @@ -37,6 +37,37 @@ export async function loginAndGetToken( return response } +export async function loginWithOAuthToken( + email: any, + provider: any, + accessToken: string +): Promise { + // Request Config + + // get origin + const HeadersConfig = new Headers({ + 'Content-Type': 'application/json', + }) + const body = { + email: email, + provider: provider, + access_token: accessToken, + } + const jsonBody = JSON.stringify(body); + + const requestOptions: any = { + method: 'POST', + headers: HeadersConfig, + body: jsonBody, + redirect: 'follow', + credentials: 'include', + } + + // fetch using await and async + const response = await fetch(`${getAPIUrl()}auth/oauth`, requestOptions) + return response +} + export async function sendResetLink(email: string, org_id: number) { const result = await fetch( `${getAPIUrl()}users/reset_password/send_reset_code/${email}?org_id=${org_id}`, @@ -102,10 +133,8 @@ export async function getUserInfo(token: string): Promise { } export async function getUserSession(token: string): Promise { - const origin = window.location.origin const HeadersConfig = new Headers({ Authorization: `Bearer ${token}`, - Origin: origin, }) const requestOptions: any = { diff --git a/apps/web/services/blocks/Image/images.ts b/apps/web/services/blocks/Image/images.ts index 6a578adf..65331e91 100644 --- a/apps/web/services/blocks/Image/images.ts +++ b/apps/web/services/blocks/Image/images.ts @@ -1,7 +1,14 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody, RequestBodyForm } from '@services/utils/ts/requests' +import { + RequestBodyFormWithAuthHeader, + RequestBodyWithAuthHeader, +} from '@services/utils/ts/requests' -export async function uploadNewImageFile(file: any, activity_uuid: string) { +export async function uploadNewImageFile( + file: any, + activity_uuid: string, + access_token: string +) { // Send file thumbnail as form data const formData = new FormData() formData.append('file_object', file) @@ -9,17 +16,17 @@ export async function uploadNewImageFile(file: any, activity_uuid: string) { return fetch( `${getAPIUrl()}blocks/image`, - RequestBodyForm('POST', formData, null) + RequestBodyFormWithAuthHeader('POST', formData, null, access_token) ) .then((result) => result.json()) .catch((error) => console.log('error', error)) } -export async function getImageFile(file_id: string) { +export async function getImageFile(file_id: string, access_token: string) { // todo : add course id to url return fetch( `${getAPIUrl()}blocks/image?file_id=${file_id}`, - RequestBody('GET', null, null) + RequestBodyWithAuthHeader('GET', null, null, access_token) ) .then((result) => result.json()) .catch((error) => console.log('error', error)) diff --git a/apps/web/services/blocks/Pdf/pdf.ts b/apps/web/services/blocks/Pdf/pdf.ts index 06b053c7..1f93ce5d 100644 --- a/apps/web/services/blocks/Pdf/pdf.ts +++ b/apps/web/services/blocks/Pdf/pdf.ts @@ -1,7 +1,14 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody, RequestBodyForm } from '@services/utils/ts/requests' +import { + RequestBodyFormWithAuthHeader, + RequestBodyWithAuthHeader, +} from '@services/utils/ts/requests' -export async function uploadNewPDFFile(file: any, activity_uuid: string) { +export async function uploadNewPDFFile( + file: any, + activity_uuid: string, + access_token: string +) { // Send file thumbnail as form data const formData = new FormData() formData.append('file_object', file) @@ -9,17 +16,17 @@ export async function uploadNewPDFFile(file: any, activity_uuid: string) { return fetch( `${getAPIUrl()}blocks/pdf`, - RequestBodyForm('POST', formData, null) + RequestBodyFormWithAuthHeader('POST', formData, null, access_token) ) .then((result) => result.json()) .catch((error) => console.log('error', error)) } -export async function getPDFFile(file_id: string) { +export async function getPDFFile(file_id: string, access_token: string) { // todo : add course id to url return fetch( `${getAPIUrl()}blocks/pdf?file_id=${file_id}`, - RequestBody('GET', null, null) + RequestBodyWithAuthHeader('GET', null, null, access_token) ) .then((result) => result.json()) .catch((error) => console.log('error', error)) diff --git a/apps/web/services/blocks/Quiz/quiz.ts b/apps/web/services/blocks/Quiz/quiz.ts index 0928ffd5..b9acae06 100644 --- a/apps/web/services/blocks/Quiz/quiz.ts +++ b/apps/web/services/blocks/Quiz/quiz.ts @@ -1,10 +1,10 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody } from '@services/utils/ts/requests' +import { RequestBodyWithAuthHeader } from '@services/utils/ts/requests' -export async function submitQuizBlock(activity_id: string, data: any) { +export async function submitQuizBlock(activity_id: string, data: any,access_token:string) { const result: any = await fetch( `${getAPIUrl()}blocks/quiz/${activity_id}"`, - RequestBody('POST', data, null) + RequestBodyWithAuthHeader('POST', data, null,access_token) ) .then((result) => result.json()) .catch((error) => console.log('error', error)) diff --git a/apps/web/services/blocks/Video/video.ts b/apps/web/services/blocks/Video/video.ts index fff4a502..6082b080 100644 --- a/apps/web/services/blocks/Video/video.ts +++ b/apps/web/services/blocks/Video/video.ts @@ -1,7 +1,14 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody, RequestBodyForm } from '@services/utils/ts/requests' +import { + RequestBodyFormWithAuthHeader, + RequestBodyWithAuthHeader, +} from '@services/utils/ts/requests' -export async function uploadNewVideoFile(file: any, activity_uuid: string) { +export async function uploadNewVideoFile( + file: any, + activity_uuid: string, + access_token: string +) { // Send file thumbnail as form data const formData = new FormData() formData.append('file_object', file) @@ -9,17 +16,17 @@ export async function uploadNewVideoFile(file: any, activity_uuid: string) { return fetch( `${getAPIUrl()}blocks/video`, - RequestBodyForm('POST', formData, null) + RequestBodyFormWithAuthHeader('POST', formData, null, access_token) ) .then((result) => result.json()) - .catch((error) => console.log('error', error)) + .catch((error) => console.error('error', error)) } -export async function getVideoFile(file_id: string) { +export async function getVideoFile(file_id: string, access_token: string) { return fetch( `${getAPIUrl()}blocks/video?file_id=${file_id}`, - RequestBody('GET', null, null) + RequestBodyWithAuthHeader('GET', null, null, access_token) ) .then((result) => result.json()) - .catch((error) => console.log('error', error)) + .catch((error) => console.error('error', error)) } diff --git a/apps/web/services/config/config.ts b/apps/web/services/config/config.ts index a66812d5..c9ec36d0 100644 --- a/apps/web/services/config/config.ts +++ b/apps/web/services/config/config.ts @@ -3,6 +3,8 @@ export const LEARNHOUSE_HTTP_PROTOCOL = const LEARNHOUSE_API_URL = `${process.env.NEXT_PUBLIC_LEARNHOUSE_API_URL}` export const LEARNHOUSE_BACKEND_URL = `${process.env.NEXT_PUBLIC_LEARNHOUSE_BACKEND_URL}` export const LEARNHOUSE_DOMAIN = process.env.NEXT_PUBLIC_LEARNHOUSE_DOMAIN +export const LEARNHOUSE_TOP_DOMAIN = + process.env.NEXT_PUBLIC_LEARNHOUSE_TOP_DOMAIN export const LEARNHOUSE_COLLABORATION_WS_URL = process.env.NEXT_PUBLIC_LEARNHOUSE_COLLABORATION_WS_URL @@ -21,6 +23,14 @@ export const getUriWithOrg = (orgslug: string, path: string) => { return `${LEARNHOUSE_HTTP_PROTOCOL}${LEARNHOUSE_DOMAIN}${path}` } +export const getUriWithoutOrg = (path: string) => { + const multi_org = isMultiOrgModeEnabled() + if (multi_org) { + return `${LEARNHOUSE_HTTP_PROTOCOL}${LEARNHOUSE_DOMAIN}${path}` + } + return `${LEARNHOUSE_HTTP_PROTOCOL}${LEARNHOUSE_DOMAIN}${path}` +} + export const getOrgFromUri = () => { const multi_org = isMultiOrgModeEnabled() if (multi_org) { diff --git a/apps/web/services/courses/activities.ts b/apps/web/services/courses/activities.ts index 1c8748a9..1fa050f0 100644 --- a/apps/web/services/courses/activities.ts +++ b/apps/web/services/courses/activities.ts @@ -1,18 +1,22 @@ import { getAPIUrl } from '@services/config/config' import { - RequestBody, - RequestBodyForm, + RequestBodyFormWithAuthHeader, RequestBodyWithAuthHeader, } from '@services/utils/ts/requests' -export async function createActivity(data: any, chapter_id: any, org_id: any) { +export async function createActivity( + data: any, + chapter_id: any, + org_id: any, + access_token: string +) { data.content = {} // remove chapter_id from data delete data.chapterId const result = await fetch( `${getAPIUrl()}activities/?coursechapter_id=${chapter_id}&org_id=${org_id}`, - RequestBody('POST', data, null) + RequestBodyWithAuthHeader('POST', data, null, access_token) ) const res = await result.json() return res @@ -22,7 +26,8 @@ export async function createFileActivity( file: File, type: string, data: any, - chapter_id: any + chapter_id: any, + access_token: string ) { // Send file thumbnail as form data const formData = new FormData() @@ -44,7 +49,7 @@ export async function createFileActivity( const result: any = await fetch( endpoint, - RequestBodyForm('POST', formData, null) + RequestBodyFormWithAuthHeader('POST', formData, null, access_token) ) const res = await result.json() return res @@ -53,7 +58,8 @@ export async function createFileActivity( export async function createExternalVideoActivity( data: any, activity: any, - chapter_id: any + chapter_id: any, + access_token: string ) { // add coursechapter_id to data data.chapter_id = chapter_id @@ -61,25 +67,29 @@ export async function createExternalVideoActivity( const result = await fetch( `${getAPIUrl()}activities/external_video`, - RequestBody('POST', data, null) + RequestBodyWithAuthHeader('POST', data, null, access_token) ) const res = await result.json() return res } -export async function getActivity(activity_id: any, next: any) { +export async function getActivity( + activity_id: any, + next: any, + access_token: string +) { const result = await fetch( `${getAPIUrl()}activities/${activity_id}`, - RequestBody('GET', null, next) + RequestBodyWithAuthHeader('GET', null, next, access_token) ) const res = await result.json() return res } -export async function deleteActivity(activity_id: any) { +export async function deleteActivity(activity_id: any, access_token: string) { const result = await fetch( `${getAPIUrl()}activities/${activity_id}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) ) const res = await result.json() return res @@ -98,10 +108,14 @@ export async function getActivityWithAuthHeader( return res } -export async function updateActivity(data: any, activity_uuid: string) { +export async function updateActivity( + data: any, + activity_uuid: string, + access_token: string +) { const result = await fetch( `${getAPIUrl()}activities/${activity_uuid}`, - RequestBody('PUT', data, null) + RequestBodyWithAuthHeader('PUT', data, null, access_token) ) const res = await result.json() return res diff --git a/apps/web/services/courses/activity.ts b/apps/web/services/courses/activity.ts index 8b0e7838..35240cf5 100644 --- a/apps/web/services/courses/activity.ts +++ b/apps/web/services/courses/activity.ts @@ -1,4 +1,4 @@ -import { RequestBody, errorHandling } from '@services/utils/ts/requests' +import { RequestBodyWithAuthHeader, errorHandling } from '@services/utils/ts/requests' import { getAPIUrl } from '@services/config/config' /* @@ -6,19 +6,19 @@ import { getAPIUrl } from '@services/config/config' GET requests are called from the frontend using SWR (https://swr.vercel.app/) */ -export async function startCourse(course_uuid: string, org_slug: string) { +export async function startCourse(course_uuid: string, org_slug: string,access_token:any) { const result: any = await fetch( `${getAPIUrl()}trail/add_course/${course_uuid}`, - RequestBody('POST', null, null) + RequestBodyWithAuthHeader('POST', null, null,access_token) ) const res = await errorHandling(result) return res } -export async function removeCourse(course_uuid: string, org_slug: string) { +export async function removeCourse(course_uuid: string, org_slug: string,access_token:any) { const result: any = await fetch( `${getAPIUrl()}trail/remove_course/${course_uuid}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null,access_token) ) const res = await errorHandling(result) return res @@ -27,11 +27,11 @@ export async function removeCourse(course_uuid: string, org_slug: string) { export async function markActivityAsComplete( org_slug: string, course_uuid: string, - activity_uuid: string + activity_uuid: string,access_token:any ) { const result: any = await fetch( `${getAPIUrl()}trail/add_activity/${activity_uuid}`, - RequestBody('POST', null, null) + RequestBodyWithAuthHeader('POST', null, null,access_token) ) const res = await errorHandling(result) return res diff --git a/apps/web/services/courses/chapters.ts b/apps/web/services/courses/chapters.ts index 58ed5d1f..f04c5b37 100644 --- a/apps/web/services/courses/chapters.ts +++ b/apps/web/services/courses/chapters.ts @@ -1,6 +1,9 @@ import { OrderPayload } from '@components/Dashboard/Course/EditCourseStructure/EditCourseStructure' import { getAPIUrl } from '@services/config/config' -import { RequestBody, errorHandling } from '@services/utils/ts/requests' +import { + RequestBodyWithAuthHeader, + errorHandling, +} from '@services/utils/ts/requests' /* This file includes only POST, PUT, DELETE requests @@ -8,28 +11,40 @@ import { RequestBody, errorHandling } from '@services/utils/ts/requests' */ //TODO : depreciate this function -export async function getCourseChaptersMetadata(course_uuid: any, next: any) { +export async function getCourseChaptersMetadata( + course_uuid: any, + next: any, + access_token: any +) { const result = await fetch( `${getAPIUrl()}chapters/meta/course_${course_uuid}`, - RequestBody('GET', null, next) + RequestBodyWithAuthHeader('GET', null, next, access_token) ) const res = await errorHandling(result) return res } -export async function updateChaptersMetadata(course_uuid: any, data: any) { +export async function updateChaptersMetadata( + course_uuid: any, + data: any, + access_token: any +) { const result: any = await fetch( `${getAPIUrl()}chapters/course/course_${course_uuid}/order`, - RequestBody('PUT', data, null) + RequestBodyWithAuthHeader('PUT', data, null, access_token) ) const res = await errorHandling(result) return res } -export async function updateChapter(coursechapter_id: any, data: any) { +export async function updateChapter( + coursechapter_id: any, + data: any, + access_token: any +) { const result: any = await fetch( `${getAPIUrl()}chapters/${coursechapter_id}`, - RequestBody('PUT', data, null) + RequestBodyWithAuthHeader('PUT', data, null, access_token) ) const res = await errorHandling(result) return res @@ -37,30 +52,31 @@ export async function updateChapter(coursechapter_id: any, data: any) { export async function updateCourseOrderStructure( course_uuid: any, - data: OrderPayload + data: OrderPayload, + access_token: any ) { const result: any = await fetch( `${getAPIUrl()}chapters/course/${course_uuid}/order`, - RequestBody('PUT', data, null) + RequestBodyWithAuthHeader('PUT', data, null, access_token) ) const res = await errorHandling(result) return res } -export async function createChapter(data: any) { +export async function createChapter(data: any, access_token: any) { const result: any = await fetch( `${getAPIUrl()}chapters/`, - RequestBody('POST', data, null) + RequestBodyWithAuthHeader('POST', data, null, access_token) ) const res = await errorHandling(result) return res } -export async function deleteChapter(coursechapter_id: any) { +export async function deleteChapter(coursechapter_id: any, access_token: any) { const result: any = await fetch( `${getAPIUrl()}chapters/${coursechapter_id}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) ) const res = await errorHandling(result) return res diff --git a/apps/web/services/courses/collections.ts b/apps/web/services/courses/collections.ts index 84575309..93051fbf 100644 --- a/apps/web/services/courses/collections.ts +++ b/apps/web/services/courses/collections.ts @@ -1,6 +1,5 @@ import { getAPIUrl } from '../config/config' import { - RequestBody, RequestBodyWithAuthHeader, errorHandling, } from '@services/utils/ts/requests' @@ -10,36 +9,29 @@ import { GET requests are called from the frontend using SWR (https://swr.vercel.app/) */ -export async function deleteCollection(collection_uuid: any) { +export async function deleteCollection( + collection_uuid: any, + access_token: any +) { const result: any = await fetch( `${getAPIUrl()}collections/${collection_uuid}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) ) const res = await errorHandling(result) return res } // Create a new collection -export async function createCollection(collection: any) { +export async function createCollection(collection: any, access_token: any) { const result: any = await fetch( `${getAPIUrl()}collections/`, - RequestBody('POST', collection, null) + RequestBodyWithAuthHeader('POST', collection, null, access_token) ) const res = await errorHandling(result) return res } -// Get a colletion by id -export async function getCollectionById(collection_uuid: any) { - const result: any = await fetch( - `${getAPIUrl()}collections/${collection_uuid}`, - { next: { revalidate: 10 } } - ) - const res = await errorHandling(result) - return res -} - -export async function getCollectionByIdWithAuthHeader( +export async function getCollectionById( collection_uuid: any, access_token: string, next: any @@ -52,17 +44,7 @@ export async function getCollectionByIdWithAuthHeader( return res } -// Get collections -// TODO : add per org filter -export async function getOrgCollections() { - const result: any = await fetch(`${getAPIUrl()}collections/page/1/limit/10`, { - next: { revalidate: 10 }, - }) - const res = await errorHandling(result) - return res -} - -export async function getOrgCollectionsWithAuthHeader( +export async function getOrgCollections( org_id: string, access_token: string, next: any diff --git a/apps/web/services/courses/courses.ts b/apps/web/services/courses/courses.ts index 3e32968a..7c9313ed 100644 --- a/apps/web/services/courses/courses.ts +++ b/apps/web/services/courses/courses.ts @@ -1,7 +1,6 @@ import { getAPIUrl } from '@services/config/config' import { - RequestBody, - RequestBodyForm, + RequestBodyFormWithAuthHeader, RequestBodyWithAuthHeader, errorHandling, getResponseMetadata, @@ -12,19 +11,10 @@ import { GET requests are called from the frontend using SWR (https://swr.vercel.app/) */ -export async function getOrgCourses(org_id: number, next: any) { - const result: any = await fetch( - `${getAPIUrl()}courses/org_slug/${org_id}/page/1/limit/10`, - RequestBody('GET', null, next) - ) - const res = await errorHandling(result) - return res -} - -export async function getOrgCoursesWithAuthHeader( +export async function getOrgCourses( org_id: number, next: any, - access_token: string + access_token: any ) { const result: any = await fetch( `${getAPIUrl()}courses/org_slug/${org_id}/page/1/limit/10`, @@ -34,7 +24,7 @@ export async function getOrgCoursesWithAuthHeader( return res } -export async function getCourseMetadataWithAuthHeader( +export async function getCourseMetadata( course_uuid: any, next: any, access_token: string @@ -47,30 +37,30 @@ export async function getCourseMetadataWithAuthHeader( return res } -export async function updateCourse(course_uuid: any, data: any) { +export async function updateCourse(course_uuid: any, data: any, access_token:any) { const result: any = await fetch( `${getAPIUrl()}courses/${course_uuid}`, - RequestBody('PUT', data, null) + RequestBodyWithAuthHeader('PUT', data, null,access_token) ) const res = await errorHandling(result) return res } -export async function getCourse(course_uuid: string, next: any) { +export async function getCourse(course_uuid: string, next: any, access_token:any) { const result: any = await fetch( `${getAPIUrl()}courses/${course_uuid}`, - RequestBody('GET', null, next) + RequestBodyWithAuthHeader('GET', null, next,access_token) ) const res = await errorHandling(result) return res } -export async function updateCourseThumbnail(course_uuid: any, thumbnail: any) { +export async function updateCourseThumbnail(course_uuid: any, thumbnail: any, access_token:any) { const formData = new FormData() formData.append('thumbnail', thumbnail) const result: any = await fetch( `${getAPIUrl()}courses/${course_uuid}/thumbnail`, - RequestBodyForm('PUT', formData, null) + RequestBodyFormWithAuthHeader('PUT', formData, null,access_token) ) const res = await getResponseMetadata(result) return res @@ -79,7 +69,8 @@ export async function updateCourseThumbnail(course_uuid: any, thumbnail: any) { export async function createNewCourse( org_id: string, course_body: any, - thumbnail: any + thumbnail: any, + access_token: any ) { // Send file thumbnail as form data const formData = new FormData() @@ -96,16 +87,16 @@ export async function createNewCourse( const result = await fetch( `${getAPIUrl()}courses/?org_id=${org_id}`, - RequestBodyForm('POST', formData, null) + RequestBodyFormWithAuthHeader('POST', formData, null, access_token) ) const res = await errorHandling(result) return res } -export async function deleteCourseFromBackend(course_uuid: any) { +export async function deleteCourseFromBackend(course_uuid: any, access_token:any) { const result: any = await fetch( `${getAPIUrl()}courses/${course_uuid}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null,access_token) ) const res = await errorHandling(result) return res diff --git a/apps/web/services/courses/updates.ts b/apps/web/services/courses/updates.ts index 8b515106..440ae0fd 100644 --- a/apps/web/services/courses/updates.ts +++ b/apps/web/services/courses/updates.ts @@ -1,10 +1,13 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody, getResponseMetadata } from '@services/utils/ts/requests' +import { + RequestBodyWithAuthHeader, + getResponseMetadata, +} from '@services/utils/ts/requests' -export async function createCourseUpdate(body: any) { +export async function createCourseUpdate(body: any, access_token: string) { const result: any = await fetch( `${getAPIUrl()}courses/${body.course_uuid}/updates`, - RequestBody('POST', body, null) + RequestBodyWithAuthHeader('POST', body, null, access_token) ) const res = await getResponseMetadata(result) return res @@ -12,11 +15,12 @@ export async function createCourseUpdate(body: any) { export async function deleteCourseUpdate( course_uuid: string, - update_uuid: number + update_uuid: number, + access_token: string ) { const result: any = await fetch( `${getAPIUrl()}courses/${course_uuid}/update/${update_uuid}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) ) const res = await getResponseMetadata(result) return res diff --git a/apps/web/services/organizations/invites.ts b/apps/web/services/organizations/invites.ts index 2fbb2bd2..dd082d1f 100644 --- a/apps/web/services/organizations/invites.ts +++ b/apps/web/services/organizations/invites.ts @@ -1,19 +1,26 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody, getResponseMetadata } from '@services/utils/ts/requests' +import { + RequestBodyWithAuthHeader, + getResponseMetadata, +} from '@services/utils/ts/requests' -export async function createInviteCode(org_id: any) { +export async function createInviteCode(org_id: any, access_token: any) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}/invites`, - RequestBody('POST', null, null) + RequestBodyWithAuthHeader('POST', null, null, access_token) ) const res = await getResponseMetadata(result) return res } -export async function createInviteCodeWithUserGroup(org_id: any, usergroup_id: number) { +export async function createInviteCodeWithUserGroup( + org_id: any, + usergroup_id: number, + access_token: any +) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}/invites_with_usergroups?usergroup_id=${usergroup_id}`, - RequestBody('POST', null, null) + RequestBodyWithAuthHeader('POST', null, null, access_token) ) const res = await getResponseMetadata(result) return res @@ -21,11 +28,12 @@ export async function createInviteCodeWithUserGroup(org_id: any, usergroup_id: n export async function deleteInviteCode( org_id: any, - org_invite_code_uuid: string + org_invite_code_uuid: string, + access_token: any ) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}/invites/${org_invite_code_uuid}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) ) const res = await getResponseMetadata(result) return res @@ -33,20 +41,25 @@ export async function deleteInviteCode( export async function changeSignupMechanism( org_id: any, - signup_mechanism: string + signup_mechanism: string, + access_token: any ) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}/signup_mechanism?signup_mechanism=${signup_mechanism}`, - RequestBody('PUT', null, null) + RequestBodyWithAuthHeader('PUT', null, null, access_token) ) const res = await getResponseMetadata(result) return res } -export async function validateInviteCode(org_id: any, invite_code: string) { +export async function validateInviteCode( + org_id: any, + invite_code: string, + access_token: any +) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}/invites/code/${invite_code}`, - RequestBody('GET', null, null) + RequestBodyWithAuthHeader('GET', null, null, access_token) ) const res = await getResponseMetadata(result) return res @@ -55,11 +68,12 @@ export async function validateInviteCode(org_id: any, invite_code: string) { export async function inviteBatchUsers( org_id: any, emails: string, - invite_code_uuid: string + invite_code_uuid: string, + access_token: any ) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}/invites/users/batch?emails=${emails}&invite_code_uuid=${invite_code_uuid}`, - RequestBody('POST', null, null) + RequestBodyWithAuthHeader('POST', null, null, access_token) ) const res = await getResponseMetadata(result) return res diff --git a/apps/web/services/organizations/orgs.ts b/apps/web/services/organizations/orgs.ts index a08e38cf..9ec5bd1a 100644 --- a/apps/web/services/organizations/orgs.ts +++ b/apps/web/services/organizations/orgs.ts @@ -1,6 +1,6 @@ import { getAPIUrl } from '@services/config/config' import { - RequestBody, + RequestBodyWithAuthHeader, errorHandling, getResponseMetadata, } from '@services/utils/ts/requests' @@ -10,37 +10,48 @@ import { GET requests are called from the frontend using SWR (https://swr.vercel.app/) */ -export async function createNewOrganization(body: any) { +export async function createNewOrganization(body: any, access_token: string) { const result = await fetch( `${getAPIUrl()}orgs/`, - RequestBody('POST', body, null) + RequestBodyWithAuthHeader('POST', body, null, access_token) ) const res = await errorHandling(result) return res } -export async function deleteOrganizationFromBackend(org_id: any) { +export async function deleteOrganizationFromBackend( + org_id: any, + access_token: string +) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) ) const res = await errorHandling(result) return res } -export async function getOrganizationContextInfo(org_slug: any, next: any) { +export async function getOrganizationContextInfo( + org_slug: any, + next: any, + access_token?: string +) { const result = await fetch( `${getAPIUrl()}orgs/slug/${org_slug}`, - RequestBody('GET', null, next) + RequestBodyWithAuthHeader('GET', null, next, access_token) ) const res = await errorHandling(result) return res } -export async function getOrganizationContextInfoWithId(org_id: any, next: any) { +export async function getOrganizationContextInfoWithId( + org_id: any, + next: any, + access_token: string +) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}`, - RequestBody('GET', null, next) + RequestBodyWithAuthHeader('GET', null, next, access_token) ) const res = await errorHandling(result) return res @@ -64,10 +75,14 @@ export async function getOrganizationContextInfoWithoutCredentials( return res } -export function getOrganizationContextInfoNoAsync(org_slug: any, next: any) { +export function getOrganizationContextInfoNoAsync( + org_slug: any, + next: any, + access_token: string +) { const result = fetch( `${getAPIUrl()}orgs/slug/${org_slug}`, - RequestBody('GET', null, next) + RequestBodyWithAuthHeader('GET', null, next, access_token) ) return result } @@ -75,20 +90,42 @@ export function getOrganizationContextInfoNoAsync(org_slug: any, next: any) { export async function updateUserRole( org_id: any, user_id: any, - role_uuid: any + role_uuid: any, + access_token: string ) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}/users/${user_id}/role/${role_uuid}`, - RequestBody('PUT', null, null) + RequestBodyWithAuthHeader('PUT', null, null, access_token) ) const res = await getResponseMetadata(result) return res } -export async function removeUserFromOrg(org_id: any, user_id: any) { +export async function removeUserFromOrg( + org_id: any, + user_id: any, + access_token: any +) { const result = await fetch( `${getAPIUrl()}orgs/${org_id}/users/${user_id}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) + ) + const res = await getResponseMetadata(result) + return res +} + +export async function joinOrg( + args: { + org_id: number + user_id: string + invite_code?: string + }, + next: any, + access_token?: string +) { + const result = await fetch( + `${getAPIUrl()}orgs/join`, + RequestBodyWithAuthHeader('POST', args, next, access_token) ) const res = await getResponseMetadata(result) return res diff --git a/apps/web/services/settings/org.ts b/apps/web/services/settings/org.ts index 7aaedb5c..c74450eb 100644 --- a/apps/web/services/settings/org.ts +++ b/apps/web/services/settings/org.ts @@ -1,8 +1,8 @@ import { getAPIUrl } from '@services/config/config' import { - RequestBody, errorHandling, - RequestBodyForm, + RequestBodyWithAuthHeader, + RequestBodyFormWithAuthHeader, } from '@services/utils/ts/requests' /* @@ -10,22 +10,30 @@ import { GET requests are called from the frontend using SWR (https://swr.vercel.app/) */ -export async function updateOrganization(org_id: string, data: any) { +export async function updateOrganization( + org_id: string, + data: any, + access_token: string +) { const result: any = await fetch( `${getAPIUrl()}orgs/` + org_id, - RequestBody('PUT', data, null) + RequestBodyWithAuthHeader('PUT', data, null, access_token) ) const res = await errorHandling(result) return res } -export async function uploadOrganizationLogo(org_id: string, logo_file: any) { +export async function uploadOrganizationLogo( + org_id: string, + logo_file: any, + access_token: string +) { // Send file thumbnail as form data const formData = new FormData() formData.append('logo_file', logo_file) const result: any = await fetch( `${getAPIUrl()}orgs/` + org_id + '/logo', - RequestBodyForm('PUT', formData, null) + RequestBodyFormWithAuthHeader('PUT', formData, null, access_token) ) const res = await errorHandling(result) return res diff --git a/apps/web/services/settings/password.ts b/apps/web/services/settings/password.ts index b5ff0331..9bf84618 100644 --- a/apps/web/services/settings/password.ts +++ b/apps/web/services/settings/password.ts @@ -1,15 +1,22 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody, errorHandling } from '@services/utils/ts/requests' +import { + RequestBodyWithAuthHeader, + errorHandling, +} from '@services/utils/ts/requests' /* This file includes only POST, PUT, DELETE requests GET requests are called from the frontend using SWR (https://swr.vercel.app/) */ -export async function updatePassword(user_id: string, data: any) { +export async function updatePassword( + user_id: string, + data: any, + access_token: any +) { const result: any = await fetch( `${getAPIUrl()}users/change_password/` + user_id, - RequestBody('PUT', data, null) + RequestBodyWithAuthHeader('PUT', data, null, access_token) ) const res = await errorHandling(result) return res diff --git a/apps/web/services/settings/profile.ts b/apps/web/services/settings/profile.ts index 10fec223..68bd5d57 100644 --- a/apps/web/services/settings/profile.ts +++ b/apps/web/services/settings/profile.ts @@ -1,15 +1,22 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody, errorHandling } from '@services/utils/ts/requests' +import { + RequestBodyWithAuthHeader, + errorHandling, +} from '@services/utils/ts/requests' /* This file includes only POST, PUT, DELETE requests GET requests are called from the frontend using SWR (https://swr.vercel.app/) */ -export async function updateProfile(data: any, user_id: number) { +export async function updateProfile( + data: any, + user_id: number, + access_token: string +) { const result: any = await fetch( `${getAPIUrl()}users/` + user_id, - RequestBody('PUT', data, null) + RequestBodyWithAuthHeader('PUT', data, null, access_token) ) const res = await errorHandling(result) return res diff --git a/apps/web/services/usergroups/usergroups.ts b/apps/web/services/usergroups/usergroups.ts index c4eaa599..b7f9e50c 100644 --- a/apps/web/services/usergroups/usergroups.ts +++ b/apps/web/services/usergroups/usergroups.ts @@ -1,46 +1,60 @@ import { getAPIUrl } from '@services/config/config' -import { RequestBody, getResponseMetadata } from '@services/utils/ts/requests' +import { + RequestBodyWithAuthHeader, + getResponseMetadata, +} from '@services/utils/ts/requests' -export async function getUserGroups(org_id: any) { +export async function getUserGroups(org_id: any, access_token: string) { const result: any = await fetch( `${getAPIUrl()}usergroups/org/${org_id}`, - RequestBody('GET', null, null) + RequestBodyWithAuthHeader('GET', null, null, access_token) ) const res = await getResponseMetadata(result) return res } -export async function createUserGroup(body: any) { +export async function createUserGroup(body: any, access_token: string) { const result: any = await fetch( `${getAPIUrl()}usergroups/`, - RequestBody('POST', body, null) + RequestBodyWithAuthHeader('POST', body, null, access_token) ) const res = await getResponseMetadata(result) return res } -export async function linkUserToUserGroup(usergroup_id: any, user_id: any) { +export async function linkUserToUserGroup( + usergroup_id: any, + user_id: any, + access_token: string +) { const result: any = await fetch( `${getAPIUrl()}usergroups/${usergroup_id}/add_users?user_ids=${user_id}`, - RequestBody('POST', null, null) + RequestBodyWithAuthHeader('POST', null, null, access_token) ) const res = await getResponseMetadata(result) return res } -export async function unLinkUserToUserGroup(usergroup_id: any, user_id: any) { +export async function unLinkUserToUserGroup( + usergroup_id: any, + user_id: any, + access_token: string +) { const result: any = await fetch( `${getAPIUrl()}usergroups/${usergroup_id}/remove_users?user_ids=${user_id}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) ) const res = await getResponseMetadata(result) return res } -export async function deleteUserGroup(usergroup_id: number) { +export async function deleteUserGroup( + usergroup_id: number, + access_token: string +) { const result: any = await fetch( `${getAPIUrl()}usergroups/${usergroup_id}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) ) const res = await getResponseMetadata(result) return res @@ -48,11 +62,12 @@ export async function deleteUserGroup(usergroup_id: number) { export async function linkResourcesToUserGroup( usergroup_id: any, - resource_uuids: any + resource_uuids: any, + access_token: string ) { const result: any = await fetch( `${getAPIUrl()}usergroups/${usergroup_id}/add_resources?resource_uuids=${resource_uuids}`, - RequestBody('POST', null, null) + RequestBodyWithAuthHeader('POST', null, null, access_token) ) const res = await getResponseMetadata(result) return res @@ -60,11 +75,12 @@ export async function linkResourcesToUserGroup( export async function unLinkResourcesToUserGroup( usergroup_id: any, - resource_uuids: any + resource_uuids: any, + access_token: string ) { const result: any = await fetch( `${getAPIUrl()}usergroups/${usergroup_id}/remove_resources?resource_uuids=${resource_uuids}`, - RequestBody('DELETE', null, null) + RequestBodyWithAuthHeader('DELETE', null, null, access_token) ) const res = await getResponseMetadata(result) return res diff --git a/apps/web/services/users/users.ts b/apps/web/services/users/users.ts index 468ad56c..7596e208 100644 --- a/apps/web/services/users/users.ts +++ b/apps/web/services/users/users.ts @@ -1,7 +1,7 @@ import { getAPIUrl } from '@services/config/config' import { RequestBody, - RequestBodyForm, + RequestBodyFormWithAuthHeader, errorHandling, getResponseMetadata, } from '@services/utils/ts/requests' @@ -15,12 +15,16 @@ export async function getUser(user_id: string) { return res } -export async function updateUserAvatar(user_uuid: any, avatar_file: any) { +export async function updateUserAvatar( + user_uuid: any, + avatar_file: any, + access_token: any +) { const formData = new FormData() formData.append('avatar_file', avatar_file) const result: any = await fetch( `${getAPIUrl()}users/update_avatar/${user_uuid}`, - RequestBodyForm('PUT', formData, null) + RequestBodyFormWithAuthHeader('PUT', formData, null, access_token) ) const res = await getResponseMetadata(result) return res diff --git a/apps/web/services/utils/ts/requests.ts b/apps/web/services/utils/ts/requests.ts index 2947964a..0c68a945 100644 --- a/apps/web/services/utils/ts/requests.ts +++ b/apps/web/services/utils/ts/requests.ts @@ -20,7 +20,7 @@ export const RequestBodyWithAuthHeader = ( method: string, data: any, next: any, - token: string + token?: string ) => { let HeadersConfig = new Headers( token @@ -32,7 +32,7 @@ export const RequestBodyWithAuthHeader = ( headers: HeadersConfig, redirect: 'follow', credentials: 'include', - body: data, + body: (method === 'POST' || method === 'PUT') ? JSON.stringify(data) : null, // Next.js next: next, } @@ -41,6 +41,27 @@ export const RequestBodyWithAuthHeader = ( export const RequestBodyForm = (method: string, data: any, next: any) => { let HeadersConfig = new Headers({}) + let options: any = { + method: method, + headers: HeadersConfig, + redirect: 'follow', + credentials: 'include', + body: (method === 'POST' || method === 'PUT') ? JSON.stringify(data) : null, + // Next.js + next: next, + } + return options +} + +export const RequestBodyFormWithAuthHeader = ( + method: string, + data: any, + next: any, + access_token: string +) => { + let HeadersConfig = new Headers({ + Authorization: `Bearer ${access_token}`, + }) let options: any = { method: method, headers: HeadersConfig, @@ -53,9 +74,13 @@ export const RequestBodyForm = (method: string, data: any, next: any) => { return options } -export const swrFetcher = async (url: string) => { +export const swrFetcher = async (url: string, token?: string) => { // Create the request options - let HeadersConfig = new Headers({ 'Content-Type': 'application/json' }) + let HeadersConfig = new Headers( + token + ? { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` } + : { 'Content-Type': 'application/json' } + ) let options: any = { method: 'GET', headers: HeadersConfig, diff --git a/apps/web/types/next-auth.d.ts b/apps/web/types/next-auth.d.ts new file mode 100644 index 00000000..ece81eac --- /dev/null +++ b/apps/web/types/next-auth.d.ts @@ -0,0 +1,16 @@ +// eslint-disable-next-line unused-imports/no-unused-imports +import type { NextAuthOptions } from 'next-auth/index'; + +// next-auth.d.ts +declare module 'next-auth' { + interface Session { + user: any | undefined + roles?: string[] | undefined + tokens?: + | { + access_token?: string | undefined + refresh_token?: string | undefined + } + | undefined + } +} diff --git a/package.json b/package.json index e80202c6..6043f5a9 100644 --- a/package.json +++ b/package.json @@ -2,15 +2,15 @@ "private": true, "scripts": { "build": "turbo run build", - "start" : "turbo run start", + "start": "turbo run start", "dev": "turbo run dev", "lint": "turbo run lint", "format": "prettier --write \"**/*.{ts,tsx,md}\"" }, "devDependencies": { "eslint": "^8.57.0", - "prettier": "^3.2.5", - "turbo": "^1.13.2" + "prettier": "^3.3.0", + "turbo": "^1.13.3" }, - "packageManager": "pnpm@8.6.10" + "packageManager": "pnpm@9.0.6" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7c0cf81..a5b4d0ae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,18 +12,14 @@ importers: specifier: ^8.57.0 version: 8.57.0 prettier: - specifier: ^3.2.5 - version: 3.2.5 + specifier: ^3.3.0 + version: 3.3.0 turbo: - specifier: ^1.13.2 - version: 1.13.2 + specifier: ^1.13.3 + version: 1.13.3 packages: - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -50,8 +46,8 @@ packages: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/object-schema@2.0.2': - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -73,8 +69,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} hasBin: true @@ -120,8 +116,8 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -209,6 +205,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} @@ -235,6 +232,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -293,8 +291,8 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} p-limit@3.1.0: @@ -325,13 +323,13 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + prettier@3.3.0: + resolution: {integrity: sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g==} engines: {node: '>=14'} hasBin: true - punycode@2.3.0: - resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} queue-microtask@1.2.3: @@ -347,6 +345,7 @@ packages: rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true run-parallel@1.2.0: @@ -375,38 +374,38 @@ packages: text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - turbo-darwin-64@1.13.2: - resolution: {integrity: sha512-CCSuD8CfmtncpohCuIgq7eAzUas0IwSbHfI8/Q3vKObTdXyN8vAo01gwqXjDGpzG9bTEVedD0GmLbD23dR0MLA==} + turbo-darwin-64@1.13.3: + resolution: {integrity: sha512-glup8Qx1qEFB5jerAnXbS8WrL92OKyMmg5Hnd4PleLljAeYmx+cmmnsmLT7tpaVZIN58EAAwu8wHC6kIIqhbWA==} cpu: [x64] os: [darwin] - turbo-darwin-arm64@1.13.2: - resolution: {integrity: sha512-0HySm06/D2N91rJJ89FbiI/AodmY8B3WDSFTVEpu2+8spUw7hOJ8okWOT0e5iGlyayUP9gr31eOeL3VFZkpfCw==} + turbo-darwin-arm64@1.13.3: + resolution: {integrity: sha512-/np2xD+f/+9qY8BVtuOQXRq5f9LehCFxamiQnwdqWm5iZmdjygC5T3uVSYuagVFsZKMvX3ycySwh8dylGTl6lg==} cpu: [arm64] os: [darwin] - turbo-linux-64@1.13.2: - resolution: {integrity: sha512-7HnibgbqZrjn4lcfIouzlPu8ZHSBtURG4c7Bedu7WJUDeZo+RE1crlrQm8wuwO54S0siYqUqo7GNHxu4IXbioQ==} + turbo-linux-64@1.13.3: + resolution: {integrity: sha512-G+HGrau54iAnbXLfl+N/PynqpDwi/uDzb6iM9hXEDG+yJnSJxaHMShhOkXYJPk9offm9prH33Khx2scXrYVW1g==} cpu: [x64] os: [linux] - turbo-linux-arm64@1.13.2: - resolution: {integrity: sha512-sUq4dbpk6SNKg/Hkwn256Vj2AEYSQdG96repio894h5/LEfauIK2QYiC/xxAeW3WBMc6BngmvNyURIg7ltrePg==} + turbo-linux-arm64@1.13.3: + resolution: {integrity: sha512-qWwEl5VR02NqRyl68/3pwp3c/olZuSp+vwlwrunuoNTm6JXGLG5pTeme4zoHNnk0qn4cCX7DFrOboArlYxv0wQ==} cpu: [arm64] os: [linux] - turbo-windows-64@1.13.2: - resolution: {integrity: sha512-DqzhcrciWq3dpzllJR2VVIyOhSlXYCo4mNEWl98DJ3FZ08PEzcI3ceudlH6F0t/nIcfSItK1bDP39cs7YoZHEA==} + turbo-windows-64@1.13.3: + resolution: {integrity: sha512-Nudr4bRChfJzBPzEmpVV85VwUYRCGKecwkBFpbp2a4NtrJ3+UP1VZES653ckqCu2FRyRuS0n03v9euMbAvzH+Q==} cpu: [x64] os: [win32] - turbo-windows-arm64@1.13.2: - resolution: {integrity: sha512-WnPMrwfCXxK69CdDfS1/j2DlzcKxSmycgDAqV0XCYpK/812KB0KlvsVAt5PjEbZGXkY88pCJ1BLZHAjF5FcbqA==} + turbo-windows-arm64@1.13.3: + resolution: {integrity: sha512-ouJCgsVLd3icjRLmRvHQDDZnmGzT64GBupM1Y+TjtYn2LVaEBoV6hicFy8x5DUpnqdLy+YpCzRMkWlwhmkX7sQ==} cpu: [arm64] os: [win32] - turbo@1.13.2: - resolution: {integrity: sha512-rX/d9f4MgRT3yK6cERPAkfavIxbpBZowDQpgvkYwGMGDQ0Nvw1nc0NVjruE76GrzXQqoxR1UpnmEP54vBARFHQ==} + turbo@1.13.3: + resolution: {integrity: sha512-n17HJv4F4CpsYTvKzUJhLbyewbXjq1oLCi90i5tW1TiWDz16ML1eDG7wi5dHaKxzh5efIM56SITnuVbMq5dk4g==} hasBin: true type-check@0.4.0: @@ -425,6 +424,10 @@ packages: engines: {node: '>= 8'} hasBin: true + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -434,8 +437,6 @@ packages: snapshots: - '@aashutoshrathi/word-wrap@1.2.6': {} - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 @@ -446,7 +447,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.5 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -461,15 +462,15 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4 + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.5 minimatch: 3.1.2 transitivePeerDependencies: - supports-color '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/object-schema@2.0.2': {} + '@humanwhocodes/object-schema@2.0.3': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -485,11 +486,11 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - acorn-jsx@5.3.2(acorn@8.10.0): + acorn-jsx@5.3.2(acorn@8.11.3): dependencies: - acorn: 8.10.0 + acorn: 8.11.3 - acorn@8.10.0: {} + acorn@8.11.3: {} ajv@6.12.6: dependencies: @@ -534,7 +535,7 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - debug@4.3.4: + debug@4.3.5: dependencies: ms: 2.1.2 @@ -566,7 +567,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.5 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -590,7 +591,7 @@ snapshots: lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 - optionator: 0.9.3 + optionator: 0.9.4 strip-ansi: 6.0.1 text-table: 0.2.0 transitivePeerDependencies: @@ -598,8 +599,8 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.10.0 - acorn-jsx: 5.3.2(acorn@8.10.0) + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) eslint-visitor-keys: 3.4.3 esquery@1.5.0: @@ -727,14 +728,14 @@ snapshots: dependencies: wrappy: 1.0.2 - optionator@0.9.3: + optionator@0.9.4: dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 + word-wrap: 1.2.5 p-limit@3.1.0: dependencies: @@ -756,9 +757,9 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.2.5: {} + prettier@3.3.0: {} - punycode@2.3.0: {} + punycode@2.3.1: {} queue-microtask@1.2.3: {} @@ -792,32 +793,32 @@ snapshots: text-table@0.2.0: {} - turbo-darwin-64@1.13.2: + turbo-darwin-64@1.13.3: optional: true - turbo-darwin-arm64@1.13.2: + turbo-darwin-arm64@1.13.3: optional: true - turbo-linux-64@1.13.2: + turbo-linux-64@1.13.3: optional: true - turbo-linux-arm64@1.13.2: + turbo-linux-arm64@1.13.3: optional: true - turbo-windows-64@1.13.2: + turbo-windows-64@1.13.3: optional: true - turbo-windows-arm64@1.13.2: + turbo-windows-arm64@1.13.3: optional: true - turbo@1.13.2: + turbo@1.13.3: optionalDependencies: - turbo-darwin-64: 1.13.2 - turbo-darwin-arm64: 1.13.2 - turbo-linux-64: 1.13.2 - turbo-linux-arm64: 1.13.2 - turbo-windows-64: 1.13.2 - turbo-windows-arm64: 1.13.2 + turbo-darwin-64: 1.13.3 + turbo-darwin-arm64: 1.13.3 + turbo-linux-64: 1.13.3 + turbo-linux-arm64: 1.13.3 + turbo-windows-64: 1.13.3 + turbo-windows-arm64: 1.13.3 type-check@0.4.0: dependencies: @@ -827,12 +828,14 @@ snapshots: uri-js@4.4.1: dependencies: - punycode: 2.3.0 + punycode: 2.3.1 which@2.0.2: dependencies: isexe: 2.0.0 + word-wrap@1.2.5: {} + wrappy@1.0.2: {} yocto-queue@0.1.0: {}