diff --git a/backend/app.py b/backend/app.py index 54e935e..d6ad1aa 100644 --- a/backend/app.py +++ b/backend/app.py @@ -19,6 +19,7 @@ from blueprints.session import session as sessionBlueprint from blueprints.admin import admin as adminBlueprint from blueprints.chat import chat as chatBlueprint from blueprints.public import public_summary as publicBlueprint +from blueprints.course import course as courseBlueprint app = Flask(__name__) @@ -29,7 +30,7 @@ CORS(app) # r"/api/*": {"origins": "*"} # Allows CORS for all `/api/` routes # }) # Set configuration directly on the app instance -app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif'} +app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif','pdf'} app.config["SQLALCHEMY_DATABASE_URI"] = DB_URI @@ -40,6 +41,7 @@ app.register_blueprint(sessionBlueprint,url_prefix='/api/session') app.register_blueprint(adminBlueprint,url_prefix='/api/admin') app.register_blueprint(chatBlueprint,url_prefix='/api/chat') app.register_blueprint(publicBlueprint,url_prefix='/api/public') +app.register_blueprint(courseBlueprint,url_prefix='/api/course') @app.route('/media/') def send_file(filename): diff --git a/backend/blueprints/chat/__init__.py b/backend/blueprints/chat/__init__.py index be930f8..f796bd7 100644 --- a/backend/blueprints/chat/__init__.py +++ b/backend/blueprints/chat/__init__.py @@ -2,7 +2,7 @@ import uuid from flask import Blueprint, request, jsonify,g from uuid import UUID -from ...db.model import db, User, Course, Enrollment,Chat +from db.model import db, User, Course, Enrollment,Chat from utils.auth import auth_required import requests from config import SPAM_SCORE_THRESHOLD, AI_SPAM_SERVICES_MICROSERVICE diff --git a/backend/blueprints/course/__init__.py b/backend/blueprints/course/__init__.py index 2f66612..0ec75da 100644 --- a/backend/blueprints/course/__init__.py +++ b/backend/blueprints/course/__init__.py @@ -13,14 +13,14 @@ from constants import * from config import * from constants import PublishedStatus from typing import Union -from backend.constants import UserRole +from db.model import UserRole course = Blueprint('course', __name__) @course.route('/listAll') def list_all_courses(): limit: int = int(request.args.get('limit', 10)) - offset: int = int(request.args.get('offset', 1)) + offset: int = int(request.args.get('offset', 0)) category_uuid: str = request.args.get('category_uuid') search_q: str = request.args.get('search_q', '').strip() sort_by: str = request.args.get('sort_by', '').strip() @@ -28,13 +28,19 @@ def list_all_courses(): if category_uuid is not None: category_uuid: uuid.UUID = uuid.UUID(request.args.get('category_uuid')) # Build the query as required - query: select = select(Course).limit(limit).offset(offset) + query: select = select(Course) if search_q != '': query = query.where(or_(Course.name.like(f'%{search_q}%'), Course.description.like(f'%{search_q}%'), - Course.author.firstName.like(f'%{search_q}%'))) + User.firstName.like(f'%{search_q}%'))) if category_uuid is not None: query = query.where(Course.categoryID == category_uuid) - total_pages_for_offset: int = db.session.execute(func.count(Course.id).select_from(Course)).scalar()/limit + + #total_pages_for_offset: int = db.session.execute(func.count(Course.id).select_from(Course)).scalar()/limit + total_pages_for_offset: int = db.session.execute( + select(func.count()).select_from(query.subquery()) + ).scalar() / limit + + query = query.limit(limit).offset(offset) total_pages: int = math.ceil(total_pages_for_offset) if sort_by in available_sorts: if sort_by == 'date_asc': @@ -64,7 +70,7 @@ def list_all_courses(): 'author': { 'id': item.author.id, 'firstName': item.author.firstName, - 'lastName': item.author.LastName, + 'lastName': item.author.lastName, 'username': item.author.username, 'bio': item.author.bio, 'lastOnline': item.author.lastOnline, @@ -104,7 +110,7 @@ def enroll_user(): return jsonify({'message': 'Already enrolled to this course'}) return jsonify({'message': 'Enrollment successful'}), 200 -@course.route('/create', methods=['POST']) +@course.route('/createCourse', methods=['POST']) @auth_required() def create_course(): form_data: dict = request.form @@ -113,10 +119,10 @@ def create_course(): cover_file_name: str = DEFAULT_COURSE_COVER pdf_file_name: str = '' if course_uploaded_cover_image is not None: - cover_file_name: str = random_string_generator(32)+course_uploaded_cover_image.filename.split('.')[-1] + cover_file_name: str = random_string_generator(32)+"."+course_uploaded_cover_image.filename.split('.')[-1] course_uploaded_cover_image.save(os.path.join(USER_UPLOADS_DIR, cover_file_name)) if course_uploaded_pdf is not None: - pdf_file_name: str = random_string_generator(32) + course_uploaded_pdf.filename.split('.')[-1] + pdf_file_name: str = random_string_generator(32) +"."+ course_uploaded_pdf.filename.split('.')[-1] course_uploaded_pdf.save(os.path.join(USER_UPLOADS_DIR, pdf_file_name)) published_status: PublishedStatus = PublishedStatus.DRAFT try: @@ -126,24 +132,27 @@ def create_course(): course_description: str = form_data.get('course_description', '') category_id: uuid.UUID = uuid.UUID(form_data['category_uuid']) page_for_community: int = int(form_data.get('page_for_community', 1)) # TODO: Add this field to model - + catgory: Category = db.session.execute(select(Category).where(Category.id == category_id)).scalar() + # author: User = db.session.execute(select(User).where(User.id == g.current_user.id)).scalar() new_course: Course = Course( name=course_name, categoryID=category_id, authorID=g.current_user.id, + category=catgory, + author=g.current_user, description=course_description, isActive=True, pageForCommunity=page_for_community, publishedStatus=int(published_status), coverImage=cover_file_name, - serverFilename =pdf_file_name, + serverFilename=pdf_file_name, enrollments=[], quizzes=[], chats=[] ) # chat: Chat = Chat(courseID=new_course.id) TODO: Add a welcome chat for this course - db.session.add_all(new_course) + db.session.add(new_course) db.session.commit() return jsonify({'message': 'Course was created successfully.'}), 200 diff --git a/backend/db/model.py b/backend/db/model.py index 82852e6..a33b7dc 100644 --- a/backend/db/model.py +++ b/backend/db/model.py @@ -73,9 +73,9 @@ class Course(db.Model): authorID: Mapped[uuid.UUID] = mapped_column(ForeignKey("user.id")) author: Mapped["User"] = relationship(back_populates="publications") description: Mapped[str] = mapped_column(String(1024), nullable=False, default='') - pageForCommunity: Mapped[[int]] = mapped_column(Integer, nullable=False, default=1) - totalPages: Mapped[[int]] = mapped_column(Integer, nullable=False, default=1) - totalEnrolled: Mapped[int] = mapped_column(Integer, nullable=False, default='') + pageForCommunity: Mapped[int] = mapped_column(Integer, nullable=False, default=1) + totalPages: Mapped[int] = mapped_column(Integer, nullable=False, default=1) + totalEnrolled: Mapped[int] = mapped_column(Integer, nullable=False, default=0) isActive: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) publishedStatus: Mapped[int] = mapped_column(SmallInteger, nullable=False, default=PublishedStatus.DRAFT) creationDate: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=func.now()) diff --git a/backend/uploads/JRyiqfKMGnWcunvfcosPJxgBGQTjasLh.jpg b/backend/uploads/JRyiqfKMGnWcunvfcosPJxgBGQTjasLh.jpg new file mode 100644 index 0000000..1862f74 Binary files /dev/null and b/backend/uploads/JRyiqfKMGnWcunvfcosPJxgBGQTjasLh.jpg differ diff --git a/backend/uploads/izvjgAZCUwVlTZpoMdoFUnMoMoPNDkPD.pdf b/backend/uploads/izvjgAZCUwVlTZpoMdoFUnMoMoPNDkPD.pdf new file mode 100644 index 0000000..0988a42 Binary files /dev/null and b/backend/uploads/izvjgAZCUwVlTZpoMdoFUnMoMoPNDkPD.pdf differ