доделал управление файлами
This commit is contained in:
parent
eb498051a1
commit
e90be8b54e
@ -78,7 +78,7 @@ async def update_lesson(
|
|||||||
|
|
||||||
|
|
||||||
@lessons_router.delete(
|
@lessons_router.delete(
|
||||||
'/{lesson_id}',
|
'/{lesson_id}/',
|
||||||
response_model=Optional[LessonRead],
|
response_model=Optional[LessonRead],
|
||||||
summary='Delete a lesson',
|
summary='Delete a lesson',
|
||||||
description='Delete a lesson',
|
description='Delete a lesson',
|
||||||
@ -89,8 +89,7 @@ async def delete_lesson(
|
|||||||
current_user: User = Depends(require_teacher),
|
current_user: User = Depends(require_teacher),
|
||||||
):
|
):
|
||||||
lessons_service = LessonsService(db)
|
lessons_service = LessonsService(db)
|
||||||
await lessons_service.delete(lesson_id, current_user)
|
return await lessons_service.delete(lesson_id, current_user)
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@lessons_router.get(
|
@lessons_router.get(
|
||||||
|
|||||||
@ -1,12 +1,16 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
from fastapi import HTTPException, status
|
from fastapi import HTTPException, status
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from app.application.courses_repository import CoursesRepository
|
from app.application.courses_repository import CoursesRepository
|
||||||
|
from app.application.lesson_files_repository import LessonFilesRepository
|
||||||
from app.application.lessons_repository import LessonsRepository
|
from app.application.lessons_repository import LessonsRepository
|
||||||
from app.domain.entities.lessons import LessonCreate, LessonUpdate, LessonRead
|
from app.domain.entities.lessons import LessonCreate, LessonUpdate, LessonRead
|
||||||
from app.domain.models import Lesson, User
|
from app.domain.models import Lesson, User
|
||||||
|
from app.infrastructure.lesson_files_service import LessonFilesService
|
||||||
from app.settings import Settings
|
from app.settings import Settings
|
||||||
|
|
||||||
|
|
||||||
@ -14,6 +18,7 @@ class LessonsService:
|
|||||||
def __init__(self, db: AsyncSession):
|
def __init__(self, db: AsyncSession):
|
||||||
self.lessons_repository = LessonsRepository(db)
|
self.lessons_repository = LessonsRepository(db)
|
||||||
self.courses_repository = CoursesRepository(db)
|
self.courses_repository = CoursesRepository(db)
|
||||||
|
self.lesson_files_repository = LessonFilesRepository(db)
|
||||||
self.settings = Settings()
|
self.settings = Settings()
|
||||||
|
|
||||||
async def get_all_by_course(self, course_id: int) -> List[LessonRead]:
|
async def get_all_by_course(self, course_id: int) -> List[LessonRead]:
|
||||||
@ -91,4 +96,19 @@ class LessonsService:
|
|||||||
detail="Доступ запрещён"
|
detail="Доступ запрещён"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
lesson_files = await self.lesson_files_repository.get_by_lesson_id(lesson_id)
|
||||||
|
for file in lesson_files:
|
||||||
|
lesson_file = await self.lesson_files_repository.get_by_id(file.id)
|
||||||
|
|
||||||
|
if lesson_file is None:
|
||||||
|
raise HTTPException(404, "Файл не найден")
|
||||||
|
|
||||||
|
if not os.path.exists(lesson_file.file_path):
|
||||||
|
raise HTTPException(404, "Файл не найден на диске")
|
||||||
|
|
||||||
|
if os.path.exists(lesson_file.file_path):
|
||||||
|
os.remove(lesson_file.file_path)
|
||||||
|
|
||||||
|
await self.lesson_files_repository.delete(lesson_file)
|
||||||
|
|
||||||
await self.lessons_repository.delete(lesson)
|
await self.lessons_repository.delete(lesson)
|
||||||
|
|||||||
@ -46,6 +46,7 @@ const CourseDetailPage = () => {
|
|||||||
handleCreateLesson,
|
handleCreateLesson,
|
||||||
handleOpenLesson,
|
handleOpenLesson,
|
||||||
handleEditLesson,
|
handleEditLesson,
|
||||||
|
handleDeleteLesson,
|
||||||
} = useCourseDetailPage(courseId);
|
} = useCourseDetailPage(courseId);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
@ -112,10 +113,10 @@ const CourseDetailPage = () => {
|
|||||||
<Popconfirm
|
<Popconfirm
|
||||||
title="Удалить лекцию?"
|
title="Удалить лекцию?"
|
||||||
description="Это действие нельзя отменить"
|
description="Это действие нельзя отменить"
|
||||||
// onConfirm={(e) => {
|
onConfirm={(e) => {
|
||||||
// e?.stopPropagation();
|
e?.stopPropagation();
|
||||||
// handleDeleteLesson(lesson.id);
|
handleDeleteLesson(lesson.id);
|
||||||
// }}
|
}}
|
||||||
okText="Удалить"
|
okText="Удалить"
|
||||||
cancelText="Отмена"
|
cancelText="Отмена"
|
||||||
>
|
>
|
||||||
@ -132,12 +133,17 @@ const CourseDetailPage = () => {
|
|||||||
>
|
>
|
||||||
<div style={{marginBottom: 16}}>
|
<div style={{marginBottom: 16}}>
|
||||||
{lesson.description ? (
|
{lesson.description ? (
|
||||||
<Text type="secondary">{lesson.description}</Text>
|
<Text type="secondary">
|
||||||
|
{lesson.description.slice(0, 100)}...
|
||||||
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
<Text type="secondary" italic>Описание отсутствует</Text>
|
<Text type="secondary" italic>Описание отсутствует</Text>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Text>
|
||||||
|
Лекционный материал
|
||||||
|
</Text>
|
||||||
<div style={{marginTop: 16, display: "flex", alignItems: "center", gap: 8}}>
|
<div style={{marginTop: 16, display: "flex", alignItems: "center", gap: 8}}>
|
||||||
<Avatar size="small" style={{backgroundColor: "#1890ff"}}>
|
<Avatar size="small" style={{backgroundColor: "#1890ff"}}>
|
||||||
{userData?.first_name?.[0] || "У"}
|
{userData?.first_name?.[0] || "У"}
|
||||||
|
|||||||
@ -7,9 +7,10 @@ import {
|
|||||||
setSelectedLessonToUpdate,
|
setSelectedLessonToUpdate,
|
||||||
setSelectedLessonToView
|
setSelectedLessonToView
|
||||||
} from "../../../Redux/Slices/lessonsSlice.js";
|
} from "../../../Redux/Slices/lessonsSlice.js";
|
||||||
import {useGetLessonsByCourseIdQuery} from "../../../Api/lessonsApi.js";
|
import {useDeleteLessonMutation, useGetLessonsByCourseIdQuery} from "../../../Api/lessonsApi.js";
|
||||||
import {ROLES} from "../../../Core/constants.js";
|
import {ROLES} from "../../../Core/constants.js";
|
||||||
import CONFIG from "../../../Core/сonfig.js";
|
import CONFIG from "../../../Core/сonfig.js";
|
||||||
|
import {notification} from "antd";
|
||||||
|
|
||||||
|
|
||||||
const useCourseDetailPage = (courseId) => {
|
const useCourseDetailPage = (courseId) => {
|
||||||
@ -39,6 +40,28 @@ const useCourseDetailPage = (courseId) => {
|
|||||||
pollingInterval: 10000,
|
pollingInterval: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [
|
||||||
|
deleteLesson,
|
||||||
|
] = useDeleteLessonMutation();
|
||||||
|
|
||||||
|
const handleDeleteLesson = async (lessonId) => {
|
||||||
|
try {
|
||||||
|
await deleteLesson(lessonId);
|
||||||
|
|
||||||
|
notification.success({
|
||||||
|
title: "Успешно",
|
||||||
|
description: "Лекция удалена",
|
||||||
|
placement: "topRight",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
notification.error({
|
||||||
|
title: "Ошибка",
|
||||||
|
description: error?.data?.detail || "Произошла ошибка при удалении лекции",
|
||||||
|
placement: "topRight",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.document.title = `Система обучения lectio - Курс: ${courseData?.title}`;
|
window.document.title = `Система обучения lectio - Курс: ${courseData?.title}`;
|
||||||
}, [courseData]);
|
}, [courseData]);
|
||||||
@ -67,6 +90,7 @@ const useCourseDetailPage = (courseId) => {
|
|||||||
handleCreateLesson,
|
handleCreateLesson,
|
||||||
handleOpenLesson,
|
handleOpenLesson,
|
||||||
handleEditLesson,
|
handleEditLesson,
|
||||||
|
handleDeleteLesson,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user