mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: assignmentTask creation and switching
This commit is contained in:
parent
6a4e16ec29
commit
acfcea026b
9 changed files with 354 additions and 55 deletions
|
|
@ -102,11 +102,7 @@ class AssignmentTaskBase(SQLModel):
|
|||
contents: Dict = Field(default={}, sa_column=Column(JSON))
|
||||
max_grade_value: int = 0 # Value is always between 0-100
|
||||
|
||||
assignment_id: int
|
||||
org_id: int
|
||||
course_id: int
|
||||
chapter_id: int
|
||||
activity_id: int
|
||||
|
||||
|
||||
|
||||
class AssignmentTaskCreate(AssignmentTaskBase):
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from src.services.courses.activities.assignments import (
|
|||
read_assignment,
|
||||
read_assignment_from_activity_uuid,
|
||||
read_assignment_submissions,
|
||||
read_assignment_task,
|
||||
read_assignment_task_submissions,
|
||||
read_assignment_tasks,
|
||||
read_user_assignment_submissions,
|
||||
|
|
@ -151,6 +152,20 @@ async def api_read_assignment_tasks(
|
|||
)
|
||||
|
||||
|
||||
@router.get("/task/{assignment_task_uuid}")
|
||||
async def api_read_assignment_task(
|
||||
request: Request,
|
||||
assignment_task_uuid: str,
|
||||
current_user: PublicUser = Depends(get_current_user),
|
||||
db_session=Depends(get_db_session),
|
||||
):
|
||||
"""
|
||||
Read task for an assignment
|
||||
"""
|
||||
return await read_assignment_task(
|
||||
request, assignment_task_uuid, current_user, db_session
|
||||
)
|
||||
|
||||
@router.put("/{assignment_uuid}/tasks/{task_uuid}")
|
||||
async def api_update_assignment_tasks(
|
||||
request: Request,
|
||||
|
|
|
|||
|
|
@ -315,6 +315,10 @@ async def create_assignment_task(
|
|||
assignment_task.creation_date = str(datetime.now())
|
||||
assignment_task.update_date = str(datetime.now())
|
||||
assignment_task.org_id = course.org_id
|
||||
assignment_task.chapter_id = assignment.chapter_id
|
||||
assignment_task.activity_id = assignment.activity_id
|
||||
assignment_task.assignment_id = assignment.id # type: ignore
|
||||
assignment_task.course_id = assignment.course_id
|
||||
|
||||
# Insert Assignment Task in DB
|
||||
db_session.add(assignment_task)
|
||||
|
|
@ -365,6 +369,48 @@ async def read_assignment_tasks(
|
|||
for assignment_task in db_session.exec(statement).all()
|
||||
]
|
||||
|
||||
async def read_assignment_task(
|
||||
request: Request,
|
||||
assignment_task_uuid: str,
|
||||
current_user: PublicUser | AnonymousUser,
|
||||
db_session: Session,
|
||||
):
|
||||
# Find assignment
|
||||
statement = select(AssignmentTask).where(AssignmentTask.assignment_task_uuid == assignment_task_uuid)
|
||||
assignmenttask = db_session.exec(statement).first()
|
||||
|
||||
if not assignmenttask:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment Task not found",
|
||||
)
|
||||
|
||||
# Check if assignment exists
|
||||
statement = select(Assignment).where(Assignment.id == assignmenttask.assignment_id)
|
||||
assignment = db_session.exec(statement).first()
|
||||
|
||||
if not assignment:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Assignment not found",
|
||||
)
|
||||
|
||||
# Check if course exists
|
||||
statement = select(Course).where(Course.id == assignment.course_id)
|
||||
course = db_session.exec(statement).first()
|
||||
|
||||
if not course:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Course not found",
|
||||
)
|
||||
|
||||
# RBAC check
|
||||
await rbac_check(request, course.course_uuid, current_user, "read", db_session)
|
||||
|
||||
# return assignment task read
|
||||
return AssignmentTaskRead.model_validate(assignmenttask)
|
||||
|
||||
|
||||
async def update_assignment_task(
|
||||
request: Request,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
import { useLHSession } from '@components/Contexts/LHSessionContext';
|
||||
import { getAPIUrl } from '@services/config/config';
|
||||
import { createAssignmentTask } from '@services/courses/assignments'
|
||||
import { AArrowUp, FileUp, ListTodo } from 'lucide-react'
|
||||
import React from 'react'
|
||||
import toast from 'react-hot-toast';
|
||||
import { mutate } from 'swr';
|
||||
|
||||
function NewTaskModal({ closeModal, assignment_uuid }: any) {
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const reminderShownRef = React.useRef(false);
|
||||
|
||||
function showReminderToast() {
|
||||
// Check if the reminder has already been shown using sessionStorage
|
||||
if (sessionStorage.getItem("TasksReminderShown") !== "true") {
|
||||
setTimeout(() => {
|
||||
toast('When editing/adding your tasks, make sure to Unpublish your Assignment to avoid any issues with students, you can Publish it again when you are ready.',
|
||||
{ icon: '✋', duration: 10000, style: { minWidth: 600 } });
|
||||
// Mark the reminder as shown in sessionStorage
|
||||
sessionStorage.setItem("TasksReminderShown", "true");
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
async function createTask(type: string) {
|
||||
const task_object = {
|
||||
title: "Untitled Task",
|
||||
description: "",
|
||||
hint: "",
|
||||
reference_file: "",
|
||||
assignment_type: type,
|
||||
contents: {},
|
||||
max_grade_value: 100,
|
||||
}
|
||||
await createAssignmentTask(task_object, assignment_uuid, access_token)
|
||||
toast.success('Task created successfully')
|
||||
showReminderToast()
|
||||
mutate(`${getAPIUrl()}assignments/${assignment_uuid}/tasks`)
|
||||
closeModal(false)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className='flex space-x-6 mx-auto justify-center items-center'>
|
||||
<div
|
||||
onClick={() => createTask('QUIZ')}
|
||||
className='flex flex-col space-y-2 justify-center text-center pt-10'>
|
||||
<div className='px-5 py-5 rounded-full nice-shadow w-fit mx-auto bg-gray-100/50 text-gray-500 cursor-pointer hover:bg-gray-100 transition-all ease-linear'>
|
||||
<ListTodo size={30} />
|
||||
</div>
|
||||
<p className='text-xl text-gray-700 font-semibold'>Quiz</p>
|
||||
<p className='text-sm text-gray-500 w-40'>Questions with multiple choice answers</p>
|
||||
</div>
|
||||
<div
|
||||
onClick={() => createTask('FILE_SUBMISSION')}
|
||||
className='flex flex-col space-y-2 justify-center text-center pt-10'>
|
||||
<div className='px-5 py-5 rounded-full nice-shadow w-fit mx-auto bg-gray-100/50 text-gray-500 cursor-pointer hover:bg-gray-100 transition-all ease-linear'>
|
||||
<FileUp size={30} />
|
||||
</div>
|
||||
<p className='text-xl text-gray-700 font-semibold'>File submissions</p>
|
||||
<p className='text-sm text-gray-500 w-40'>Students can submit files for this task</p>
|
||||
</div>
|
||||
<div
|
||||
onClick={() => toast.error('Forms are not yet supported')}
|
||||
className='flex flex-col space-y-2 justify-center text-center pt-10 opacity-25'>
|
||||
<div className='px-5 py-5 rounded-full nice-shadow w-fit mx-auto bg-gray-100/50 text-gray-500 cursor-pointer hover:bg-gray-100 transition-all ease-linear'>
|
||||
<AArrowUp size={30} />
|
||||
</div>
|
||||
<p className='text-xl text-gray-700 font-semibold'>Forms</p>
|
||||
<p className='text-sm text-gray-500 w-40'>Forms for students to fill out</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default NewTaskModal
|
||||
|
|
@ -1,30 +1,52 @@
|
|||
'use client';
|
||||
import { Info, Link } from 'lucide-react'
|
||||
import React from 'react'
|
||||
import { useAssignmentsTask } from '@components/Contexts/Assignments/AssignmentsTaskContext';
|
||||
import { Info, TentTree } from 'lucide-react'
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
function AssignmentTaskEditor({ task_uuid, page }: any) {
|
||||
function AssignmentTaskEditor({ page }: any) {
|
||||
const [selectedSubPage, setSelectedSubPage] = React.useState(page)
|
||||
const assignmentTaskState = useAssignmentsTask() as any
|
||||
|
||||
useEffect(() => {
|
||||
console.log(assignmentTaskState)
|
||||
}
|
||||
, [assignmentTaskState])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col font-black text-sm w-full z-20">
|
||||
|
||||
<div className='flex flex-col bg-white pl-10 pr-10 text-sm tracking-tight z-10 shadow-[0px_4px_16px_rgba(0,0,0,0.06)] pt-5'>
|
||||
<div className='font-semibold text-lg py-1'>
|
||||
Assignment Test #1
|
||||
</div>
|
||||
<div className='flex space-x-2 '>
|
||||
<div
|
||||
className={`flex space-x-4 py-2 w-fit text-center border-black transition-all ease-linear ${selectedSubPage === 'overview'
|
||||
? 'border-b-4'
|
||||
: 'opacity-50'
|
||||
} cursor-pointer`}
|
||||
>
|
||||
<div className="flex items-center space-x-2.5 mx-2">
|
||||
<Info size={16} />
|
||||
<div>Overview</div>
|
||||
{assignmentTaskState.assignmentTask && Object.keys(assignmentTaskState.assignmentTask).length > 0 && (
|
||||
<div className='flex flex-col bg-white pl-10 pr-10 text-sm tracking-tight z-10 shadow-[0px_4px_16px_rgba(0,0,0,0.06)] pt-5'>
|
||||
<div className='font-semibold text-lg py-1'>
|
||||
Assignment Test #1
|
||||
</div>
|
||||
<div className='flex space-x-2 '>
|
||||
<div
|
||||
className={`flex space-x-4 py-2 w-fit text-center border-black transition-all ease-linear ${selectedSubPage === 'overview'
|
||||
? 'border-b-4'
|
||||
: 'opacity-50'
|
||||
} cursor-pointer`}
|
||||
>
|
||||
<div className="flex items-center space-x-2.5 mx-2">
|
||||
<Info size={16} />
|
||||
<div>Overview</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{Object.keys(assignmentTaskState.assignmentTask).length == 0 && (
|
||||
<div className='flex flex-col h-full bg-white pl-10 pr-10 text-sm tracking-tight z-10 shadow-[0px_4px_16px_rgba(0,0,0,0.06)] pt-5'>
|
||||
<div className='flex justify-center items-center h-full text-gray-300 antialiased'>
|
||||
<div className='flex flex-col space-y-2 items-center'>
|
||||
<TentTree size={60} />
|
||||
<div className='font-semibold text-2xl py-1'>
|
||||
No Task Selected
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
import { useAssignments } from '@components/Contexts/Assignments/AssignmentContext'
|
||||
import { Plus } from 'lucide-react';
|
||||
import Modal from '@components/StyledElements/Modal/Modal';
|
||||
import { FileUp, ListTodo, PanelLeftOpen, Plus } from 'lucide-react';
|
||||
import React, { useEffect } from 'react'
|
||||
import NewTaskModal from './Modals/NewTaskModal';
|
||||
import { useAssignmentsTaskDispatch } from '@components/Contexts/Assignments/AssignmentsTaskContext';
|
||||
|
||||
function AssignmentTasks() {
|
||||
function AssignmentTasks({ assignment_uuid }: any) {
|
||||
const assignments = useAssignments() as any;
|
||||
const assignmentTaskHook = useAssignmentsTaskDispatch() as any;
|
||||
const [isNewTaskModalOpen, setIsNewTaskModalOpen] = React.useState(false)
|
||||
|
||||
async function setSelectTask(task_uuid: string) {
|
||||
assignmentTaskHook({ type: 'setSelectedAssignmentTaskUUID', payload: task_uuid })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log(assignments)
|
||||
}, [assignments])
|
||||
|
||||
|
||||
|
|
@ -15,19 +23,47 @@ function AssignmentTasks() {
|
|||
<div className='flex flex-col space-y-3 mx-auto'>
|
||||
{assignments && assignments?.assignment_tasks?.map((task: any) => {
|
||||
return (
|
||||
<div key={task.id} className='flex flex-col w-[250px] nice-shadow bg-white shadow-[0px_4px_16px_rgba(0,0,0,0.06)] p-3 rounded-md'>
|
||||
<div className='flex justify-between px-2'>
|
||||
<div className='font-semibold text-sm'>{task.title}</div>
|
||||
<div
|
||||
key={task.id}
|
||||
className='flex flex-col w-[250px] nice-shadow bg-white shadow-[0px_4px_16px_rgba(0,0,0,0.06)] p-3 rounded-md'
|
||||
onClick={() => setSelectTask(task.assignment_task_uuid)}
|
||||
>
|
||||
<div className='flex items-center px-2 justify-between'>
|
||||
<div className="flex space-x-3 items-center">
|
||||
<div className='text-gray-500'>
|
||||
{task.assignment_type === 'QUIZ' && <ListTodo size={15} />}
|
||||
{task.assignment_type === 'FILE_SUBMISSION' && <FileUp size={15} />}
|
||||
</div>
|
||||
<div className='font-semibold text-sm'>{task.title}</div>
|
||||
</div>
|
||||
<button className="outline outline-1 outline-gray-200 hover:bg-slate-100/50 rounded-md text-gray-500 font-bold py-2 px-3 focus:bg-slate-100 ease-linear transition-all">
|
||||
<PanelLeftOpen size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<div className='flex space-x-1.5 px-2 py-2 bg-black text-white text-xs rounded-md antialiased items-center font-semibold cursor-pointer'>
|
||||
<Plus size={17} />
|
||||
<p>Add Task</p>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
isDialogOpen={isNewTaskModalOpen}
|
||||
onOpenChange={setIsNewTaskModalOpen}
|
||||
minHeight="sm"
|
||||
minWidth='sm'
|
||||
dialogContent={
|
||||
<NewTaskModal assignment_uuid={assignment_uuid} closeModal={setIsNewTaskModalOpen} />
|
||||
}
|
||||
dialogTitle="Add an Assignment Task"
|
||||
dialogDescription="Create a new task for this assignment"
|
||||
dialogTrigger={
|
||||
<div className='flex space-x-1.5 px-2 py-2 justify-center bg-black text-white text-xs rounded-md antialiased items-center font-semibold cursor-pointer'>
|
||||
<Plus size={17} />
|
||||
<p>Add Task</p>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
'use client';
|
||||
import BreadCrumbs from '@components/Dashboard/UI/BreadCrumbs'
|
||||
import AuthenticatedClientElement from '@components/Security/AuthenticatedClientElement'
|
||||
import { BookOpen, BookOpenCheck, BookX, Check, Ellipsis, EllipsisVertical, GalleryVerticalEnd, Info, LayoutList, UserRoundCog } from 'lucide-react'
|
||||
import { BookOpen, BookX, EllipsisVertical, LayoutList } from 'lucide-react'
|
||||
import React from 'react'
|
||||
import AssignmentTaskEditor from './_components/TaskEditor';
|
||||
import { AssignmentProvider } from '@components/Contexts/Assignments/AssignmentContext';
|
||||
import AssignmentTasks from './_components/Tasks';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { AssignmentsTaskProvider } from '@components/Contexts/Assignments/AssignmentsTaskContext';
|
||||
import ToolTip from '@components/StyledElements/Tooltip/Tooltip';
|
||||
|
||||
function AssignmentEdit() {
|
||||
const params = useParams<{ assignmentuuid: string; }>()
|
||||
|
|
@ -24,33 +25,47 @@ function AssignmentEdit() {
|
|||
<div className='flex mx-auto mt-5 items-center space-x-4'>
|
||||
<div className='flex bg-green-200/60 text-xs rounded-full px-3.5 py-2 mx-auto font-bold outline outline-1 outline-green-300'>Published</div>
|
||||
<div><EllipsisVertical className='text-gray-500' size={13} /></div>
|
||||
<div className='flex px-3 py-2 cursor-pointer rounded-md space-x-2 items-center bg-gradient-to-bl text-green-800 font-medium from-green-400/50 to-lime-200/80 border border-green-600/10 shadow-green-900/10 shadow-lg'>
|
||||
<BookOpen size={18} />
|
||||
<p className=' text-sm font-bold'>Publish</p>
|
||||
</div>
|
||||
<ToolTip
|
||||
side='left'
|
||||
slateBlack
|
||||
sideOffset={10}
|
||||
content="Make your Assignment public and available for students" >
|
||||
<div className='flex px-3 py-2 cursor-pointer rounded-md space-x-2 items-center bg-gradient-to-bl text-green-800 font-medium from-green-400/50 to-lime-200/80 border border-green-600/10 shadow-green-900/10 shadow-lg'>
|
||||
<BookOpen size={18} />
|
||||
<p className=' text-sm font-bold'>Publish</p>
|
||||
</div>
|
||||
</ToolTip>
|
||||
<ToolTip
|
||||
side='left'
|
||||
slateBlack
|
||||
sideOffset={10}
|
||||
content="Make your Assignment unavailable for students" >
|
||||
<div className='flex px-3 py-2 cursor-pointer rounded-md space-x-2 items-center bg-gradient-to-bl text-gray-800 font-medium from-gray-400/50 to-gray-200/80 border border-gray-600/10 shadow-gray-900/10 shadow-lg'>
|
||||
<BookX size={18} />
|
||||
<p className='text-sm font-bold'>Unpublish</p>
|
||||
</div>
|
||||
</ToolTip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-full">
|
||||
<div className='flex w-[400px] flex-col h-screen custom-dots-bg'>
|
||||
<div className='flex mx-auto px-3.5 py-1 bg-neutral-600/80 space-x-2 my-5 items-center text-sm font-bold text-white rounded-full'>
|
||||
<LayoutList size={18} />
|
||||
<p>Tasks</p>
|
||||
<div className="flex h-full w-full">
|
||||
<AssignmentsTaskProvider>
|
||||
<div className='flex w-[400px] flex-col h-full custom-dots-bg'>
|
||||
<div className='flex mx-auto px-3.5 py-1 bg-neutral-600/80 space-x-2 my-5 items-center text-sm font-bold text-white rounded-full'>
|
||||
<LayoutList size={18} />
|
||||
<p>Tasks</p>
|
||||
</div>
|
||||
<AssignmentProvider assignment_uuid={'assignment_' + params.assignmentuuid}>
|
||||
<AssignmentTasks assignment_uuid={'assignment_' + params.assignmentuuid} />
|
||||
</AssignmentProvider>
|
||||
</div>
|
||||
<AssignmentProvider assignment_uuid='assignment_a35fdbb9-11bd-40cf-a781-f6bdd5d87165'>
|
||||
<AssignmentTasks />
|
||||
</AssignmentProvider>
|
||||
</div>
|
||||
<div className='flex flex-grow bg-[#fefcfe] nice-shadow h-screen w-full'>
|
||||
<AssignmentProvider assignment_uuid={'assignment_' + params.assignmentuuid}>
|
||||
<AssignmentTaskEditor task_uuid='UUID' page='overview' />
|
||||
</AssignmentProvider>
|
||||
</div>
|
||||
<div className='flex flex-grow bg-[#fefcfe] nice-shadow h-full w-full'>
|
||||
<AssignmentProvider assignment_uuid={'assignment_' + params.assignmentuuid}>
|
||||
<AssignmentTaskEditor task_uuid='UUID' page='overview' />
|
||||
</AssignmentProvider>
|
||||
</div>
|
||||
</AssignmentsTaskProvider>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
'use client'
|
||||
import React, { createContext, useContext, useEffect, useReducer } from 'react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import { getAssignmentTask } from '@services/courses/assignments'
|
||||
|
||||
interface State {
|
||||
selectedAssignmentTaskUUID: string | null;
|
||||
assignmentTask: Record<string, any>;
|
||||
}
|
||||
|
||||
interface Action {
|
||||
type: string;
|
||||
payload?: any;
|
||||
}
|
||||
|
||||
const initialState: State = {
|
||||
selectedAssignmentTaskUUID: null,
|
||||
assignmentTask: {}
|
||||
};
|
||||
|
||||
export const AssignmentsTaskContext = createContext<State | undefined>(undefined);
|
||||
export const AssignmentsTaskDispatchContext = createContext<React.Dispatch<Action> | undefined>(undefined);
|
||||
|
||||
export function AssignmentsTaskProvider({ children }: { children: React.ReactNode }) {
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
|
||||
const [state, dispatch] = useReducer(assignmentstaskReducer, initialState);
|
||||
|
||||
async function fetchAssignmentTask(assignmentTaskUUID: string) {
|
||||
const res = await getAssignmentTask(assignmentTaskUUID, access_token);
|
||||
if (res.success) {
|
||||
dispatch({ type: 'setAssignmentTask', payload: res });
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (state.selectedAssignmentTaskUUID) {
|
||||
fetchAssignmentTask(state.selectedAssignmentTaskUUID);
|
||||
}
|
||||
}, [state.selectedAssignmentTaskUUID]);
|
||||
|
||||
return (
|
||||
<AssignmentsTaskContext.Provider value={state}>
|
||||
<AssignmentsTaskDispatchContext.Provider value={dispatch}>
|
||||
{children}
|
||||
</AssignmentsTaskDispatchContext.Provider>
|
||||
</AssignmentsTaskContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useAssignmentsTask() {
|
||||
const context = useContext(AssignmentsTaskContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useAssignmentsTask must be used within an AssignmentsTaskProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
export function useAssignmentsTaskDispatch() {
|
||||
const context = useContext(AssignmentsTaskDispatchContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useAssignmentsTaskDispatch must be used within an AssignmentsTaskProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
function assignmentstaskReducer(state: State, action: Action): State {
|
||||
switch (action.type) {
|
||||
case 'setSelectedAssignmentTaskUUID':
|
||||
return { ...state, selectedAssignmentTaskUUID: action.payload };
|
||||
case 'setAssignmentTask':
|
||||
return { ...state, assignmentTask: action.payload };
|
||||
case 'reload':
|
||||
return { ...state };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -64,3 +64,15 @@ export async function createAssignmentTask(
|
|||
const res = await getResponseMetadata(result)
|
||||
return res
|
||||
}
|
||||
|
||||
export async function getAssignmentTask(
|
||||
assignmentTaskUUID: string,
|
||||
access_token: string
|
||||
) {
|
||||
const result: any = await fetch(
|
||||
`${getAPIUrl()}assignments/task/${assignmentTaskUUID}`,
|
||||
RequestBodyWithAuthHeader('GET', null, null, access_token)
|
||||
)
|
||||
const res = await getResponseMetadata(result)
|
||||
return res
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue