mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
fix: session auth issues
This commit is contained in:
parent
1708b36818
commit
08cc97f557
70 changed files with 607 additions and 427 deletions
4
apps/collaboration/pnpm-lock.yaml
generated
4
apps/collaboration/pnpm-lock.yaml
generated
|
|
@ -10,7 +10,7 @@ importers:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@hocuspocus/server':
|
'@hocuspocus/server':
|
||||||
specifier: ^2.11.3
|
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:
|
bun:
|
||||||
specifier: ^1.0.36
|
specifier: ^1.0.36
|
||||||
version: 1.1.1
|
version: 1.1.1
|
||||||
|
|
@ -133,7 +133,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
lib0: 0.2.93
|
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:
|
dependencies:
|
||||||
'@hocuspocus/common': 2.11.3
|
'@hocuspocus/common': 2.11.3
|
||||||
async-lock: 1.4.1
|
async-lock: 1.4.1
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export const nextAuthOptions = {
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
callbacks: {
|
callbacks: {
|
||||||
async jwt({ token, user, account }) {
|
async jwt({ token, user, account }: any) {
|
||||||
// First sign in with Credentials provider
|
// First sign in with Credentials provider
|
||||||
if (account?.provider == 'credentials' && user) {
|
if (account?.provider == 'credentials' && user) {
|
||||||
token.user = user
|
token.user = user
|
||||||
|
|
@ -78,7 +78,7 @@ export const nextAuthOptions = {
|
||||||
}
|
}
|
||||||
return token
|
return token
|
||||||
},
|
},
|
||||||
async session({ session, token }) {
|
async session({ session, token }: any) {
|
||||||
// Include user information in the session
|
// Include user information in the session
|
||||||
if (token.user) {
|
if (token.user) {
|
||||||
let api_SESSION = await getUserSession(token.user.tokens.access_token)
|
let api_SESSION = await getUserSession(token.user.tokens.access_token)
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@ import PageLoading from '@components/Objects/Loaders/PageLoading'
|
||||||
export default function Loading() {
|
export default function Loading() {
|
||||||
// Or a custom loading skeleton component
|
// Or a custom loading skeleton component
|
||||||
return <PageLoading></PageLoading>
|
return <PageLoading></PageLoading>
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { default as React } from 'react'
|
import { default as React } from 'react'
|
||||||
import dynamic from 'next/dynamic'
|
import dynamic from 'next/dynamic'
|
||||||
import { getCourseMetadataWithAuthHeader } from '@services/courses/courses'
|
import { getCourseMetadata } from '@services/courses/courses'
|
||||||
import { cookies } from 'next/headers'
|
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { getActivityWithAuthHeader } from '@services/courses/activities'
|
import { getActivityWithAuthHeader } from '@services/courses/activities'
|
||||||
import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
|
||||||
import { getOrganizationContextInfoWithId } from '@services/organizations/orgs'
|
import { getOrganizationContextInfoWithId } from '@services/organizations/orgs'
|
||||||
import EditorOptionsProvider from '@components/Contexts/Editor/EditorContext'
|
import EditorOptionsProvider from '@components/Contexts/Editor/EditorContext'
|
||||||
import AIEditorProvider from '@components/Contexts/AI/AIEditorContext'
|
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 })
|
const EditorWrapper = dynamic(() => import('@components/Objects/Editor/EditorWrapper'), { ssr: false })
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -19,10 +19,10 @@ type MetadataProps = {
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
}: MetadataProps): Promise<Metadata> {
|
}: MetadataProps): Promise<Metadata> {
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
// Get Org context information
|
// Get Org context information
|
||||||
const course_meta = await getCourseMetadataWithAuthHeader(
|
const course_meta = await getCourseMetadata(
|
||||||
params.courseid,
|
params.courseid,
|
||||||
{ revalidate: 0, tags: ['courses'] },
|
{ revalidate: 0, tags: ['courses'] },
|
||||||
access_token ? access_token : null
|
access_token ? access_token : null
|
||||||
|
|
@ -35,11 +35,11 @@ export async function generateMetadata({
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditActivity = async (params: any) => {
|
const EditActivity = async (params: any) => {
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
const activityuuid = params.params.activityuuid
|
const activityuuid = params.params.activityuuid
|
||||||
const courseid = params.params.courseid
|
const courseid = params.params.courseid
|
||||||
const courseInfo = await getCourseMetadataWithAuthHeader(
|
const courseInfo = await getCourseMetadata(
|
||||||
courseid,
|
courseid,
|
||||||
{ revalidate: 0, tags: ['courses'] },
|
{ revalidate: 0, tags: ['courses'] },
|
||||||
access_token ? access_token : null
|
access_token ? access_token : null
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { getAPIUrl } from '@services/config/config'
|
||||||
import { createNewUserInstall, updateInstall } from '@services/install/install'
|
import { createNewUserInstall, updateInstall } from '@services/install/install'
|
||||||
import { swrFetcher } from '@services/utils/ts/requests'
|
import { swrFetcher } from '@services/utils/ts/requests'
|
||||||
import { useFormik } from 'formik'
|
import { useFormik } from 'formik'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { BarLoader } from 'react-spinners'
|
import { BarLoader } from 'react-spinners'
|
||||||
|
|
@ -47,11 +48,13 @@ const validate = (values: any) => {
|
||||||
|
|
||||||
function AccountCreation() {
|
function AccountCreation() {
|
||||||
const [isSubmitting, setIsSubmitting] = React.useState(false)
|
const [isSubmitting, setIsSubmitting] = React.useState(false)
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const {
|
const {
|
||||||
data: install,
|
data: install,
|
||||||
error: error,
|
error: error,
|
||||||
isLoading,
|
isLoading,
|
||||||
} = useSWR(`${getAPIUrl()}install/latest`, swrFetcher)
|
} = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token))
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
import { getAPIUrl } from '@services/config/config'
|
import { getAPIUrl } from '@services/config/config'
|
||||||
import { createDefaultElements, updateInstall } from '@services/install/install'
|
import { createDefaultElements, updateInstall } from '@services/install/install'
|
||||||
import { swrFetcher } from '@services/utils/ts/requests'
|
import { swrFetcher } from '@services/utils/ts/requests'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
|
|
||||||
function DefaultElements() {
|
function DefaultElements() {
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const {
|
const {
|
||||||
data: install,
|
data: install,
|
||||||
error: error,
|
error: error,
|
||||||
isLoading,
|
isLoading,
|
||||||
} = useSWR(`${getAPIUrl()}install/latest`, swrFetcher)
|
} = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token))
|
||||||
const [isSubmitting, setIsSubmitting] = React.useState(false)
|
const [isSubmitting, setIsSubmitting] = React.useState(false)
|
||||||
const [isSubmitted, setIsSubmitted] = React.useState(false)
|
const [isSubmitted, setIsSubmitted] = React.useState(false)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,19 @@ import { getAPIUrl } from '@services/config/config'
|
||||||
import { updateInstall } from '@services/install/install'
|
import { updateInstall } from '@services/install/install'
|
||||||
import { swrFetcher } from '@services/utils/ts/requests'
|
import { swrFetcher } from '@services/utils/ts/requests'
|
||||||
import { Check } from 'lucide-react'
|
import { Check } from 'lucide-react'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
|
|
||||||
const Finish = () => {
|
const Finish = () => {
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const {
|
const {
|
||||||
data: install,
|
data: install,
|
||||||
error: error,
|
error: error,
|
||||||
isLoading,
|
isLoading,
|
||||||
} = useSWR(`${getAPIUrl()}install/latest`, swrFetcher)
|
} = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token))
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
async function finishInstall() {
|
async function finishInstall() {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
import PageLoading from '@components/Objects/Loaders/PageLoading'
|
import PageLoading from '@components/Objects/Loaders/PageLoading'
|
||||||
import { getAPIUrl } from '@services/config/config'
|
import { getAPIUrl } from '@services/config/config'
|
||||||
import { swrFetcher } from '@services/utils/ts/requests'
|
import { swrFetcher } from '@services/utils/ts/requests'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import useSWR, { mutate } from 'swr'
|
import useSWR, { mutate } from 'swr'
|
||||||
|
|
||||||
function GetStarted() {
|
function GetStarted() {
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const {
|
const {
|
||||||
data: install,
|
data: install,
|
||||||
error: error,
|
error: error,
|
||||||
isLoading,
|
isLoading,
|
||||||
} = useSWR(`${getAPIUrl()}install/latest`, swrFetcher)
|
} = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token))
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
async function startInstallation() {
|
async function startInstallation() {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import useSWR from 'swr'
|
||||||
import { createNewOrgInstall, updateInstall } from '@services/install/install'
|
import { createNewOrgInstall, updateInstall } from '@services/install/install'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { Check } from 'lucide-react'
|
import { Check } from 'lucide-react'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
const validate = (values: any) => {
|
const validate = (values: any) => {
|
||||||
const errors: any = {}
|
const errors: any = {}
|
||||||
|
|
@ -40,11 +41,13 @@ const validate = (values: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function OrgCreation() {
|
function OrgCreation() {
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const {
|
const {
|
||||||
data: install,
|
data: install,
|
||||||
error: error,
|
error: error,
|
||||||
isLoading,
|
isLoading,
|
||||||
} = useSWR(`${getAPIUrl()}install/latest`, swrFetcher)
|
} = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token))
|
||||||
const [isSubmitting, setIsSubmitting] = React.useState(false)
|
const [isSubmitting, setIsSubmitting] = React.useState(false)
|
||||||
const [isSubmitted, setIsSubmitted] = React.useState(false)
|
const [isSubmitted, setIsSubmitted] = React.useState(false)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,19 @@ import {
|
||||||
updateInstall,
|
updateInstall,
|
||||||
} from '@services/install/install'
|
} from '@services/install/install'
|
||||||
import { swrFetcher } from '@services/utils/ts/requests'
|
import { swrFetcher } from '@services/utils/ts/requests'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
|
|
||||||
function SampleData() {
|
function SampleData() {
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const {
|
const {
|
||||||
data: install,
|
data: install,
|
||||||
error: error,
|
error: error,
|
||||||
isLoading,
|
isLoading,
|
||||||
} = useSWR(`${getAPIUrl()}install/latest`, swrFetcher)
|
} = useSWR(`${getAPIUrl()}install/latest`, (url) => swrFetcher(url, access_token))
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
function createSampleData() {
|
function createSampleData() {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import '../styles/globals.css'
|
||||||
import StyledComponentsRegistry from '../components/Utils/libs/styled-registry'
|
import StyledComponentsRegistry from '../components/Utils/libs/styled-registry'
|
||||||
import { motion } from 'framer-motion'
|
import { motion } from 'framer-motion'
|
||||||
import { SessionProvider } from 'next-auth/react'
|
import { SessionProvider } from 'next-auth/react'
|
||||||
|
import LHSessionProvider from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
children,
|
children,
|
||||||
|
|
@ -19,18 +20,20 @@ export default function RootLayout({
|
||||||
<head />
|
<head />
|
||||||
<body>
|
<body>
|
||||||
<SessionProvider>
|
<SessionProvider>
|
||||||
<StyledComponentsRegistry>
|
<LHSessionProvider>
|
||||||
<motion.main
|
<StyledComponentsRegistry>
|
||||||
variants={variants} // Pass the variant object into Framer Motion
|
<motion.main
|
||||||
initial="hidden" // Set the initial state to variants.hidden
|
variants={variants} // Pass the variant object into Framer Motion
|
||||||
animate="enter" // Animated state to variants.enter
|
initial="hidden" // Set the initial state to variants.hidden
|
||||||
exit="exit" // Exit state (used later) to variants.exit
|
animate="enter" // Animated state to variants.enter
|
||||||
transition={{ type: 'linear' }} // Set the transition to linear
|
exit="exit" // Exit state (used later) to variants.exit
|
||||||
className=""
|
transition={{ type: 'linear' }} // Set the transition to linear
|
||||||
>
|
className=""
|
||||||
{children}
|
>
|
||||||
</motion.main>
|
{children}
|
||||||
</StyledComponentsRegistry>
|
</motion.main>
|
||||||
|
</StyledComponentsRegistry>
|
||||||
|
</LHSessionProvider>
|
||||||
</SessionProvider>
|
</SessionProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper'
|
import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper'
|
||||||
import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
|
||||||
import { getUriWithOrg } from '@services/config/config'
|
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 { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||||
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
||||||
|
import { nextAuthOptions } from 'app/auth/options'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
|
import { getServerSession } from 'next-auth'
|
||||||
import { cookies } from 'next/headers'
|
import { cookies } from 'next/headers'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
|
@ -16,15 +17,15 @@ type MetadataProps = {
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
}: MetadataProps): Promise<Metadata> {
|
}: MetadataProps): Promise<Metadata> {
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
|
|
||||||
// Get Org context information
|
// Get Org context information
|
||||||
const org = await getOrganizationContextInfo(params.orgslug, {
|
const org = await getOrganizationContextInfo(params.orgslug, {
|
||||||
revalidate: 1800,
|
revalidate: 1800,
|
||||||
tags: ['organizations'],
|
tags: ['organizations'],
|
||||||
})
|
})
|
||||||
const col = await getCollectionByIdWithAuthHeader(
|
const col = await getCollectionById(
|
||||||
params.collectionid,
|
params.collectionid,
|
||||||
access_token ? access_token : null,
|
access_token ? access_token : null,
|
||||||
{ revalidate: 0, tags: ['collections'] }
|
{ revalidate: 0, tags: ['collections'] }
|
||||||
|
|
@ -53,14 +54,14 @@ export async function generateMetadata({
|
||||||
}
|
}
|
||||||
|
|
||||||
const CollectionPage = async (params: any) => {
|
const CollectionPage = async (params: any) => {
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
const org = await getOrganizationContextInfo(params.params.orgslug, {
|
const org = await getOrganizationContextInfo(params.params.orgslug, {
|
||||||
revalidate: 1800,
|
revalidate: 1800,
|
||||||
tags: ['organizations'],
|
tags: ['organizations'],
|
||||||
})
|
})
|
||||||
const orgslug = params.params.orgslug
|
const orgslug = params.params.orgslug
|
||||||
const col = await getCollectionByIdWithAuthHeader(
|
const col = await getCollectionById(
|
||||||
params.params.collectionid,
|
params.params.collectionid,
|
||||||
access_token ? access_token : null,
|
access_token ? access_token : null,
|
||||||
{ revalidate: 0, tags: ['collections'] }
|
{ revalidate: 0, tags: ['collections'] }
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,12 @@ import useSWR from 'swr'
|
||||||
import { getAPIUrl, getUriWithOrg } from '@services/config/config'
|
import { getAPIUrl, getUriWithOrg } from '@services/config/config'
|
||||||
import { revalidateTags, swrFetcher } from '@services/utils/ts/requests'
|
import { revalidateTags, swrFetcher } from '@services/utils/ts/requests'
|
||||||
import { useOrg } from '@components/Contexts/OrgContext'
|
import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
function NewCollection(params: any) {
|
function NewCollection(params: any) {
|
||||||
const org = useOrg() as 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 orgslug = params.params.orgslug
|
||||||
const [name, setName] = React.useState('')
|
const [name, setName] = React.useState('')
|
||||||
const [description, setDescription] = React.useState('')
|
const [description, setDescription] = React.useState('')
|
||||||
|
|
@ -16,7 +19,7 @@ function NewCollection(params: any) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { data: courses, error: error } = useSWR(
|
const { data: courses, error: error } = useSWR(
|
||||||
`${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`,
|
`${getAPIUrl()}courses/org_slug/${orgslug}/page/1/limit/10`,
|
||||||
swrFetcher
|
(url) => swrFetcher(url, access_token)
|
||||||
)
|
)
|
||||||
const [isPublic, setIsPublic] = useState('true')
|
const [isPublic, setIsPublic] = useState('true')
|
||||||
|
|
||||||
|
|
@ -44,7 +47,7 @@ function NewCollection(params: any) {
|
||||||
public: isPublic,
|
public: isPublic,
|
||||||
org_id: org.id,
|
org_id: org.id,
|
||||||
}
|
}
|
||||||
await createCollection(collection)
|
await createCollection(collection, session.data?.tokens?.access_token)
|
||||||
await revalidateTags(['collections'], org.slug)
|
await revalidateTags(['collections'], org.slug)
|
||||||
// reload the page
|
// reload the page
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import AuthenticatedClientElement from '@components/Security/AuthenticatedClient
|
||||||
import TypeOfContentTitle from '@components/StyledElements/Titles/TypeOfContentTitle'
|
import TypeOfContentTitle from '@components/StyledElements/Titles/TypeOfContentTitle'
|
||||||
import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper'
|
import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper'
|
||||||
import { getUriWithOrg } from '@services/config/config'
|
import { getUriWithOrg } from '@services/config/config'
|
||||||
import { getOrgCollectionsWithAuthHeader } from '@services/courses/collections'
|
|
||||||
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { cookies } from 'next/headers'
|
import { cookies } from 'next/headers'
|
||||||
|
|
@ -11,6 +10,9 @@ import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
||||||
import CollectionThumbnail from '@components/Objects/Thumbnails/CollectionThumbnail'
|
import CollectionThumbnail from '@components/Objects/Thumbnails/CollectionThumbnail'
|
||||||
import NewCollectionButton from '@components/StyledElements/Buttons/NewCollectionButton'
|
import NewCollectionButton from '@components/StyledElements/Buttons/NewCollectionButton'
|
||||||
import ContentPlaceHolderIfUserIsNotAdmin from '@components/ContentPlaceHolder'
|
import ContentPlaceHolderIfUserIsNotAdmin from '@components/ContentPlaceHolder'
|
||||||
|
import { nextAuthOptions } from 'app/auth/options'
|
||||||
|
import { getServerSession } from 'next-auth'
|
||||||
|
import { getOrgCollections } from '@services/courses/collections'
|
||||||
|
|
||||||
type MetadataProps = {
|
type MetadataProps = {
|
||||||
params: { orgslug: string; courseid: string }
|
params: { orgslug: string; courseid: string }
|
||||||
|
|
@ -49,15 +51,15 @@ export async function generateMetadata({
|
||||||
}
|
}
|
||||||
|
|
||||||
const CollectionsPage = async (params: any) => {
|
const CollectionsPage = async (params: any) => {
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
const orgslug = params.params.orgslug
|
const orgslug = params.params.orgslug
|
||||||
const org = await getOrganizationContextInfo(orgslug, {
|
const org = await getOrganizationContextInfo(orgslug, {
|
||||||
revalidate: 1800,
|
revalidate: 1800,
|
||||||
tags: ['organizations'],
|
tags: ['organizations'],
|
||||||
})
|
})
|
||||||
const org_id = org.id
|
const org_id = org.id
|
||||||
const collections = await getOrgCollectionsWithAuthHeader(
|
const collections = await getOrgCollections(
|
||||||
org_id,
|
org_id,
|
||||||
access_token ? access_token : null,
|
access_token ? access_token : null,
|
||||||
{ revalidate: 0, tags: ['collections'] }
|
{ revalidate: 0, tags: ['collections'] }
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
import { CourseProvider } from '@components/Contexts/CourseContext'
|
import { CourseProvider } from '@components/Contexts/CourseContext'
|
||||||
import AIActivityAsk from '@components/Objects/Activities/AI/AIActivityAsk'
|
import AIActivityAsk from '@components/Objects/Activities/AI/AIActivityAsk'
|
||||||
import AIChatBotProvider from '@components/Contexts/AI/AIChatBotContext'
|
import AIChatBotProvider from '@components/Contexts/AI/AIChatBotContext'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
interface ActivityClientProps {
|
interface ActivityClientProps {
|
||||||
activityid: string
|
activityid: string
|
||||||
|
|
@ -106,11 +107,10 @@ function ActivityClient(props: ActivityClientProps) {
|
||||||
|
|
||||||
{activity ? (
|
{activity ? (
|
||||||
<div
|
<div
|
||||||
className={`p-7 pt-4 drop-shadow-sm rounded-lg ${
|
className={`p-7 pt-4 drop-shadow-sm rounded-lg ${activity.activity_type == 'TYPE_DYNAMIC'
|
||||||
activity.activity_type == 'TYPE_DYNAMIC'
|
|
||||||
? 'bg-white'
|
? 'bg-white'
|
||||||
: 'bg-zinc-950'
|
: 'bg-zinc-950'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{activity.activity_type == 'TYPE_DYNAMIC' && (
|
{activity.activity_type == 'TYPE_DYNAMIC' && (
|
||||||
|
|
@ -147,13 +147,15 @@ export function MarkStatus(props: {
|
||||||
orgslug: string
|
orgslug: string
|
||||||
}) {
|
}) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const session = useLHSession()
|
||||||
console.log(props.course.trail)
|
console.log(props.course.trail)
|
||||||
|
|
||||||
async function markActivityAsCompleteFront() {
|
async function markActivityAsCompleteFront() {
|
||||||
const trail = await markActivityAsComplete(
|
const trail = await markActivityAsComplete(
|
||||||
props.orgslug,
|
props.orgslug,
|
||||||
props.course.course_uuid,
|
props.course.course_uuid,
|
||||||
'activity_' + props.activityid
|
'activity_' + props.activityid,
|
||||||
|
session.data?.tokens?.access_token
|
||||||
)
|
)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import { getActivityWithAuthHeader } from '@services/courses/activities'
|
import { getActivityWithAuthHeader } from '@services/courses/activities'
|
||||||
import { getCourseMetadataWithAuthHeader } from '@services/courses/courses'
|
import { getCourseMetadata } from '@services/courses/courses'
|
||||||
import { cookies } from 'next/headers'
|
import { cookies } from 'next/headers'
|
||||||
import ActivityClient from './activity'
|
import ActivityClient from './activity'
|
||||||
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
||||||
|
import { getServerSession } from 'next-auth'
|
||||||
|
import { nextAuthOptions } from 'app/auth/options'
|
||||||
|
|
||||||
type MetadataProps = {
|
type MetadataProps = {
|
||||||
params: { orgslug: string; courseuuid: string; activityid: string }
|
params: { orgslug: string; courseuuid: string; activityid: string }
|
||||||
|
|
@ -14,15 +16,15 @@ type MetadataProps = {
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
}: MetadataProps): Promise<Metadata> {
|
}: MetadataProps): Promise<Metadata> {
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
|
|
||||||
// Get Org context information
|
// Get Org context information
|
||||||
const org = await getOrganizationContextInfo(params.orgslug, {
|
const org = await getOrganizationContextInfo(params.orgslug, {
|
||||||
revalidate: 1800,
|
revalidate: 1800,
|
||||||
tags: ['organizations'],
|
tags: ['organizations'],
|
||||||
})
|
})
|
||||||
const course_meta = await getCourseMetadataWithAuthHeader(
|
const course_meta = await getCourseMetadata(
|
||||||
params.courseuuid,
|
params.courseuuid,
|
||||||
{ revalidate: 0, tags: ['courses'] },
|
{ revalidate: 0, tags: ['courses'] },
|
||||||
access_token ? access_token : null
|
access_token ? access_token : null
|
||||||
|
|
@ -58,13 +60,13 @@ export async function generateMetadata({
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActivityPage = async (params: any) => {
|
const ActivityPage = async (params: any) => {
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
const activityid = params.params.activityid
|
const activityid = params.params.activityid
|
||||||
const courseuuid = params.params.courseuuid
|
const courseuuid = params.params.courseuuid
|
||||||
const orgslug = params.params.orgslug
|
const orgslug = params.params.orgslug
|
||||||
|
|
||||||
const course_meta = await getCourseMetadataWithAuthHeader(
|
const course_meta = await getCourseMetadata(
|
||||||
courseuuid,
|
courseuuid,
|
||||||
{ revalidate: 0, tags: ['courses'] },
|
{ revalidate: 0, tags: ['courses'] },
|
||||||
access_token ? access_token : null
|
access_token ? access_token : null
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,12 @@ import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
import UserAvatar from '@components/Objects/UserAvatar'
|
import UserAvatar from '@components/Objects/UserAvatar'
|
||||||
import CourseUpdates from '@components/Objects/CourseUpdates/CourseUpdates'
|
import CourseUpdates from '@components/Objects/CourseUpdates/CourseUpdates'
|
||||||
import { CourseProvider } from '@components/Contexts/CourseContext'
|
import { CourseProvider } from '@components/Contexts/CourseContext'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
const CourseClient = (props: any) => {
|
const CourseClient = (props: any) => {
|
||||||
const [user, setUser] = useState<any>({})
|
const [user, setUser] = useState<any>({})
|
||||||
const [learnings, setLearnings] = useState<any>([])
|
const [learnings, setLearnings] = useState<any>([])
|
||||||
|
const session = useLHSession()
|
||||||
const courseuuid = props.courseuuid
|
const courseuuid = props.courseuuid
|
||||||
const orgslug = props.orgslug
|
const orgslug = props.orgslug
|
||||||
const course = props.course
|
const course = props.course
|
||||||
|
|
@ -35,7 +37,7 @@ const CourseClient = (props: any) => {
|
||||||
|
|
||||||
async function startCourseUI() {
|
async function startCourseUI() {
|
||||||
// Create activity
|
// Create activity
|
||||||
await startCourse('course_' + courseuuid, orgslug)
|
await startCourse('course_' + courseuuid, orgslug, session.data?.tokens?.access_token)
|
||||||
await revalidateTags(['courses'], orgslug)
|
await revalidateTags(['courses'], orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
||||||
|
|
@ -54,7 +56,7 @@ const CourseClient = (props: any) => {
|
||||||
|
|
||||||
async function quitCourse() {
|
async function quitCourse() {
|
||||||
// Close activity
|
// Close activity
|
||||||
let activity = await removeCourse('course_' + courseuuid, orgslug)
|
let activity = await removeCourse('course_' + courseuuid, orgslug, session.data?.tokens?.access_token)
|
||||||
// Mutate course
|
// Mutate course
|
||||||
await revalidateTags(['courses'], orgslug)
|
await revalidateTags(['courses'], orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
@ -277,7 +279,7 @@ const CourseClient = (props: any) => {
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
border="border-8"
|
border="border-8"
|
||||||
avatar_url={course.authors[0].avatar_image ? getUserAvatarMediaDirectory(course.authors[0].user_uuid, course.authors[0].avatar_image) : ''}
|
avatar_url={course.authors[0].avatar_image ? getUserAvatarMediaDirectory(course.authors[0].user_uuid, course.authors[0].avatar_image) : ''}
|
||||||
predefined_avatar={course.authors[0].avatar_image ? undefined : 'empty'}
|
predefined_avatar={course.authors[0].avatar_image ? undefined : 'empty'}
|
||||||
width={100}
|
width={100}
|
||||||
/>
|
/>
|
||||||
<div className="-space-y-2 ">
|
<div className="-space-y-2 ">
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import CourseClient from './course'
|
import CourseClient from './course'
|
||||||
import { cookies } from 'next/headers'
|
import { cookies } from 'next/headers'
|
||||||
import { getCourseMetadataWithAuthHeader } from '@services/courses/courses'
|
import { getCourseMetadata } from '@services/courses/courses'
|
||||||
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
||||||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||||
|
import { nextAuthOptions } from 'app/auth/options'
|
||||||
|
import { getServerSession } from 'next-auth'
|
||||||
|
|
||||||
type MetadataProps = {
|
type MetadataProps = {
|
||||||
params: { orgslug: string; courseuuid: string }
|
params: { orgslug: string; courseuuid: string }
|
||||||
|
|
@ -15,15 +17,15 @@ type MetadataProps = {
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
}: MetadataProps): Promise<Metadata> {
|
}: MetadataProps): Promise<Metadata> {
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
|
|
||||||
// Get Org context information
|
// Get Org context information
|
||||||
const org = await getOrganizationContextInfo(params.orgslug, {
|
const org = await getOrganizationContextInfo(params.orgslug, {
|
||||||
revalidate: 1800,
|
revalidate: 1800,
|
||||||
tags: ['organizations'],
|
tags: ['organizations'],
|
||||||
})
|
})
|
||||||
const course_meta = await getCourseMetadataWithAuthHeader(
|
const course_meta = await getCourseMetadata(
|
||||||
params.courseuuid,
|
params.courseuuid,
|
||||||
{ revalidate: 0, tags: ['courses'] },
|
{ revalidate: 0, tags: ['courses'] },
|
||||||
access_token ? access_token : null
|
access_token ? access_token : null
|
||||||
|
|
@ -67,11 +69,11 @@ export async function generateMetadata({
|
||||||
}
|
}
|
||||||
|
|
||||||
const CoursePage = async (params: any) => {
|
const CoursePage = async (params: any) => {
|
||||||
const cookieStore = cookies()
|
|
||||||
const courseuuid = params.params.courseuuid
|
const courseuuid = params.params.courseuuid
|
||||||
const orgslug = params.params.orgslug
|
const orgslug = params.params.orgslug
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const course_meta = await getCourseMetadataWithAuthHeader(
|
const access_token = session?.tokens?.access_token
|
||||||
|
const course_meta = await getCourseMetadata(
|
||||||
courseuuid,
|
courseuuid,
|
||||||
{ revalidate: 0, tags: ['courses'] },
|
{ revalidate: 0, tags: ['courses'] },
|
||||||
access_token ? access_token : null
|
access_token ? access_token : null
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Courses from './courses'
|
import Courses from './courses'
|
||||||
import { getOrgCoursesWithAuthHeader } from '@services/courses/courses'
|
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
||||||
import { cookies } from 'next/headers'
|
import { cookies } from 'next/headers'
|
||||||
import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
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 = {
|
type MetadataProps = {
|
||||||
params: { orgslug: string }
|
params: { orgslug: string }
|
||||||
|
|
@ -49,9 +51,10 @@ const CoursesPage = async (params: any) => {
|
||||||
revalidate: 1800,
|
revalidate: 1800,
|
||||||
tags: ['organizations'],
|
tags: ['organizations'],
|
||||||
})
|
})
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
const courses = await getOrgCoursesWithAuthHeader(
|
|
||||||
|
const courses = await getOrgCourses(
|
||||||
orgslug,
|
orgslug,
|
||||||
{ revalidate: 0, tags: ['courses'] },
|
{ revalidate: 0, tags: ['courses'] },
|
||||||
access_token ? access_token : null
|
access_token ? access_token : null
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { getUriWithOrg } from '@services/config/config'
|
import { getUriWithOrg } from '@services/config/config'
|
||||||
import { getOrgCoursesWithAuthHeader } from '@services/courses/courses'
|
import { getOrgCourses } from '@services/courses/courses'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { getOrgCollectionsWithAuthHeader } from '@services/courses/collections'
|
|
||||||
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
||||||
import { cookies } from 'next/headers'
|
|
||||||
import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper'
|
import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper'
|
||||||
import TypeOfContentTitle from '@components/StyledElements/Titles/TypeOfContentTitle'
|
import TypeOfContentTitle from '@components/StyledElements/Titles/TypeOfContentTitle'
|
||||||
import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
|
||||||
import CourseThumbnail from '@components/Objects/Thumbnails/CourseThumbnail'
|
import CourseThumbnail from '@components/Objects/Thumbnails/CourseThumbnail'
|
||||||
import CollectionThumbnail from '@components/Objects/Thumbnails/CollectionThumbnail'
|
import CollectionThumbnail from '@components/Objects/Thumbnails/CollectionThumbnail'
|
||||||
import AuthenticatedClientElement from '@components/Security/AuthenticatedClientElement'
|
import AuthenticatedClientElement from '@components/Security/AuthenticatedClientElement'
|
||||||
import NewCourseButton from '@components/StyledElements/Buttons/NewCourseButton'
|
import NewCourseButton from '@components/StyledElements/Buttons/NewCourseButton'
|
||||||
import NewCollectionButton from '@components/StyledElements/Buttons/NewCollectionButton'
|
import NewCollectionButton from '@components/StyledElements/Buttons/NewCollectionButton'
|
||||||
import ContentPlaceHolderIfUserIsNotAdmin from '@components/ContentPlaceHolder'
|
import ContentPlaceHolderIfUserIsNotAdmin from '@components/ContentPlaceHolder'
|
||||||
|
import { getOrgCollections } from '@services/courses/collections'
|
||||||
|
import { getServerSession } from 'next-auth'
|
||||||
|
import { nextAuthOptions } from 'app/auth/options'
|
||||||
|
|
||||||
type MetadataProps = {
|
type MetadataProps = {
|
||||||
params: { orgslug: string }
|
params: { orgslug: string }
|
||||||
|
|
@ -54,10 +54,9 @@ export async function generateMetadata({
|
||||||
|
|
||||||
const OrgHomePage = async (params: any) => {
|
const OrgHomePage = async (params: any) => {
|
||||||
const orgslug = params.params.orgslug
|
const orgslug = params.params.orgslug
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
|
const access_token = session?.tokens?.access_token
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const courses = await getOrgCourses(
|
||||||
const courses = await getOrgCoursesWithAuthHeader(
|
|
||||||
orgslug,
|
orgslug,
|
||||||
{ revalidate: 0, tags: ['courses'] },
|
{ revalidate: 0, tags: ['courses'] },
|
||||||
access_token ? access_token : null
|
access_token ? access_token : null
|
||||||
|
|
@ -67,7 +66,7 @@ const OrgHomePage = async (params: any) => {
|
||||||
tags: ['organizations'],
|
tags: ['organizations'],
|
||||||
})
|
})
|
||||||
const org_id = org.id
|
const org_id = org.id
|
||||||
const collections = await getOrgCollectionsWithAuthHeader(
|
const collections = await getOrgCollections(
|
||||||
org.id,
|
org.id,
|
||||||
access_token ? access_token : null,
|
access_token ? access_token : null,
|
||||||
{ revalidate: 0, tags: ['courses'] }
|
{ revalidate: 0, tags: ['courses'] }
|
||||||
|
|
|
||||||
26
apps/web/app/orgs/[orgslug]/dash/ClientAdminLayout.tsx
Normal file
26
apps/web/app/orgs/[orgslug]/dash/ClientAdminLayout.tsx
Normal file
|
|
@ -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 (
|
||||||
|
<SessionProvider>
|
||||||
|
<AdminAuthorization authorizationMode="page">
|
||||||
|
<div className="flex">
|
||||||
|
<LeftMenu />
|
||||||
|
<div className="flex w-full">{children}</div>
|
||||||
|
</div>
|
||||||
|
</AdminAuthorization>
|
||||||
|
</SessionProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ClientAdminLayout
|
||||||
|
|
@ -30,7 +30,6 @@ function CoursesHome(params: CourseProps) {
|
||||||
<div>
|
<div>
|
||||||
<div className="pl-10 mr-10 tracking-tighter">
|
<div className="pl-10 mr-10 tracking-tighter">
|
||||||
<BreadCrumbs type="courses" />
|
<BreadCrumbs type="courses" />
|
||||||
|
|
||||||
<div className="w-100 flex justify-between">
|
<div className="w-100 flex justify-between">
|
||||||
<div className="pt-3 flex font-bold text-4xl">Courses</div>
|
<div className="pt-3 flex font-bold text-4xl">Courses</div>
|
||||||
<AuthenticatedClientElement
|
<AuthenticatedClientElement
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { getAccessTokenFromRefreshTokenCookie } from '@services/auth/auth'
|
|
||||||
import { getOrgCoursesWithAuthHeader } from '@services/courses/courses'
|
|
||||||
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
import { getOrganizationContextInfo } from '@services/organizations/orgs'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { cookies } from 'next/headers'
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import CoursesHome from './client'
|
import CoursesHome from './client'
|
||||||
|
import { nextAuthOptions } from 'app/auth/options'
|
||||||
|
import { getServerSession } from 'next-auth'
|
||||||
|
import { getOrgCourses } from '@services/courses/courses'
|
||||||
|
|
||||||
type MetadataProps = {
|
type MetadataProps = {
|
||||||
params: { orgslug: string }
|
params: { orgslug: string }
|
||||||
|
|
@ -49,9 +49,9 @@ async function CoursesPage(params: any) {
|
||||||
revalidate: 1800,
|
revalidate: 1800,
|
||||||
tags: ['organizations'],
|
tags: ['organizations'],
|
||||||
})
|
})
|
||||||
const cookieStore = cookies()
|
const session = await getServerSession(nextAuthOptions)
|
||||||
const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore)
|
const access_token = session?.tokens?.access_token
|
||||||
const courses = await getOrgCoursesWithAuthHeader(
|
const courses = await getOrgCourses(
|
||||||
orgslug,
|
orgslug,
|
||||||
{ revalidate: 0, tags: ['courses'] },
|
{ revalidate: 0, tags: ['courses'] },
|
||||||
access_token ? access_token : null
|
access_token ? access_token : null
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import ClientComponentSkeleton from '@components/Utils/ClientComp'
|
||||||
import { Metadata } from 'next'
|
import { Metadata } from 'next'
|
||||||
import { SessionProvider } from 'next-auth/react'
|
import { SessionProvider } from 'next-auth/react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import ClientAdminLayout from './ClientAdminLayout'
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'LearnHouse Dashboard',
|
title: 'LearnHouse Dashboard',
|
||||||
|
|
@ -18,12 +19,10 @@ function DashboardLayout({
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AdminAuthorization authorizationMode="page">
|
<ClientAdminLayout
|
||||||
<div className="flex">
|
params={params}>
|
||||||
<LeftMenu />
|
{children}
|
||||||
<div className="flex w-full">{children}</div>
|
</ClientAdminLayout>
|
||||||
</div>
|
|
||||||
</AdminAuthorization>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import Link from 'next/link'
|
||||||
import { getUriWithOrg } from '@services/config/config'
|
import { getUriWithOrg } from '@services/config/config'
|
||||||
import { Info, Lock } from 'lucide-react'
|
import { Info, Lock } from 'lucide-react'
|
||||||
import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs'
|
import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
export type SettingsParams = {
|
export type SettingsParams = {
|
||||||
subpage: string
|
subpage: string
|
||||||
|
|
@ -15,7 +15,7 @@ export type SettingsParams = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function SettingsPage({ params }: { params: SettingsParams }) {
|
function SettingsPage({ params }: { params: SettingsParams }) {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
|
|
||||||
useEffect(() => {}, [session])
|
useEffect(() => {}, [session])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import Link from 'next/link'
|
||||||
import { getUriWithOrg } from '@services/config/config'
|
import { getUriWithOrg } from '@services/config/config'
|
||||||
import { ScanEye, SquareUserRound, UserPlus, Users } from 'lucide-react'
|
import { ScanEye, SquareUserRound, UserPlus, Users } from 'lucide-react'
|
||||||
import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs'
|
import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { useOrg } from '@components/Contexts/OrgContext'
|
import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
import OrgUsers from '@components/Dashboard/Users/OrgUsers/OrgUsers'
|
import OrgUsers from '@components/Dashboard/Users/OrgUsers/OrgUsers'
|
||||||
import OrgAccess from '@components/Dashboard/Users/OrgAccess/OrgAccess'
|
import OrgAccess from '@components/Dashboard/Users/OrgAccess/OrgAccess'
|
||||||
|
|
@ -18,7 +18,7 @@ export type SettingsParams = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function UsersSettingsPage({ params }: { params: SettingsParams }) {
|
function UsersSettingsPage({ params }: { params: SettingsParams }) {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const org = useOrg() as any
|
const org = useOrg() as any
|
||||||
const [H1Label, setH1Label] = React.useState('')
|
const [H1Label, setH1Label] = React.useState('')
|
||||||
const [H2Label, setH2Label] = React.useState('')
|
const [H2Label, setH2Label] = React.useState('')
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
import LHSessionProvider from '@components/Contexts/LHSessionContext'
|
||||||
import { OrgProvider } from '@components/Contexts/OrgContext'
|
import { OrgProvider } from '@components/Contexts/OrgContext'
|
||||||
import Toast from '@components/StyledElements/Toast/Toast'
|
import Toast from '@components/StyledElements/Toast/Toast'
|
||||||
import '@styles/globals.css'
|
import '@styles/globals.css'
|
||||||
import { SessionProvider } from 'next-auth/react'
|
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
children,
|
children,
|
||||||
|
|
@ -13,9 +13,9 @@ export default function RootLayout({
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Toast />
|
|
||||||
<OrgProvider orgslug={params.orgslug}>
|
<OrgProvider orgslug={params.orgslug}>
|
||||||
<SessionProvider>{children}</SessionProvider>
|
<Toast />
|
||||||
|
{children}
|
||||||
</OrgProvider>
|
</OrgProvider>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@ import * as Form from '@radix-ui/react-form'
|
||||||
import { useFormik } from 'formik'
|
import { useFormik } from 'formik'
|
||||||
import { getOrgLogoMediaDirectory } from '@services/media/media'
|
import { getOrgLogoMediaDirectory } from '@services/media/media'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { loginAndGetToken } from '@services/auth/auth'
|
|
||||||
import { AlertTriangle } from 'lucide-react'
|
import { AlertTriangle } from 'lucide-react'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { signIn, useSession } from "next-auth/react"
|
import { signIn, useSession } from "next-auth/react"
|
||||||
import { getUriWithOrg } from '@services/config/config'
|
import { getUriWithOrg } from '@services/config/config'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
interface LoginClientProps {
|
interface LoginClientProps {
|
||||||
org: any
|
org: any
|
||||||
|
|
@ -42,7 +42,7 @@ const validate = (values: any) => {
|
||||||
const LoginClient = (props: LoginClientProps) => {
|
const LoginClient = (props: LoginClientProps) => {
|
||||||
const [isSubmitting, setIsSubmitting] = React.useState(false)
|
const [isSubmitting, setIsSubmitting] = React.useState(false)
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const session = useSession();
|
const session = useLHSession();
|
||||||
|
|
||||||
const [error, setError] = React.useState('')
|
const [error, setError] = React.useState('')
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
|
|
@ -53,19 +53,21 @@ const LoginClient = (props: LoginClientProps) => {
|
||||||
validate,
|
validate,
|
||||||
onSubmit: async (values) => {
|
onSubmit: async (values) => {
|
||||||
setIsSubmitting(true)
|
setIsSubmitting(true)
|
||||||
//let res = await loginAndGetToken(values.email, values.password)
|
|
||||||
const res = await signIn('credentials', {
|
const res = await signIn('credentials', {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
email: values.email,
|
email: values.email,
|
||||||
password: values.password,
|
password: values.password,
|
||||||
|
callbackUrl: '/'
|
||||||
});
|
});
|
||||||
if (res && res.error) {
|
if (res && res.error) {
|
||||||
setError("Wrong Email or password");
|
setError("Wrong Email or password");
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
}
|
}else {
|
||||||
else {
|
await signIn('credentials', {
|
||||||
router.push(`/`)
|
email: values.email,
|
||||||
setIsSubmitting(false)
|
password: values.password,
|
||||||
|
callbackUrl: '/'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import Image from 'next/image'
|
||||||
import { getOrgLogoMediaDirectory } from '@services/media/media'
|
import { getOrgLogoMediaDirectory } from '@services/media/media'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { getUriWithOrg } from '@services/config/config'
|
import { getUriWithOrg } from '@services/config/config'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { MailWarning, Shield, Ticket, UserPlus } from 'lucide-react'
|
import { MailWarning, Shield, Ticket, UserPlus } from 'lucide-react'
|
||||||
import { useOrg } from '@components/Contexts/OrgContext'
|
import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
|
|
@ -22,7 +22,7 @@ interface SignUpClientProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function SignUpClient(props: SignUpClientProps) {
|
function SignUpClient(props: SignUpClientProps) {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const [joinMethod, setJoinMethod] = React.useState('open')
|
const [joinMethod, setJoinMethod] = React.useState('open')
|
||||||
const [inviteCode, setInviteCode] = React.useState('')
|
const [inviteCode, setInviteCode] = React.useState('')
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
|
|
@ -113,7 +113,7 @@ function SignUpClient(props: SignUpClientProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const LoggedInJoinScreen = (props: any) => {
|
const LoggedInJoinScreen = (props: any) => {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const org = useOrg() as any
|
const org = useOrg() as any
|
||||||
const [isLoading, setIsLoading] = React.useState(true)
|
const [isLoading, setIsLoading] = React.useState(true)
|
||||||
|
|
||||||
|
|
@ -144,7 +144,7 @@ const LoggedInJoinScreen = (props: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const NoTokenScreen = (props: any) => {
|
const NoTokenScreen = (props: any) => {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const org = useOrg() as any
|
const org = useOrg() as any
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [isLoading, setIsLoading] = React.useState(true)
|
const [isLoading, setIsLoading] = React.useState(true)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { getAPIUrl } from '@services/config/config'
|
||||||
import { swrFetcher } from '@services/utils/ts/requests'
|
import { swrFetcher } from '@services/utils/ts/requests'
|
||||||
import React, { createContext, useContext, useEffect, useReducer } from 'react'
|
import React, { createContext, useContext, useEffect, useReducer } from 'react'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
export const CourseContext = createContext(null) as any
|
export const CourseContext = createContext(null) as any
|
||||||
export const CourseDispatchContext = createContext(null) as any
|
export const CourseDispatchContext = createContext(null) as any
|
||||||
|
|
@ -15,9 +16,11 @@ export function CourseProvider({
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
courseuuid: string
|
courseuuid: string
|
||||||
}) {
|
}) {
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const { data: courseStructureData } = useSWR(
|
const { data: courseStructureData } = useSWR(
|
||||||
`${getAPIUrl()}courses/${courseuuid}/meta`,
|
`${getAPIUrl()}courses/${courseuuid}/meta`,
|
||||||
swrFetcher
|
(url) => swrFetcher(url, access_token)
|
||||||
)
|
)
|
||||||
const [courseStructure, dispatchCourseStructure] = useReducer(courseReducer, {
|
const [courseStructure, dispatchCourseStructure] = useReducer(courseReducer, {
|
||||||
courseStructure: courseStructureData ? courseStructureData : {},
|
courseStructure: courseStructureData ? courseStructureData : {},
|
||||||
|
|
@ -33,7 +36,7 @@ export function CourseProvider({
|
||||||
payload: courseStructureData,
|
payload: courseStructureData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [courseStructureData])
|
}, [courseStructureData,session])
|
||||||
|
|
||||||
if (!courseStructureData) return <PageLoading></PageLoading>
|
if (!courseStructureData) return <PageLoading></PageLoading>
|
||||||
|
|
||||||
|
|
|
||||||
33
apps/web/components/Contexts/LHSessionContext.tsx
Normal file
33
apps/web/components/Contexts/LHSessionContext.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
'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(() => {
|
||||||
|
console.log('useLHSession', session);
|
||||||
|
}, [session])
|
||||||
|
|
||||||
|
|
||||||
|
if (session.status == 'loading') {
|
||||||
|
return <PageLoading />
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
<SessionContext.Provider value={session}>
|
||||||
|
{children}
|
||||||
|
</SessionContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useLHSession() {
|
||||||
|
return useContext(SessionContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LHSessionProvider
|
||||||
|
|
@ -5,6 +5,8 @@ import React, { useContext, useEffect } from 'react'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
import { createContext } from 'react'
|
import { createContext } from 'react'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
import ErrorUI from '@components/StyledElements/Error/Error'
|
||||||
|
|
||||||
export const OrgContext = createContext({}) as any
|
export const OrgContext = createContext({}) as any
|
||||||
|
|
||||||
|
|
@ -15,7 +17,10 @@ export function OrgProvider({
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
orgslug: string
|
orgslug: string
|
||||||
}) {
|
}) {
|
||||||
const { data: org } = useSWR(`${getAPIUrl()}orgs/slug/${orgslug}`, swrFetcher)
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
|
const { data: org } = useSWR(`${getAPIUrl()}orgs/slug/${orgslug}`, (url) => swrFetcher(url, access_token))
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
// Check if Org is Active
|
// Check if Org is Active
|
||||||
const verifyIfOrgIsActive = () => {
|
const verifyIfOrgIsActive = () => {
|
||||||
|
|
@ -28,7 +33,12 @@ export function OrgProvider({
|
||||||
verifyIfOrgIsActive()
|
verifyIfOrgIsActive()
|
||||||
}, [org])
|
}, [org])
|
||||||
|
|
||||||
return <OrgContext.Provider value={org}>{children}</OrgContext.Provider>
|
if (org) {
|
||||||
|
return <OrgContext.Provider value={org}>{children}</OrgContext.Provider>
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return <ErrorUI />
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useOrg() {
|
export function useOrg() {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { getAPIUrl } from '@services/config/config'
|
||||||
import { unLinkResourcesToUserGroup } from '@services/usergroups/usergroups'
|
import { unLinkResourcesToUserGroup } from '@services/usergroups/usergroups'
|
||||||
import { swrFetcher } from '@services/utils/ts/requests'
|
import { swrFetcher } from '@services/utils/ts/requests'
|
||||||
import { Globe, SquareUserRound, Users, UsersRound, X } from 'lucide-react'
|
import { Globe, SquareUserRound, Users, UsersRound, X } from 'lucide-react'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import useSWR, { mutate } from 'swr'
|
import useSWR, { mutate } from 'swr'
|
||||||
|
|
@ -17,13 +18,15 @@ type EditCourseAccessProps = {
|
||||||
|
|
||||||
function EditCourseAccess(props: EditCourseAccessProps) {
|
function EditCourseAccess(props: EditCourseAccessProps) {
|
||||||
const [error, setError] = React.useState('')
|
const [error, setError] = React.useState('')
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
|
|
||||||
const course = useCourse() as any
|
const course = useCourse() as any
|
||||||
const dispatchCourse = useCourseDispatch() as any
|
const dispatchCourse = useCourseDispatch() as any
|
||||||
const courseStructure = course.courseStructure
|
const courseStructure = course.courseStructure
|
||||||
const { data: usergroups } = useSWR(
|
const { data: usergroups } = useSWR(
|
||||||
courseStructure ? `${getAPIUrl()}usergroups/resource/${courseStructure.course_uuid}` : null,
|
courseStructure ? `${getAPIUrl()}usergroups/resource/${courseStructure.course_uuid}` : null,
|
||||||
swrFetcher
|
(url) => swrFetcher(url, access_token)
|
||||||
)
|
)
|
||||||
const [isPublic, setIsPublic] = React.useState(courseStructure.public)
|
const [isPublic, setIsPublic] = React.useState(courseStructure.public)
|
||||||
|
|
||||||
|
|
@ -109,7 +112,7 @@ function EditCourseAccess(props: EditCourseAccessProps) {
|
||||||
status="info"
|
status="info"
|
||||||
></ConfirmationModal>
|
></ConfirmationModal>
|
||||||
</div>
|
</div>
|
||||||
{!isPublic ? ( <UserGroupsSection usergroups={usergroups} />) : null}
|
{!isPublic ? (<UserGroupsSection usergroups={usergroups} />) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,13 @@ import { getAPIUrl } from '@services/config/config'
|
||||||
import { updateCourseThumbnail } from '@services/courses/courses'
|
import { updateCourseThumbnail } from '@services/courses/courses'
|
||||||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||||
import { ArrowBigUpDash, UploadCloud } from 'lucide-react'
|
import { ArrowBigUpDash, UploadCloud } from 'lucide-react'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { mutate } from 'swr'
|
import { mutate } from 'swr'
|
||||||
|
|
||||||
function ThumbnailUpdate() {
|
function ThumbnailUpdate() {
|
||||||
const course = useCourse() as any
|
const course = useCourse() as any
|
||||||
|
const session = useLHSession()
|
||||||
const org = useOrg() as any
|
const org = useOrg() as any
|
||||||
const [localThumbnail, setLocalThumbnail] = React.useState(null) as any
|
const [localThumbnail, setLocalThumbnail] = React.useState(null) as any
|
||||||
const [isLoading, setIsLoading] = React.useState(false) as any
|
const [isLoading, setIsLoading] = React.useState(false) as any
|
||||||
|
|
@ -20,7 +22,8 @@ function ThumbnailUpdate() {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
const res = await updateCourseThumbnail(
|
const res = await updateCourseThumbnail(
|
||||||
course.courseStructure.course_uuid,
|
course.courseStructure.course_uuid,
|
||||||
file
|
file,
|
||||||
|
session.data?.tokens?.access_token
|
||||||
)
|
)
|
||||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||||
// wait for 1 second to show loading animation
|
// wait for 1 second to show loading animation
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import {
|
||||||
import { getOrganizationContextInfoWithoutCredentials } from '@services/organizations/orgs'
|
import { getOrganizationContextInfoWithoutCredentials } from '@services/organizations/orgs'
|
||||||
import { revalidateTags } from '@services/utils/ts/requests'
|
import { revalidateTags } from '@services/utils/ts/requests'
|
||||||
import { Layers } from 'lucide-react'
|
import { Layers } from 'lucide-react'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { mutate } from 'swr'
|
import { mutate } from 'swr'
|
||||||
|
|
@ -23,6 +24,8 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
||||||
const [newActivityModal, setNewActivityModal] = React.useState(false)
|
const [newActivityModal, setNewActivityModal] = React.useState(false)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const course = useCourse() as any
|
const course = useCourse() as any
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
|
|
||||||
const openNewActivityModal = async (chapterId: any) => {
|
const openNewActivityModal = async (chapterId: any) => {
|
||||||
setNewActivityModal(true)
|
setNewActivityModal(true)
|
||||||
|
|
@ -38,7 +41,7 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
||||||
props.orgslug,
|
props.orgslug,
|
||||||
{ revalidate: 1800 }
|
{ 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`)
|
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||||
setNewActivityModal(false)
|
setNewActivityModal(false)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
|
|
@ -52,7 +55,7 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
||||||
activity: any,
|
activity: any,
|
||||||
chapterId: string
|
chapterId: string
|
||||||
) => {
|
) => {
|
||||||
await createFileActivity(file, type, activity, chapterId)
|
await createFileActivity(file, type, activity, chapterId, access_token)
|
||||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||||
setNewActivityModal(false)
|
setNewActivityModal(false)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
|
|
@ -68,7 +71,7 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
||||||
await createExternalVideoActivity(
|
await createExternalVideoActivity(
|
||||||
external_video_data,
|
external_video_data,
|
||||||
activity,
|
activity,
|
||||||
props.chapterId
|
props.chapterId, access_token
|
||||||
)
|
)
|
||||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||||
setNewActivityModal(false)
|
setNewActivityModal(false)
|
||||||
|
|
@ -76,7 +79,7 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
||||||
router.refresh()
|
router.refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {}, [course])
|
useEffect(() => { }, [course])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import {
|
||||||
Video,
|
Video,
|
||||||
X,
|
X,
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
@ -32,6 +33,8 @@ interface ModifiedActivityInterface {
|
||||||
|
|
||||||
function ActivityElement(props: ActivitiyElementProps) {
|
function ActivityElement(props: ActivitiyElementProps) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const [modifiedActivity, setModifiedActivity] = React.useState<
|
const [modifiedActivity, setModifiedActivity] = React.useState<
|
||||||
ModifiedActivityInterface | undefined
|
ModifiedActivityInterface | undefined
|
||||||
>(undefined)
|
>(undefined)
|
||||||
|
|
@ -41,7 +44,7 @@ function ActivityElement(props: ActivitiyElementProps) {
|
||||||
const activityUUID = props.activity.activity_uuid
|
const activityUUID = props.activity.activity_uuid
|
||||||
|
|
||||||
async function deleteActivityUI() {
|
async function deleteActivityUI() {
|
||||||
await deleteActivity(props.activity.activity_uuid)
|
await deleteActivity(props.activity.activity_uuid,access_token)
|
||||||
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
@ -60,7 +63,7 @@ function ActivityElement(props: ActivitiyElementProps) {
|
||||||
content: props.activity.content,
|
content: props.activity.content,
|
||||||
}
|
}
|
||||||
|
|
||||||
await updateActivity(modifiedActivityCopy, activityUUID)
|
await updateActivity(modifiedActivityCopy, activityUUID,access_token)
|
||||||
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import { revalidateTags } from '@services/utils/ts/requests'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { getAPIUrl } from '@services/config/config'
|
import { getAPIUrl } from '@services/config/config'
|
||||||
import { mutate } from 'swr'
|
import { mutate } from 'swr'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
type ChapterElementProps = {
|
type ChapterElementProps = {
|
||||||
chapter: any
|
chapter: any
|
||||||
|
|
@ -31,6 +32,8 @@ interface ModifiedChapterInterface {
|
||||||
|
|
||||||
function ChapterElement(props: ChapterElementProps) {
|
function ChapterElement(props: ChapterElementProps) {
|
||||||
const activities = props.chapter.activities || []
|
const activities = props.chapter.activities || []
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const [modifiedChapter, setModifiedChapter] = React.useState<
|
const [modifiedChapter, setModifiedChapter] = React.useState<
|
||||||
ModifiedChapterInterface | undefined
|
ModifiedChapterInterface | undefined
|
||||||
>(undefined)
|
>(undefined)
|
||||||
|
|
@ -41,7 +44,7 @@ function ChapterElement(props: ChapterElementProps) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const deleteChapterUI = async () => {
|
const deleteChapterUI = async () => {
|
||||||
await deleteChapter(props.chapter.id)
|
await deleteChapter(props.chapter.id, access_token)
|
||||||
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
@ -53,7 +56,7 @@ function ChapterElement(props: ChapterElementProps) {
|
||||||
let modifiedChapterCopy = {
|
let modifiedChapterCopy = {
|
||||||
name: modifiedChapter.chapterName,
|
name: modifiedChapter.chapterName,
|
||||||
}
|
}
|
||||||
await updateChapter(chapterId, modifiedChapterCopy)
|
await updateChapter(chapterId, modifiedChapterCopy, access_token)
|
||||||
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import {
|
||||||
import { Hexagon } from 'lucide-react'
|
import { Hexagon } from 'lucide-react'
|
||||||
import Modal from '@components/StyledElements/Modal/Modal'
|
import Modal from '@components/StyledElements/Modal/Modal'
|
||||||
import NewChapterModal from '@components/Objects/Modals/Chapters/NewChapter'
|
import NewChapterModal from '@components/Objects/Modals/Chapters/NewChapter'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
type EditCourseStructureProps = {
|
type EditCourseStructureProps = {
|
||||||
orgslug: string
|
orgslug: string
|
||||||
|
|
@ -38,6 +39,8 @@ export type OrderPayload =
|
||||||
|
|
||||||
const EditCourseStructure = (props: EditCourseStructureProps) => {
|
const EditCourseStructure = (props: EditCourseStructureProps) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
// Check window availability
|
// Check window availability
|
||||||
const [winReady, setwinReady] = useState(false)
|
const [winReady, setwinReady] = useState(false)
|
||||||
|
|
||||||
|
|
@ -57,7 +60,7 @@ const EditCourseStructure = (props: EditCourseStructureProps) => {
|
||||||
|
|
||||||
// Submit new chapter
|
// Submit new chapter
|
||||||
const submitChapter = async (chapter: any) => {
|
const submitChapter = async (chapter: any) => {
|
||||||
await createChapter(chapter)
|
await createChapter(chapter,access_token)
|
||||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
'use client'
|
'use client'
|
||||||
import { useOrg } from '@components/Contexts/OrgContext'
|
import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
import { useSession } from 'next-auth/react'
|
import { signOut } from 'next-auth/react'
|
||||||
import ToolTip from '@components/StyledElements/Tooltip/Tooltip'
|
import ToolTip from '@components/StyledElements/Tooltip/Tooltip'
|
||||||
import LearnHouseDashboardLogo from '@public/dashLogo.png'
|
import LearnHouseDashboardLogo from '@public/dashLogo.png'
|
||||||
import { logout } from '@services/auth/auth'
|
|
||||||
import { BookCopy, Home, LogOut, School, Settings, Users } from 'lucide-react'
|
import { BookCopy, Home, LogOut, School, Settings, Users } from 'lucide-react'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
@ -11,10 +10,11 @@ import { useRouter } from 'next/navigation'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import UserAvatar from '../../Objects/UserAvatar'
|
import UserAvatar from '../../Objects/UserAvatar'
|
||||||
import AdminAuthorization from '@components/Security/AdminAuthorization'
|
import AdminAuthorization from '@components/Security/AdminAuthorization'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
function LeftMenu() {
|
function LeftMenu() {
|
||||||
const org = useOrg() as any
|
const org = useOrg() as any
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const [loading, setLoading] = React.useState(true)
|
const [loading, setLoading] = React.useState(true)
|
||||||
const route = useRouter()
|
const route = useRouter()
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ function LeftMenu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logOutUI() {
|
async function logOutUI() {
|
||||||
const res = await logout()
|
const res = await signOut()
|
||||||
if (res) {
|
if (res) {
|
||||||
route.push('/login')
|
route.push('/login')
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@ import { useRouter } from 'next/navigation'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { mutate } from 'swr'
|
import { mutate } from 'swr'
|
||||||
import { updateCourse } from '@services/courses/courses'
|
import { updateCourse } from '@services/courses/courses'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
function SaveState(props: { orgslug: string }) {
|
function SaveState(props: { orgslug: string }) {
|
||||||
const course = useCourse() as any
|
const course = useCourse() as any
|
||||||
|
const session = useLHSession() as any;
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const saved = course ? course.isSaved : true
|
const saved = course ? course.isSaved : true
|
||||||
const dispatchCourse = useCourseDispatch() as any
|
const dispatchCourse = useCourseDispatch() as any
|
||||||
|
|
@ -37,7 +39,8 @@ function SaveState(props: { orgslug: string }) {
|
||||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||||
await updateCourseOrderStructure(
|
await updateCourseOrderStructure(
|
||||||
course.courseStructure.course_uuid,
|
course.courseStructure.course_uuid,
|
||||||
course.courseOrder
|
course.courseOrder,
|
||||||
|
session.data?.tokens?.access_token
|
||||||
)
|
)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
@ -49,7 +52,8 @@ function SaveState(props: { orgslug: string }) {
|
||||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||||
await updateCourse(
|
await updateCourse(
|
||||||
course.courseStructure.course_uuid,
|
course.courseStructure.course_uuid,
|
||||||
course.courseStructure
|
course.courseStructure,
|
||||||
|
session.data?.tokens?.access_token
|
||||||
)
|
)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { updateProfile } from '@services/settings/profile'
|
import { updateProfile } from '@services/settings/profile'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { Formik, Form, Field } from 'formik'
|
import { Formik, Form, Field } from 'formik'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import {
|
import {
|
||||||
ArrowBigUpDash,
|
ArrowBigUpDash,
|
||||||
Check,
|
Check,
|
||||||
|
|
@ -14,7 +14,7 @@ import UserAvatar from '@components/Objects/UserAvatar'
|
||||||
import { updateUserAvatar } from '@services/users/users'
|
import { updateUserAvatar } from '@services/users/users'
|
||||||
|
|
||||||
function UserEditGeneral() {
|
function UserEditGeneral() {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const [localAvatar, setLocalAvatar] = React.useState(null) as any
|
const [localAvatar, setLocalAvatar] = React.useState(null) as any
|
||||||
const [isLoading, setIsLoading] = React.useState(false) as any
|
const [isLoading, setIsLoading] = React.useState(false) as any
|
||||||
const [error, setError] = React.useState() as any
|
const [error, setError] = React.useState() as any
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { updatePassword } from '@services/settings/password'
|
import { updatePassword } from '@services/settings/password'
|
||||||
import { Formik, Form, Field } from 'formik'
|
import { Formik, Form, Field } from 'formik'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
|
||||||
function UserEditPassword() {
|
function UserEditPassword() {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
|
|
||||||
const updatePasswordUI = async (values: any) => {
|
const updatePasswordUI = async (values: any) => {
|
||||||
let user_id = session.data.user.id
|
let user_id = session.data.user.id
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,40 @@
|
||||||
import { useOrg } from '@components/Contexts/OrgContext'
|
import { useOrg } from '@components/Contexts/OrgContext';
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext';
|
||||||
import { useEffect } from 'react'
|
import { useEffect, useState, useMemo } from 'react';
|
||||||
|
|
||||||
|
interface Role {
|
||||||
|
org: { id: number };
|
||||||
|
role: { id: number; role_uuid: string };
|
||||||
|
}
|
||||||
|
|
||||||
function useAdminStatus() {
|
function useAdminStatus() {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any;
|
||||||
const org = useOrg() as any
|
const org = useOrg() as any;
|
||||||
console.log('useAdminStatus', {
|
const [isAdmin, setIsAdmin] = useState<boolean | null>(null);
|
||||||
session,
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
})
|
|
||||||
|
|
||||||
// If session is not loaded, redirect to login
|
const userRoles = useMemo(() => session?.data?.roles || [], [session?.data?.roles]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (session.status == 'loading') {
|
if (session.status === 'authenticated' && org?.id) {
|
||||||
return
|
const isAdminVar = userRoles.some((role: Role) => {
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
, [session])
|
|
||||||
|
|
||||||
const isUserAdmin = () => {
|
|
||||||
if (session.status == 'authenticated') {
|
|
||||||
const isAdmin = session?.data?.roles.some((role: any) => {
|
|
||||||
return (
|
return (
|
||||||
role.org.id === org.id &&
|
role.org.id === org.id &&
|
||||||
(role.role.id === 1 ||
|
(role.role.id === 1 ||
|
||||||
role.role.id === 2 ||
|
role.role.id === 2 ||
|
||||||
role.role.role_uuid === 'role_global_admin' ||
|
role.role.role_uuid === 'role_global_admin' ||
|
||||||
role.role.role_uuid === 'role_global_maintainer')
|
role.role.role_uuid === 'role_global_maintainer')
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
return isAdmin
|
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
|
||||||
}
|
}
|
||||||
return false
|
}, [session.status, userRoles, org.id]);
|
||||||
}
|
|
||||||
|
|
||||||
// Return the user admin status
|
|
||||||
return isUserAdmin()
|
|
||||||
|
|
||||||
|
return { isAdmin, loading };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useAdminStatus
|
export default useAdminStatus;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import {
|
import {
|
||||||
sendActivityAIChatMessage,
|
sendActivityAIChatMessage,
|
||||||
startActivityAIChatSession,
|
startActivityAIChatSession,
|
||||||
|
|
@ -74,7 +74,7 @@ type ActivityChatMessageBoxProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
|
function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes
|
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes
|
||||||
const dispatchAIChatBot = useAIChatBotDispatch() as any
|
const dispatchAIChatBot = useAIChatBotDispatch() as any
|
||||||
|
|
||||||
|
|
@ -328,7 +328,7 @@ type AIMessageProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function AIMessage(props: AIMessageProps) {
|
function AIMessage(props: AIMessageProps) {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
|
|
||||||
const words = props.message.message.split(' ')
|
const words = props.message.message.split(' ')
|
||||||
|
|
||||||
|
|
@ -378,7 +378,7 @@ const AIMessagePlaceHolder = (props: {
|
||||||
activity_uuid: string
|
activity_uuid: string
|
||||||
sendMessage: any
|
sendMessage: any
|
||||||
}) => {
|
}) => {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const [feedbackModal, setFeedbackModal] = React.useState(false)
|
const [feedbackModal, setFeedbackModal] = React.useState(false)
|
||||||
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes
|
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,15 @@ import toast from 'react-hot-toast'
|
||||||
import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal'
|
import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal'
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
dayjs.extend(relativeTime);
|
dayjs.extend(relativeTime);
|
||||||
|
|
||||||
function CourseUpdates() {
|
function CourseUpdates() {
|
||||||
const course = useCourse() as any;
|
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)
|
const [isModelOpen, setIsModelOpen] = React.useState(false)
|
||||||
|
|
||||||
function handleModelOpen() {
|
function handleModelOpen() {
|
||||||
|
|
@ -71,7 +74,7 @@ function CourseUpdates() {
|
||||||
|
|
||||||
const UpdatesSection = () => {
|
const UpdatesSection = () => {
|
||||||
const [selectedView, setSelectedView] = React.useState('list')
|
const [selectedView, setSelectedView] = React.useState('list')
|
||||||
const isAdmin = useAdminStatus() as boolean;
|
const adminStatus = useAdminStatus() ;
|
||||||
return (
|
return (
|
||||||
<div className='bg-white/95 backdrop-blur-md nice-shadow rounded-lg w-[700px] overflow-hidden'>
|
<div className='bg-white/95 backdrop-blur-md nice-shadow rounded-lg w-[700px] overflow-hidden'>
|
||||||
<div className='bg-gray-50/70 flex justify-between outline outline-1 rounded-lg outline-neutral-200/40'>
|
<div className='bg-gray-50/70 flex justify-between outline outline-1 rounded-lg outline-neutral-200/40'>
|
||||||
|
|
@ -80,7 +83,7 @@ const UpdatesSection = () => {
|
||||||
<span>Updates</span>
|
<span>Updates</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{isAdmin && <div
|
{adminStatus.isAdmin && <div
|
||||||
onClick={() => setSelectedView('new')}
|
onClick={() => 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'>
|
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'>
|
||||||
<PencilLine size={14} />
|
<PencilLine size={14} />
|
||||||
|
|
@ -98,6 +101,7 @@ const UpdatesSection = () => {
|
||||||
const NewUpdateForm = ({ setSelectedView }: any) => {
|
const NewUpdateForm = ({ setSelectedView }: any) => {
|
||||||
const org = useOrg() as any;
|
const org = useOrg() as any;
|
||||||
const course = useCourse() as any;
|
const course = useCourse() as any;
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
|
||||||
const validate = (values: any) => {
|
const validate = (values: any) => {
|
||||||
const errors: any = {}
|
const errors: any = {}
|
||||||
|
|
@ -124,7 +128,7 @@ const NewUpdateForm = ({ setSelectedView }: any) => {
|
||||||
course_uuid: course.courseStructure.course_uuid,
|
course_uuid: course.courseStructure.course_uuid,
|
||||||
org_id: org.id
|
org_id: org.id
|
||||||
}
|
}
|
||||||
const res = await createCourseUpdate(body)
|
const res = await createCourseUpdate(body, session.data?.tokens?.access_token)
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
toast.success('Update added successfully')
|
toast.success('Update added successfully')
|
||||||
setSelectedView('list')
|
setSelectedView('list')
|
||||||
|
|
@ -192,23 +196,25 @@ const NewUpdateForm = ({ setSelectedView }: any) => {
|
||||||
|
|
||||||
const UpdatesListView = () => {
|
const UpdatesListView = () => {
|
||||||
const course = useCourse() as any;
|
const course = useCourse() as any;
|
||||||
const isAdmin = useAdminStatus() as boolean;
|
const adminStatus = useAdminStatus() ;
|
||||||
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))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='px-5 bg-white overflow-y-auto' style={{ maxHeight: '400px' }}>
|
<div className='px-5 bg-white overflow-y-auto' style={{ maxHeight: '400px' }}>
|
||||||
{updates && updates.map((update: any) => (
|
{updates && !adminStatus.loading && updates.map((update: any) => (
|
||||||
<div key={update.id} className='py-2 border-b border-neutral-200 antialiased'>
|
<div key={update.id} className='py-2 border-b border-neutral-200 antialiased'>
|
||||||
<div className='font-bold text-gray-500 flex space-x-2 items-center justify-between '>
|
<div className='font-bold text-gray-500 flex space-x-2 items-center justify-between '>
|
||||||
<div className='flex space-x-2 items-center'>
|
<div className='flex space-x-2 items-center'>
|
||||||
<span> {update.title}</span>
|
<span> {update.title}</span>
|
||||||
<span
|
<span
|
||||||
title={"Created at " + dayjs(update.creation_date).format('MMMM D, YYYY')}
|
title={"Created at " + dayjs(update.creation_date).format('MMMM D, YYYY')}
|
||||||
className='text-xs font-semibold text-gray-300'>
|
className='text-xs font-semibold text-gray-300'>
|
||||||
{dayjs(update.creation_date).fromNow()}
|
{dayjs(update.creation_date).fromNow()}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{isAdmin && <DeleteUpdateButton update={update} />}</div>
|
{adminStatus.isAdmin && !adminStatus.loading && <DeleteUpdateButton update={update} />}</div>
|
||||||
<div className='text-gray-600'>{update.content}</div>
|
<div className='text-gray-600'>{update.content}</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
@ -223,11 +229,12 @@ const UpdatesListView = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeleteUpdateButton = ({ update }: any) => {
|
const DeleteUpdateButton = ({ update }: any) => {
|
||||||
|
const session = useLHSession() as any;
|
||||||
const course = useCourse() as any;
|
const course = useCourse() as any;
|
||||||
const org = useOrg() as any;
|
const org = useOrg() as any;
|
||||||
|
|
||||||
const handleDelete = async () => {
|
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) {
|
if (res.status === 200) {
|
||||||
toast.success('Update deleted successfully')
|
toast.success('Update deleted successfully')
|
||||||
mutate(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`)
|
mutate(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import UserAvatar from '../UserAvatar'
|
import UserAvatar from '../UserAvatar'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { getUserAvatarMediaDirectory } from '@services/media/media';
|
import { getUserAvatarMediaDirectory } from '@services/media/media';
|
||||||
import { getCollaborationServerUrl } from '@services/config/config';
|
import { getCollaborationServerUrl } from '@services/config/config';
|
||||||
import { useOrg } from '@components/Contexts/OrgContext';
|
import { useOrg } from '@components/Contexts/OrgContext';
|
||||||
|
|
@ -11,7 +11,7 @@ type ActiveAvatarsProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ActiveAvatars(props: ActiveAvatarsProps) {
|
function ActiveAvatars(props: ActiveAvatarsProps) {
|
||||||
const session = useSession() as any;
|
const session = useLHSession() as any;
|
||||||
const org = useOrg() as any;
|
const org = useOrg() as any;
|
||||||
const [activeUsers, setActiveUsers] = useState({} as any);
|
const [activeUsers, setActiveUsers] = useState({} as any);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ import html from 'highlight.js/lib/languages/xml'
|
||||||
import python from 'highlight.js/lib/languages/python'
|
import python from 'highlight.js/lib/languages/python'
|
||||||
import java from 'highlight.js/lib/languages/java'
|
import java from 'highlight.js/lib/languages/java'
|
||||||
import { CourseProvider } from '@components/Contexts/CourseContext'
|
import { CourseProvider } from '@components/Contexts/CourseContext'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import AIEditorToolkit from './AI/AIEditorToolkit'
|
import AIEditorToolkit from './AI/AIEditorToolkit'
|
||||||
import useGetAIFeatures from '@components/AI/Hooks/useGetAIFeatures'
|
import useGetAIFeatures from '@components/AI/Hooks/useGetAIFeatures'
|
||||||
import UserAvatar from '../UserAvatar'
|
import UserAvatar from '../UserAvatar'
|
||||||
|
|
@ -65,7 +65,7 @@ interface Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
function Editor(props: Editor) {
|
function Editor(props: Editor) {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const dispatchAIEditor = useAIEditorDispatch() as any
|
const dispatchAIEditor = useAIEditorDispatch() as any
|
||||||
const aiEditorState = useAIEditor() as AIEditorStateTypes
|
const aiEditorState = useAIEditor() as AIEditorStateTypes
|
||||||
const is_ai_feature_enabled = useGetAIFeatures({ feature: 'editor' })
|
const is_ai_feature_enabled = useGetAIFeatures({ feature: 'editor' })
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { updateActivity } from '@services/courses/activities'
|
||||||
import { toast } from 'react-hot-toast'
|
import { toast } from 'react-hot-toast'
|
||||||
import Toast from '@components/StyledElements/Toast/Toast'
|
import Toast from '@components/StyledElements/Toast/Toast'
|
||||||
import { OrgProvider } from '@components/Contexts/OrgContext'
|
import { OrgProvider } from '@components/Contexts/OrgContext'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
// Collaboration
|
// Collaboration
|
||||||
import { HocuspocusProvider } from '@hocuspocus/provider'
|
import { HocuspocusProvider } from '@hocuspocus/provider'
|
||||||
|
|
@ -24,7 +24,7 @@ interface EditorWrapperProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function EditorWrapper(props: EditorWrapperProps): JSX.Element {
|
function EditorWrapper(props: EditorWrapperProps): JSX.Element {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
// Define provider in the state
|
// Define provider in the state
|
||||||
const [provider, setProvider] = React.useState<HocuspocusProvider | null>(null);
|
const [provider, setProvider] = React.useState<HocuspocusProvider | null>(null);
|
||||||
const [thisPageColor, setThisPageColor] = useState(randomColor({ luminosity: 'light' }) as string)
|
const [thisPageColor, setThisPageColor] = useState(randomColor({ luminosity: 'light' }) as string)
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,15 @@ import MenuLinks from './MenuLinks'
|
||||||
import { getOrgLogoMediaDirectory } from '@services/media/media'
|
import { getOrgLogoMediaDirectory } from '@services/media/media'
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
import { swrFetcher } from '@services/utils/ts/requests'
|
import { swrFetcher } from '@services/utils/ts/requests'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
|
|
||||||
export const Menu = (props: any) => {
|
export const Menu = (props: any) => {
|
||||||
const orgslug = props.orgslug
|
const orgslug = props.orgslug
|
||||||
|
const session = useLHSession() as any;
|
||||||
|
const access_token = session?.data?.tokens?.access_token;
|
||||||
const [feedbackModal, setFeedbackModal] = React.useState(false)
|
const [feedbackModal, setFeedbackModal] = React.useState(false)
|
||||||
const {
|
const org = useOrg() as any;
|
||||||
data: org,
|
|
||||||
error: error,
|
|
||||||
isLoading,
|
|
||||||
} = useSWR(`${getAPIUrl()}orgs/slug/${orgslug}`, swrFetcher)
|
|
||||||
|
|
||||||
function closeFeedbackModal() {
|
function closeFeedbackModal() {
|
||||||
setFeedbackModal(false)
|
setFeedbackModal(false)
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,11 @@ import React, { useState } from 'react'
|
||||||
import { BarLoader } from 'react-spinners'
|
import { BarLoader } from 'react-spinners'
|
||||||
import { revalidateTags } from '@services/utils/ts/requests'
|
import { revalidateTags } from '@services/utils/ts/requests'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
function CreateCourseModal({ closeModal, orgslug }: any) {
|
function CreateCourseModal({ closeModal, orgslug }: any) {
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||||
|
const session = useLHSession()
|
||||||
const [name, setName] = React.useState('')
|
const [name, setName] = React.useState('')
|
||||||
const [description, setDescription] = React.useState('')
|
const [description, setDescription] = React.useState('')
|
||||||
const [learnings, setLearnings] = React.useState('')
|
const [learnings, setLearnings] = React.useState('')
|
||||||
|
|
@ -71,7 +73,8 @@ function CreateCourseModal({ closeModal, orgslug }: any) {
|
||||||
let status = await createNewCourse(
|
let status = await createNewCourse(
|
||||||
orgId,
|
orgId,
|
||||||
{ name, description, tags, visibility },
|
{ name, description, tags, visibility },
|
||||||
thumbnail
|
thumbnail,
|
||||||
|
session.data?.tokens?.access_token
|
||||||
)
|
)
|
||||||
await revalidateTags(['courses'], orgslug)
|
await revalidateTags(['courses'], orgslug)
|
||||||
setIsSubmitting(false)
|
setIsSubmitting(false)
|
||||||
|
|
@ -80,9 +83,6 @@ function CreateCourseModal({ closeModal, orgslug }: any) {
|
||||||
closeModal()
|
closeModal()
|
||||||
router.refresh()
|
router.refresh()
|
||||||
await revalidateTags(['courses'], orgslug)
|
await revalidateTags(['courses'], orgslug)
|
||||||
|
|
||||||
// refresh page (FIX for Next.js BUG)
|
|
||||||
// window.location.reload();
|
|
||||||
} else {
|
} else {
|
||||||
alert('Error creating course, please see console logs')
|
alert('Error creating course, please see console logs')
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { getAPIUrl } from '@services/config/config'
|
||||||
import { createInviteCode, createInviteCodeWithUserGroup } from '@services/organizations/invites'
|
import { createInviteCode, createInviteCodeWithUserGroup } from '@services/organizations/invites'
|
||||||
import { swrFetcher } from '@services/utils/ts/requests'
|
import { swrFetcher } from '@services/utils/ts/requests'
|
||||||
import { Shield, Ticket } from 'lucide-react'
|
import { Shield, Ticket } from 'lucide-react'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import useSWR, { mutate } from 'swr'
|
import useSWR, { mutate } from 'swr'
|
||||||
|
|
@ -13,6 +14,7 @@ type OrgInviteCodeGenerateProps = {
|
||||||
|
|
||||||
function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) {
|
function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) {
|
||||||
const org = useOrg() as any
|
const org = useOrg() as any
|
||||||
|
const session = useLHSession()
|
||||||
const [usergroup_id, setUsergroup_id] = React.useState(0);
|
const [usergroup_id, setUsergroup_id] = React.useState(0);
|
||||||
const { data: usergroups } = useSWR(
|
const { data: usergroups } = useSWR(
|
||||||
org ? `${getAPIUrl()}usergroups/org/${org.id}` : null,
|
org ? `${getAPIUrl()}usergroups/org/${org.id}` : null,
|
||||||
|
|
@ -20,7 +22,7 @@ function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) {
|
||||||
)
|
)
|
||||||
|
|
||||||
async function createInviteWithUserGroup() {
|
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) {
|
if (res.status == 200) {
|
||||||
mutate(`${getAPIUrl()}orgs/${org.id}/invites`)
|
mutate(`${getAPIUrl()}orgs/${org.id}/invites`)
|
||||||
props.setInvitesModal(false)
|
props.setInvitesModal(false)
|
||||||
|
|
@ -30,7 +32,7 @@ function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createInvite() {
|
async function createInvite() {
|
||||||
let res = await createInviteCode(org.id)
|
let res = await createInviteCode(org.id, session.data?.tokens?.access_token)
|
||||||
if (res.status == 200) {
|
if (res.status == 200) {
|
||||||
mutate(`${getAPIUrl()}orgs/${org.id}/invites`)
|
mutate(`${getAPIUrl()}orgs/${org.id}/invites`)
|
||||||
props.setInvitesModal(false)
|
props.setInvitesModal(false)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { deleteCollection } from '@services/courses/collections'
|
||||||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||||
import { revalidateTags } from '@services/utils/ts/requests'
|
import { revalidateTags } from '@services/utils/ts/requests'
|
||||||
import { X } from 'lucide-react'
|
import { X } from 'lucide-react'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
@ -74,9 +75,10 @@ function CollectionThumbnail(props: PropsType) {
|
||||||
|
|
||||||
const CollectionAdminEditsArea = (props: any) => {
|
const CollectionAdminEditsArea = (props: any) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const session = useLHSession() ;
|
||||||
|
|
||||||
const deleteCollectionUI = async (collectionId: number) => {
|
const deleteCollectionUI = async (collectionId: number) => {
|
||||||
await deleteCollection(collectionId)
|
await deleteCollection(collectionId, session.data?.tokens?.access_token)
|
||||||
await revalidateTags(['collections'], props.orgslug)
|
await revalidateTags(['collections'], props.orgslug)
|
||||||
// reload the page
|
// reload the page
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { deleteCourseFromBackend } from '@services/courses/courses'
|
||||||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||||
import { revalidateTags } from '@services/utils/ts/requests'
|
import { revalidateTags } from '@services/utils/ts/requests'
|
||||||
import { Settings, X } from 'lucide-react'
|
import { Settings, X } from 'lucide-react'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
|
@ -24,15 +25,16 @@ function removeCoursePrefix(course_uuid: string) {
|
||||||
function CourseThumbnail(props: PropsType) {
|
function CourseThumbnail(props: PropsType) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const org = useOrg() as any
|
const org = useOrg() as any
|
||||||
|
const session = useLHSession();
|
||||||
|
|
||||||
async function deleteCourses(course_uuid: 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)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
|
|
||||||
router.refresh()
|
router.refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {}, [org])
|
useEffect(() => { }, [org])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
@ -92,8 +94,8 @@ const AdminEditsArea = (props: {
|
||||||
href={getUriWithOrg(
|
href={getUriWithOrg(
|
||||||
props.orgSlug,
|
props.orgSlug,
|
||||||
'/dash/courses/course/' +
|
'/dash/courses/course/' +
|
||||||
removeCoursePrefix(props.courseId) +
|
removeCoursePrefix(props.courseId) +
|
||||||
'/general'
|
'/general'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { useEffect } from 'react'
|
||||||
import { getUriWithOrg } from '@services/config/config'
|
import { getUriWithOrg } from '@services/config/config'
|
||||||
import { useParams } from 'next/navigation'
|
import { useParams } from 'next/navigation'
|
||||||
import { getUserAvatarMediaDirectory } from '@services/media/media'
|
import { getUserAvatarMediaDirectory } from '@services/media/media'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
type UserAvatarProps = {
|
type UserAvatarProps = {
|
||||||
width?: number
|
width?: number
|
||||||
|
|
@ -20,7 +20,7 @@ type UserAvatarProps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function UserAvatar(props: UserAvatarProps) {
|
function UserAvatar(props: UserAvatarProps) {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const params = useParams() as any
|
const params = useParams() as any
|
||||||
|
|
||||||
function checkUrlProtocol(url: string): boolean {
|
function checkUrlProtocol(url: string): boolean {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import { revalidateTags } from '@services/utils/ts/requests'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal'
|
import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal'
|
||||||
import { deleteActivity, updateActivity } from '@services/courses/activities'
|
import { deleteActivity, updateActivity } from '@services/courses/activities'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
interface ModifiedActivityInterface {
|
interface ModifiedActivityInterface {
|
||||||
activityId: string
|
activityId: string
|
||||||
|
|
@ -25,6 +26,7 @@ interface ModifiedActivityInterface {
|
||||||
|
|
||||||
function Activity(props: any) {
|
function Activity(props: any) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const session = useLHSession() as any;
|
||||||
const [modifiedActivity, setModifiedActivity] = React.useState<
|
const [modifiedActivity, setModifiedActivity] = React.useState<
|
||||||
ModifiedActivityInterface | undefined
|
ModifiedActivityInterface | undefined
|
||||||
>(undefined)
|
>(undefined)
|
||||||
|
|
@ -33,7 +35,7 @@ function Activity(props: any) {
|
||||||
>(undefined)
|
>(undefined)
|
||||||
|
|
||||||
async function removeActivity() {
|
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}`)
|
mutate(`${getAPIUrl()}chapters/meta/course_${props.courseid}`)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
@ -52,7 +54,7 @@ function Activity(props: any) {
|
||||||
content: props.activity.content,
|
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 mutate(`${getAPIUrl()}chapters/meta/course_${props.courseid}`)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { updateChapter } from '@services/courses/chapters'
|
||||||
import { mutate } from 'swr'
|
import { mutate } from 'swr'
|
||||||
import { getAPIUrl } from '@services/config/config'
|
import { getAPIUrl } from '@services/config/config'
|
||||||
import { revalidateTags } from '@services/utils/ts/requests'
|
import { revalidateTags } from '@services/utils/ts/requests'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
interface ModifiedChapterInterface {
|
interface ModifiedChapterInterface {
|
||||||
chapterId: string
|
chapterId: string
|
||||||
|
|
@ -17,6 +18,7 @@ interface ModifiedChapterInterface {
|
||||||
|
|
||||||
function Chapter(props: any) {
|
function Chapter(props: any) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const session = useLHSession() as any;
|
||||||
const [modifiedChapter, setModifiedChapter] = React.useState<
|
const [modifiedChapter, setModifiedChapter] = React.useState<
|
||||||
ModifiedChapterInterface | undefined
|
ModifiedChapterInterface | undefined
|
||||||
>(undefined)
|
>(undefined)
|
||||||
|
|
@ -30,7 +32,7 @@ function Chapter(props: any) {
|
||||||
let modifiedChapterCopy = {
|
let modifiedChapterCopy = {
|
||||||
name: modifiedChapter.chapterName,
|
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 mutate(`${getAPIUrl()}chapters/course/${props.course_uuid}/meta`)
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { getAPIUrl, getUriWithOrg } from '@services/config/config'
|
||||||
import { removeCourse } from '@services/courses/activity'
|
import { removeCourse } from '@services/courses/activity'
|
||||||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||||
import { revalidateTags } from '@services/utils/ts/requests'
|
import { revalidateTags } from '@services/utils/ts/requests'
|
||||||
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
|
@ -17,6 +18,8 @@ interface TrailCourseElementProps {
|
||||||
|
|
||||||
function TrailCourseElement(props: TrailCourseElementProps) {
|
function TrailCourseElement(props: TrailCourseElementProps) {
|
||||||
const org = useOrg() as any
|
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 courseid = props.course.course_uuid.replace('course_', '')
|
||||||
const course = props.course
|
const course = props.course
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
@ -29,7 +32,7 @@ function TrailCourseElement(props: TrailCourseElementProps) {
|
||||||
|
|
||||||
async function quitCourse(course_uuid: string) {
|
async function quitCourse(course_uuid: string) {
|
||||||
// Close activity
|
// Close activity
|
||||||
let activity = await removeCourse(course_uuid, props.orgslug)
|
let activity = await removeCourse(course_uuid, props.orgslug,access_token)
|
||||||
// Mutate course
|
// Mutate course
|
||||||
await revalidateTags(['courses'], props.orgslug)
|
await revalidateTags(['courses'], props.orgslug)
|
||||||
router.refresh()
|
router.refresh()
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
'use client'
|
'use client';
|
||||||
import { useOrg } from '@components/Contexts/OrgContext'
|
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
||||||
import { useSession } from 'next-auth/react'
|
import { useOrg } from '@components/Contexts/OrgContext';
|
||||||
import useAdminStatus from '@components/Hooks/useAdminStatus'
|
import { useLHSession } from '@components/Contexts/LHSessionContext';
|
||||||
import { usePathname, useRouter } from 'next/navigation'
|
import useAdminStatus from '@components/Hooks/useAdminStatus';
|
||||||
import React from 'react'
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
|
|
||||||
type AuthorizationProps = {
|
type AuthorizationProps = {
|
||||||
children: React.ReactNode
|
children: React.ReactNode;
|
||||||
// Authorize components rendering or page rendering
|
authorizationMode: 'component' | 'page';
|
||||||
authorizationMode: 'component' | 'page'
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const ADMIN_PATHS = [
|
const ADMIN_PATHS = [
|
||||||
'/dash/org/*',
|
'/dash/org/*',
|
||||||
|
|
@ -19,106 +18,71 @@ const ADMIN_PATHS = [
|
||||||
'/dash/courses/*',
|
'/dash/courses/*',
|
||||||
'/dash/courses',
|
'/dash/courses',
|
||||||
'/dash/org/settings/general',
|
'/dash/org/settings/general',
|
||||||
]
|
];
|
||||||
|
|
||||||
function AdminAuthorization(props: AuthorizationProps) {
|
const AdminAuthorization: React.FC<AuthorizationProps> = ({ children, authorizationMode }) => {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any;
|
||||||
const org = useOrg() as any
|
const pathname = usePathname();
|
||||||
const pathname = usePathname()
|
const router = useRouter();
|
||||||
const router = useRouter()
|
const { isAdmin, loading } = useAdminStatus() as any
|
||||||
|
const [isAuthorized, setIsAuthorized] = useState(false);
|
||||||
|
|
||||||
// States
|
const isUserAuthenticated = useMemo(() => session.status === 'authenticated', [session.status]);
|
||||||
const [isLoading, setIsLoading] = React.useState(true)
|
|
||||||
const [isAuthorized, setIsAuthorized] = React.useState(false)
|
|
||||||
|
|
||||||
// Verify if the user is authenticated
|
const checkPathname = useCallback((pattern: string, pathname: string) => {
|
||||||
const isUserAuthenticated = () => {
|
const regexPattern = new RegExp(`^${pattern.replace(/\//g, '\\/').replace(/\*/g, '.*')}$`);
|
||||||
if (session.status === 'authenticated') {
|
return regexPattern.test(pathname);
|
||||||
return true
|
}, []);
|
||||||
} else {
|
|
||||||
return false
|
const isAdminPath = useMemo(() => ADMIN_PATHS.some(path => checkPathname(path, pathname)), [pathname, checkPathname]);
|
||||||
|
|
||||||
|
const authorizeUser = useCallback(() => {
|
||||||
|
if (loading) {
|
||||||
|
return; // Wait until the admin status is determined
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Verify if the user is an Admin (1), Maintainer (2) or Member (3) of the organization
|
if (!isUserAuthenticated) {
|
||||||
const isUserAdmin = useAdminStatus()
|
router.push('/login');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function checkPathname(pattern: string, pathname: string) {
|
if (authorizationMode === 'page') {
|
||||||
// Escape special characters in the pattern and replace '*' with a regex pattern
|
if (isAdminPath) {
|
||||||
const regexPattern = new RegExp(
|
if (isAdmin) {
|
||||||
`^${pattern.replace(/\//g, '\\/').replace(/\*/g, '.*')}$`
|
setIsAuthorized(true);
|
||||||
)
|
|
||||||
|
|
||||||
// Test if the pathname matches the regex pattern
|
|
||||||
const isMatch = regexPattern.test(pathname)
|
|
||||||
|
|
||||||
return isMatch
|
|
||||||
}
|
|
||||||
|
|
||||||
const Authorize = () => {
|
|
||||||
if (props.authorizationMode === 'page') {
|
|
||||||
// Check if user is in an admin path
|
|
||||||
if (ADMIN_PATHS.some((path) => checkPathname(path, pathname))) {
|
|
||||||
if (isUserAuthenticated()) {
|
|
||||||
// Check if the user is an Admin
|
|
||||||
if (isUserAdmin) {
|
|
||||||
setIsAuthorized(true)
|
|
||||||
} else {
|
|
||||||
setIsAuthorized(false)
|
|
||||||
router.push('/dash')
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
router.push('/login')
|
setIsAuthorized(false);
|
||||||
|
router.push('/dash');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isUserAuthenticated()) {
|
setIsAuthorized(true);
|
||||||
setIsAuthorized(true)
|
|
||||||
} else {
|
|
||||||
setIsAuthorized(false)
|
|
||||||
router.push('/login')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else if (authorizationMode === 'component') {
|
||||||
|
setIsAuthorized(isAdmin);
|
||||||
}
|
}
|
||||||
|
}, [loading, isUserAuthenticated, isAdmin, isAdminPath, authorizationMode, router]);
|
||||||
|
|
||||||
if (props.authorizationMode === 'component') {
|
useEffect(() => {
|
||||||
// Component mode
|
authorizeUser();
|
||||||
if (isUserAuthenticated() && isUserAdmin) {
|
}, [authorizeUser]);
|
||||||
setIsAuthorized(true)
|
|
||||||
} else {
|
if (loading) {
|
||||||
setIsAuthorized(false)
|
return (
|
||||||
}
|
<div className="flex justify-center items-center h-screen">
|
||||||
}
|
<h1 className="text-2xl">Loading...</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
if (authorizationMode === 'page' && !isAuthorized) {
|
||||||
if (session.status == 'loading') {
|
return (
|
||||||
return
|
<div className="flex justify-center items-center h-screen">
|
||||||
}
|
<h1 className="text-2xl">You are not authorized to access this page</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Authorize()
|
return <>{isAuthorized && children}</>;
|
||||||
setIsLoading(false)
|
};
|
||||||
}, [session, org, pathname])
|
|
||||||
|
|
||||||
return (
|
export default AdminAuthorization;
|
||||||
<>
|
|
||||||
{props.authorizationMode === 'component' &&
|
|
||||||
isAuthorized === true &&
|
|
||||||
props.children}
|
|
||||||
{props.authorizationMode === 'page' &&
|
|
||||||
isAuthorized === true &&
|
|
||||||
!isLoading &&
|
|
||||||
props.children}
|
|
||||||
{props.authorizationMode === 'page' &&
|
|
||||||
isAuthorized === false &&
|
|
||||||
!isLoading && (
|
|
||||||
<div className="flex justify-center items-center h-screen">
|
|
||||||
<h1 className="text-2xl">
|
|
||||||
You are not authorized to access this page
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AdminAuthorization
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use client'
|
'use client'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
import { useOrg } from '@components/Contexts/OrgContext'
|
import { useOrg } from '@components/Contexts/OrgContext'
|
||||||
|
|
||||||
interface AuthenticatedClientElementProps {
|
interface AuthenticatedClientElementProps {
|
||||||
|
|
@ -20,7 +20,7 @@ export const AuthenticatedClientElement = (
|
||||||
props: AuthenticatedClientElementProps
|
props: AuthenticatedClientElementProps
|
||||||
) => {
|
) => {
|
||||||
const [isAllowed, setIsAllowed] = React.useState(false)
|
const [isAllowed, setIsAllowed] = React.useState(false)
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const org = useOrg() as any
|
const org = useOrg() as any
|
||||||
|
|
||||||
function isUserAllowed(
|
function isUserAllowed(
|
||||||
|
|
@ -49,13 +49,13 @@ export const AuthenticatedClientElement = (
|
||||||
}
|
}
|
||||||
|
|
||||||
function check() {
|
function check() {
|
||||||
if (session.status == 'authenticated') {
|
if (session.status == 'unauthenticated') {
|
||||||
setIsAllowed(false)
|
setIsAllowed(false)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
if (props.checkMethod === 'authentication') {
|
if (props.checkMethod === 'authentication') {
|
||||||
setIsAllowed(session.status == 'authenticated')
|
setIsAllowed(session.status == 'authenticated')
|
||||||
} else if (props.checkMethod === 'roles' && session.status == 'authenticated') {
|
} else if (props.checkMethod === 'roles' ) {
|
||||||
return setIsAllowed(
|
return setIsAllowed(
|
||||||
isUserAllowed(
|
isUserAllowed(
|
||||||
session?.data?.roles,
|
session?.data?.roles,
|
||||||
|
|
@ -74,7 +74,7 @@ export const AuthenticatedClientElement = (
|
||||||
}
|
}
|
||||||
|
|
||||||
check()
|
check()
|
||||||
}, [session, org])
|
}, [session.data, org])
|
||||||
|
|
||||||
return <>{isAllowed && props.children}</>
|
return <>{isAllowed && props.children}</>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ import Link from 'next/link'
|
||||||
import { Settings } from 'lucide-react'
|
import { Settings } from 'lucide-react'
|
||||||
import UserAvatar from '@components/Objects/UserAvatar'
|
import UserAvatar from '@components/Objects/UserAvatar'
|
||||||
import useAdminStatus from '@components/Hooks/useAdminStatus'
|
import useAdminStatus from '@components/Hooks/useAdminStatus'
|
||||||
import { useSession } from 'next-auth/react'
|
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||||
|
|
||||||
export const HeaderProfileBox = () => {
|
export const HeaderProfileBox = () => {
|
||||||
const session = useSession() as any
|
const session = useLHSession() as any
|
||||||
const isUserAdmin = useAdminStatus() as any
|
const isUserAdmin = useAdminStatus() as any
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
59
apps/web/pnpm-lock.yaml
generated
59
apps/web/pnpm-lock.yaml
generated
|
|
@ -1549,6 +1549,7 @@ packages:
|
||||||
"@typescript-eslint/visitor-keys": 6.21.0
|
"@typescript-eslint/visitor-keys": 6.21.0
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
|
optionalDependencies:
|
||||||
typescript: 5.4.4
|
typescript: 5.4.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
@ -1570,6 +1571,7 @@ packages:
|
||||||
minimatch: 9.0.3
|
minimatch: 9.0.3
|
||||||
semver: 7.6.0
|
semver: 7.6.0
|
||||||
ts-api-utils: 1.3.0(typescript@5.4.4)
|
ts-api-utils: 1.3.0(typescript@5.4.4)
|
||||||
|
optionalDependencies:
|
||||||
typescript: 5.4.4
|
typescript: 5.4.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
@ -1713,8 +1715,8 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
possible-typed-array-names: 1.0.0
|
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.2.0(react@18.2.0))(react@18.2.0)
|
||||||
dependencies:
|
: dependencies:
|
||||||
goober: 2.1.14(csstype@3.1.3)
|
goober: 2.1.14(csstype@3.1.3)
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
|
@ -2070,11 +2072,12 @@ packages:
|
||||||
"@typescript-eslint/parser": 6.21.0(eslint@8.57.0)(typescript@5.4.4)
|
"@typescript-eslint/parser": 6.21.0(eslint@8.57.0)(typescript@5.4.4)
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-import-resolver-node: 0.3.9
|
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@6.21.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-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@6.21.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||||
eslint-plugin-jsx-a11y: 6.8.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: 7.34.1(eslint@8.57.0)
|
||||||
eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0)
|
eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0)
|
||||||
|
optionalDependencies:
|
||||||
typescript: 5.4.4
|
typescript: 5.4.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
|
|
@ -2093,8 +2096,8 @@ packages:
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
enhanced-resolve: 5.16.0
|
enhanced-resolve: 5.16.0
|
||||||
eslint: 8.57.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-module-utils: 2.8.1(@typescript-eslint/parser@6.21.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@6.21.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@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
get-tsconfig: 4.7.3
|
get-tsconfig: 4.7.3
|
||||||
is-core-module: 2.13.1
|
is-core-module: 2.13.1
|
||||||
|
|
@ -2109,9 +2112,11 @@ packages:
|
||||||
: dependencies:
|
: dependencies:
|
||||||
"@typescript-eslint/parser": 6.21.0(eslint@8.57.0)(typescript@5.4.4)
|
"@typescript-eslint/parser": 6.21.0(eslint@8.57.0)(typescript@5.4.4)
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
|
optionalDependencies:
|
||||||
|
"@typescript-eslint/parser": 6.21.0(eslint@8.57.0)(typescript@5.4.4)
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-import-resolver-node: 0.3.9
|
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@6.21.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)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -2126,7 +2131,7 @@ packages:
|
||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 8.57.0
|
eslint: 8.57.0
|
||||||
eslint-import-resolver-node: 0.3.9
|
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@6.21.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@6.21.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)
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
is-core-module: 2.13.1
|
is-core-module: 2.13.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
|
@ -2136,6 +2141,8 @@ packages:
|
||||||
object.values: 1.2.0
|
object.values: 1.2.0
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
tsconfig-paths: 3.15.0
|
tsconfig-paths: 3.15.0
|
||||||
|
optionalDependencies:
|
||||||
|
"@typescript-eslint/parser": 6.21.0(eslint@8.57.0)(typescript@5.4.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- eslint-import-resolver-typescript
|
- eslint-import-resolver-typescript
|
||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
|
|
@ -2324,10 +2331,8 @@ packages:
|
||||||
|
|
||||||
fraction.js@4.3.7: {}
|
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.2.0(react@18.2.0))(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.2.0
|
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
|
||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@emotion/is-prop-valid": 0.8.8
|
"@emotion/is-prop-valid": 0.8.8
|
||||||
|
|
@ -2985,8 +2990,9 @@ packages:
|
||||||
postcss-load-config@4.0.2(postcss@8.4.38):
|
postcss-load-config@4.0.2(postcss@8.4.38):
|
||||||
dependencies:
|
dependencies:
|
||||||
lilconfig: 3.1.1
|
lilconfig: 3.1.1
|
||||||
postcss: 8.4.38
|
|
||||||
yaml: 2.4.1
|
yaml: 2.4.1
|
||||||
|
optionalDependencies:
|
||||||
|
postcss: 8.4.38
|
||||||
|
|
||||||
postcss-nested@6.0.1(postcss@8.4.38):
|
postcss-nested@6.0.1(postcss@8.4.38):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -3146,12 +3152,12 @@ packages:
|
||||||
|
|
||||||
randomcolor@0.6.2: {}
|
randomcolor@0.6.2: {}
|
||||||
|
|
||||||
re-resizable@6.9.11(react-dom@18.2.0)(react@18.2.0):
|
re-resizable@6.9.11(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
|
||||||
react-beautiful-dnd@13.1.1(react-dom@18.2.0)(react@18.2.0):
|
react-beautiful-dnd@13.1.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": 7.24.4
|
"@babel/runtime": 7.24.4
|
||||||
css-box-model: 1.2.1
|
css-box-model: 1.2.1
|
||||||
|
|
@ -3159,7 +3165,7 @@ packages:
|
||||||
raf-schd: 4.0.3
|
raf-schd: 4.0.3
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(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-redux: 7.2.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
|
||||||
redux: 4.2.1
|
redux: 4.2.1
|
||||||
use-memo-one: 1.1.3(react@18.2.0)
|
use-memo-one: 1.1.3(react@18.2.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|
@ -3178,8 +3184,8 @@ packages:
|
||||||
|
|
||||||
react-fast-compare@2.0.4: {}
|
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.2.0(react@18.2.0))(react@18.2.0)
|
||||||
dependencies:
|
: dependencies:
|
||||||
goober: 2.1.14(csstype@3.1.3)
|
goober: 2.1.14(csstype@3.1.3)
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
|
@ -3196,7 +3202,7 @@ packages:
|
||||||
prop-types: 15.8.1
|
prop-types: 15.8.1
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
|
|
||||||
react-redux@7.2.9(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.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": 7.24.4
|
"@babel/runtime": 7.24.4
|
||||||
"@types/react-redux": 7.1.33
|
"@types/react-redux": 7.1.33
|
||||||
|
|
@ -3204,8 +3210,9 @@ packages:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
prop-types: 15.8.1
|
prop-types: 15.8.1
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
|
||||||
react-is: 17.0.2
|
react-is: 17.0.2
|
||||||
|
optionalDependencies:
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
|
||||||
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.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -3213,6 +3220,8 @@ packages:
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
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.2.0)
|
||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
|
optionalDependencies:
|
||||||
|
"@types/react": 18.2.74
|
||||||
|
|
||||||
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.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -3223,8 +3232,10 @@ packages:
|
||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
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.2.0)
|
||||||
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.2.0)
|
||||||
|
optionalDependencies:
|
||||||
|
"@types/react": 18.2.74
|
||||||
|
|
||||||
react-spinners@0.13.8(react-dom@18.2.0)(react@18.2.0):
|
react-spinners@0.13.8(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
|
@ -3236,6 +3247,8 @@ packages:
|
||||||
invariant: 2.2.4
|
invariant: 2.2.4
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
|
optionalDependencies:
|
||||||
|
"@types/react": 18.2.74
|
||||||
|
|
||||||
react-youtube@10.1.0(react@18.2.0):
|
react-youtube@10.1.0(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -3485,7 +3498,7 @@ packages:
|
||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
strip-json-comments@3.1.1: {}
|
||||||
|
|
||||||
styled-components@6.1.8(react-dom@18.2.0)(react@18.2.0):
|
styled-components@6.1.8(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
"@emotion/is-prop-valid": 1.2.1
|
"@emotion/is-prop-valid": 1.2.1
|
||||||
"@emotion/unitless": 0.8.0
|
"@emotion/unitless": 0.8.0
|
||||||
|
|
@ -3672,6 +3685,8 @@ packages:
|
||||||
"@types/react": 18.2.74
|
"@types/react": 18.2.74
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
|
optionalDependencies:
|
||||||
|
"@types/react": 18.2.74
|
||||||
|
|
||||||
use-memo-one@1.1.3(react@18.2.0):
|
use-memo-one@1.1.3(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -3683,6 +3698,8 @@ packages:
|
||||||
detect-node-es: 1.1.0
|
detect-node-es: 1.1.0
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
|
optionalDependencies:
|
||||||
|
"@types/react": 18.2.74
|
||||||
|
|
||||||
use-sync-external-store@1.2.0(react@18.2.0):
|
use-sync-external-store@1.2.0(react@18.2.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,22 @@
|
||||||
import { getAPIUrl } from '@services/config/config'
|
import { getAPIUrl } from '@services/config/config'
|
||||||
import {
|
import {
|
||||||
RequestBody,
|
RequestBodyFormWithAuthHeader,
|
||||||
RequestBodyForm,
|
|
||||||
RequestBodyWithAuthHeader,
|
RequestBodyWithAuthHeader,
|
||||||
} from '@services/utils/ts/requests'
|
} 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 = {}
|
data.content = {}
|
||||||
// remove chapter_id from data
|
// remove chapter_id from data
|
||||||
delete data.chapterId
|
delete data.chapterId
|
||||||
|
|
||||||
const result = await fetch(
|
const result = await fetch(
|
||||||
`${getAPIUrl()}activities/?coursechapter_id=${chapter_id}&org_id=${org_id}`,
|
`${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()
|
const res = await result.json()
|
||||||
return res
|
return res
|
||||||
|
|
@ -22,7 +26,8 @@ export async function createFileActivity(
|
||||||
file: File,
|
file: File,
|
||||||
type: string,
|
type: string,
|
||||||
data: any,
|
data: any,
|
||||||
chapter_id: any
|
chapter_id: any,
|
||||||
|
access_token: string
|
||||||
) {
|
) {
|
||||||
// Send file thumbnail as form data
|
// Send file thumbnail as form data
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
|
@ -44,7 +49,7 @@ export async function createFileActivity(
|
||||||
|
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
endpoint,
|
endpoint,
|
||||||
RequestBodyForm('POST', formData, null)
|
RequestBodyFormWithAuthHeader('POST', formData, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await result.json()
|
const res = await result.json()
|
||||||
return res
|
return res
|
||||||
|
|
@ -53,7 +58,8 @@ export async function createFileActivity(
|
||||||
export async function createExternalVideoActivity(
|
export async function createExternalVideoActivity(
|
||||||
data: any,
|
data: any,
|
||||||
activity: any,
|
activity: any,
|
||||||
chapter_id: any
|
chapter_id: any,
|
||||||
|
access_token: string
|
||||||
) {
|
) {
|
||||||
// add coursechapter_id to data
|
// add coursechapter_id to data
|
||||||
data.chapter_id = chapter_id
|
data.chapter_id = chapter_id
|
||||||
|
|
@ -61,25 +67,29 @@ export async function createExternalVideoActivity(
|
||||||
|
|
||||||
const result = await fetch(
|
const result = await fetch(
|
||||||
`${getAPIUrl()}activities/external_video`,
|
`${getAPIUrl()}activities/external_video`,
|
||||||
RequestBody('POST', data, null)
|
RequestBodyWithAuthHeader('POST', data, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await result.json()
|
const res = await result.json()
|
||||||
return res
|
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(
|
const result = await fetch(
|
||||||
`${getAPIUrl()}activities/${activity_id}`,
|
`${getAPIUrl()}activities/${activity_id}`,
|
||||||
RequestBody('GET', null, next)
|
RequestBodyWithAuthHeader('GET', null, next, access_token)
|
||||||
)
|
)
|
||||||
const res = await result.json()
|
const res = await result.json()
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteActivity(activity_id: any) {
|
export async function deleteActivity(activity_id: any, access_token: string) {
|
||||||
const result = await fetch(
|
const result = await fetch(
|
||||||
`${getAPIUrl()}activities/${activity_id}`,
|
`${getAPIUrl()}activities/${activity_id}`,
|
||||||
RequestBody('DELETE', null, null)
|
RequestBodyWithAuthHeader('DELETE', null, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await result.json()
|
const res = await result.json()
|
||||||
return res
|
return res
|
||||||
|
|
@ -98,10 +108,14 @@ export async function getActivityWithAuthHeader(
|
||||||
return res
|
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(
|
const result = await fetch(
|
||||||
`${getAPIUrl()}activities/${activity_uuid}`,
|
`${getAPIUrl()}activities/${activity_uuid}`,
|
||||||
RequestBody('PUT', data, null)
|
RequestBodyWithAuthHeader('PUT', data, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await result.json()
|
const res = await result.json()
|
||||||
return res
|
return res
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { RequestBody, errorHandling } from '@services/utils/ts/requests'
|
import { RequestBody, RequestBodyWithAuthHeader, errorHandling } from '@services/utils/ts/requests'
|
||||||
import { getAPIUrl } from '@services/config/config'
|
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/)
|
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(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}trail/add_course/${course_uuid}`,
|
`${getAPIUrl()}trail/add_course/${course_uuid}`,
|
||||||
RequestBody('POST', null, null)
|
RequestBodyWithAuthHeader('POST', null, null,access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
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(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}trail/remove_course/${course_uuid}`,
|
`${getAPIUrl()}trail/remove_course/${course_uuid}`,
|
||||||
RequestBody('DELETE', null, null)
|
RequestBodyWithAuthHeader('DELETE', null, null,access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
return res
|
||||||
|
|
@ -27,11 +27,11 @@ export async function removeCourse(course_uuid: string, org_slug: string) {
|
||||||
export async function markActivityAsComplete(
|
export async function markActivityAsComplete(
|
||||||
org_slug: string,
|
org_slug: string,
|
||||||
course_uuid: string,
|
course_uuid: string,
|
||||||
activity_uuid: string
|
activity_uuid: string,access_token:any
|
||||||
) {
|
) {
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}trail/add_activity/${activity_uuid}`,
|
`${getAPIUrl()}trail/add_activity/${activity_uuid}`,
|
||||||
RequestBody('POST', null, null)
|
RequestBodyWithAuthHeader('POST', null, null,access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
return res
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import { OrderPayload } from '@components/Dashboard/Course/EditCourseStructure/EditCourseStructure'
|
import { OrderPayload } from '@components/Dashboard/Course/EditCourseStructure/EditCourseStructure'
|
||||||
import { getAPIUrl } from '@services/config/config'
|
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
|
This file includes only POST, PUT, DELETE requests
|
||||||
|
|
@ -8,28 +11,40 @@ import { RequestBody, errorHandling } from '@services/utils/ts/requests'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//TODO : depreciate this function
|
//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(
|
const result = await fetch(
|
||||||
`${getAPIUrl()}chapters/meta/course_${course_uuid}`,
|
`${getAPIUrl()}chapters/meta/course_${course_uuid}`,
|
||||||
RequestBody('GET', null, next)
|
RequestBodyWithAuthHeader('GET', null, next, access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
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(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}chapters/course/course_${course_uuid}/order`,
|
`${getAPIUrl()}chapters/course/course_${course_uuid}/order`,
|
||||||
RequestBody('PUT', data, null)
|
RequestBodyWithAuthHeader('PUT', data, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
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(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}chapters/${coursechapter_id}`,
|
`${getAPIUrl()}chapters/${coursechapter_id}`,
|
||||||
RequestBody('PUT', data, null)
|
RequestBodyWithAuthHeader('PUT', data, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
return res
|
||||||
|
|
@ -37,30 +52,31 @@ export async function updateChapter(coursechapter_id: any, data: any) {
|
||||||
|
|
||||||
export async function updateCourseOrderStructure(
|
export async function updateCourseOrderStructure(
|
||||||
course_uuid: any,
|
course_uuid: any,
|
||||||
data: OrderPayload
|
data: OrderPayload,
|
||||||
|
access_token: any
|
||||||
) {
|
) {
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}chapters/course/${course_uuid}/order`,
|
`${getAPIUrl()}chapters/course/${course_uuid}/order`,
|
||||||
RequestBody('PUT', data, null)
|
RequestBodyWithAuthHeader('PUT', data, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createChapter(data: any) {
|
export async function createChapter(data: any, access_token: any) {
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}chapters/`,
|
`${getAPIUrl()}chapters/`,
|
||||||
RequestBody('POST', data, null)
|
RequestBodyWithAuthHeader('POST', data, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteChapter(coursechapter_id: any) {
|
export async function deleteChapter(coursechapter_id: any, access_token: any) {
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}chapters/${coursechapter_id}`,
|
`${getAPIUrl()}chapters/${coursechapter_id}`,
|
||||||
RequestBody('DELETE', null, null)
|
RequestBodyWithAuthHeader('DELETE', null, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
return res
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { getAPIUrl } from '../config/config'
|
import { getAPIUrl } from '../config/config'
|
||||||
import {
|
import {
|
||||||
RequestBody,
|
|
||||||
RequestBodyWithAuthHeader,
|
RequestBodyWithAuthHeader,
|
||||||
errorHandling,
|
errorHandling,
|
||||||
} from '@services/utils/ts/requests'
|
} from '@services/utils/ts/requests'
|
||||||
|
|
@ -10,36 +9,30 @@ import {
|
||||||
GET requests are called from the frontend using SWR (https://swr.vercel.app/)
|
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(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}collections/${collection_uuid}`,
|
`${getAPIUrl()}collections/${collection_uuid}`,
|
||||||
RequestBody('DELETE', null, null)
|
RequestBodyWithAuthHeader('DELETE', null, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new collection
|
// Create a new collection
|
||||||
export async function createCollection(collection: any) {
|
export async function createCollection(collection: any, access_token: any) {
|
||||||
|
console.log(collection)
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}collections/`,
|
`${getAPIUrl()}collections/`,
|
||||||
RequestBody('POST', collection, null)
|
RequestBodyWithAuthHeader('POST', collection, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a colletion by id
|
export async function getCollectionById(
|
||||||
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(
|
|
||||||
collection_uuid: any,
|
collection_uuid: any,
|
||||||
access_token: string,
|
access_token: string,
|
||||||
next: any
|
next: any
|
||||||
|
|
@ -52,17 +45,7 @@ export async function getCollectionByIdWithAuthHeader(
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get collections
|
export async function getOrgCollections(
|
||||||
// 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(
|
|
||||||
org_id: string,
|
org_id: string,
|
||||||
access_token: string,
|
access_token: string,
|
||||||
next: any
|
next: any
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { getAPIUrl } from '@services/config/config'
|
||||||
import {
|
import {
|
||||||
RequestBody,
|
RequestBody,
|
||||||
RequestBodyForm,
|
RequestBodyForm,
|
||||||
|
RequestBodyFormWithAuthHeader,
|
||||||
RequestBodyWithAuthHeader,
|
RequestBodyWithAuthHeader,
|
||||||
errorHandling,
|
errorHandling,
|
||||||
getResponseMetadata,
|
getResponseMetadata,
|
||||||
|
|
@ -12,19 +13,10 @@ import {
|
||||||
GET requests are called from the frontend using SWR (https://swr.vercel.app/)
|
GET requests are called from the frontend using SWR (https://swr.vercel.app/)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export async function getOrgCourses(org_id: number, next: any) {
|
export async function getOrgCourses(
|
||||||
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(
|
|
||||||
org_id: number,
|
org_id: number,
|
||||||
next: any,
|
next: any,
|
||||||
access_token: string
|
access_token: any
|
||||||
) {
|
) {
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}courses/org_slug/${org_id}/page/1/limit/10`,
|
`${getAPIUrl()}courses/org_slug/${org_id}/page/1/limit/10`,
|
||||||
|
|
@ -34,7 +26,7 @@ export async function getOrgCoursesWithAuthHeader(
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCourseMetadataWithAuthHeader(
|
export async function getCourseMetadata(
|
||||||
course_uuid: any,
|
course_uuid: any,
|
||||||
next: any,
|
next: any,
|
||||||
access_token: string
|
access_token: string
|
||||||
|
|
@ -47,30 +39,30 @@ export async function getCourseMetadataWithAuthHeader(
|
||||||
return res
|
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(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}courses/${course_uuid}`,
|
`${getAPIUrl()}courses/${course_uuid}`,
|
||||||
RequestBody('PUT', data, null)
|
RequestBodyWithAuthHeader('PUT', data, null,access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
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(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}courses/${course_uuid}`,
|
`${getAPIUrl()}courses/${course_uuid}`,
|
||||||
RequestBody('GET', null, next)
|
RequestBodyWithAuthHeader('GET', null, next,access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
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()
|
const formData = new FormData()
|
||||||
formData.append('thumbnail', thumbnail)
|
formData.append('thumbnail', thumbnail)
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}courses/${course_uuid}/thumbnail`,
|
`${getAPIUrl()}courses/${course_uuid}/thumbnail`,
|
||||||
RequestBodyForm('PUT', formData, null)
|
RequestBodyFormWithAuthHeader('PUT', formData, null,access_token)
|
||||||
)
|
)
|
||||||
const res = await getResponseMetadata(result)
|
const res = await getResponseMetadata(result)
|
||||||
return res
|
return res
|
||||||
|
|
@ -79,7 +71,8 @@ export async function updateCourseThumbnail(course_uuid: any, thumbnail: any) {
|
||||||
export async function createNewCourse(
|
export async function createNewCourse(
|
||||||
org_id: string,
|
org_id: string,
|
||||||
course_body: any,
|
course_body: any,
|
||||||
thumbnail: any
|
thumbnail: any,
|
||||||
|
access_token: any
|
||||||
) {
|
) {
|
||||||
// Send file thumbnail as form data
|
// Send file thumbnail as form data
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
|
@ -96,16 +89,16 @@ export async function createNewCourse(
|
||||||
|
|
||||||
const result = await fetch(
|
const result = await fetch(
|
||||||
`${getAPIUrl()}courses/?org_id=${org_id}`,
|
`${getAPIUrl()}courses/?org_id=${org_id}`,
|
||||||
RequestBodyForm('POST', formData, null)
|
RequestBodyFormWithAuthHeader('POST', formData, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteCourseFromBackend(course_uuid: any) {
|
export async function deleteCourseFromBackend(course_uuid: any, access_token:any) {
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}courses/${course_uuid}`,
|
`${getAPIUrl()}courses/${course_uuid}`,
|
||||||
RequestBody('DELETE', null, null)
|
RequestBodyWithAuthHeader('DELETE', null, null,access_token)
|
||||||
)
|
)
|
||||||
const res = await errorHandling(result)
|
const res = await errorHandling(result)
|
||||||
return res
|
return res
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
import { getAPIUrl } from '@services/config/config'
|
import { getAPIUrl } from '@services/config/config'
|
||||||
import { RequestBody, getResponseMetadata } from '@services/utils/ts/requests'
|
import {
|
||||||
|
RequestBody,
|
||||||
|
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(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}courses/${body.course_uuid}/updates`,
|
`${getAPIUrl()}courses/${body.course_uuid}/updates`,
|
||||||
RequestBody('POST', body, null)
|
RequestBodyWithAuthHeader('POST', body, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await getResponseMetadata(result)
|
const res = await getResponseMetadata(result)
|
||||||
return res
|
return res
|
||||||
|
|
@ -12,11 +16,12 @@ export async function createCourseUpdate(body: any) {
|
||||||
|
|
||||||
export async function deleteCourseUpdate(
|
export async function deleteCourseUpdate(
|
||||||
course_uuid: string,
|
course_uuid: string,
|
||||||
update_uuid: number
|
update_uuid: number,
|
||||||
|
access_token: string
|
||||||
) {
|
) {
|
||||||
const result: any = await fetch(
|
const result: any = await fetch(
|
||||||
`${getAPIUrl()}courses/${course_uuid}/update/${update_uuid}`,
|
`${getAPIUrl()}courses/${course_uuid}/update/${update_uuid}`,
|
||||||
RequestBody('DELETE', null, null)
|
RequestBodyWithAuthHeader('DELETE', null, null, access_token)
|
||||||
)
|
)
|
||||||
const res = await getResponseMetadata(result)
|
const res = await getResponseMetadata(result)
|
||||||
return res
|
return res
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ export const RequestBodyWithAuthHeader = (
|
||||||
headers: HeadersConfig,
|
headers: HeadersConfig,
|
||||||
redirect: 'follow',
|
redirect: 'follow',
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
body: data,
|
body: (method === 'POST' || method === 'PUT') ? JSON.stringify(data) : null,
|
||||||
// Next.js
|
// Next.js
|
||||||
next: next,
|
next: next,
|
||||||
}
|
}
|
||||||
|
|
@ -41,6 +41,27 @@ export const RequestBodyWithAuthHeader = (
|
||||||
|
|
||||||
export const RequestBodyForm = (method: string, data: any, next: any) => {
|
export const RequestBodyForm = (method: string, data: any, next: any) => {
|
||||||
let HeadersConfig = new Headers({})
|
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 = {
|
let options: any = {
|
||||||
method: method,
|
method: method,
|
||||||
headers: HeadersConfig,
|
headers: HeadersConfig,
|
||||||
|
|
@ -53,9 +74,13 @@ export const RequestBodyForm = (method: string, data: any, next: any) => {
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
export const swrFetcher = async (url: string) => {
|
export const swrFetcher = async (url: string, token?: string) => {
|
||||||
// Create the request options
|
// 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 = {
|
let options: any = {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: HeadersConfig,
|
headers: HeadersConfig,
|
||||||
|
|
|
||||||
15
apps/web/types/next-auth.d.ts
vendored
Normal file
15
apps/web/types/next-auth.d.ts
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,5 +12,5 @@
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"turbo": "^1.13.2"
|
"turbo": "^1.13.2"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@8.6.10"
|
"packageManager": "pnpm@9.0.6"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue