Skip to content

Commit 1558fdc

Browse files
Merge branch 'main' into #45-Booking_Expiry_Logic_and_Reviews_Model
2 parents 31f8c88 + 9db90b8 commit 1558fdc

File tree

100 files changed

+4669
-243
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+4669
-243
lines changed

.DS_Store

6 KB
Binary file not shown.

.github/workflows/django_ci_cd.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ jobs:
2828
sudo service redis-server start
2929
sudo service redis-server status
3030
31+
- name: Install Flake8 and Run Linter
32+
run: |
33+
pip install flake8
34+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
35+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics
36+
3137
- name: Install Dependencies
3238
run: |
3339
python -m pip install --upgrade pip
@@ -59,3 +65,4 @@ jobs:
5965
with:
6066
name: coverage-report-html
6167
path: backend/htmlcov/ # Upload the entire 'htmlcov' directory
68+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: ReactJS CI/CD
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
jobs:
9+
lint:
10+
name: Run ESLint
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Node.js
18+
uses: actions/setup-node@v4
19+
with:
20+
node-version: 20
21+
22+
- name: Install root dependencies
23+
run: npm install # This will install the dependencies from the root `package.json`
24+
25+
- name: Install frontend dependencies
26+
run: |
27+
cd frontend # Navigate to the frontend directory
28+
npm install # Install the frontend dependencies from `frontend/package.json`
29+
30+
- name: Run ESLint # Finds syntax/style errors
31+
run: npx eslint --config ./frontend/eslint.config.js frontend

README.md

9.93 KB

2025-S-GROUP2-LessonConnect

This is our project LessonConnect! We aim to promote safety in the field of private tutoring.

LessonConnect

Project Description

LessonConnect streamlines communication, scheduling, and resource sharing for private tutors, students, and parents. Focused on one-on-one or small group tutoring, it features tailored messaging, parental oversight, and an integrated calendar—making it a modern, targeted alternative to general platforms like Google Classroom or Canvas.

🔑 Key Features

  • Real-Time Messaging (Channels + Redis)
    Chat with read receipts and attachments for individual or group sessions using Django Channels for WebSocket-based updates.

  • Scheduling & Booking
    Calendar-driven scheduling and rescheduling, including confirmations and parental approval flows.

  • Resource Sharing
    Tutors can upload PDFs, videos, and documents. Students can submit homework and quizzes.

  • Pomodoro Timer & Productivity Tools
    Helps students stay focused and prevent burnout with integrated time management tools.

  • Parental Oversight
    Parents access logs, messaging transcripts, and scheduling history for accountability.

  • Scalable Architecture
    Django backend with Redis and Celery for real-time and async tasks; deployment-ready for cloud platforms.


🏗️ Architecture Overview

Frontend

  • Built with: React + Vite
  • Styling: TailwindCSS + Bootstrap
  • Tooling: ESLint for consistency
  • Runs at: http://localhost:5173/

Backend

  • Built with: Django (5.1.6) + Django REST Framework
  • Database: SQLite (dev) → PostgreSQL (prod-ready)
  • Real-Time: Django Channels, Redis
  • Async Tasks: Celery
  • External Media Storage: cloudinary

🔧 Architecture Diagram: See /diagrams/architecture/lessonconnect-architecture.png (upload diagram in this folder)


⚙️ Setup Instructions

🖥️ Frontend: React + Vite

Prerequisites

  • Node.js
  • IDE (e.g., VSCode)

Install & Run

# 1. Clone the repo
git clone https://github.com/UNLV-CS472-672/2025-S-GROUP2-LessonConnect.git

# 2. Enter frontend directory
cd 2025-S-GROUP2-LessonConnect/frontend

# 3. Install dependencies
npm install

# 4. Start development server
npm run dev

Runs at: http://localhost:5173/


🛠️ Backend: Django + SQLite

Prerequisites

  • Python 3.8+
  • pip
  • Optional: Redis for local testing

Setup (Linux/macOS)

cd 2025-S-GROUP2-LessonConnect/backend
python3 -m venv env
source env/bin/activate
pip install -r requirements.txt

Setup (Windows PowerShell)

cd 2025-S-GROUP2-LessonConnect�ackend
python -m venv env
env\Scripts\Activate.ps1
pip install -r requirements.txt

Run

# Run migrations
python manage.py migrate

# Create admin (optional)
python manage.py createsuperuser

# Start the server
python manage.py runserver

Visit: http://127.0.0.1:8000/


