{"id":14972581,"url":"https://github.com/hoangsonww/learning-management-system-fullstack","last_synced_at":"2025-10-26T19:31:45.775Z","repository":{"id":256079513,"uuid":"854270390","full_name":"hoangsonww/Learning-Management-System-Fullstack","owner":"hoangsonww","description":"📚 This repository hosts the E-Learning Management Full-Stack System, a demo LMS platform crafted with the dynamic MAD-Stack (MongoDB, Angular, and Django) to deliver a seamless and efficient online learning management experience!","archived":false,"fork":false,"pushed_at":"2024-10-23T20:00:46.000Z","size":13691,"stargazers_count":14,"open_issues_count":0,"forks_count":12,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-10-24T02:44:13.222Z","etag":null,"topics":["angular","angular-cli","angular-material","angularjs","django","django-application","django-framework","django-project","django-rest-framework","docker","docker-compose","mongodb","mongodb-database","mongoose","redis","redis-cache","redis-database","redis-server","rest-api","restful-api"],"latest_commit_sha":null,"homepage":"https://hoangsonww.github.io/Learning-Management-System-Fullstack/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hoangsonww.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-08T20:24:41.000Z","updated_at":"2024-10-23T17:16:56.000Z","dependencies_parsed_at":"2024-10-26T03:28:33.373Z","dependency_job_id":"1becc848-f969-4f36-8dcf-371608b01521","html_url":"https://github.com/hoangsonww/Learning-Management-System-Fullstack","commit_stats":{"total_commits":2031,"total_committers":1,"mean_commits":2031.0,"dds":0.0,"last_synced_commit":"ad82f515d2a9e0a7b3bd5a566097ac2c85f18d14"},"previous_names":["hoangsonww/learning-management-system","hoangsonww/learning-management-system-fullstack"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoangsonww%2FLearning-Management-System-Fullstack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoangsonww%2FLearning-Management-System-Fullstack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoangsonww%2FLearning-Management-System-Fullstack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hoangsonww%2FLearning-Management-System-Fullstack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hoangsonww","download_url":"https://codeload.github.com/hoangsonww/Learning-Management-System-Fullstack/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238394323,"owners_count":19464583,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular-cli","angular-material","angularjs","django","django-application","django-framework","django-project","django-rest-framework","docker","docker-compose","mongodb","mongodb-database","mongoose","redis","redis-cache","redis-database","redis-server","rest-api","restful-api"],"created_at":"2024-09-24T13:47:09.843Z","updated_at":"2025-10-26T19:31:45.761Z","avatar_url":"https://github.com/hoangsonww.png","language":"TypeScript","readme":"# E-Learning Management Fullstack System\n\nWelcome to the **E-Learning Management System (LMS)**! This project consists of two main components: the **Frontend** (built with **Angular**) and the **Backend** (developed using **Django and Django REST Framework**), combined with CI/CD technologies such as **Docker** and **Jenkins**. The LMS is a full-featured web application designed to manage users, courses, lessons, quizzes, and much more. This README provides a complete guide on how to set up, run, and contribute to both parts of the system.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://learning-manangement-system.vercel.app\" target=\"_blank\"\u003e\n    \u003cimg src=\"docs/logo.png\" alt=\"E-Learning Management System Logo\" style=\"border-radius: 10px\" width=\"35%\"/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n**Visit the live demo app here: [E-Learning Management System](https://learning-manangement-system.vercel.app)**\n\n\u003cp align=\"center\"\u003e\n  \u003c!-- Frontend --\u003e\n  \u003ca href=\"https://angular.io/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Frontend-Angular-DD0031?style=for-the-badge\u0026logo=angular\u0026logoColor=white\" alt=\"Angular\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://nodejs.org\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Node.js-18.19-339933?style=for-the-badge\u0026logo=node.js\u0026logoColor=white\" alt=\"Node.js\"/\u003e\n  \u003c/a\u003e\n\n  \u003c!-- Backend --\u003e\n  \u003ca href=\"https://www.djangoproject.com/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Backend-Django-092E20?style=for-the-badge\u0026logo=django\u0026logoColor=white\" alt=\"Django\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.python.org/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Python-3.12-3776AB?style=for-the-badge\u0026logo=python\u0026logoColor=white\" alt=\"Python\"/\u003e\n  \u003c/a\u003e\n\n  \u003c!-- Database \u0026 Cache --\u003e\n  \u003ca href=\"https://www.mongodb.com/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Database-MongoDB-47A248?style=for-the-badge\u0026logo=mongodb\u0026logoColor=white\" alt=\"MongoDB\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://redis.io/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Cache-Redis-DC382D?style=for-the-badge\u0026logo=redis\u0026logoColor=white\" alt=\"Redis\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.sqlite.org/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/SQLite-003B57?style=for-the-badge\u0026logo=sqlite\u0026logoColor=white\" alt=\"SQLite\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.swagger.io/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/API%20Docs-Swagger-85EA2D?style=for-the-badge\u0026logo=swagger\u0026logoColor=black\" alt=\"Swagger\"/\u003e\n  \u003c/a\u003e\n\n  \u003c!-- DevOps / CI/CD --\u003e\n  \u003ca href=\"https://github.com/features/actions\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/GitHub%20Actions-Automation-2088FF?style=for-the-badge\u0026logo=githubactions\u0026logoColor=white\" alt=\"GitHub Actions\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.jenkins.io/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Jenkins-CI/CD-D24939?style=for-the-badge\u0026logo=jenkins\u0026logoColor=white\" alt=\"Jenkins\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.docker.com/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Container-Docker-2496ED?style=for-the-badge\u0026logo=docker\u0026logoColor=white\" alt=\"Docker\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://kubernetes.io/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Orchestration-Kubernetes-326CE5?style=for-the-badge\u0026logo=kubernetes\u0026logoColor=white\" alt=\"Kubernetes\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://nginx.org/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Proxy_\u0026_Load_Balancer-NGINX-009639?style=for-the-badge\u0026logo=nginx\u0026logoColor=white\" alt=\"NGINX\"/\u003e\n  \u003c/a\u003e\n\n  \u003c!-- Hosting --\u003e\n  \u003ca href=\"https://vercel.com/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Hosting-Vercel-000000?style=for-the-badge\u0026logo=vercel\u0026logoColor=white\" alt=\"Vercel\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.mongodb.com/cloud/atlas\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Database%20Host-MongoDB%20Atlas-47A248?style=for-the-badge\u0026logo=mongodb\u0026logoColor=white\" alt=\"MongoDB Atlas\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://aws.amazon.com/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Cloud-AWS-232F3E?style=for-the-badge\u0026logo=amazonaws\u0026logoColor=white\" alt=\"AWS\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://terraform.io/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Infrastructure-Terraform-623CE4?style=for-the-badge\u0026logo=terraform\u0026logoColor=white\" alt=\"Terraform\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Container_Registry-GHCR-CF142B?style=for-the-badge\u0026logo=github\u0026logoColor=white\" alt=\"GitHub\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://render.com/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Backup-Render-46E3B7?style=for-the-badge\u0026logo=render\u0026logoColor=black\" alt=\"Render\"/\u003e\n  \u003c/a\u003e\n\n  \u003c!-- Testing --\u003e\n  \u003ca href=\"https://www.cypress.io/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Testing-Cypress-17202C?style=for-the-badge\u0026logo=cypress\u0026logoColor=white\" alt=\"Cypress\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://jestjs.io/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Jest-Testing-FF6F61?style=for-the-badge\u0026logo=jest\u0026logoColor=white\" alt=\"Jest\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://pytesting.io/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Testing-Pytest-FFCA28?style=for-the-badge\u0026logo=pytest\u0026logoColor=black\" alt=\"Pytest\"/\u003e\n  \u003c/a\u003e\n\n  \u003c!-- Version Control --\u003e\n  \u003ca href=\"https://docs.github.com/en/actions\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/GitHub-Actions-2088FF?style=for-the-badge\u0026logo=githubactions\u0026logoColor=white\" alt=\"GitHub Actions\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://git-scm.com/\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Version%20Control-Git-F05032?style=for-the-badge\u0026logo=git\u0026logoColor=white\" alt=\"Git\"/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Table of Contents\n\n- [Project Overview](#project-overview)\n  - [The MAD-Stack](#the-mad-stack)\n- [System Architecture](#system-architecture)\n  - [High-Level Architecture](#high-level-architecture)\n  - [Technology Stack](#technology-stack)\n  - [Database Schema](#database-schema)\n  - [Authentication Flow](#authentication-flow)\n  - [Component Architecture](#component-architecture)\n  - [Deployment Architecture](#deployment-architecture)\n  - [API Request Flow with Caching](#api-request-flow-with-caching)\n  - [CI/CD Pipeline](#cicd-pipeline)\n- [Features](#features)\n- [Live Deployment](#live-deployment)\n- [Detailed Project Information](#detailed-project-information)\n  - [Frontend User Interfaces](#frontend-user-interfaces)\n  - [Available API Endpoints](#available-api-endpoints)\n  - [Unit Tests for APIs](#unit-tests-for-apis)\n- [File Structure](#file-structure)\n- [Getting Started](#getting-started)\n  - [Prerequisites](#prerequisites)\n  - [Backend Setup (Django)](#backend-setup)\n  - [Frontend Setup (Angular)](#frontend-setup)\n- [API Documentation](#api-documentation)\n  - [Authentication](#authentication)\n  - [Testing the APIs](#testing-the-apis)\n  - [Seeding Sample Data](#seeding-sample-data)\n  - [Recommended GUI Tools](#recommended-gui-tools)\n  - [MongoDB Atlas](#mongodb-atlas)\n- [Deployment](#deployment)\n- [Containerization](#containerization)\n- [Kubernetes](#kubernetes)\n- [Testing](#testing)\n  - [Backend Tests](#backend-tests)\n  - [Frontend Tests](#frontend-tests)\n- [OpenAPI Specification](#openapi-specification)\n- [Jenkins CI/CD](#jenkins-cicd)\n- [Troubleshooting](#troubleshooting)\n  - [Common Issues](#common-issues)\n  - [Debugging Tips](#debugging-tips)\n- [Additional Information](#additional-information)\n- [Contributing](#contributing)\n- [License](#license)\n- [Contact](#contact)\n\n## Project Overview\n\nThe **E-Learning Management System** is a web-based platform designed to facilitate online education and training. It provides a comprehensive set of features for managing courses, lessons, users, quizzes, and more. The system is composed of:\n\n- **Frontend**: Built with **Angular** and **Bootstrap**, it offers a user-friendly interface for interacting with the platform.\n- **Backend**: Developed using **Django** and **Django REST Framework**, it provides robust **REST APIs** for all the operations.\n- **Database**: The system uses **MongoDB** to store data and **Redis** for efficient server-side caching, as well as **SQLite** for user authentication with Django Auth.\n- **CI/CD**: The project includes a `Dockerfile` and `docker-compose.yml` for containerization and deployment, as well as a `Jenkinsfile` for CI/CD pipelines and `Kubernetes` configuration files for orchestration.\n\nBecause we use **MongoDB**, **Angular**, and **Django**, we call this a **MAD-Stack** application! _(Just a fun name to remember the technologies used)_\n\n### The MAD-Stack\n\nThe **MAD-Stack** is a modern web development stack that combines the following technologies:\n\n- **MongoDB**: A NoSQL database used to store course, lessons, enrollments, users, and other data.\n- **Angular**: A frontend framework for building web applications.\n- **Django**: A high-level Python web framework for backend development.\n\nThe **MAD-Stack** is a powerful combination that allows developers to build scalable, responsive, and feature-rich web applications. It leverages the strengths of each technology to create a seamless user experience.\n\n\u003e Sounds mad, but it's actually a great stack for building modern web applications!\n\n## System Architecture\n\nFor a comprehensive and detailed architecture documentation, please refer to [ARCHITECTURE.md](ARCHITECTURE.md).\n\n### High-Level Architecture\n\nThe system follows a modern three-tier architecture with clear separation of concerns:\n\n```mermaid\ngraph TB\n    subgraph \"Client Layer\"\n        A[Web Browser]\n        B[Mobile Browser]\n    end\n\n    subgraph \"Frontend - Angular SPA\"\n        C[Angular Components]\n        D[Angular Services]\n        E[HTTP Interceptors]\n        F[State Management]\n    end\n\n    subgraph \"API Gateway\"\n        G[NGINX Reverse Proxy]\n    end\n\n    subgraph \"Backend - Django REST API\"\n        H[Django REST Framework]\n        I[Authentication Layer]\n        J[Business Logic]\n        K[Serializers \u0026 ViewSets]\n    end\n\n    subgraph \"Caching Layer\"\n        L[Redis Cache]\n    end\n\n    subgraph \"Data Persistence\"\n        M[(MongoDB - Course Data)]\n        N[(SQLite - Auth Data)]\n    end\n\n    A --\u003e C\n    B --\u003e C\n    C --\u003e D\n    D --\u003e E\n    E --\u003e G\n    G --\u003e H\n    H --\u003e I\n    I --\u003e J\n    J --\u003e K\n    K --\u003e L\n    K --\u003e M\n    I --\u003e N\n```\n\n### Technology Stack\n\n```mermaid\ngraph LR\n    subgraph \"Frontend Stack\"\n        A[Angular 18]\n        B[TypeScript]\n        C[Bootstrap 5]\n        D[RxJS]\n    end\n\n    subgraph \"Backend Stack\"\n        E[Django 4.2]\n        F[Django REST Framework]\n        G[Python 3.12]\n        H[MongoEngine ODM]\n    end\n\n    subgraph \"Database Stack\"\n        I[(MongoDB 5.0)]\n        J[(SQLite 3)]\n        K[(Redis 6)]\n    end\n\n    subgraph \"DevOps Stack\"\n        L[Docker]\n        M[Kubernetes]\n        N[Jenkins]\n        O[GitHub Actions]\n    end\n\n    A --\u003e E\n    E --\u003e I\n    E --\u003e J\n    E --\u003e K\n    L --\u003e M\n    N --\u003e O\n\n    style A fill:#dd0031\n    style E fill:#092e20\n    style I fill:#47a248\n    style K fill:#dc382d\n    style L fill:#2496ed\n```\n\n### Database Schema\n\nThe system uses MongoDB for storing course-related data with the following entity relationships:\n\n```mermaid\nerDiagram\n    USER ||--o{ COURSE : instructs\n    USER ||--o{ ENROLLMENT : enrolls\n    USER ||--o{ PROGRESS : tracks\n    USER ||--o{ NOTIFICATION : receives\n\n    CATEGORY ||--o{ COURSE : categorizes\n\n    COURSE ||--o{ LESSON : contains\n    COURSE ||--o{ ENROLLMENT : has\n\n    LESSON ||--o{ QUIZ : includes\n    LESSON ||--o{ PROGRESS : tracks\n\n    QUIZ ||--o{ QUESTION : contains\n    QUESTION ||--o{ CHOICE : has\n\n    USER {\n        ObjectId id PK\n        string username UK\n        string email UK\n        boolean is_instructor\n        boolean is_student\n        string bio\n        string profile_picture\n    }\n\n    COURSE {\n        ObjectId id PK\n        string title\n        string description\n        ObjectId instructor_id FK\n        ObjectId category_id FK\n        decimal price\n        boolean published\n        datetime created_at\n    }\n\n    LESSON {\n        ObjectId id PK\n        string title\n        ObjectId course_id FK\n        string content\n        string video_url\n        datetime created_at\n    }\n\n    ENROLLMENT {\n        ObjectId id PK\n        ObjectId student_id FK\n        ObjectId course_id FK\n        datetime enrolled_at\n    }\n\n    PROGRESS {\n        ObjectId id PK\n        ObjectId student_id FK\n        ObjectId lesson_id FK\n        boolean completed\n        datetime completed_at\n    }\n```\n\n### Authentication Flow\n\nThe system uses JWT-based authentication with token storage:\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant Angular\n    participant Django\n    participant SQLite\n    participant Redis\n\n    User-\u003e\u003eAngular: Enter Credentials\n    Angular-\u003e\u003eDjango: POST /api/auth/login/\n    Django-\u003e\u003eSQLite: Verify Credentials\n\n    alt Valid Credentials\n        SQLite--\u003e\u003eDjango: User Valid\n        Django-\u003e\u003eDjango: Generate JWT Token\n        Django-\u003e\u003eRedis: Cache Token\n        Django--\u003e\u003eAngular: {token, user}\n        Angular-\u003e\u003eAngular: Store in localStorage\n        Angular--\u003e\u003eUser: Redirect to Dashboard\n    else Invalid Credentials\n        SQLite--\u003e\u003eDjango: Invalid\n        Django--\u003e\u003eAngular: 401 Unauthorized\n        Angular--\u003e\u003eUser: Show Error\n    end\n\n    Note over User,Redis: Subsequent Requests\n\n    User-\u003e\u003eAngular: Access Protected Route\n    Angular-\u003e\u003eDjango: Request + Bearer Token\n    Django-\u003e\u003eSQLite: Validate Token\n\n    alt Valid Token\n        Django-\u003e\u003eRedis: Check Cache\n        Redis--\u003e\u003eDjango: Data\n        Django--\u003e\u003eAngular: Protected Resource\n        Angular--\u003e\u003eUser: Display Content\n    else Invalid Token\n        Django--\u003e\u003eAngular: 401 Unauthorized\n        Angular--\u003e\u003eUser: Redirect to Login\n    end\n```\n\n### Component Architecture\n\n```mermaid\ngraph TB\n    subgraph \"Frontend Components\"\n        A[Login Component]\n        B[Course List Component]\n        C[Lesson List Component]\n        D[Enrollment Component]\n        E[Progress Component]\n    end\n\n    subgraph \"Angular Services\"\n        F[Auth Service]\n        G[Course Service]\n        H[Lesson Service]\n        I[Enrollment Service]\n        J[Progress Service]\n    end\n\n    subgraph \"Backend ViewSets\"\n        K[CourseViewSet]\n        L[LessonViewSet]\n        M[EnrollmentViewSet]\n        N[ProgressViewSet]\n    end\n\n    subgraph \"Data Models\"\n        O[(Course Model)]\n        P[(Lesson Model)]\n        Q[(Enrollment Model)]\n        R[(Progress Model)]\n    end\n\n    A --\u003e F\n    B --\u003e G\n    C --\u003e H\n    D --\u003e I\n    E --\u003e J\n\n    F --\u003e K\n    G --\u003e K\n    H --\u003e L\n    I --\u003e M\n    J --\u003e N\n\n    K --\u003e O\n    L --\u003e P\n    M --\u003e Q\n    N --\u003e R\n```\n\n### Deployment Architecture\n\n```mermaid\ngraph TB\n    subgraph \"Cloud Infrastructure\"\n        subgraph \"Frontend Hosting - Vercel\"\n            A[Vercel CDN]\n            B[Static Assets]\n        end\n\n        subgraph \"Backend Hosting - Render\"\n            C[Django Application]\n            D[Auto-scaling]\n        end\n\n        subgraph \"Database Services\"\n            E[(MongoDB Atlas)]\n            F[(Redis Cloud)]\n        end\n    end\n\n    subgraph \"CI/CD Pipeline\"\n        G[GitHub]\n        H[GitHub Actions]\n        I[Jenkins]\n    end\n\n    subgraph \"Containerization\"\n        J[Docker Images]\n        K[Kubernetes Cluster]\n    end\n\n    A --\u003e B\n    C --\u003e D\n    E --\u003e F\n\n    G --\u003e H\n    H --\u003e I\n    I --\u003e J\n    J --\u003e K\n\n    B --\u003e C\n    D --\u003e E\n    D --\u003e F\n\n    style A fill:#000000\n    style E fill:#47a248\n    style F fill:#dc382d\n    style G fill:#181717\n```\n\n### API Request Flow with Caching\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant NGINX\n    participant Django\n    participant Redis\n    participant MongoDB\n\n    Client-\u003e\u003eNGINX: HTTP Request\n    NGINX-\u003e\u003eDjango: Forward Request\n\n    alt Cache Hit\n        Django-\u003e\u003eRedis: Check Cache\n        Redis--\u003e\u003eDjango: Cached Data\n        Django--\u003e\u003eClient: Response (Fast)\n    else Cache Miss\n        Django-\u003e\u003eRedis: Check Cache\n        Redis--\u003e\u003eDjango: Cache Miss\n        Django-\u003e\u003eMongoDB: Query Database\n        MongoDB--\u003e\u003eDjango: Fresh Data\n        Django-\u003e\u003eRedis: Store Cache (TTL)\n        Django--\u003e\u003eClient: Response\n    end\n\n    Note over Client,MongoDB: Write Operations Invalidate Cache\n\n    Client-\u003e\u003eDjango: POST/PUT/DELETE Request\n    Django-\u003e\u003eMongoDB: Update Database\n    MongoDB--\u003e\u003eDjango: Success\n    Django-\u003e\u003eRedis: Invalidate Related Caches\n    Django--\u003e\u003eClient: Response\n```\n\n### CI/CD Pipeline\n\n```mermaid\ngraph LR\n    subgraph \"Source Control\"\n        A[GitHub Repository]\n        B[Push/PR]\n    end\n\n    subgraph \"CI Pipeline\"\n        C[Run Tests]\n        D[Lint Code]\n        E[Build Docker Image]\n    end\n\n    subgraph \"CD Pipeline\"\n        F[Deploy to Staging]\n        G{Tests Pass?}\n        H[Deploy to Production]\n    end\n\n    subgraph \"Monitoring\"\n        I[Health Checks]\n        J[Performance Monitoring]\n    end\n\n    A --\u003e B\n    B --\u003e C\n    C --\u003e D\n    D --\u003e E\n    E --\u003e F\n    F --\u003e G\n    G --\u003e|Yes| H\n    G --\u003e|No| A\n    H --\u003e I\n    I --\u003e J\n```\n\n## Features\n\nOur E-Learning Management System comes packed with a variety of features to enhance the learning experience:\n\n- **User Authentication**: Token-based authentication for secure login, built with Django Auth.\n- **Server-Side Caching**: Redis caching for improved performance and reduced server load.\n- **Course Management**: Create, update, delete, and display courses.\n- **Lesson Management**: Manage lessons associated with courses.\n- **Quiz Management**: Handle quizzes, questions, and choices.\n- **User Management**: Administrate users, enrollments, and user roles.\n- **Progress Tracking**: Monitor and visualize user progress.\n- **Notification System**: Send and manage notifications.\n- **Responsive Design**: Optimized for all devices.\n- **Search and Filtering**: Search and filter courses and lessons.\n- **Data Visualization**: Dynamic charts using Chart.js.\n- **Comprehensive APIs**: Powerful RESTful APIs for all operations.\n- **API Documentation**: Comprehensive REST API documentation with Swagger and Redoc.\n- **Unit \u0026 Integration Tests**: Automated tests for backend APIs and frontend components.\n- **PWA Support**: Progressive Web App features for offline access and installation.\n- **CI/CD Pipeline**: Automated deployment using Jenkins, Docker, and GitHub Actions.\n- _and many more features!_\n\n## Live Deployment\n\nThe project is currently deployed live! You can access the live deployment using the following link: **[E-Learning Management System](https://learning-manangement-system.vercel.app).**\n\nThe backend is deployed on Render: **[Backend API](https://learning-management-system-fullstack.onrender.com/).**\n\nFeel free to explore the platform, create an account, and test out the features!\n\n\u003e [!IMPORTANT] \n\u003e **Note:** Our backend server may spin down due to inactivity, so you may experience delays in loading data initially as the backend is hosted on the free tier of Render. If you encounter any issues, please let me know.\n\n## Detailed Project Information:\n\n### Frontend User Interfaces\n\n**Home Page**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/home-ui.png\" alt=\"Home Page\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Course List**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/course-ui.png\" alt=\"Course List\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Lesson List**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/lesson-ui.png\" alt=\"Lesson List\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**User List**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/user-ui.png\" alt=\"User List\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Enrollment List**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/enrollments-ui.png\" alt=\"Enrollment List\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Progress List**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/progress-ui.png\" alt=\"Progress List\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Registration Page**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/register-ui.png\" alt=\"Registration Page\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Login Page**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/login-ui.png\" alt=\"Login Page\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Unauthorized Access (when not logged in)**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/unauthorized-ui.png\" alt=\"Unauthorized Access Page\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Not Found Page**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/notfound.png\" alt=\"Not Found Page\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Footer**:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/footer-ui.png\" alt=\"Footer\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Responsive Design**: The frontend is fully responsive and optimized for all devices. Here is an example of the mobile view:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/mobile-ui.png\" alt=\"Mobile View\" style=\"border-radius: 10px\" width=\"60%\"/\u003e\n\u003c/p\u003e\n\n**And many more pages \u0026 features. Feel free to explore the frontend and backend to see all the functionalities!**\n\n### Available API Endpoints\n\n| Endpoint                   | Method | Description                                   |\n| -------------------------- | ------ | --------------------------------------------- |\n| `/api/users/`              | GET    | Retrieve a list of all users.                 |\n| `/api/users/{id}/`         | GET    | Retrieve a specific user instance.            |\n| `/api/users/`              | POST   | Create a new user instance.                   |\n| `/api/users/{id}/`         | PUT    | Update a specific user instance.              |\n| `/api/users/{id}/`         | DELETE | Delete a specific user instance.              |\n| `/api/courses/`            | GET    | Retrieve a list of all courses.               |\n| `/api/courses/{id}/`       | GET    | Retrieve a specific course instance.          |\n| `/api/courses/`            | POST   | Create a new course instance.                 |\n| `/api/courses/{id}/`       | PUT    | Update a specific course instance.            |\n| `/api/courses/{id}/`       | DELETE | Delete a specific course instance.            |\n| `/api/categories/`         | GET    | Retrieve a list of all categories.            |\n| `/api/categories/{id}/`    | GET    | Retrieve a specific category instance.        |\n| `/api/categories/`         | POST   | Create a new category instance.               |\n| `/api/categories/{id}/`    | PUT    | Update a specific category instance.          |\n| `/api/categories/{id}/`    | DELETE | Delete a specific category instance.          |\n| `/api/lessons/`            | GET    | Retrieve a list of all lessons.               |\n| `/api/lessons/{id}/`       | GET    | Retrieve a specific lesson instance.          |\n| `/api/lessons/`            | POST   | Create a new lesson instance.                 |\n| `/api/lessons/{id}/`       | PUT    | Update a specific lesson instance.            |\n| `/api/lessons/{id}/`       | DELETE | Delete a specific lesson instance.            |\n| `/api/quizzes/`            | GET    | Retrieve a list of all quizzes.               |\n| `/api/quizzes/{id}/`       | GET    | Retrieve a specific quiz instance.            |\n| `/api/quizzes/`            | POST   | Create a new quiz instance.                   |\n| `/api/quizzes/{id}/`       | PUT    | Update a specific quiz instance.              |\n| `/api/quizzes/{id}/`       | DELETE | Delete a specific quiz instance.              |\n| `/api/questions/`          | GET    | Retrieve a list of all questions.             |\n| `/api/questions/{id}/`     | GET    | Retrieve a specific question instance.        |\n| `/api/questions/`          | POST   | Create a new question instance.               |\n| `/api/questions/{id}/`     | PUT    | Update a specific question instance.          |\n| `/api/questions/{id}/`     | DELETE | Delete a specific question instance.          |\n| `/api/choices/`            | GET    | Retrieve a list of all choices.               |\n| `/api/choices/{id}/`       | GET    | Retrieve a specific choice instance.          |\n| `/api/choices/`            | POST   | Create a new choice instance.                 |\n| `/api/choices/{id}/`       | PUT    | Update a specific choice instance.            |\n| `/api/choices/{id}/`       | DELETE | Delete a specific choice instance.            |\n| `/api/enrollments/`        | GET    | Retrieve a list of all enrollments.           |\n| `/api/enrollments/{id}/`   | GET    | Retrieve a specific enrollment instance.      |\n| `/api/enrollments/`        | POST   | Create a new enrollment instance.             |\n| `/api/enrollments/{id}/`   | PUT    | Update a specific enrollment instance.        |\n| `/api/enrollments/{id}/`   | DELETE | Delete a specific enrollment instance.        |\n| `/api/progress/`           | GET    | Retrieve a list of all progress records.      |\n| `/api/progress/{id}/`      | GET    | Retrieve a specific progress record instance. |\n| `/api/progress/`           | POST   | Create a new progress record instance.        |\n| `/api/progress/{id}/`      | PUT    | Update a specific progress record instance.   |\n| `/api/progress/{id}/`      | DELETE | Delete a specific progress record instance.   |\n| `/api/notifications/`      | GET    | Retrieve a list of all notifications.         |\n| `/api/notifications/{id}/` | GET    | Retrieve a specific notification instance.    |\n| `/api/notifications/`      | POST   | Create a new notification instance.           |\n| `/api/notifications/{id}/` | PUT    | Update a specific notification instance.      |\n| `/api/notifications/{id}/` | DELETE | Delete a specific notification instance.      |\n\n### Unit Tests for APIs\n\nThe backend includes unit tests for the APIs. You can run the tests using the following command:\n\n```bash\npython manage.py test\n```\n\nFeel free to view and modify the tests in the `core/tests.py` file. Also, be sure to adjust the URLs in the test cases to match your actual URL configuration if different from the default.\n\n## File Structure\n\nThe project structure is as follows:\n\n```plaintext\nLearning-Management-System/\n├── LMS-Backend\n│   ├── .gitignore\n│   ├── Dockerfile\n│   ├── manage.py\n│   ├── requirements.txt\n│   ├── LICENSE\n│   ├── db.sqlite3\n│   ├── README.md\n│   ├── LMSBackend/\n│   │   ├── settings.py\n│   │   ├── urls.py\n│   │   ├── asgi.py\n│   │   └── wsgi.py\n│   └── core/\n│       ├── management/\n│       │   └── commands/\n│       │       └── seed_sample_data.py\n│       ├── migrations/\n│       │   └── __init__.py\n│       ├── models.py\n│       ├── views.py\n│       ├── tests.py\n│       ├── admin.py\n│       ├── apps.py\n│       ├── serializers.py\n│       └── urls.py\n│\n├── LMS-Frontend\n│   ├── angular.json\n│   ├── package.json\n│   ├── Dockerfile\n│   ├── README.md\n│   ├── LICENSE\n│   ├── app/\n│   │   ├── src/\n│   │   │   ├── app/\n│   │   │   │   ├── auth/\n│   │   │   │   │   ├── login/\n│   │   │   │   │   │   ├── login.component.ts\n│   │   │   │   │   │   ├── login.component.html\n│   │   │   │   │   │   └── login.component.css\n│   │   │   │   │   ├── register/\n│   │   │   │   │   │   ├── register.component.ts\n│   │   │   │   │   │   ├── register.component.html\n│   │   │   │   │   │   └── register.component.css\n│   │   │   │   ├── core/\n│   │   │   │   │   ├── footer/\n│   │   │   │   │   │   ├── footer.component.ts\n│   │   │   │   │   │   ├── footer.component.html\n│   │   │   │   │   │   └── footer.component.css\n│   │   │   │   │   ├── header/\n│   │   │   │   │   │   ├── header.component.ts\n│   │   │   │   │   │   ├── header.component.html\n│   │   │   │   │   │   └── header.component.css\n│   │   │   │   ├── pages/\n│   │   │   │   │   ├── home/\n│   │   │   │   │   │   ├── notfound.component.ts\n│   │   │   │   │   │   ├── notfound.component.html\n│   │   │   │   │   │   └── home.component.css\n│   │   │   │   │   ├── notfound/\n│   │   │   │   │   │   ├── notfound.component.ts\n│   │   │   │   │   │   ├── notfound.component.html\n│   │   │   │   │   │   └── notfound.component.css\n│   │   │   │   ├── components/\n│   │   │   │   │   ├── course-list/\n│   │   │   │   │   │   ├── course-list.component.ts\n│   │   │   │   │   │   ├── course-list.component.html\n│   │   │   │   │   │   └── course-list.component.css\n│   │   │   │   │   ├── lesson-list/\n│   │   │   │   │   │   ├── lesson-list.component.ts\n│   │   │   │   │   │   ├── lesson-list.component.html\n│   │   │   │   │   │   └── lesson-list.component.css\n│   │   │   │   │   ├── user-list/\n│   │   │   │   │   │   ├── user-list.component.ts\n│   │   │   │   │   │   ├── user-list.component.html\n│   │   │   │   │   │   └── user-list.component.css\n│   │   │   │   │   ├── enrollment-list/\n│   │   │   │   │   │   ├── enrollment-list.component.ts\n│   │   │   │   │   │   ├── enrollment-list.component.html\n│   │   │   │   │   │   └── enrollment-list.component.css\n│   │   │   │   │   ├── progress-list/\n│   │   │   │   │   │   ├── progress-list.component.ts\n│   │   │   │   │   │   ├── progress-list.component.html\n│   │   │   │   │   │   └── progress-list.component.css\n│   │   │   │   ├── services/\n│   │   │   │   │   ├── auth.interceptor.ts\n│   │   │   │   │   ├── auth.service.ts\n│   │   │   │   │   ├── user.service.ts\n│   │   │   │   │   ├── course.service.ts\n│   │   │   │   │   ├── lesson.service.ts\n│   │   │   │   │   ├── enrollment.service.ts\n│   │   │   │   │   └── progress.service.ts\n│   │   │   │   ├── app.routes.ts\n│   │   │   │   ├── app.component.ts\n│   │   │   │   ├── app.config.ts\n│   │   │   │   ├── app.config.service.ts\n│   │   │   │   ├── app.component.html\n│   │   │   │   └── app.component.css\n│   │   │   ├── assets/\n│   │   │   │   ├── \u003cimages...\u003e\n│   │   │   │   └── .gitkeep\n│   │   │   ├── main.ts\n│   │   │   ├── styles.css\n│   │   │   ├── manifest.json\n│   │   │   └── index.html\n│   │   ├── .editorconfig\n│   │   ├── .gitignore\n│   │   ├── angular.json\n│   │   ├── package.json\n│   │   ├── package-lock.json\n│   │   ├── tsconfig.json\n│   │   ├── tsconfig.app.json\n│   │   └── tsconfig.spec.json\n│   ├── LICENSE\n│   └── README.md\n│\n├── nginx\n│   ├── nginx.conf\n│   └── Dockerfile\n│\n├── kubernetes\n│   ├── configmap.yaml\n│   ├── backend-deployment.yaml\n│   ├── backend-service.yaml\n│   ├── frontend-deployment.yaml\n│   └── frontend-service.yaml\n│\n├── .gitignore\n├── .env.example\n├── docker-compose.yml\n├── Jenkinsfile\n├── openapi.yaml\n├── LICENSE\n└── README.md\n```\n\n## Getting Started\n\n### Prerequisites\n\nEnsure the following prerequisites are installed:\n\n- **Node.js** (v18.19 or later)\n- **Angular CLI** (v12 or later)\n- **Python** (v3.7 or later)\n- **Django** and **Django REST Framework**\n- **MongoDB** and **Redis** running locally or remotely\n\n### Backend Setup\n\n**Note:** Before running the backend server, ensure MongoDB and Redis are running and accessible on your system. You can install MongoDB and Redis locally or use cloud services like MongoDB Atlas and Redis Cloud.\n\n1. **Clone the repository:**\n\n   ```bash\n   git clone https://github.com/hoangsonww/Learning-Management-System-Fullstack.git\n   cd Fullstack-Learning-Management-System/LMS-Backend\n   ```\n\n2. **Create and activate a virtual environment:**\n\n   ```bash\n   python -m venv .venv\n   source .venv/bin/activate  # On Windows, use `.venv\\Scripts\\activate`\n   ```\n\n3. **Install dependencies:**\n\n   ```bash\n   pip install -r requirements.txt\n   ```\n\n4. **Configure MongoDB and Redis:**\n\n   Ensure MongoDB and Redis are running and configured in `settings.py`. If not installed, follow the instructions to install them. It is very important to run MongoDB and Redis before running the backend server.\n\n   Additionally, edit the `.env` file according to the `.env.example` file with the correct MongoDB and Redis connection strings.\n\n5. **Apply migrations:**\n\n   ```bash\n   python manage.py makemigrations\n   python manage.py migrate\n   ```\n\n6. **Create a superuser:**\n\n   ```bash\n   python manage.py createsuperuser\n   ```\n\n   Follow the prompts to create a superuser account. Remember to note down the username and password because you will need it to authenticate when using the APIs later, as well as to access the Django admin panel.\n\n7. **Put the `SECRET_KEY` and set `Debug` to `True` in the `settings.py` file:**\n\n   ```plaintext\n   SECRET_KEY = 'your_secret_key_here'\n   DEBUG = True\n   ```\n\n   Replace `your_secret_key_here` with a random string of characters. This key is used for cryptographic signing and should be kept secret. Or you can also contact me to get the secret key.\n\n   Alternatively, create an `.env` file in the project root directory following the format in the `.env.example` file:\n\n   ```plaintext\n   DJANGO_SECRET_KEY=your_secret_key_here\n   DJANGO_DEBUG=True\n   (...)\n   ```\n\n8. **Seed the database with sample data:**\n\n   ```bash\n   python manage.py seed_sample_data\n   ```\n\n9. **Run the backend server:**\n\n   ```bash\n   python manage.py runserver\n   ```\n\n   The backend server should now be running at `http://127.0.0.1:8000/`. If the server is run successfully, you should see the Django REST Framework browsable API interface at `http://127.0.0.1:8000`, as well as the following console output:\n\n   ```plaintext\n   python manage.py runserver\n   Successfully seeded realistic sample data\n   Successfully seeded realistic sample data\n   Watching for file changes with StatReloader\n   Performing system checks...\n\n   System check identified no issues (0 silenced).\n   September 08, 2024 - 20:35:21\n   Django version 4.2.16, using settings 'LMSBackend.settings'\n   Starting development server at http://127.0.0.1:8000/\n   Quit the server with CONTROL-C.\n   ```\n\n### Frontend Setup\n\n1. **Navigate to the frontend directory:**\n\n   ```bash\n   cd Learning-Management-System/LMS-Frontend/app\n   ```\n\n2. **Install dependencies:**\n\n   ```bash\n   npm install\n   ```\n\n3. **Start the development server:**\n\n   ```bash\n   ng serve\n   ```\n\n4. **Open the application in your browser:**\n\n   ```\n   http://localhost:4200\n   ```\n\n5. **Test out the PWA functionality:**\n\n   - Open the application in your browser.\n   - Click on the \"Install\" button in the address bar to install the PWA.\n   - Check the installed PWA in your system applications.\n   - Open the installed PWA and test its functionality.\n\n## API Documentation\n\n### Authentication\n\nMost API endpoints require authentication. Use the `/api/auth/login/` endpoint to log in and obtain an authentication token.\n\n1. **Log in to get a token:**\n\n   ```bash\n   curl -X POST http://127.0.0.1:8000/api/auth/login/ -H \"Content-Type: application/json\" -d '{\n     \"username\": \"your_username\",\n     \"password\": \"your_password\"\n   }'\n   ```\n\n   Use the obtained token in the `Authorization` header for subsequent requests:\n\n   ```bash\n   -H \"Authorization: Token \u003cyour_token_here\u003e\"\n   ```\n\n### Testing the APIs\n\nYou can test the API using `curl`, Postman, or Swagger UI.\n\n#### Using `curl`\n\nTo test the API using `curl`, use the commands below. Replace `\u003cyour_token_here\u003e` with the token obtained from the login endpoint.\n\n- **List All Users**\n\n  ```bash\n  curl -X GET http://127.0.0.1:8000/api/users/ -H \"Content-Type: application/json\" -H \"Authorization: Token \u003cyour_token_here\u003e\"\n  ```\n\n  - You should get something like this:\n\n    ```json\n    [\n      {\n        \"id\": \"66dde39af395abfee65d1f86\",\n        \"username\": \"gibsonstacey\",\n        \"email\": \"xcaldwell@example.org\",\n        \"is_instructor\": false,\n        \"is_student\": false,\n        \"bio\": \"Consider red specific within chance fund successful out.\",\n        \"profile_picture\": \"https://placekitten.com/970/531\"\n      }\n    ]\n    ```\n\n- **Create a New Course**\n\n  ```bash\n  curl -X POST http://127.0.0.1:8000/api/courses/ -H \"Content-Type: application/json\" -H \"Authorization: Token \u003cyour_token_here\u003e\" -d '{\n    \"title\": \"New Course\",\n    \"description\": \"This is a new course description.\",\n    \"instructor\": \"{user_id}\",\n    \"category\": \"{category_id}\",\n    \"price\": 150.00,\n    \"published\": true\n  }'\n  ```\n\nRepeat similar `curl` commands for other endpoints.\n\n#### Using Postman\n\n1. Open Postman.\n2. Create a new request for each endpoint.\n3. Set the method (GET, POST, PUT, DELETE) and URL (e.g., `http://127.0.0.1:8000/api/users/`).\n4. Under the \"Authorization\" tab, choose \"Bearer Token\" and paste your token.\n5. Send the request and check the response.\n\n#### Using Swagger UI\n\n1. Navigate to the Swagger UI at [http://127.0.0.1:8000/swagger/](http://127.0.0.1:8000/swagger/).\n2. Click on an endpoint to expand it.\n3. Click the \"Try it out\" button.\n4. Enter the required parameters and authentication token (`Token \u003cyour_token_here\u003e`) in the \"Authorization\" header. **Note that the token should be prefixed with `Token` and a space.**\n5. Click \"Execute\" to see the API response.\n6. Alternatively, you can simply click the \"Authorize\" button in the top right corner of the page and enter your token there. This will automatically include the token in all requests. Then repeat steps 3 and 5 to test the endpoints.\n\nHere is how the Swagger UI looks like:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/swagger-ui.png\" alt=\"Swagger UI\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n#### Using Redoc\n\n1. Navigate to the Redoc UI at [http://127.0.0.1:8000/redoc/](http://127.0.1:8000/redoc/).\n2. Click on an endpoint to expand it.\n3. View the API documentation and test the endpoints.\n\nHere is how the Redoc UI looks like:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/redoc-ui.png\" alt=\"Redoc UI\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n#### Using Django REST Framework Browsable API\n\n1. Choose any endpoint from the list above.\n2. Navigate to the endpoint URL in your browser.\n3. Log in using the superuser credentials.\n4. You will see a browsable interface where you can view the details of the endpoint.\n\nFor example, to view the list of all lessons, go to [http://127.0.0.1:8000/api/lessons/](http://127.0.0.1:8000/api/lessons/). The interface should look like this:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"docs/browsable-api.png\" alt=\"Browsable API\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n**Well, remember to log in first before accessing the API... Don't forget to log in!**\n\n### Seeding Sample Data\n\nIf you want to seed the database with realistic sample data, you can also run the `seed_sample_data` management command:\n\n```bash\npython manage.py seed_sample_data\n```\n\nThis command will populate the database with randomly generated users, courses, categories, lessons, quizzes, questions, choices, enrollments, progress records, and notifications.\n\n**Note:** By default, the `seed_sample_data` command will be executed when you run the `python manage.py migrate` command. If you don't want to seed the database at that time, you can disable it by setting `SEED_SAMPLE_DATA_ON_MIGRATE = False` in the `settings.py` file. Also, your data might be different from mine because the data is randomly generated.\n\n#### Recommended GUI Tools\n\nTo interact with the APIs and databases more easily, you can use the following GUI tools:\n\n- **MongoDB Compass**: A GUI tool for MongoDB that allows you to explore and interact with your MongoDB databases. You can download it from [here](https://www.mongodb.com/try/download/compass).\n- **RedisInsight**: A GUI tool for Redis that allows you to explore and interact with your Redis databases. You can download it from [here](https://redislabs.com/redis-enterprise/redis-insight/).\n- **Postman**: A powerful GUI tool for testing APIs. You can download it from [here](https://www.postman.com/downloads/).\n- **Insomnia**: Another great GUI tool for testing APIs. You can download it from [here](https://insomnia.rest/download).\n- **Swagger UI**: An interactive API documentation tool. You can access the Swagger UI at [http://127.0.0.1:8000/swagger/](http://127.0.0.1:8000/swagger/). Ensure the server is running before accessing the UI.\n- **Redoc**: Another interactive API documentation tool. You can access the Redoc UI at [http://127.0.0.1:8000/redoc/](http://127.0.0.1:8000/redoc/). Ensure the server is running before accessing the UI.\n\nFor example, you can use MongoDB Compass to view the data in your MongoDB database, RedisInsight to view the data in your Redis database, and Postman to test the API endpoints, like below:\n\n\u003cp align=\"center\" style=\"cursor: pointer\"\u003e\n  \u003cimg src=\"/docs/gui-tools.png\" alt=\"GUI Tools\" style=\"border-radius: 10px\" width=\"100%\"/\u003e\n\u003c/p\u003e\n\n#### MongoDB Atlas\n\nThis project is set up to use MongoDB Atlas as the cloud database. You can create a free account on MongoDB Atlas and set up a free cluster to use with the project. Follow these steps to set up MongoDB Atlas:\n\n1. **Create a MongoDB Atlas account:**\n\n   - Go to the [MongoDB Atlas website](https://www.mongodb.com/cloud/atlas).\n   - Click on \"Get started free\".\n   - Create an account and log in.\n\n2. **Create a free cluster:**\n\n   - Click on \"Build a Cluster\".\n   - Choose the free tier option.\n   - Select the cloud provider and region.\n   - Click \"Create Cluster\".\n\n3. **Connect to your cluster:**\n\n   - Click on \"Connect\" to connect to your cluster.\n   - Whitelist your IP address.\n   - Create a MongoDB user and password.\n\n4. **Get your connection string:**\n\n   - Click on \"Connect\" and choose \"Connect your application\".\n   - Copy the connection string.\n\n5. **Set up the connection string in the Django settings:**\n\n   - Replace the `.env` configuration file with the connection string from MongoDB Atlas.\n\nAlternatively, you can use the local MongoDB server for development and testing purposes.\n\n## Deployment\n\nThe Learning Management System supports multiple deployment options, from local development to production-grade cloud infrastructure.\n\n### Deployment Options Overview\n\n| Option | Environment | Complexity | Cost | Scalability | Best For |\n|--------|-------------|------------|------|-------------|----------|\n| **Docker Compose** | Local/Dev | Low | Free | Limited | Development, Testing |\n| **Kubernetes** | Any | Medium | Variable | High | Self-hosted Production |\n| **AWS (Terraform)** | Cloud | Medium-High | ~$1400/mo | Very High | Enterprise Production |\n| **Vercel + Render** | Cloud | Low | ~$25/mo | Medium | Small-Medium Projects |\n\n### Quick Deployment Links\n\n- **Current Live Deployment**: [https://learning-manangement-system.vercel.app](https://learning-manangement-system.vercel.app)\n- **Backend API**: [https://learning-management-system-fullstack.onrender.com](https://learning-management-system-fullstack.onrender.com)\n- **Deployment Guide**: [DEPLOYMENT.md](DEPLOYMENT.md) - Comprehensive deployment documentation\n\n### Deployment Architecture\n\n```mermaid\ngraph TB\n    subgraph \"Development\"\n        LOCAL[Local Development\u003cbr/\u003eDocker Compose]\n    end\n\n    subgraph \"Staging/Testing\"\n        K8S[Kubernetes\u003cbr/\u003eSelf-Hosted]\n    end\n\n    subgraph \"Production Options\"\n        AWS[AWS Full Stack\u003cbr/\u003eECS + RDS + DocumentDB]\n        VERCEL[Vercel + Render\u003cbr/\u003eManaged Services]\n    end\n\n    LOCAL --\u003e K8S\n    K8S --\u003e AWS\n    K8S --\u003e VERCEL\n```\n\n### Infrastructure as Code\n\nThe project includes production-ready Infrastructure as Code:\n\n- **`/aws`** - AWS deployment scripts and CloudFormation templates\n- **`/terraform`** - Terraform modules for complete AWS infrastructure\n- **`/kubernetes`** - Kubernetes manifests for container orchestration\n\nSee [DEPLOYMENT.md](DEPLOYMENT.md) for detailed deployment instructions for each option.\n\n## Containerization\n\nThe project can be containerized using Docker. The `Dockerfile` and `docker-compose.yml` files are provided in the repository. To containerize the project, follow these steps:\n\n1. **Change directory into the project root:**\n\n   ```bash\n   cd Learning-Management-System\n   ```\n\n2. **Build the Docker image:**\n\n   ```bash\n   docker compose up --build\n   ```\n\nThe above command will build the Docker image and start the containers for the backend, frontend, MongoDB, and Redis. You can access the application at `http://localhost:4200` and the Django REST Framework API at `http://localhost:8000`.\n\n## Kubernetes\n\nThe project includes Kubernetes configuration files for deploying the backend and frontend applications. The `Kubernetes` directory contains the following files:\n\n- **configmap.yaml**: Contains the configuration settings for the backend application.\n- **backend-deployment.yaml**: Defines the deployment for the backend application.\n- **backend-service.yaml**: Defines the service for the backend application.\n- **frontend-deployment.yaml**: Defines the deployment for the frontend application.\n- **frontend-service.yaml**: Defines the service for the frontend application.\n\nTo deploy the applications to a Kubernetes cluster, follow these steps:\n\n1. **Change directory into the `Kubernetes` directory:**\n\n   ```bash\n   cd Kubernetes\n   ```\n\n2. **Create the configmap:**\n\n   ```bash\n    kubectl apply -f configmap.yaml\n   ```\n\n3. **Create the backend deployment:**\n\n   ```bash\n   kubectl apply -f backend-deployment.yaml\n   ```\n\n4. **Create the backend service:**\n\n   ```bash\n    kubectl apply -f backend-service.yaml\n   ```\n\n5. **Create the frontend deployment:**\n\n   ```bash\n    kubectl apply -f frontend-deployment.yaml\n   ```\n\n6. **Create the frontend service:**\n\n   ```bash\n    kubectl apply -f frontend-service.yaml\n   ```\n\nThe above commands will create the deployments and services for the backend and frontend applications. You can access the applications using the NodePort or LoadBalancer service IP addresses.\n\n## Testing\n\nThe project includes unit tests for both the backend and frontend applications. You can run the tests using the following commands:\n\n### Backend Tests\n\nTo run the backend tests, navigate to the `LMS-Backend` directory and run:\n\n```bash\ncd LMS-Backend\n\npytest -q\n```\n\n### Frontend Tests\n\nTo run the frontend tests, navigate to the `LMS-Frontend/app` directory and run:\n\n```bash\ncd LMS-Frontend/app\n\n# Run tests (normal mode)\nnpm run test\n\n# Run tests (code coverage mode)\nnpm run coverage\n```\n\n## OpenAPI Specification\n\n### Using the `openapi.yaml` File\n\n1. **View the API Documentation**\n\n- Open [Swagger Editor](https://editor.swagger.io/).\n- Upload the `openapi.yaml` file or paste its content.\n- Visualize and interact with the API documentation.\n\n2. **Test the API**\n\n- Import `openapi.yaml` into [Postman](https://www.postman.com/):\n  - Open Postman → Import → Select `openapi.yaml`.\n  - Test the API endpoints directly from Postman.\n- Or use [Swagger UI](https://swagger.io/tools/swagger-ui/):\n  - Provide the file URL or upload it to view and test endpoints.\n\n3. **Generate Client Libraries**\n\n- Install OpenAPI Generator:\n  ```bash\n  npm install @openapitools/openapi-generator-cli -g\n  ```\n- Generate a client library:\n  ```bash\n  openapi-generator-cli generate -i openapi.yaml -g \u003clanguage\u003e -o ./client\n  ```\n- Replace `\u003clanguage\u003e` with the desired programming language.\n\n4. **Generate Server Stubs**\n\n- Generate a server stub:\n  ```bash\n  openapi-generator-cli generate -i openapi.yaml -g \u003cframework\u003e -o ./server\n  ```\n- Replace `\u003cframework\u003e` with the desired framework.\n\n5. **Run a Mock Server**\n\n- Install Prism:\n  ```bash\n  npm install -g @stoplight/prism-cli\n  ```\n- Start the mock server:\n  ```bash\n  prism mock openapi.yaml\n  ```\n\n6. **Validate the OpenAPI File**\n\n- Use [Swagger Validator](https://validator.swagger.io/):\n  - Upload `openapi.yaml` or paste its content to check for errors.\n\nThis guide enables you to view, test, and utilize the API. You can also generate client libraries, server stubs, and run a mock server using the OpenAPI specification.\n\n## Jenkins CI/CD\n\nThe project includes a `Jenkinsfile` for setting up CI/CD pipelines using Jenkins. The Jenkinsfile defines the stages for building, testing, and deploying the backend and frontend applications.\n\nTo set up the CI/CD pipelines using Jenkins, follow these steps:\n\n1. **Install Jenkins on your system or use a cloud-based Jenkins service.**\n\n2. **Create a new Jenkins pipeline project.**\n\n3. **Configure the pipeline to use the Jenkinsfile in the project repository.**\n\n4. **Run the pipeline to build, test, and deploy the applications.**\n\nThe Jenkins pipeline will automatically build the Docker images, run the unit tests, and deploy the applications to a Kubernetes cluster.\n\n## Troubleshooting\n\n### Common Issues\n\n1. **CORS Errors**:\n\n- Ensure backend CORS settings allow requests from `http://localhost:4200`.\n\n2. **Unauthorized Access**:\n\n- Confirm that tokens are stored correctly in `localStorage`.\n\n3. **API Connection**:\n\n- Verify the backend server is running at `http://127.0.0.1:8000`.\n\n4. **Database Connection**:\n\n- Check MongoDB and Redis are running and accessible.\n\n5. **Dependencies**:\n\n- Ensure all required dependencies are installed, using `pip install -r requirements.txt` and `npm install`.\n\n6. **UI Issues**:\n\n- Check the Angular console for errors and warnings. Alternatively, you can try clearing the cache using `npm cache clean --force` and `npm install`.\n\n7. **Unable to Log In**:\n\n- Because we are using default Django Auth and SQLite to optimize infrastructure costs, perhaps the user you are trying to log in with does not exist. Sometimes SQLite does not save the data after the server is restarted.\n- Therefore, please try registering a new user and logging in with that user to bypass this issue.\n- You can also try to create a new user using the Django admin panel or the `createsuperuser` command.\n- Sorry for any inconvenience this may cause! I am planning to switch to Firebase Auth in the future to avoid this issue, but I will need to get some funding first since I have run out of free tier resources...\n\n### Debugging Tips\n\n- Use browser Developer Tools to inspect requests and console logs.\n- Check the network tab for failed requests.\n- Use `console.log` statements in the frontend code to debug.\n- Use `print` statements in the backend code to debug.\n- Check the Django console for server-side errors.\n- Check the Angular console for client-side errors.\n- Refer to the official documentation for troubleshooting tips.\n- Feel free to open an issue or contact me for help. Refer to the [Contact](#contact) section below.\n\n## Additional Information\n\nRefer to the README files in the `LMS-Backend` and `LMS-Frontend` directories for more detailed information on each part of the system.\n\n- [Backend README](LMS-Backend/README.md)\n- [Frontend README](LMS-Frontend/README.md)\n\nThese README files contain additional information on how to run, test, and contribute to the project.\n\n## Contributing\n\nWe welcome contributions! Feel free to submit issues and create pull requests.\n\n1. **Fork** the repository.\n2. **Clone** the forked repository to your local machine.\n3. **Create a new branch** and make your changes.\n4. **Commit** your changes and **push** them to your fork.\n5. **Create a pull request** to the main repository.\n6. I will **review your changes** and **merge them if they are accepted**.\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE).\n\n## Contact\n\nIf you have any questions or need further assistance, contact us at [hoangson091104@gmail.com](mailto:hoangson091104@gmail.com).\n\nAlternatively, you can also open an issue in the repository [here](https://github.com/hoangsonww/Learning-Management-System-Fullstack/issues).\n\n---\n\n**[⬆ Back to Top](#e-learning-management-fullstack-system)**\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoangsonww%2Flearning-management-system-fullstack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoangsonww%2Flearning-management-system-fullstack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoangsonww%2Flearning-management-system-fullstack/lists"}