feat: use session access_tokens

This commit is contained in:
swve 2024-06-01 12:23:01 +01:00
parent 08cc97f557
commit 52f2235942
74 changed files with 413 additions and 440 deletions

View file

@ -75,6 +75,7 @@ type ActivityChatMessageBoxProps = {
function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes
const dispatchAIChatBot = useAIChatBotDispatch() as any
@ -115,7 +116,8 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
const response = await sendActivityAIChatMessage(
message,
aiChatBotState.aichat_uuid,
props.activity.activity_uuid
props.activity.activity_uuid,
access_token
)
if (response.success == false) {
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' })
@ -143,8 +145,9 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
})
await dispatchAIChatBot({ type: 'setIsWaitingForResponse' })
const response = await startActivityAIChatSession(
message,
message,access_token,
props.activity.activity_uuid
)
if (response.success == false) {
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' })
@ -219,14 +222,12 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
/>
</div>
<div
className={`flex space-x-2 items-center -ml-[100px] ${
aiChatBotState.isWaitingForResponse ? 'animate-pulse' : ''
}`}
className={`flex space-x-2 items-center -ml-[100px] ${aiChatBotState.isWaitingForResponse ? 'animate-pulse' : ''
}`}
>
<Image
className={`outline outline-1 outline-neutral-200/20 rounded-lg ${
aiChatBotState.isWaitingForResponse ? 'animate-pulse' : ''
}`}
className={`outline outline-1 outline-neutral-200/20 rounded-lg ${aiChatBotState.isWaitingForResponse ? 'animate-pulse' : ''
}`}
width={24}
src={learnhouseAI_icon}
alt=""
@ -244,12 +245,11 @@ function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
</div>
</div>
<div
className={`w-100 h-0.5 bg-white/5 rounded-full mx-auto mb-3 ${
aiChatBotState.isWaitingForResponse ? 'animate-pulse' : ''
}`}
className={`w-100 h-0.5 bg-white/5 rounded-full mx-auto mb-3 ${aiChatBotState.isWaitingForResponse ? 'animate-pulse' : ''
}`}
></div>
{aiChatBotState.messages.length > 0 &&
!aiChatBotState.error.isError ? (
!aiChatBotState.error.isError ? (
<div className="flex-col h-[237px] w-full space-y-4 overflow-scroll scrollbar-w-2 scrollbar scrollbar-thumb-white/20 scrollbar-thumb-rounded-full scrollbar-track-rounded-full">
{aiChatBotState.messages.map(
(message: AIMessage, index: number) => {

View file

@ -12,7 +12,6 @@ function DocumentPdfActivity({
const org = useOrg() as any
React.useEffect(() => {
console.log(activity)
}, [activity, org])
return (

View file

@ -15,6 +15,7 @@ import {
startActivityAIChatSession,
} from '@services/ai/ai'
import useGetAIFeatures from '../../../../AI/Hooks/useGetAIFeatures'
import { useLHSession } from '@components/Contexts/LHSessionContext'
type AICanvaToolkitProps = {
editor: Editor
@ -92,6 +93,8 @@ function AIActionButton(props: {
label: string
activity: any
}) {
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const dispatchAIChatBot = useAIChatBotDispatch() as any
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes
@ -132,7 +135,7 @@ function AIActionButton(props: {
const response = await sendActivityAIChatMessage(
message,
aiChatBotState.aichat_uuid,
props.activity.activity_uuid
props.activity.activity_uuid, access_token
)
if (response.success == false) {
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' })
@ -160,8 +163,7 @@ function AIActionButton(props: {
})
await dispatchAIChatBot({ type: 'setIsWaitingForResponse' })
const response = await startActivityAIChatSession(
message,
props.activity.activity_uuid
message, access_token
)
if (response.success == false) {
await dispatchAIChatBot({ type: 'setIsNoLongerWaitingForResponse' })
@ -193,10 +195,10 @@ function AIActionButton(props: {
props.label === 'Explain'
? 'Explain a word or a sentence with AI'
: props.label === 'Summarize'
? 'Summarize a long paragraph or text with AI'
: props.label === 'Translate'
? 'Translate to different languages with AI'
: 'Give examples to understand better with AI'
? 'Summarize a long paragraph or text with AI'
: props.label === 'Translate'
? 'Translate to different languages with AI'
: 'Give examples to understand better with AI'
return (
<div className="flex space-x-2">
<ToolTip sideOffset={10} slateBlack content={tooltipLabel}>

View file

@ -7,22 +7,6 @@ function VideoActivity({ activity, course }: { activity: any; course: any }) {
const org = useOrg() as any
const [videoId, setVideoId] = React.useState('')
function getYouTubeEmbed(url: any) {
// Extract video ID from the YouTube URL
var videoId = url.match(
/(?:\?v=|\/embed\/|\/\d\/|\/vi\/|\/v\/|https?:\/\/(?:www\.)?youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([^#\&\?\/]+)/
)[1]
// Create the embed object
var embedObject = {
videoId: videoId,
width: 560,
height: 315,
}
return embedObject
}
React.useEffect(() => {
if (activity && activity.content && activity.content.uri) {
var getYouTubeID = require('get-youtube-id');

View file

@ -38,7 +38,6 @@ function CourseUpdates() {
// if user clicks outside the model, close the model
React.useLayoutEffect(() => {
function handleClickOutside(event: any) {
console.log(event.target.id)
if (event.target.closest('.bg-white') || event.target.id === 'delete-update-button') return;
setIsModelOpen(false);
}

View file

@ -24,6 +24,7 @@ import {
startActivityAIChatSession,
} from '@services/ai/ai'
import useGetAIFeatures from '@components/AI/Hooks/useGetAIFeatures'
import { useLHSession } from '@components/Contexts/LHSessionContext'
type AIEditorToolkitProps = {
editor: Editor
@ -32,11 +33,11 @@ type AIEditorToolkitProps = {
type AIPromptsLabels = {
label:
| 'Writer'
| 'ContinueWriting'
| 'MakeLonger'
| 'GenerateQuiz'
| 'Translate'
| 'Writer'
| 'ContinueWriting'
| 'MakeLonger'
| 'GenerateQuiz'
| 'Translate'
selection: string
}
@ -141,6 +142,8 @@ function AIEditorToolkit(props: AIEditorToolkitProps) {
const UserFeedbackModal = (props: AIEditorToolkitProps) => {
const dispatchAIEditor = useAIEditorDispatch() as any
const aiEditorState = useAIEditor() as AIEditorStateTypes
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
await dispatchAIEditor({
@ -159,7 +162,7 @@ const UserFeedbackModal = (props: AIEditorToolkitProps) => {
const response = await sendActivityAIChatMessage(
message,
aiEditorState.aichat_uuid,
props.activity.activity_uuid
props.activity.activity_uuid, access_token
)
if (response.success === false) {
await dispatchAIEditor({ type: 'setIsNoLongerWaitingForResponse' })
@ -191,7 +194,7 @@ const UserFeedbackModal = (props: AIEditorToolkitProps) => {
})
await dispatchAIEditor({ type: 'setIsWaitingForResponse' })
const response = await startActivityAIChatSession(
message,
message, access_token,
props.activity.activity_uuid
)
if (response.success === false) {

View file

@ -44,8 +44,6 @@ import { CourseProvider } from '@components/Contexts/CourseContext'
import { useLHSession } from '@components/Contexts/LHSessionContext'
import AIEditorToolkit from './AI/AIEditorToolkit'
import useGetAIFeatures from '@components/AI/Hooks/useGetAIFeatures'
import UserAvatar from '../UserAvatar'
import randomColor from 'randomcolor'
import Collaboration from '@tiptap/extension-collaboration'
import CollaborationCursor from '@tiptap/extension-collaboration-cursor'
import ActiveAvatars from './ActiveAvatars'

View file

@ -25,6 +25,7 @@ interface EditorWrapperProps {
function EditorWrapper(props: EditorWrapperProps): JSX.Element {
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
// Define provider in the state
const [provider, setProvider] = React.useState<HocuspocusProvider | null>(null);
const [thisPageColor, setThisPageColor] = useState(randomColor({ luminosity: 'light' }) as string)
@ -79,7 +80,7 @@ function EditorWrapper(props: EditorWrapperProps): JSX.Element {
}
});
toast.promise(updateActivity(activity, activity.activity_uuid), {
toast.promise(updateActivity(activity, activity.activity_uuid,access_token), {
loading: 'Saving...',
success: <b>Activity saved!</b>,
error: <b>Could not save.</b>,

View file

@ -9,11 +9,14 @@ import { getActivityBlockMediaDirectory } from '@services/media/media'
import { useOrg } from '@components/Contexts/OrgContext'
import { useCourse } from '@components/Contexts/CourseContext'
import { useEditorProvider } from '@components/Contexts/Editor/EditorContext'
import { useLHSession } from '@components/Contexts/LHSessionContext'
function ImageBlockComponent(props: any) {
const org = useOrg() as any
const course = useCourse() as any
const editorState = useEditorProvider() as any
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const isEditable = editorState.isEditable
const [image, setImage] = React.useState(null)
@ -36,7 +39,7 @@ function ImageBlockComponent(props: any) {
setIsLoading(true)
let object = await uploadNewImageFile(
image,
props.extension.options.activity.activity_uuid
props.extension.options.activity.activity_uuid,access_token
)
setIsLoading(false)
setblockObject(object)

View file

@ -8,10 +8,13 @@ import { getActivityBlockMediaDirectory } from '@services/media/media'
import { useOrg } from '@components/Contexts/OrgContext'
import { useCourse } from '@components/Contexts/CourseContext'
import { useEditorProvider } from '@components/Contexts/Editor/EditorContext'
import { useLHSession } from '@components/Contexts/LHSessionContext'
function PDFBlockComponent(props: any) {
const org = useOrg() as any
const course = useCourse() as any
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const [pdf, setPDF] = React.useState(null)
const [isLoading, setIsLoading] = React.useState(false)
const [blockObject, setblockObject] = React.useState(
@ -32,7 +35,7 @@ function PDFBlockComponent(props: any) {
setIsLoading(true)
let object = await uploadNewPDFFile(
pdf,
props.extension.options.activity.activity_uuid
props.extension.options.activity.activity_uuid, access_token
)
setIsLoading(false)
setblockObject(object)
@ -41,7 +44,7 @@ function PDFBlockComponent(props: any) {
})
}
useEffect(() => {}, [course, org])
useEffect(() => { }, [course, org])
return (
<NodeViewWrapper className="block-pdf">

View file

@ -86,10 +86,8 @@ function QuizBlockComponent(props: any) {
if (allCorrect) {
setSubmissionMessage('All answers are correct!')
console.log('All answers are correct!')
} else {
setSubmissionMessage('Some answers are incorrect!')
console.log('Some answers are incorrect!')
}
}

View file

@ -8,6 +8,7 @@ import { UploadIcon } from '@radix-ui/react-icons'
import { useOrg } from '@components/Contexts/OrgContext'
import { useCourse } from '@components/Contexts/CourseContext'
import { useEditorProvider } from '@components/Contexts/Editor/EditorContext'
import { useLHSession } from '@components/Contexts/LHSessionContext'
function VideoBlockComponents(props: any) {
const org = useOrg() as any
@ -15,6 +16,8 @@ function VideoBlockComponents(props: any) {
const editorState = useEditorProvider() as any
const isEditable = editorState.isEditable
const [video, setVideo] = React.useState(null)
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const [isLoading, setIsLoading] = React.useState(false)
const [blockObject, setblockObject] = React.useState(
props.node.attrs.blockObject
@ -32,7 +35,7 @@ function VideoBlockComponents(props: any) {
setIsLoading(true)
let object = await uploadNewVideoFile(
video,
props.extension.options.activity.activity_uuid
props.extension.options.activity.activity_uuid, access_token
)
setIsLoading(false)
setblockObject(object)
@ -41,7 +44,7 @@ function VideoBlockComponents(props: any) {
})
}
useEffect(() => {}, [course, org])
useEffect(() => { }, [course, org])
return (
<NodeViewWrapper className="block-video">
@ -98,7 +101,7 @@ function VideoBlockComponents(props: any) {
)
}
const BlockVideoWrapper = styled.div`
//border: ${(props) =>
border: ${(props) =>
props.contentEditable ? '2px dashed #713f1117' : 'none'};
// center

View file

@ -1,12 +1,10 @@
'use client'
import React from 'react'
import Link from 'next/link'
import { getAPIUrl, getUriWithOrg } from '@services/config/config'
import { getUriWithOrg } from '@services/config/config'
import { HeaderProfileBox } from '@components/Security/HeaderProfileBox'
import MenuLinks from './MenuLinks'
import { getOrgLogoMediaDirectory } from '@services/media/media'
import useSWR from 'swr'
import { swrFetcher } from '@services/utils/ts/requests'
import { useLHSession } from '@components/Contexts/LHSessionContext'
import { useOrg } from '@components/Contexts/OrgContext'

View file

@ -19,7 +19,7 @@ import { useLHSession } from '@components/Contexts/LHSessionContext'
function CreateCourseModal({ closeModal, orgslug }: any) {
const [isSubmitting, setIsSubmitting] = useState(false)
const session = useLHSession()
const session = useLHSession() as any;
const [name, setName] = React.useState('')
const [description, setDescription] = React.useState('')
const [learnings, setLearnings] = React.useState('')
@ -55,7 +55,6 @@ function CreateCourseModal({ closeModal, orgslug }: any) {
const handleVisibilityChange = (event: React.ChangeEvent<any>) => {
setVisibility(event.target.value)
console.log(visibility)
}
const handleTagsChange = (event: React.ChangeEvent<any>) => {

View file

@ -1,10 +1,11 @@
'use client';
import { useCourse } from '@components/Contexts/CourseContext';
import { useLHSession } from '@components/Contexts/LHSessionContext';
import { useOrg } from '@components/Contexts/OrgContext';
import { getAPIUrl } from '@services/config/config';
import { linkResourcesToUserGroup } from '@services/usergroups/usergroups';
import { swrFetcher } from '@services/utils/ts/requests';
import { AlertTriangle, Info } from 'lucide-react';
import { Info } from 'lucide-react';
import React, { useEffect } from 'react'
import toast from 'react-hot-toast';
import useSWR, { mutate } from 'swr'
@ -17,6 +18,8 @@ type LinkToUserGroupProps = {
function LinkToUserGroup(props: LinkToUserGroupProps) {
const course = useCourse() as any
const org = useOrg() as any
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const courseStructure = course.courseStructure
const { data: usergroups } = useSWR(
@ -27,8 +30,7 @@ function LinkToUserGroup(props: LinkToUserGroupProps) {
const handleLink = async () => {
console.log('selectedUserGroup', selectedUserGroup)
const res = await linkResourcesToUserGroup(selectedUserGroup, courseStructure.course_uuid)
const res = await linkResourcesToUserGroup(selectedUserGroup, courseStructure.course_uuid, access_token)
if (res.status === 200) {
props.setUserGroupModal(false)
toast.success('Successfully linked to usergroup')
@ -37,7 +39,6 @@ function LinkToUserGroup(props: LinkToUserGroupProps) {
else {
toast.error('Error ' + res.status + ': ' + res.data.detail)
}
}
useEffect(() => {
@ -54,25 +55,25 @@ function LinkToUserGroup(props: LinkToUserGroupProps) {
<h1 className=' font-medium'>Users that are not part of the UserGroup will no longer have access to this course</h1>
</div>
<div className='p-4 flex-row flex justify-between items-center'>
<div className='py-1'>
<span className='px-3 text-gray-400 font-bold rounded-full py-1 bg-gray-100 mx-3'>UserGroup Name </span>
<select
onChange={(e) => setSelectedUserGroup(e.target.value)}
defaultValue={selectedUserGroup}
>
{usergroups && usergroups.map((group: any) => (
<option key={group.id} value={group.id}>{group.name}</option>
))}
</select>
</div>
<div className='py-3'>
<button onClick={() => { handleLink() }} className='bg-green-700 text-white font-bold px-4 py-2 rounded-md shadow'>Link</button>
<div className='py-1'>
<span className='px-3 text-gray-400 font-bold rounded-full py-1 bg-gray-100 mx-3'>UserGroup Name </span>
<select
onChange={(e) => setSelectedUserGroup(e.target.value)}
defaultValue={selectedUserGroup}
>
{usergroups && usergroups.map((group: any) => (
<option key={group.id} value={group.id}>{group.name}</option>
))}
</select>
</div>
<div className='py-3'>
<button onClick={() => { handleLink() }} className='bg-green-700 text-white font-bold px-4 py-2 rounded-md shadow'>Link</button>
</div>
</div>
</div>
</div>
)
}

View file

@ -2,7 +2,7 @@ import { useOrg } from '@components/Contexts/OrgContext'
import { getAPIUrl } from '@services/config/config'
import { createInviteCode, createInviteCodeWithUserGroup } from '@services/organizations/invites'
import { swrFetcher } from '@services/utils/ts/requests'
import { Shield, Ticket } from 'lucide-react'
import { Ticket } from 'lucide-react'
import { useLHSession } from '@components/Contexts/LHSessionContext'
import React, { useEffect } from 'react'
import toast from 'react-hot-toast'
@ -14,7 +14,8 @@ type OrgInviteCodeGenerateProps = {
function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) {
const org = useOrg() as any
const session = useLHSession()
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const [usergroup_id, setUsergroup_id] = React.useState(0);
const { data: usergroups } = useSWR(
org ? `${getAPIUrl()}usergroups/org/${org.id}` : null,

View file

@ -14,13 +14,16 @@ import { BarLoader } from 'react-spinners'
import { createUserGroup } from '@services/usergroups/usergroups'
import { mutate } from 'swr'
import { getAPIUrl } from '@services/config/config'
import { useLHSession } from '@components/Contexts/LHSessionContext'
type AddUserGroupProps = {
setCreateUserGroupModal: any
}
function AddUserGroup(props: AddUserGroupProps) {
const org = useOrg() as any
const org = useOrg() as any;
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const [userGroupName, setUserGroupName] = React.useState('')
const [userGroupDescription, setUserGroupDescription] = React.useState('')
const [isSubmitting, setIsSubmitting] = React.useState(false)
@ -42,7 +45,7 @@ function AddUserGroup(props: AddUserGroupProps) {
description: userGroupDescription,
org_id: org.id
}
const res = await createUserGroup(obj)
const res = await createUserGroup(obj, access_token)
if (res.status == 200) {
setIsSubmitting(false)
mutate(`${getAPIUrl()}usergroups/org/${org.id}`)

View file

@ -1,3 +1,4 @@
import { useLHSession } from '@components/Contexts/LHSessionContext'
import { useOrg } from '@components/Contexts/OrgContext'
import { getAPIUrl } from '@services/config/config'
import { linkUserToUserGroup, unLinkUserToUserGroup } from '@services/usergroups/usergroups'
@ -14,6 +15,8 @@ type ManageUsersProps = {
function ManageUsers(props: ManageUsersProps) {
const org = useOrg() as any
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const { data: OrgUsers } = useSWR(
org ? `${getAPIUrl()}orgs/${org.id}/users` : null,
swrFetcher
@ -31,7 +34,7 @@ function ManageUsers(props: ManageUsersProps) {
}
const handleLinkUser = async (user_id: any) => {
const res = await linkUserToUserGroup(props.usergroup_id, user_id)
const res = await linkUserToUserGroup(props.usergroup_id, user_id,access_token)
if (res.status === 200) {
toast.success('User linked successfully')
mutate(`${getAPIUrl()}usergroups/${props.usergroup_id}/users`)
@ -41,7 +44,7 @@ function ManageUsers(props: ManageUsersProps) {
}
const handleUnlinkUser = async (user_id: any) => {
const res = await unLinkUserToUserGroup(props.usergroup_id, user_id)
const res = await unLinkUserToUserGroup(props.usergroup_id, user_id,access_token)
if (res.status === 200) {
toast.success('User unlinked successfully')
mutate(`${getAPIUrl()}usergroups/${props.usergroup_id}/users`)

View file

@ -1,4 +1,5 @@
'use client'
import { useLHSession } from '@components/Contexts/LHSessionContext'
import { useOrg } from '@components/Contexts/OrgContext'
import FormLayout, {
ButtonBlack,
@ -22,6 +23,8 @@ interface Props {
function RolesUpdate(props: Props) {
const org = useOrg() as any
const session = useLHSession() as any
const access_token = session.data.tokens.access_token;
const [isSubmitting, setIsSubmitting] = React.useState(false)
const [assignedRole, setAssignedRole] = React.useState(
props.alreadyAssignedRole
@ -36,7 +39,7 @@ function RolesUpdate(props: Props) {
const handleSubmit = async (e: any) => {
e.preventDefault()
setIsSubmitting(true)
const res = await updateUserRole(org.id, props.user.user.id, assignedRole)
const res = await updateUserRole(org.id, props.user.user.id, assignedRole,access_token)
if (res.status === 200) {
await mutate(`${getAPIUrl()}orgs/${org.id}/users`)

View file

@ -34,7 +34,7 @@ function CollectionThumbnail(props: PropsType) {
href={getUriWithOrg(
props.orgslug,
'/collection/' +
removeCollectionPrefix(props.collection.collection_uuid)
removeCollectionPrefix(props.collection.collection_uuid)
)}
>
<div
@ -55,7 +55,7 @@ function CollectionThumbnail(props: PropsType) {
href={getUriWithOrg(
props.orgslug,
'/collection/' +
removeCollectionPrefix(props.collection.collection_uuid)
removeCollectionPrefix(props.collection.collection_uuid)
)}
>
<h1 className="font-bold text-md justify-center">
@ -75,7 +75,7 @@ function CollectionThumbnail(props: PropsType) {
const CollectionAdminEditsArea = (props: any) => {
const router = useRouter()
const session = useLHSession() ;
const session = useLHSession() as any;
const deleteCollectionUI = async (collectionId: number) => {
await deleteCollection(collectionId, session.data?.tokens?.access_token)

View file

@ -25,7 +25,7 @@ function removeCoursePrefix(course_uuid: string) {
function CourseThumbnail(props: PropsType) {
const router = useRouter()
const org = useOrg() as any
const session = useLHSession();
const session = useLHSession() as any;
async function deleteCourses(course_uuid: any) {
await deleteCourseFromBackend(course_uuid, session.data?.tokens?.access_token)