🔁 Real-Time Messaging (Optional)

To test live chat locally:

  1. Start Redis server (redis-server)
  2. Ensure settings.py uses:
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {"hosts": [("127.0.0.1", 6379)]},
    }
}
  1. Run the dev server again to test chat.

📦 Dependencies (Partial List)

Dependency Purpose
Django==5.1.6 Core framework
channels[daphne] Real-time WebSocket support
channels-redis Redis-based channel layer
celery, django-celery-* Async tasks + scheduled jobs
redis Real-time messaging
psycopg2-binary PostgreSQL support (for deployment)
cloudinary Cloud file storage
python-dotenv Environment variable handling

🧪 Testing & CI/CD

  • Linting via ESLint (frontend) and flake8 (backend)
  • Test coverage tools integrated
  • CI workflow blocks PRs unless:
    • All tests pass
    • Linting is clean
    • PR is linked to an Issue

🤝 Contribution Guidelines

Pull Requests

  • Link all PRs to an issue
  • Include a design diagram in /diagrams/<feature-name>/
  • Follow AI-generated code annotation format:
# ai-gen start (ChatGPT-4, 1)
def example():
    pass
# ai-gen end

Branch Naming

Use clear, descriptive branch names:

  • feature/calendar-sync
  • fix/login-crash
  • test/user-auth-flow

📂 Repo Structure

LessonConnect/
├── backend/            # Django app
├── frontend/           # React app
├── diagrams/
│   ├── use-cases/
│   ├── sequence/
│   └── architecture/
└── README.md

📬 Contact & Support


📄 License

This project is licensed under the MIT License. See LICENSE.md for more info.

backend/apps/chat/admin.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
from django.contrib import admin
2+
from .models import Chat, Message
23

3-
# Register your models here.
4+
admin.site.register(Chat)
5+
admin.site.register(Message)

backend/apps/chat/forms.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from django import forms
2+
from .models import Message
3+
4+
# https://docs.djangoproject.com/en/5.1/topics/forms/modelforms/
5+
class MessageForm(forms.ModelForm):
6+
class Meta:
7+
model = Message
8+
fields = ['content']
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Generated by Django 5.1.6 on 2025-03-06 19:53
2+
3+
import django.db.models.deletion
4+
import django.utils.timezone
5+
from django.conf import settings
6+
from django.db import migrations, models
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
initial = True
12+
13+
dependencies = [
14+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='Message',
20+
fields=[
21+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('content', models.TextField()),
23+
('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
24+
('receiver', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='received_messages', to=settings.AUTH_USER_MODEL)),
25+
('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sent_messages', to=settings.AUTH_USER_MODEL)),
26+
],
27+
options={
28+
'ordering': ['-timestamp'],
29+
},
30+
),
31+
]
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Generated by Django 5.1.6 on 2025-03-06 20:46
2+
3+
import django.db.models.deletion
4+
from django.conf import settings
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('chat', '0001_initial'),
12+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13+
]
14+
15+
operations = [
16+
migrations.AlterModelOptions(
17+
name='message',
18+
options={'ordering': ['timestamp']},
19+
),
20+
migrations.RemoveField(
21+
model_name='message',
22+
name='receiver',
23+
),
24+
migrations.CreateModel(
25+
name='Chat',
26+
fields=[
27+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
28+
('createdAt', models.DateTimeField(auto_now_add=True)),
29+
('updatedAt', models.DateTimeField(auto_now=True)),
30+
('user1', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='chats_initiated', to=settings.AUTH_USER_MODEL)),
31+
('user2', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='chats_received', to=settings.AUTH_USER_MODEL)),
32+
],
33+
options={
34+
'ordering': ['-updatedAt'],
35+
'unique_together': {('user1', 'user2')},
36+
},
37+
),
38+
migrations.AddField(
39+
model_name='message',
40+
name='chat',
41+
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='chat.chat'),
42+
),
43+
]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.1.6 on 2025-03-06 21:18
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('chat', '0002_alter_message_options_remove_message_receiver_chat_and_more'),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name='message',
15+
name='id',
16+
field=models.AutoField(primary_key=True, serialize=False),
17+
),
18+
]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 5.1.6 on 2025-03-06 23:38
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('chat', '0003_alter_message_id'),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name='message',
16+
name='chat',
17+
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='chat.chat'),
18+
),
19+
migrations.AlterField(
20+
model_name='message',
21+
name='id',
22+
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
23+
),
24+
]

0 commit comments

Comments
 (0)