Spaces:
Sleeping
Sleeping
| import re | |
| import streamlit as st | |
| from datetime import datetime, date, time, timedelta | |
| from pathlib import Path | |
| # from utils.sample_data import SAMPLE_COURSES, SAMPLE_SESSIONS | |
| from session_page import display_session_content | |
| from db import ( | |
| courses_collection2, | |
| faculty_collection, | |
| students_collection, | |
| research_assistants_collection, | |
| analysts_collection, | |
| ) | |
| from werkzeug.security import generate_password_hash, check_password_hash | |
| import os | |
| from openai import OpenAI | |
| from dotenv import load_dotenv | |
| from create_course2 import create_course, courses_collection, generate_perplexity_response, generate_session_resources, PERPLEXITY_API_KEY, validate_course_plan | |
| import json | |
| from bson import ObjectId | |
| client = OpenAI(api_key=os.getenv("OPENAI_KEY")) | |
| from dotenv import load_dotenv | |
| from create_course3 import generate_course_outcomes, generate_resources_by_titles_chunking, generate_session_outcomes, generate_module_outcomes, generate_submodule_outcomes, generate_session_resources, GEMINI_API_KEY, PERPLEXITY_API_KEY, merge_course_structure | |
| load_dotenv() | |
| # PERPLEXITY_API_KEY = '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' | |
| def get_research_papers(query): | |
| """Get research paper recommendations based on query""" | |
| try: | |
| response = client.chat.completions.create( | |
| model="gpt-3.5-turbo", | |
| messages=[ | |
| { | |
| "role": "system", | |
| "content": "You are a helpful research assistant. Provide 10 relevant research papers with titles, authors, brief descriptions, and DOI/URL links. Format each paper as: \n\n1. **Title**\nAuthors: [names]\nLink: [DOI/URL]\nDescription: [brief summary]", | |
| }, | |
| { | |
| "role": "user", | |
| "content": f"Give me 10 research papers about: {query}. Include valid DOI links or URLs to the papers where available.", | |
| }, | |
| ], | |
| ) | |
| return response.choices[0].message.content | |
| except Exception as e: | |
| return f"Error getting recommendations: {str(e)}" | |
| def analyze_research_gaps(papers): | |
| """Analyze gaps in research based on recommended papers""" | |
| try: | |
| response = client.chat.completions.create( | |
| model="gpt-3.5-turbo", | |
| messages=[ | |
| { | |
| "role": "system", | |
| "content": "You are a research analysis expert. Based on the provided papers, identify potential research gaps and future research directions.", | |
| }, | |
| { | |
| "role": "user", | |
| "content": f"Based on these papers, what are the key areas that need more research?\n\nPapers:\n{papers}", | |
| }, | |
| ], | |
| ) | |
| return response.choices[0].message.content | |
| except Exception as e: | |
| return f"Error analyzing research gaps: {str(e)}" | |
| def init_session_state(): | |
| """Initialize session state variables""" | |
| if "authenticated" not in st.session_state: | |
| st.session_state.authenticated = False | |
| if "user_id" not in st.session_state: | |
| st.session_state.user_id = None | |
| if "user_type" not in st.session_state: | |
| st.session_state.user_type = None | |
| if "username" not in st.session_state: | |
| st.session_state.username = None | |
| if "selected_course" not in st.session_state: | |
| st.session_state.selected_course = None | |
| if "show_create_course_form" not in st.session_state: | |
| st.session_state.show_create_course_form = False | |
| if "show_create_session_form" not in st.session_state: | |
| st.session_state.show_create_session_form = False | |
| if "show_enroll_course_page" not in st.session_state: | |
| st.session_state.show_enroll_course_page = False | |
| if "course_to_enroll" not in st.session_state: | |
| st.session_state.course_to_enroll = None | |
| def login_user(username, password, user_type): | |
| """Login user based on credentials""" | |
| if user_type == "student": | |
| # user = students_collection.find_one({"full_name": username}) or students_collection.find_one({"username": username}) | |
| user = students_collection.find_one({"$or": [{"full_name": username}, {"username": username}]}) | |
| elif user_type == "faculty": | |
| user = faculty_collection.find_one({"full_name": username}) | |
| elif user_type == "research_assistant": | |
| user = research_assistants_collection.find_one({"full_name": username}) | |
| elif user_type == "analyst": | |
| user = analysts_collection.find_one({"full_name": username}) | |
| if user and check_password_hash(user["password"], password): | |
| st.session_state.user_id = user["_id"] | |
| print(st.session_state.user_id) | |
| st.session_state.authenticated = True | |
| st.session_state.user_type = user_type | |
| st.session_state.username = username | |
| return True | |
| return False | |
| # def login_form(): | |
| # """Display login form""" | |
| # st.title("Welcome to NOVAScholar") | |
| # with st.form("login_form"): | |
| # user_type = st.selectbox( | |
| # "Please select your Role", ["student", "faculty", "research_assistant", "analyst"] | |
| # ) | |
| # username = st.text_input("Username") | |
| # password = st.text_input("Password", type="password") | |
| # submit = st.form_submit_button("Login") | |
| # if submit: | |
| # if login_user(username, password, user_type): | |
| # st.success("Login successful!") | |
| # st.rerun() | |
| # else: | |
| # st.error("Invalid credentials!") | |
| def login_form(): | |
| """Display enhanced login form""" | |
| st.title("Welcome to NOVAScholar") | |
| with st.form("login_form"): | |
| # Role selection at the top | |
| user_type = st.selectbox( | |
| "Please select your Role", | |
| ["student", "faculty", "research_assistant", "analyst"] | |
| ) | |
| # Username/email and password stacked vertically | |
| username = st.text_input("Username or Email") | |
| password = st.text_input("Password", type="password") | |
| # Login button | |
| submit = st.form_submit_button("Login") | |
| if submit: | |
| # Handle both username and email login | |
| if '@' in username: | |
| username = extract_username(username) | |
| if login_user(username, password, user_type): | |
| st.success("Login successful!") | |
| st.rerun() | |
| else: | |
| st.error("Invalid credentials!") | |
| def get_courses(username, user_type): | |
| if user_type == "student": | |
| student = students_collection.find_one({"$or": [{"full_name": username}, {"username": username}]}) | |
| if student: | |
| enrolled_course_ids = [ | |
| course["course_id"] for course in student.get("enrolled_courses", []) | |
| ] | |
| courses = courses_collection.find( | |
| {"course_id": {"$in": enrolled_course_ids}} | |
| ) | |
| # courses += courses_collection2.find( | |
| # {"course_id": {"$in": enrolled_course_ids}} | |
| # ) | |
| # # course_titles = [course['title'] for course in courses] | |
| # return list(courses) | |
| # courses_cursor1 = courses_collection.find( | |
| # {"course_id": {"$in": enrolled_course_ids}} | |
| # ) | |
| # courses_cursor2 = courses_collection2.find( | |
| # {"course_id": {"$in": enrolled_course_ids}} | |
| # ) | |
| # courses = list(courses_cursor1) + list(courses_cursor2) | |
| return list(courses) | |
| elif user_type == "faculty": | |
| faculty = faculty_collection.find_one({"full_name": username}) | |
| if faculty: | |
| course_ids = [ | |
| course["course_id"] for course in faculty.get("courses_taught", []) | |
| ] | |
| # courses_1 = list(courses_collection2.find({"course_id": {"$in": course_ids}})) | |
| courses_2 = list(courses_collection.find({"course_id": {"$in": course_ids}})) | |
| return courses_2 | |
| elif user_type == "research_assistant": | |
| research_assistant = research_assistants_collection.find_one( | |
| {"full_name": username} | |
| ) | |
| if research_assistant: | |
| course_ids = [ | |
| course["course_id"] | |
| for course in research_assistant.get("courses_assisted", []) | |
| ] | |
| courses = courses_collection2.find({"course_id": {"$in": course_ids}}) | |
| return list(courses) | |
| else: | |
| return [] | |
| def get_course_ids(): | |
| """Get course IDs for sample courses""" | |
| return [course["course_id"] for course in SAMPLE_COURSES] | |
| def get_sessions(course_id, course_title): | |
| """Get sessions for a given course ID""" | |
| course = courses_collection.find_one({"course_id": course_id, "title": course_title}) | |
| if course: | |
| return course.get("sessions", []) | |
| return [] | |
| def create_session(new_session, course_id): | |
| """Create a new session for a given course ID""" | |
| course = courses_collection2.find_one({"course_id": course_id}) | courses_collection.find_one({"course_id": course_id}) | |
| if course: | |
| last_session_id = max((session["session_id"] for session in course["sessions"])) | |
| last_session_id = int(last_session_id[1:]) | |
| new_session_id = last_session_id + 1 | |
| new_session["session_id"] = "S" + str(new_session_id) | |
| courses_collection2.update_one( | |
| {"course_id": new_session["course_id"]}, | |
| {"$push": {"sessions": new_session}}, | |
| ) | |
| return True | |
| return False | |
| def create_session_form(course_id): | |
| """Display form to create a new session and perform the creation operation""" | |
| st.title("Create New Session") | |
| if 'session_time' not in st.session_state: | |
| st.session_state.session_time = datetime.now().time() | |
| if 'show_create_session_form' not in st.session_state: | |
| st.session_state.show_create_session_form = False | |
| with st.form("create_session_form"): | |
| session_title = st.text_input("Session Title") | |
| session_date = st.date_input("Session Date", date.today(), key="session_date") | |
| session_time = st.time_input( | |
| "Session Time", st.session_state.session_time, key="session_time" | |
| ) | |
| new_session_id = None | |
| # Generate new session ID | |
| course = courses_collection2.find_one({"course_id": course_id}) | |
| if course and "sessions" in course and course["sessions"]: | |
| last_session_id = max( | |
| int(session["session_id"][1:]) for session in course["sessions"] | |
| ) | |
| new_session_id = last_session_id + 1 | |
| else: | |
| new_session_id = 1 | |
| if st.form_submit_button("Create Session"): | |
| clicked = True | |
| new_session = { | |
| "session_id": f"S{new_session_id}", | |
| "course_id": course_id, | |
| "title": session_title, | |
| "date": datetime.combine(session_date, session_time), | |
| "status": "upcoming", | |
| "created_at": datetime.utcnow(), | |
| "pre_class": { | |
| "resources": [], | |
| "completetion_required": True, | |
| }, | |
| "in_class": { | |
| "topics": [], | |
| "quiz": {"title": "", "questions": 0, "duration": 0}, | |
| "polls": [], | |
| }, | |
| "post_class": { | |
| "assignments": [], | |
| }, | |
| } | |
| courses_collection2.update_one( | |
| {"course_id": course_id}, {"$push": {"sessions": new_session}} | |
| ) | |
| st.success("Session created successfully!") | |
| st.session_state.show_create_session_form = False | |
| # new_session_id = None | |
| # creation_success = False | |
| # # Generate new session ID | |
| # course = courses_collection2.find_one({"course_id": course_id}) | |
| # if course and 'sessions' in course and course['sessions']: | |
| # last_session_id = max((session['session_id'] for session in course['sessions'])) | |
| # last_session_id = int(last_session_id[1:]) | |
| # new_session_id = last_session_id + 1 | |
| # else: | |
| # new_session_id = 1 | |
| # new_session = { | |
| # "session_id": 'S' + new_session_id, | |
| # "title": session_title, | |
| # "date": datetime.datetime.combine(session_date, session_time).isoformat(), | |
| # "status": "upcoming", | |
| # "created_at": datetime.datetime.utcnow().isoformat(), | |
| # "pre_class": { | |
| # "resources": [], | |
| # "completetion_required": True, | |
| # }, | |
| # "in_class": { | |
| # "topics": [], | |
| # "quiz": | |
| # { | |
| # "title": '', | |
| # "questions": 0, | |
| # "duration": 0 | |
| # }, | |
| # "polls": [] | |
| # }, | |
| # "post_class": { | |
| # "assignments": [], | |
| # } | |
| # } | |
| # courses_collection2.update_one( | |
| # {"course_id": course_id}, | |
| # {"$push": {"sessions": new_session}} | |
| # ) | |
| # creation_success = True | |
| # st.form_submit_button("Create Session") | |
| # if creation_success == True: | |
| # st.success("Session created successfully!") | |
| # else: | |
| def get_new_student_id(): | |
| """Generate a new student ID by incrementing the last student ID""" | |
| last_student = students_collection.find_one(sort=[("SID", -1)]) | |
| if last_student: | |
| last_student_id = int(last_student["SID"][1:]) | |
| new_student_id = f"S{last_student_id + 1}" | |
| else: | |
| new_student_id = "S101" | |
| return new_student_id | |
| def get_new_faculty_id(): | |
| """Generate a new faculty ID by incrementing the last faculty ID""" | |
| last_faculty = faculty_collection.find_one(sort=[("TID", -1)]) | |
| if last_faculty: | |
| last_faculty_id = int(last_faculty["TID"][1:]) | |
| new_faculty_id = f"T{last_faculty_id + 1}" | |
| else: | |
| new_faculty_id = "T101" | |
| return new_faculty_id | |
| def get_new_course_id(): | |
| """Generate a new course ID by incrementing the last course ID""" | |
| last_course = courses_collection2.find_one(sort=[("course_id", -1)]) | |
| if last_course: | |
| last_course_id = int(last_course["course_id"][2:]) | |
| new_course_id = f"CS{last_course_id + 1}" | |
| else: | |
| new_course_id = "CS101" | |
| return new_course_id | |
| # def register_page(): | |
| # st.title("Register") | |
| # if "user_type" not in st.session_state: | |
| # st.session_state.user_type = "student" | |
| # # Select user type | |
| # st.session_state.user_type = st.selectbox( | |
| # "Select User Type", ["student", "faculty", "research_assistant"] | |
| # ) | |
| # user_type = st.session_state.user_type | |
| # print(user_type) | |
| # with st.form("register_form"): | |
| # # user_type = st.selectbox("Select User Type", ["student", "faculty", "research_assistant"]) | |
| # # print(user_type) | |
| # full_name = st.text_input("Full Name") | |
| # password = st.text_input("Password", type="password") | |
| # confirm_password = st.text_input("Confirm Password", type="password") | |
| # if user_type == "student": | |
| # # Fetch courses for students to select from | |
| # courses = list(courses_collection2.find({}, {"course_id": 1, "title": 1})) | |
| # course_options = [ | |
| # f"{course['title']} ({course['course_id']})" for course in courses | |
| # ] | |
| # selected_courses = st.multiselect("Available Courses", course_options) | |
| # submit = st.form_submit_button("Register") | |
| # if submit: | |
| # if password == confirm_password: | |
| # hashed_password = generate_password_hash(password) | |
| # if user_type == "student": | |
| # new_student_id = get_new_student_id() | |
| # enrolled_courses = [ | |
| # { | |
| # "course_id": course.split("(")[-1][:-1], | |
| # "title": course.split(" (")[0], | |
| # } | |
| # for course in selected_courses | |
| # ] | |
| # students_collection.insert_one( | |
| # { | |
| # "SID": new_student_id, | |
| # "full_name": full_name, | |
| # "password": hashed_password, | |
| # "enrolled_courses": enrolled_courses, | |
| # "created_at": datetime.utcnow(), | |
| # } | |
| # ) | |
| # st.success( | |
| # f"Student registered successfully with ID: {new_student_id}" | |
| # ) | |
| # elif user_type == "faculty": | |
| # new_faculty_id = get_new_faculty_id() | |
| # faculty_collection.insert_one( | |
| # { | |
| # "TID": new_faculty_id, | |
| # "full_name": full_name, | |
| # "password": hashed_password, | |
| # "courses_taught": [], | |
| # "created_at": datetime.utcnow(), | |
| # } | |
| # ) | |
| # st.success( | |
| # f"Faculty registered successfully with ID: {new_faculty_id}" | |
| # ) | |
| # elif user_type == "research_assistant": | |
| # research_assistants_collection.insert_one( | |
| # { | |
| # "full_name": full_name, | |
| # "password": hashed_password, | |
| # "created_at": datetime.utcnow(), | |
| # } | |
| # ) | |
| # st.success("Research Assistant registered successfully!") | |
| # else: | |
| # st.error("Passwords do not match") | |
| def get_new_analyst_id(): | |
| """Generate a new analyst ID by incrementing the last analyst ID""" | |
| last_analyst = analysts_collection.find_one(sort=[("AID", -1)]) | |
| if last_analyst: | |
| last_id = int(last_analyst["AID"][1:]) | |
| new_id = f"A{last_id + 1}" | |
| else: | |
| new_id = "A1" | |
| return new_id | |
| # def register_page(): | |
| # st.title("Register") | |
| # if "user_type" not in st.session_state: | |
| # st.session_state.user_type = "student" | |
| # # Select user type | |
| # st.session_state.user_type = st.selectbox( | |
| # "Please select your Role", ["student", "faculty", "research_assistant", "analyst"] | |
| # ) | |
| # user_type = st.session_state.user_type | |
| # print(user_type) | |
| # with st.form("register_form"): | |
| # full_name = st.text_input("Full Name") | |
| # password = st.text_input("Password", type="password") | |
| # confirm_password = st.text_input("Confirm Password", type="password") | |
| # if user_type == "student": | |
| # # Fetch courses for students to select from | |
| # courses = list(courses_collection.find({}, {"course_id": 1, "title": 1})) | |
| # course_options = [ | |
| # f"{course['title']} ({course['course_id']})" for course in courses | |
| # ] | |
| # selected_courses = st.multiselect("Available Courses", course_options) | |
| # submit = st.form_submit_button("Register") | |
| # if submit: | |
| # if password == confirm_password: | |
| # hashed_password = generate_password_hash(password) | |
| # if user_type == "student": | |
| # new_student_id = get_new_student_id() | |
| # enrolled_courses = [ | |
| # { | |
| # "course_id": course.split("(")[-1][:-1], | |
| # "title": course.split(" (")[0], | |
| # } | |
| # for course in selected_courses | |
| # ] | |
| # students_collection.insert_one( | |
| # { | |
| # "SID": new_student_id, | |
| # "full_name": full_name, | |
| # "password": hashed_password, | |
| # "enrolled_courses": enrolled_courses, | |
| # "created_at": datetime.utcnow(), | |
| # } | |
| # ) | |
| # st.success( | |
| # f"Student registered successfully with ID: {new_student_id}" | |
| # ) | |
| # elif user_type == "faculty": | |
| # new_faculty_id = get_new_faculty_id() | |
| # faculty_collection.insert_one( | |
| # { | |
| # "TID": new_faculty_id, | |
| # "full_name": full_name, | |
| # "password": hashed_password, | |
| # "courses_taught": [], | |
| # "created_at": datetime.utcnow(), | |
| # } | |
| # ) | |
| # st.success( | |
| # f"Faculty registered successfully with ID: {new_faculty_id}" | |
| # ) | |
| # elif user_type == "research_assistant": | |
| # research_assistants_collection.insert_one( | |
| # { | |
| # "full_name": full_name, | |
| # "password": hashed_password, | |
| # "created_at": datetime.utcnow(), | |
| # } | |
| # ) | |
| # st.success("Research Assistant registered successfully!") | |
| # elif user_type == "analyst": | |
| # # new_analyst_id = get_new_analyst_id() | |
| # analysts_collection.insert_one( | |
| # { | |
| # # "AID": new_analyst_id, | |
| # "full_name": full_name, | |
| # "password": hashed_password, | |
| # "created_at": datetime.utcnow(), | |
| # } | |
| # ) | |
| # st.success("Analyst registered successfully!") | |
| # else: | |
| # st.error("Passwords do not match") | |
| def register_page(): | |
| st.title("Register for NOVAScholar") | |
| if "user_type" not in st.session_state: | |
| st.session_state.user_type = "student" | |
| # Select user type | |
| st.session_state.user_type = st.selectbox( | |
| "Please select your Role", | |
| ["student", "faculty", "research_assistant", "analyst"] | |
| ) | |
| user_type = st.session_state.user_type | |
| with st.form("register_form"): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| full_name = st.text_input("Full Name") | |
| email = st.text_input("Institutional Email") | |
| phone = st.text_input("Phone Number") | |
| with col2: | |
| password = st.text_input("Password", type="password") | |
| confirm_password = st.text_input("Confirm Password", type="password") | |
| if user_type == "student": | |
| courses = list(courses_collection.find({}, {"course_id": 1, "title": 1})) | |
| course_options = [f"{course['title']} ({course['course_id']})" for course in courses] | |
| selected_courses = st.multiselect("Available Courses", course_options) | |
| submit = st.form_submit_button("Register") | |
| if submit: | |
| # Validate email | |
| email_valid, email_msg = validate_email(email) | |
| if not email_valid: | |
| st.error(email_msg) | |
| return | |
| # Validate phone | |
| phone_valid, phone_msg = validate_phone(phone) | |
| if not phone_valid: | |
| st.error(phone_msg) | |
| return | |
| # Validate password match | |
| if password != confirm_password: | |
| st.error("Passwords do not match") | |
| return | |
| # Extract username from email | |
| username = extract_username(email) | |
| # Check if username already exists | |
| if user_type == "student": | |
| existing_user = students_collection.find_one({"username": username}) | |
| elif user_type == "faculty": | |
| existing_user = faculty_collection.find_one({"username": username}) | |
| elif user_type == "research_assistant": | |
| existing_user = research_assistants_collection.find_one({"username": username}) | |
| elif user_type == "analyst": | |
| existing_user = analysts_collection.find_one({"username": username}) | |
| if existing_user: | |
| st.error("A user with this email already exists") | |
| return | |
| # Hash password and create user | |
| hashed_password = generate_password_hash(password) | |
| user_data = { | |
| "username": username, | |
| "full_name": full_name, | |
| "email": email, | |
| "phone": phone, | |
| "password": hashed_password, | |
| "created_at": datetime.utcnow() | |
| } | |
| if user_type == "student": | |
| new_student_id = get_new_student_id() | |
| enrolled_courses = [ | |
| { | |
| "course_id": course.split("(")[-1][:-1], | |
| "title": course.split(" (")[0], | |
| } | |
| for course in selected_courses | |
| ] | |
| user_data["SID"] = new_student_id | |
| user_data["enrolled_courses"] = enrolled_courses | |
| students_collection.insert_one(user_data) | |
| st.success(f"Student registered successfully! Your username is: {username}") | |
| elif user_type == "faculty": | |
| new_faculty_id = get_new_faculty_id() | |
| user_data["TID"] = new_faculty_id | |
| user_data["courses_taught"] = [] | |
| faculty_collection.insert_one(user_data) | |
| st.success(f"Faculty registered successfully! Your username is: {username}") | |
| elif user_type == "research_assistant": | |
| research_assistants_collection.insert_one(user_data) | |
| st.success(f"Research Assistant registered successfully! Your username is: {username}") | |
| elif user_type == "analyst": | |
| analysts_collection.insert_one(user_data) | |
| st.success(f"Analyst registered successfully! Your username is: {username}") | |
| # Create Course feature | |
| # def create_course_form2(faculty_name, faculty_id): | |
| # """Display enhanced form to create a new course with AI-generated content""" | |
| # st.title("Create New Course") | |
| # if 'course_plan' not in st.session_state: | |
| # st.session_state.course_plan = None | |
| # if 'edit_mode' not in st.session_state: | |
| # st.session_state.edit_mode = False | |
| # # Initial Course Creation Form | |
| # if not st.session_state.course_plan: | |
| # with st.form("initial_course_form"): | |
| # col1, col2 = st.columns(2) | |
| # with col1: | |
| # course_name = st.text_input("Course Name", placeholder="e.g., Introduction to Computer Science") | |
| # faculty_info = st.text_input("Faculty", value=faculty_name, disabled=True) | |
| # with col2: | |
| # duration_weeks = st.number_input("Duration (weeks)", min_value=1, max_value=16, value=12) | |
| # start_date = st.date_input("Start Date") | |
| # generate_button = st.form_submit_button("Generate Course Structure", use_container_width=True) | |
| # if generate_button and course_name: | |
| # with st.spinner("Generating course structure..."): | |
| # try: | |
| # course_plan = generate_perplexity_response(PERPLEXITY_API_KEY, course_name) | |
| # # print(course_plan) | |
| # st.session_state.course_plan = json.loads(course_plan) | |
| # st.session_state.start_date = start_date | |
| # st.session_state.duration_weeks = duration_weeks | |
| # st.rerun() | |
| # except Exception as e: | |
| # st.error(f"Error generating course structure: {e}") | |
| # # Display and Edit Generated Course Content | |
| # if st.session_state.course_plan: | |
| # with st.expander("Course Overview", expanded=True): | |
| # if not st.session_state.edit_mode: | |
| # st.subheader(st.session_state.course_plan['course_title']) | |
| # st.write(st.session_state.course_plan['course_description']) | |
| # edit_button = st.button("Edit Course Details", use_container_width=True) | |
| # if edit_button: | |
| # st.session_state.edit_mode = True | |
| # st.rerun() | |
| # else: | |
| # with st.form("edit_course_details"): | |
| # st.session_state.course_plan['course_title'] = st.text_input( | |
| # "Course Title", | |
| # value=st.session_state.course_plan['course_title'] | |
| # ) | |
| # st.session_state.course_plan['course_description'] = st.text_area( | |
| # "Course Description", | |
| # value=st.session_state.course_plan['course_description'] | |
| # ) | |
| # if st.form_submit_button("Save Course Details"): | |
| # st.session_state.edit_mode = False | |
| # st.rerun() | |
| # # Display Modules and Sessions | |
| # st.subheader("Course Modules and Sessions") | |
| # start_date = st.session_state.start_date | |
| # current_date = start_date | |
| # all_sessions = [] | |
| # for module_idx, module in enumerate(st.session_state.course_plan['modules']): | |
| # with st.expander(f"📚 Module {module_idx + 1}: {module['module_title']}", expanded=True): | |
| # # Edit module title | |
| # new_module_title = st.text_input( | |
| # f"Module {module_idx + 1} Title", | |
| # value=module['module_title'], | |
| # key=f"module_{module_idx}" | |
| # ) | |
| # module['module_title'] = new_module_title | |
| # for sub_idx, sub_module in enumerate(module['sub_modules']): | |
| # st.markdown(f"### 📖 {sub_module['title']}") | |
| # # Create sessions for each topic | |
| # for topic_idx, topic in enumerate(sub_module['topics']): | |
| # session_key = f"session_{module_idx}_{sub_idx}_{topic_idx}" | |
| # with st.container(): | |
| # col1, col2, col3 = st.columns([3, 2, 1]) | |
| # with col1: | |
| # new_topic = st.text_input( | |
| # "Topic", | |
| # value=topic, | |
| # key=f"{session_key}_topic" | |
| # ) | |
| # sub_module['topics'][topic_idx] = new_topic | |
| # with col2: | |
| # session_date = st.date_input( | |
| # "Session Date", | |
| # value=current_date, | |
| # key=f"{session_key}_date" | |
| # ) | |
| # with col3: | |
| # session_status = st.selectbox( | |
| # "Status", | |
| # options=["upcoming", "in-progress", "completed"], | |
| # key=f"{session_key}_status" | |
| # ) | |
| # # Create session object | |
| # session = { | |
| # "session_id": str(ObjectId()), | |
| # "title": new_topic, | |
| # "date": datetime.combine(session_date, datetime.min.time()), | |
| # "status": session_status, | |
| # "module_name": module['module_title'], | |
| # "created_at": datetime.utcnow(), | |
| # "pre_class": { | |
| # "resources": [], | |
| # "completion_required": True | |
| # }, | |
| # "in_class": { | |
| # "quiz": [], | |
| # "polls": [] | |
| # }, | |
| # "post_class": { | |
| # "assignments": [] | |
| # } | |
| # } | |
| # all_sessions.append(session) | |
| # current_date = session_date + timedelta(days=7) | |
| # new_course_id = get_new_course_id() | |
| # course_title = st.session_state.course_plan['course_title'] | |
| # # Final Save Button | |
| # if st.button("Save Course", type="primary", use_container_width=True): | |
| # try: | |
| # course_doc = { | |
| # "course_id": new_course_id, | |
| # "title": course_title, | |
| # "description": st.session_state.course_plan['course_description'], | |
| # "faculty": faculty_name, | |
| # "faculty_id": faculty_id, | |
| # "duration": f"{st.session_state.duration_weeks} weeks", | |
| # "start_date": datetime.combine(st.session_state.start_date, datetime.min.time()), | |
| # "created_at": datetime.utcnow(), | |
| # "sessions": all_sessions | |
| # } | |
| # # Insert into database | |
| # courses_collection.insert_one(course_doc) | |
| # st.success("Course successfully created!") | |
| # # Update faculty collection | |
| # faculty_collection.update_one( | |
| # {"_id": st.session_state.user_id}, | |
| # { | |
| # "$push": { | |
| # "courses_taught": { | |
| # "course_id": new_course_id, | |
| # "title": course_title, | |
| # } | |
| # } | |
| # }, | |
| # ) | |
| # # Clear session state | |
| # st.session_state.course_plan = None | |
| # st.session_state.edit_mode = False | |
| # # Optional: Add a button to view the created course | |
| # if st.button("View Course"): | |
| # # Add navigation logic here | |
| # pass | |
| # except Exception as e: | |
| # st.error(f"Error saving course: {e}") | |
| def remove_json_backticks(json_string): | |
| """Remove backticks and 'json' from the JSON object string""" | |
| return json_string.replace("```json", "").replace("```", "").strip() | |
| # def create_course_form(faculty_name, faculty_id): | |
| # """Display enhanced form to create a new course with AI-generated content and resources""" | |
| # st.title("Create New Course") | |
| # if 'course_plan' not in st.session_state: | |
| # st.session_state.course_plan = None | |
| # if 'edit_mode' not in st.session_state: | |
| # st.session_state.edit_mode = False | |
| # if 'resources_map' not in st.session_state: | |
| # st.session_state.resources_map = {} | |
| # if 'start_date' not in st.session_state: | |
| # st.session_state.start_date = None | |
| # if 'duration_weeks' not in st.session_state: | |
| # st.session_state.duration_weeks = None | |
| # if 'sessions_per_week' not in st.session_state: | |
| # st.session_state.sessions_per_week = None | |
| # # Initial Course Creation Form | |
| # if not st.session_state.course_plan: | |
| # with st.form("initial_course_form"): | |
| # col1, col2 = st.columns(2) | |
| # with col1: | |
| # course_name = st.text_input("Course Name", placeholder="e.g., Introduction to Computer Science") | |
| # faculty_info = st.text_input("Faculty", value=faculty_name, disabled=True) | |
| # sessions_per_week = st.number_input("Sessions Per Week", min_value=1, max_value=5, value=2) | |
| # with col2: | |
| # duration_weeks = st.number_input("Duration (weeks)", min_value=1, max_value=16, value=12) | |
| # start_date = st.date_input("Start Date") | |
| # generate_button = st.form_submit_button("Generate Course Structure", use_container_width=True) | |
| # if generate_button and course_name: | |
| # with st.spinner("Generating course structure and resources..."): | |
| # try: | |
| # # Generate course plan with resources | |
| # course_plan = generate_perplexity_response( | |
| # PERPLEXITY_API_KEY, | |
| # course_name, | |
| # duration_weeks, | |
| # sessions_per_week | |
| # ) | |
| # try: | |
| # course_plan_json = json.loads(course_plan) | |
| # validate_course_plan(course_plan_json) | |
| # st.session_state.course_plan = course_plan_json | |
| # except (json.JSONDecodeError, ValueError) as e: | |
| # st.error(f"Error in course plan structure: {e}") | |
| # return | |
| # st.session_state.start_date = start_date | |
| # st.session_state.duration_weeks = duration_weeks | |
| # st.session_state.sessions_per_week = sessions_per_week | |
| # # Generate resources for all sessions | |
| # session_titles = [] | |
| # for module in st.session_state.course_plan['modules']: | |
| # for sub_module in module['sub_modules']: | |
| # for topic in sub_module['topics']: | |
| # # session_titles.append(topic['title']) | |
| # # session_titles.append(topic) | |
| # if isinstance(topic, dict): | |
| # session_titles.append(topic['title']) | |
| # else: | |
| # session_titles.append(topic) | |
| # # In generate_session_resources function, add validation: | |
| # if not session_titles: | |
| # return json.dumps({"session_resources": []}) | |
| # resources_response = generate_session_resources(PERPLEXITY_API_KEY, session_titles) | |
| # without_backticks = remove_json_backticks(resources_response) | |
| # resources = json.loads(without_backticks) | |
| # st.session_state.resources_map = { | |
| # resource['session_title']: resource['resources'] | |
| # for resource in resources['session_resources'] | |
| # } | |
| # # Add error handling for the resources map | |
| # # if st.session_state.resources_map is None: | |
| # # st.session_state.resources_map = {} | |
| # st.rerun() | |
| # except Exception as e: | |
| # st.error(f"Error generating course structure: {e}") | |
| # # Display and Edit Generated Course Content | |
| # if st.session_state.course_plan: | |
| # with st.expander("Course Overview", expanded=True): | |
| # if not st.session_state.edit_mode: | |
| # st.subheader(st.session_state.course_plan['course_title']) | |
| # st.write(st.session_state.course_plan['course_description']) | |
| # col1, col2, col3 = st.columns(3) | |
| # with col1: | |
| # st.write(f"**Start Date:** {st.session_state.start_date}") | |
| # with col2: | |
| # st.write(f"**Duration (weeks):** {st.session_state.duration_weeks}") | |
| # with col3: | |
| # st.write(f"**Sessions Per Week:** {st.session_state.sessions_per_week}") | |
| # edit_button = st.button("Edit Course Details", use_container_width=True) | |
| # if edit_button: | |
| # st.session_state.edit_mode = True | |
| # st.rerun() | |
| # else: | |
| # with st.form("edit_course_details"): | |
| # st.session_state.course_plan['course_title'] = st.text_input( | |
| # "Course Title", | |
| # value=st.session_state.course_plan['course_title'] | |
| # ) | |
| # st.session_state.course_plan['course_description'] = st.text_area( | |
| # "Course Description", | |
| # value=st.session_state.course_plan['course_description'] | |
| # ) | |
| # if st.form_submit_button("Save Course Details"): | |
| # st.session_state.edit_mode = False | |
| # st.rerun() | |
| # # Display Modules and Sessions | |
| # st.subheader("Course Modules and Sessions") | |
| # start_date = st.session_state.start_date | |
| # current_date = start_date | |
| # all_sessions = [] | |
| # for module_idx, module in enumerate(st.session_state.course_plan['modules']): | |
| # with st.expander(f"📚 Module {module_idx + 1}: {module['module_title']}", expanded=True): | |
| # # Edit module title | |
| # new_module_title = st.text_input( | |
| # f"Edit Module Title", | |
| # value=module['module_title'], | |
| # key=f"module_{module_idx}" | |
| # ) | |
| # module['module_title'] = new_module_title | |
| # for sub_idx, sub_module in enumerate(module['sub_modules']): | |
| # st.markdown("<br>", unsafe_allow_html=True) # Add gap between sessions | |
| # # st.markdown(f"### 📖 {sub_module['title']}") | |
| # st.markdown(f'<h3 style="font-size: 1.25rem;">📖 Chapter {sub_idx + 1}: {sub_module["title"]}</h3>', unsafe_allow_html=True) | |
| # # Possible fix: | |
| # # Inside the loop where topics are being processed: | |
| # for topic_idx, topic in enumerate(sub_module['topics']): | |
| # st.markdown("<br>", unsafe_allow_html=True) # Add gap between sessions | |
| # session_key = f"session_{module_idx}_{sub_idx}_{topic_idx}" | |
| # # Get topic title based on type | |
| # if isinstance(topic, dict): | |
| # current_topic_title = topic.get('title', '') | |
| # current_topic_display = current_topic_title | |
| # else: | |
| # current_topic_title = str(topic) | |
| # current_topic_display = current_topic_title | |
| # with st.container(): | |
| # # Session Details | |
| # col1, col2, col3 = st.columns([3, 2, 1]) | |
| # with col1: | |
| # new_topic = st.text_input( | |
| # f"Session {topic_idx + 1} Title", | |
| # value=current_topic_display, | |
| # key=f"{session_key}_topic" | |
| # ) | |
| # # Update the topic in the data structure | |
| # if isinstance(topic, dict): | |
| # topic['title'] = new_topic | |
| # else: | |
| # sub_module['topics'][topic_idx] = new_topic | |
| # with col2: | |
| # session_date = st.date_input( | |
| # "Session Date", | |
| # value=current_date, | |
| # key=f"{session_key}_date" | |
| # ) | |
| # with col3: | |
| # session_status = st.selectbox( | |
| # "Status", | |
| # options=["upcoming", "in-progress", "completed"], | |
| # key=f"{session_key}_status" | |
| # ) | |
| # # Display Resources | |
| # if st.session_state.resources_map: | |
| # # Try both the full topic title and the display title | |
| # resources = None | |
| # if isinstance(topic, dict) and topic.get('title') in st.session_state.resources_map: | |
| # resources = st.session_state.resources_map[topic['title']] | |
| # elif current_topic_title in st.session_state.resources_map: | |
| # resources = st.session_state.resources_map[current_topic_title] | |
| # if resources: | |
| # with st.container(): | |
| # # st.markdown("#### 📚 Session Resources") | |
| # st.markdown(f'<h4 style="font-size: 1.25rem;">📚 Session Resources</h4>', unsafe_allow_html=True) | |
| # # Readings Tab | |
| # if resources.get('readings'): | |
| # st.markdown(f'<h5 style="font-size: 1.1rem; margin-top: 1rem;">📖 External Resources</h5>', unsafe_allow_html=True) | |
| # col1, col2 = st.columns(2) | |
| # for idx, reading in enumerate(resources['readings']): | |
| # with col1 if idx % 2 == 0 else col2: | |
| # st.markdown(f""" | |
| # - **{reading['title']}** | |
| # - Type: {reading['type']} | |
| # - Estimated reading time: {reading['estimated_read_time']} | |
| # - [Access Resource]({reading['url']}) | |
| # """) | |
| # # Books Tab and Additional Resources Tab side-by-side | |
| # col1, col2 = st.columns(2) | |
| # with col1: | |
| # if resources.get('books'): | |
| # st.markdown(f'<h5 style="font-size: 1.1rem; margin-top: 1rem;">📚 Reference Books</h5>', unsafe_allow_html=True) | |
| # for book in resources['books']: | |
| # with st.container(): | |
| # st.markdown(f""" | |
| # - **{book['title']}** | |
| # - Author: {book['author']} | |
| # - ISBN: {book['isbn']} | |
| # - Chapters: {book['chapters']} | |
| # """) | |
| # with col2: | |
| # if resources.get('additional_resources'): | |
| # st.markdown(f'<h5 style="font-size: 1.1rem; margin-top: 1rem;">🔗 Additional Study Resources</h5>', unsafe_allow_html=True) | |
| # for resource in resources['additional_resources']: | |
| # with st.container(): | |
| # st.markdown(f""" | |
| # - **{resource['title']}** | |
| # - Type: {resource['type']} | |
| # - Description: {resource['description']} | |
| # - [Access Resource]({resource['url']}) | |
| # """) | |
| # # Create session object | |
| # session = { | |
| # "session_id": str(ObjectId()), | |
| # "title": new_topic, | |
| # "date": datetime.combine(session_date, datetime.min.time()), | |
| # "status": session_status, | |
| # "module_name": module['module_title'], | |
| # "created_at": datetime.utcnow(), | |
| # "pre_class": { | |
| # "resources": [], | |
| # "completion_required": True | |
| # }, | |
| # "in_class": { | |
| # "quiz": [], | |
| # "polls": [] | |
| # }, | |
| # "post_class": { | |
| # "assignments": [] | |
| # }, | |
| # "external_resources": st.session_state.resources_map.get(current_topic_title, {}) | |
| # } | |
| # all_sessions.append(session) | |
| # current_date = session_date + timedelta(days=7) | |
| # new_course_id = get_new_course_id() | |
| # course_title = st.session_state.course_plan['course_title'] | |
| # # Final Save Button | |
| # if st.button("Save Course", type="primary", use_container_width=True): | |
| # try: | |
| # course_doc = { | |
| # "course_id": new_course_id, | |
| # "title": course_title, | |
| # "description": st.session_state.course_plan['course_description'], | |
| # "faculty": faculty_name, | |
| # "faculty_id": faculty_id, | |
| # "duration": f"{st.session_state.duration_weeks} weeks", | |
| # "sessions_per_week": st.session_state.sessions_per_week, | |
| # "start_date": datetime.combine(st.session_state.start_date, datetime.min.time()), | |
| # "created_at": datetime.utcnow(), | |
| # "sessions": all_sessions | |
| # } | |
| # # Insert into database | |
| # courses_collection.insert_one(course_doc) | |
| # st.success("Course successfully created!") | |
| # # Update faculty collection | |
| # faculty_collection.update_one( | |
| # {"_id": st.session_state.user_id}, | |
| # { | |
| # "$push": { | |
| # "courses_taught": { | |
| # "course_id": new_course_id, | |
| # "title": course_title, | |
| # } | |
| # } | |
| # } | |
| # ) | |
| # # Clear session state | |
| # st.session_state.course_plan = None | |
| # st.session_state.edit_mode = False | |
| # st.session_state.resources_map = {} | |
| # # Optional: Add a button to view the created course | |
| # if st.button("View Course"): | |
| # # Add navigation logic here | |
| # pass | |
| # except Exception as e: | |
| # st.error(f"Error saving course: {e}") | |
| def create_course_form(faculty_name, faculty_id): | |
| """Display enhanced form to create a new course with AI-generated content and faculty validation""" | |
| st.title("Create New Course - Outcome Based Approach") | |
| # Initialize session states | |
| if 'current_step' not in st.session_state: | |
| st.session_state.current_step = 1 | |
| if 'course_details' not in st.session_state: | |
| st.session_state.course_details = None | |
| if 'course_outcomes' not in st.session_state: | |
| st.session_state.course_outcomes = None | |
| if 'module_outcomes' not in st.session_state: | |
| st.session_state.module_outcomes = None | |
| if 'submodule_outcomes' not in st.session_state: | |
| st.session_state.submodule_outcomes = None | |
| # Step 1: Initial Course Details | |
| if st.session_state.current_step == 1: | |
| st.subheader("Step 1: Course Details") | |
| with st.form("initial_course_form"): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| course_name = st.text_input("Course Name", placeholder="e.g., Introduction to Computer Science") | |
| faculty_info = st.text_input("Faculty", value=faculty_name, disabled=True) | |
| sessions_per_week = st.number_input("Sessions Per Week", min_value=1, max_value=5, value=2) | |
| with col2: | |
| duration_weeks = st.number_input("Duration (weeks)", min_value=1, max_value=16, value=12) | |
| start_date = st.date_input("Start Date") | |
| if st.form_submit_button("Generate Course Outcomes", use_container_width=True): | |
| if course_name: | |
| with st.spinner("Generating course outcomes..."): | |
| try: | |
| # Store course details | |
| st.session_state.course_details = { | |
| "name": course_name, | |
| "faculty": faculty_name, | |
| "duration": duration_weeks, | |
| "sessions_per_week": sessions_per_week, | |
| "start_date": start_date | |
| } | |
| # Generate course outcomes | |
| outcomes = generate_course_outcomes( | |
| GEMINI_API_KEY, | |
| course_name, | |
| duration_weeks, | |
| sessions_per_week | |
| ) | |
| st.session_state.course_outcomes = json.loads(outcomes) | |
| st.session_state.current_step = 2 | |
| st.rerun() | |
| except Exception as e: | |
| st.error(f"Error generating course outcomes: {e}") | |
| else: | |
| st.error("Please enter a course name") | |
| # Step 2: Course Outcomes Validation | |
| elif st.session_state.current_step == 2: | |
| st.subheader("Step 2: Course Learning Outcomes (CLOs)") | |
| with st.expander("Course Details", expanded=True): | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.write(f"**Course:** {st.session_state.course_details['name']}") | |
| with col2: | |
| st.write(f"**Duration:** {st.session_state.course_details['duration']} weeks") | |
| with col3: | |
| st.write(f"**Sessions/Week:** {st.session_state.course_details['sessions_per_week']}") | |
| st.write("Please review and validate the generated course outcomes:") | |
| # Display and edit course description | |
| st.text_area( | |
| "Course Description", | |
| value=st.session_state.course_outcomes['course_description'], | |
| key="course_description", | |
| height=100 | |
| ) | |
| st.markdown("### Course Learning Outcomes") | |
| # Display existing outcomes with edit/delete capabilities | |
| outcomes = st.session_state.course_outcomes['learning_outcomes'] | |
| for i, outcome in enumerate(outcomes): | |
| col1, col2, col3 = st.columns([6, 2, 1]) | |
| with col1: | |
| outcomes[i]['outcome_description'] = st.text_area( | |
| f"CO{i+1}", | |
| value=outcome['outcome_description'], | |
| key=f"co_{i}", | |
| height=100 | |
| ) | |
| with col2: | |
| outcomes[i]['aligned_blooms_taxonomy_level'] = st.selectbox( | |
| "Bloom's Level", | |
| ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], | |
| index=["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"].index(outcome['aligned_blooms_taxonomy_level']), | |
| key=f"bloom_{i}" | |
| ) | |
| with col3: | |
| if st.button("🗑️", key=f"delete_co_{i}"): | |
| outcomes.pop(i) | |
| st.rerun() | |
| # Add new outcome | |
| st.markdown("### Add New Outcome") | |
| with st.form("add_outcome"): | |
| new_outcome = st.text_area("Outcome Description", placeholder="Enter new course outcome...") | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| bloom_level = st.selectbox( | |
| "Bloom's Taxonomy Level", | |
| ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"] | |
| ) | |
| with col2: | |
| if st.form_submit_button("Add Outcome", use_container_width=True): | |
| if new_outcome: | |
| outcomes.append({ | |
| "outcome_number": f"CO{len(outcomes)+1}", | |
| "outcome_description": new_outcome, | |
| "aligned_blooms_taxonomy_level": bloom_level | |
| }) | |
| st.rerun() | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.button("⬅️ Back to Course Details", use_container_width=True): | |
| st.session_state.current_step = 1 | |
| st.rerun() | |
| with col2: | |
| if st.button("Generate Module Outcomes ➡️", use_container_width=True): | |
| with st.spinner("Generating module outcomes..."): | |
| try: | |
| module_outcomes = generate_module_outcomes( | |
| st.session_state.course_details['name'], | |
| json.dumps(st.session_state.course_outcomes), | |
| st.session_state.course_details['duration'], | |
| st.session_state.course_details['sessions_per_week'] | |
| ) | |
| st.session_state.module_outcomes = json.loads(module_outcomes) | |
| st.session_state.current_step = 3 | |
| st.rerun() | |
| except Exception as e: | |
| st.error(f"Error generating module outcomes: {e}") | |
| # Step 3: Module Outcomes Validation | |
| elif st.session_state.current_step == 3: | |
| st.subheader("Step 3: Module Learning Outcomes (MLOs)") | |
| modules = st.session_state.module_outcomes['modules'] | |
| for module_idx, module in enumerate(modules): | |
| with st.expander(f"Module {module_idx + 1}: {module['module_title']}", expanded=True): | |
| # Edit module title and duration | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| module['module_title'] = st.text_input( | |
| "Module Title", | |
| value=module['module_title'], | |
| key=f"module_title_{module_idx}" | |
| ) | |
| with col2: | |
| module['module_duration_sessions'] = st.number_input( | |
| "Sessions", | |
| min_value=1, | |
| value=module['module_duration_sessions'], | |
| key=f"module_duration_{module_idx}" | |
| ) | |
| # Display and edit module outcomes | |
| st.markdown("#### Module Learning Outcomes") | |
| for outcome_idx, outcome in enumerate(module['module_learning_outcomes']): | |
| col1, col2, col3 = st.columns([6, 2, 1]) | |
| with col1: | |
| outcome['outcome_description'] = st.text_area( | |
| f"MLO{module_idx+1}.{outcome_idx+1}", | |
| value=outcome['outcome_description'], | |
| key=f"mlo_{module_idx}_{outcome_idx}", | |
| height=100 | |
| ) | |
| with col2: | |
| outcome['aligned_blooms_taxonomy_level'] = st.selectbox( | |
| "Bloom's Level", | |
| ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], | |
| index=["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"].index(outcome['aligned_blooms_taxonomy_level']), | |
| key=f"module_bloom_{module_idx}_{outcome_idx}" | |
| ) | |
| with col3: | |
| if st.button("🗑️", key=f"delete_mlo_{module_idx}_{outcome_idx}"): | |
| module['module_learning_outcomes'].pop(outcome_idx) | |
| st.rerun() | |
| # Add new module outcome | |
| with st.form(f"add_module_outcome_{module_idx}"): | |
| new_outcome = st.text_area("New Module Outcome", placeholder="Enter new module outcome...") | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| bloom_level = st.selectbox( | |
| "Bloom's Taxonomy Level", | |
| ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], | |
| key=f"new_module_bloom_{module_idx}" | |
| ) | |
| with col2: | |
| if st.form_submit_button("Add Outcome", use_container_width=True): | |
| if new_outcome: | |
| module['module_learning_outcomes'].append({ | |
| "outcome_number": f"MLO{module_idx+1}.{len(module['module_learning_outcomes'])+1}", | |
| "outcome_description": new_outcome, | |
| "aligned_blooms_taxonomy_level": bloom_level | |
| }) | |
| st.rerun() | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.button("⬅️ Back to Course Outcomes", use_container_width=True): | |
| st.session_state.current_step = 2 | |
| st.rerun() | |
| with col2: | |
| if st.button("Generate Submodule Outcomes ➡️", use_container_width=True): | |
| with st.spinner("Generating submodule outcomes..."): | |
| try: | |
| submodule_outcomes = generate_submodule_outcomes( | |
| st.session_state.course_details['name'], | |
| json.dumps(st.session_state.course_outcomes), | |
| json.dumps(st.session_state.module_outcomes), | |
| st.session_state.course_details['duration'], | |
| st.session_state.course_details['sessions_per_week'] | |
| ) | |
| st.session_state.submodule_outcomes = json.loads(submodule_outcomes) | |
| st.session_state.current_step = 4 | |
| st.rerun() | |
| except Exception as e: | |
| st.error(f"Error generating submodule outcomes: {e}") | |
| # Step 4: Submodule Outcomes Validation | |
| elif st.session_state.current_step == 4: | |
| st.subheader("Step 4: Submodule Learning Outcomes (SMLOs)") | |
| try: | |
| submodule_outcomes = st.session_state.get('submodule_outcomes', None) | |
| if submodule_outcomes is None: | |
| st.error("Submodule outcomes are not set in the session state.") | |
| elif 'modules' not in submodule_outcomes: | |
| st.error("The 'modules' key is missing in submodule outcomes.") | |
| else: | |
| print("No problem here") | |
| except Exception as e: | |
| st.error(f"Error accessing submodule outcomes: {e}") | |
| for module_idx, module in enumerate(st.session_state.module_outcomes['modules']): | |
| st.markdown(f"### Module {module_idx + 1}: {module['module_title']}") | |
| if module_idx < len(st.session_state.submodule_outcomes['modules']): | |
| for submodule_idx, submodule in enumerate(st.session_state.submodule_outcomes['modules'][module_idx]['submodules']): | |
| with st.expander(f"Submodule {module_idx + 1}.{submodule_idx + 1}: {submodule['submodule_title']}", expanded=True): | |
| # Edit submodule title and duration | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| submodule['submodule_title'] = st.text_input( | |
| "Submodule Title", | |
| value=submodule['submodule_title'], | |
| key=f"submodule_title_{module_idx}_{submodule_idx}" | |
| ) | |
| with col2: | |
| submodule['submodule_duration_sessions'] = st.number_input( | |
| "Sessions", | |
| min_value=1, | |
| value=submodule['submodule_duration_sessions'], | |
| key=f"submodule_duration_{module_idx}_{submodule_idx}" | |
| ) | |
| # Display and edit submodule outcomes | |
| st.markdown("#### Submodule Learning Outcomes") | |
| for outcome_idx, outcome in enumerate(submodule['submodule_learning_outcomes']): | |
| col1, col2, col3 = st.columns([6, 2, 1]) | |
| with col1: | |
| outcome['outcome_description'] = st.text_area( | |
| f"SMLO{module_idx+1}.{submodule_idx+1}.{outcome_idx+1}", | |
| value=outcome['outcome_description'], | |
| key=f"smlo_{module_idx}_{submodule_idx}_{outcome_idx}", | |
| height=100 | |
| ) | |
| with col2: | |
| outcome['aligned_blooms_taxonomy_level'] = st.selectbox( | |
| "Bloom's Level", | |
| ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], | |
| index=["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"].index(outcome['aligned_blooms_taxonomy_level']), | |
| key=f"submodule_bloom_{module_idx}_{submodule_idx}_{outcome_idx}" | |
| ) | |
| with col3: | |
| if st.button("🗑️", key=f"delete_smlo_{module_idx}_{submodule_idx}_{outcome_idx}"): | |
| submodule['submodule_learning_outcomes'].pop(outcome_idx) | |
| st.rerun() | |
| # Add new submodule outcome | |
| with st.form(f"add_submodule_outcome_{module_idx}_{submodule_idx}"): | |
| new_outcome = st.text_area("New Submodule Outcome", placeholder="Enter new submodule outcome...") | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| bloom_level = st.selectbox( | |
| "Bloom's Taxonomy Level", | |
| ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], | |
| key=f"new_submodule_bloom_{module_idx}_{submodule_idx}" | |
| ) | |
| with col2: | |
| if st.form_submit_button("Add Outcome", use_container_width=True): | |
| if new_outcome: | |
| submodule['submodule_learning_outcomes'].append({ | |
| "outcome_number": f"SMLO{module_idx+1}.{submodule_idx+1}.{len(submodule['submodule_learning_outcomes'])+1}", | |
| "outcome_description": new_outcome, | |
| "aligned_blooms_taxonomy_level": bloom_level | |
| }) | |
| st.rerun() | |
| # Navigation buttons | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.button("⬅️ Back to Module Outcomes", use_container_width=True): | |
| st.session_state.current_step = 3 | |
| st.rerun() | |
| with col2: | |
| if st.button("Proceed to Sessions Generation ➡️", use_container_width=True): | |
| # Validate total sessions distribution | |
| total_sessions = st.session_state.course_details['duration'] * st.session_state.course_details['sessions_per_week'] | |
| # current_sessions = sum( | |
| # sum(submodule['submodule_duration_sessions'] | |
| # for submodule in module['submodules']) | |
| # for module in st.session_state.module_outcomes['modules'] | |
| # ) | |
| current_sessions = sum( | |
| sum(submodule['submodule_duration_sessions'] | |
| for submodule in st.session_state.submodule_outcomes['modules'][module_idx]['submodules']) | |
| for module_idx in range(len(st.session_state.submodule_outcomes['modules']))) | |
| if current_sessions != total_sessions: | |
| st.error(f""" | |
| Session distribution mismatch! | |
| Total available sessions: {total_sessions} | |
| Currently allocated sessions: {current_sessions} | |
| Please adjust the session distribution in modules and submodules. | |
| """) | |
| else: | |
| try: | |
| # Merge all outcomes into final structure | |
| final_course_structure = { | |
| "course_title": st.session_state.course_outcomes['course_title'], | |
| "course_description": st.session_state.course_outcomes['course_description'], | |
| "learning_outcomes": st.session_state.course_outcomes['learning_outcomes'], | |
| "modules": st.session_state.module_outcomes['modules'] | |
| } | |
| # Store in session state for next step | |
| st.session_state.final_course_structure = final_course_structure | |
| st.session_state.current_step = 5 # Move to resources generation | |
| st.rerun() | |
| except Exception as e: | |
| st.error(f"Error finalizing course structure: {e}") | |
| # Add helper text about session distribution | |
| total_sessions = st.session_state.course_details['duration'] * st.session_state.course_details['sessions_per_week'] | |
| # current_sessions = sum( | |
| # sum(submodule['submodule_duration_sessions'] | |
| # for submodule in module['submodules']) | |
| # for module in st.session_state.module_outcomes['modules'] | |
| # ) | |
| current_sessions = sum( | |
| sum(submodule['submodule_duration_sessions'] | |
| for submodule in st.session_state.submodule_outcomes['modules'][module_idx]['submodules']) | |
| for module_idx in range(len(st.session_state.submodule_outcomes['modules']))) | |
| st.info(f""" | |
| Session Distribution: | |
| - Total available sessions: {total_sessions} | |
| - Currently allocated sessions: {current_sessions} | |
| - Remaining sessions: {total_sessions - current_sessions} | |
| """) | |
| # Step 4: Session Outcomes Generation | |
| elif st.session_state.current_step == 5: | |
| st.subheader("Step 5: Session Learning Outcomes (SLOs)") | |
| # Calculate total sessions for validation | |
| total_sessions = st.session_state.course_details['duration'] * st.session_state.course_details['sessions_per_week'] | |
| try: | |
| # Generate session outcomes if not already generated | |
| if 'session_outcomes' not in st.session_state: | |
| with st.spinner("Generating session outcomes..."): | |
| session_outcomes = generate_session_outcomes( | |
| st.session_state.course_details['name'], | |
| json.dumps(st.session_state.course_outcomes), | |
| json.dumps(st.session_state.module_outcomes), | |
| json.dumps(st.session_state.submodule_outcomes), | |
| st.session_state.course_details['duration'], | |
| st.session_state.course_details['sessions_per_week'] | |
| ) | |
| st.session_state.session_outcomes = json.loads(session_outcomes) | |
| # Warning about final edits | |
| st.warning(""" | |
| ⚠️ **Important Notice**: You cannot edit the Session Details after this step. Please ensure all the Session Details are correct. | |
| """) | |
| # Display and edit session outcomes for each submodule | |
| # for module_idx, module in enumerate(st.session_state.submodule_outcomes['modules']): | |
| # st.markdown(f"### Module {module_idx + 1}: {module['module_title']}") | |
| # for submodule_idx, submodule in enumerate(module['submodules']): | |
| # with st.expander(f"Submodule {module_idx + 1}.{submodule_idx + 1}: {submodule['submodule_title']}", expanded=True): | |
| # st.markdown(f"#### Sessions ({submodule['submodule_duration_sessions']} allocated)") | |
| # # Get sessions for this submodule | |
| # sessions = st.session_state.session_outcomes['submodules'][submodule_idx]['sessions'] | |
| # for session_idx, session in enumerate(sessions): | |
| # with st.expander(f"Session {session_idx + 1}: {session['session_title']}", expanded=True): | |
| # # Edit session details | |
| # session['session_title'] = st.text_input( | |
| # "Session Title", | |
| # value=session['session_title'], | |
| # key=f"session_title_{module_idx}_{submodule_idx}_{session_idx}" | |
| # ) | |
| # # Prerequisites | |
| # st.markdown("##### Prerequisites") | |
| # prereq_container = st.container() | |
| # for prereq_idx, prereq in enumerate(session['prerequisites']): | |
| # col1, col2 = prereq_container.columns([5, 1]) | |
| # with col1: | |
| # session['prerequisites'][prereq_idx] = st.text_input( | |
| # f"Prerequisite {prereq_idx + 1}", | |
| # value=prereq, | |
| # key=f"prereq_{module_idx}_{submodule_idx}_{session_idx}_{prereq_idx}" | |
| # ) | |
| # with col2: | |
| # if st.button("🗑️", key=f"del_prereq_{module_idx}_{submodule_idx}_{session_idx}_{prereq_idx}"): | |
| # session['prerequisites'].pop(prereq_idx) | |
| # st.rerun() | |
| # if st.button("Add Prerequisite", key=f"add_prereq_{module_idx}_{submodule_idx}_{session_idx}"): | |
| # session['prerequisites'].append("") | |
| # st.rerun() | |
| # # Key Concepts | |
| # st.markdown("##### Key Concepts") | |
| # concept_container = st.container() | |
| # for concept_idx, concept in enumerate(session['key_concepts']): | |
| # col1, col2 = concept_container.columns([5, 1]) | |
| # with col1: | |
| # session['key_concepts'][concept_idx] = st.text_input( | |
| # f"Concept {concept_idx + 1}", | |
| # value=concept, | |
| # key=f"concept_{module_idx}_{submodule_idx}_{session_idx}_{concept_idx}" | |
| # ) | |
| # with col2: | |
| # if st.button("🗑️", key=f"del_concept_{module_idx}_{submodule_idx}_{session_idx}_{concept_idx}"): | |
| # session['key_concepts'].pop(concept_idx) | |
| # st.rerun() | |
| # if st.button("Add Concept", key=f"add_concept_{module_idx}_{submodule_idx}_{session_idx}"): | |
| # session['key_concepts'].append("") | |
| # st.rerun() | |
| # # Session Learning Outcomes | |
| # st.markdown("##### Session Learning Outcomes") | |
| # for outcome_idx, outcome in enumerate(session['session_learning_outcomes']): | |
| # col1, col2, col3, col4 = st.columns([4, 2, 2, 1]) | |
| # with col1: | |
| # outcome['outcome_description'] = st.text_area( | |
| # f"SLO{session_idx+1}.{outcome_idx+1}", | |
| # value=outcome['outcome_description'], | |
| # key=f"slo_{module_idx}_{submodule_idx}_{session_idx}_{outcome_idx}", | |
| # height=100 | |
| # ) | |
| # with col2: | |
| # outcome['bloom_taxonomy_level'] = st.selectbox( | |
| # "Bloom's Level", | |
| # ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], | |
| # index=["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"].index(outcome['bloom_taxonomy_level']), | |
| # key=f"slo_bloom_{module_idx}_{submodule_idx}_{session_idx}_{outcome_idx}" | |
| # ) | |
| # with col3: | |
| # outcome['aligned_smlo'] = st.selectbox( | |
| # "Aligned SMLO", | |
| # [f"SMLO{module_idx+1}.{submodule_idx+1}.{i+1}" for i in range(len(submodule['submodule_learning_outcomes']))], | |
| # index=0, | |
| # key=f"slo_align_{module_idx}_{submodule_idx}_{session_idx}_{outcome_idx}" | |
| # ) | |
| # with col4: | |
| # if st.button("🗑️", key=f"del_slo_{module_idx}_{submodule_idx}_{session_idx}_{outcome_idx}"): | |
| # session['session_learning_outcomes'].pop(outcome_idx) | |
| # st.rerun() | |
| # # Add new session outcome | |
| # with st.form(f"add_session_outcome_{module_idx}_{submodule_idx}_{session_idx}"): | |
| # new_outcome = st.text_area("New Session Outcome", placeholder="Enter new session outcome...") | |
| # col1, col2, col3 = st.columns([2, 2, 1]) | |
| # with col1: | |
| # bloom_level = st.selectbox( | |
| # "Bloom's Level", | |
| # ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], | |
| # key=f"new_slo_bloom_{module_idx}_{submodule_idx}_{session_idx}" | |
| # ) | |
| # with col2: | |
| # aligned_smlo = st.selectbox( | |
| # "Aligned SMLO", | |
| # [f"SMLO{module_idx+1}.{submodule_idx+1}.{i+1}" for i in range(len(submodule['submodule_learning_outcomes']))], | |
| # key=f"new_slo_align_{module_idx}_{submodule_idx}_{session_idx}" | |
| # ) | |
| # with col3: | |
| # if st.form_submit_button("Add Outcome"): | |
| # if new_outcome: | |
| # session['session_learning_outcomes'].append({ | |
| # "outcome_number": f"SLO{session_idx+1}.{len(session['session_learning_outcomes'])+1}", | |
| # "outcome_description": new_outcome, | |
| # "bloom_taxonomy_level": bloom_level, | |
| # "aligned_smlo": aligned_smlo | |
| # }) | |
| # st.rerun() | |
| for module_idx, module in enumerate(st.session_state.module_outcomes['modules']): | |
| st.markdown(f"### Module {module_idx + 1}: {module['module_title']}") | |
| # Ensure the module index exists in submodule_outcomes | |
| if module_idx < len(st.session_state.submodule_outcomes['modules']): | |
| for submodule_idx, submodule in enumerate(st.session_state.submodule_outcomes['modules'][module_idx]['submodules']): | |
| with st.container(): | |
| st.markdown(f"#### Submodule {module_idx + 1}.{submodule_idx + 1}: {submodule['submodule_title']}") | |
| st.markdown(f"**Sessions ({submodule['submodule_duration_sessions']} allocated)**") | |
| # Get sessions for this submodule | |
| sessions = st.session_state.session_outcomes['submodules'][submodule_idx]['sessions'] | |
| for session_idx, session in enumerate(sessions): | |
| with st.container(): | |
| st.markdown(f"**Session {session_idx + 1}: {session['session_title']}**") | |
| # Edit session details | |
| session['session_title'] = st.text_input( | |
| "Session Title", | |
| value=session['session_title'], | |
| key=f"session_title_{module_idx}_{submodule_idx}_{session_idx}" | |
| ) | |
| # Prerequisites | |
| st.markdown("##### Prerequisites") | |
| prereq_container = st.container() | |
| for prereq_idx, prereq in enumerate(session['prerequisites']): | |
| col1, col2 = prereq_container.columns([5, 1]) | |
| with col1: | |
| session['prerequisites'][prereq_idx] = st.text_input( | |
| f"Prerequisite {prereq_idx + 1}", | |
| value=prereq, | |
| key=f"prereq_{module_idx}_{submodule_idx}_{session_idx}_{prereq_idx}" | |
| ) | |
| with col2: | |
| if st.button("🗑️", key=f"del_prereq_{module_idx}_{submodule_idx}_{session_idx}_{prereq_idx}"): | |
| session['prerequisites'].pop(prereq_idx) | |
| st.rerun() | |
| if st.button("Add Prerequisite", key=f"add_prereq_{module_idx}_{submodule_idx}_{session_idx}"): | |
| session['prerequisites'].append("") | |
| st.rerun() | |
| # Key Concepts | |
| st.markdown("##### Key Concepts") | |
| concept_container = st.container() | |
| for concept_idx, concept in enumerate(session['key_concepts']): | |
| col1, col2 = concept_container.columns([5, 1]) | |
| with col1: | |
| session['key_concepts'][concept_idx] = st.text_input( | |
| f"Concept {concept_idx + 1}", | |
| value=concept, | |
| key=f"concept_{module_idx}_{submodule_idx}_{session_idx}_{concept_idx}" | |
| ) | |
| with col2: | |
| if st.button("🗑️", key=f"del_concept_{module_idx}_{submodule_idx}_{session_idx}_{concept_idx}"): | |
| session['key_concepts'].pop(concept_idx) | |
| st.rerun() | |
| if st.button("Add Concept", key=f"add_concept_{module_idx}_{submodule_idx}_{session_idx}"): | |
| session['key_concepts'].append("") | |
| st.rerun() | |
| # Session Learning Outcomes | |
| st.markdown("##### Session Learning Outcomes") | |
| for outcome_idx, outcome in enumerate(session['session_learning_outcomes']): | |
| col1, col2, col3, col4 = st.columns([4, 2, 2, 1]) | |
| with col1: | |
| outcome['outcome_description'] = st.text_area( | |
| f"SLO{session_idx+1}.{outcome_idx+1}", | |
| value=outcome['outcome_description'], | |
| key=f"slo_{module_idx}_{submodule_idx}_{session_idx}_{outcome_idx}", | |
| height=100 | |
| ) | |
| with col2: | |
| outcome['bloom_taxonomy_level'] = st.selectbox( | |
| "Bloom's Level", | |
| ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], | |
| index=["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"].index(outcome['bloom_taxonomy_level']), | |
| key=f"slo_bloom_{module_idx}_{submodule_idx}_{session_idx}_{outcome_idx}" | |
| ) | |
| with col3: | |
| outcome['aligned_smlo'] = st.selectbox( | |
| "Aligned SMLO", | |
| [f"SMLO{module_idx+1}.{submodule_idx+1}.{i+1}" for i in range(len(submodule['submodule_learning_outcomes']))], | |
| index=0, | |
| key=f"slo_align_{module_idx}_{submodule_idx}_{session_idx}_{outcome_idx}" | |
| ) | |
| with col4: | |
| if st.button("🗑️", key=f"del_slo_{module_idx}_{submodule_idx}_{session_idx}_{outcome_idx}"): | |
| session['session_learning_outcomes'].pop(outcome_idx) | |
| st.rerun() | |
| # Add new session outcome | |
| with st.form(f"add_session_outcome_{module_idx}_{submodule_idx}_{session_idx}"): | |
| new_outcome = st.text_area("New Session Outcome", placeholder="Enter new session outcome...") | |
| col1, col2, col3 = st.columns([2, 2, 1]) | |
| with col1: | |
| bloom_level = st.selectbox( | |
| "Bloom's Level", | |
| ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], | |
| key=f"new_slo_bloom_{module_idx}_{submodule_idx}_{session_idx}" | |
| ) | |
| with col2: | |
| aligned_smlo = st.selectbox( | |
| "Aligned SMLO", | |
| [f"SMLO{module_idx+1}.{submodule_idx+1}.{i+1}" for i in range(len(submodule['submodule_learning_outcomes']))], | |
| key=f"new_slo_align_{module_idx}_{submodule_idx}_{session_idx}" | |
| ) | |
| with col3: | |
| if st.form_submit_button("Add Outcome"): | |
| if new_outcome: | |
| session['session_learning_outcomes'].append({ | |
| "outcome_number": f"SLO{session_idx+1}.{len(session['session_learning_outcomes'])+1}", | |
| "outcome_description": new_outcome, | |
| "bloom_taxonomy_level": bloom_level, | |
| "aligned_smlo": aligned_smlo | |
| }) | |
| st.rerun() | |
| # Navigation buttons | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.button("⬅️ Back to Submodule Outcomes", use_container_width=True): | |
| st.session_state.current_step = 3 | |
| st.rerun() | |
| with col2: | |
| if st.button("Generate Session Resources ➡️", use_container_width=True): | |
| # Merge all structures before moving to resources | |
| final_structure = merge_course_structure( | |
| st.session_state.course_outcomes, | |
| st.session_state.module_outcomes, | |
| st.session_state.submodule_outcomes, | |
| st.session_state.session_outcomes | |
| ) | |
| st.session_state.final_structure = final_structure | |
| st.session_state.current_step = 6 | |
| st.rerun() | |
| except Exception as e: | |
| st.error(f"Error accessing session outcomes: {e}") | |
| # Step 5: Resources Generation and Final Save | |
| elif st.session_state.current_step == 6: | |
| st.subheader("Step 5: Course Resources") | |
| try: | |
| if 'generated_resources' not in st.session_state: | |
| with st.spinner("Generating course resources..."): | |
| # Extract all session titles | |
| session_titles = [] | |
| for module in st.session_state.final_structure['modules']: | |
| for submodule in module['submodules']: | |
| for session in submodule['sessions']: | |
| session_titles.append(session['session_title']) | |
| resources = generate_resources_by_titles_chunking(session_titles, st.session_state.final_structure['course_title']) | |
| # Load sample resources from JSON file: | |
| # with open("sample_files/session_resources.json", "r") as file: | |
| # resources = json.load(file) | |
| # Debug print | |
| st.write("Type of resources:", type(resources)) | |
| st.write("Resources content:", resources) | |
| st.session_state.generated_resources = resources | |
| # Display Course Reference Books | |
| st.markdown("### 📚 Course Reference Books") | |
| for book in st.session_state.generated_resources['course_reference_books']: | |
| with st.container(): | |
| st.markdown(f""" | |
| **{book['title']}** | |
| *by {book['author']}* | |
| Publisher: {book['publisher']}, {book['year']} | |
| {book['description']} | |
| """) | |
| # Display Session Resources | |
| st.markdown("### 📖 Session Resources") | |
| for session_resource in st.session_state.generated_resources['session_resources']: | |
| with st.expander(f"Session: {session_resource['session_title']}", expanded=False): | |
| # Readings | |
| readings = session_resource['resources'].get('readings', []) | |
| videos = session_resource['resources'].get('videos', []) | |
| # Separate readings and videos | |
| filtered_readings = [] | |
| for reading in readings: | |
| if reading['type'].lower() == 'video': | |
| videos.append(reading) | |
| else: | |
| filtered_readings.append(reading) | |
| # Display filtered readings | |
| if filtered_readings: | |
| st.markdown("#### 📚 Required Readings") | |
| for reading in filtered_readings: | |
| st.markdown(f""" | |
| - **{reading['title']}** | |
| - Type: {reading['type']} | |
| - Estimated reading time: {reading['estimated_read_time']} | |
| - [Access Resource]({reading['url']}) | |
| """) | |
| # Display videos | |
| if videos: | |
| st.markdown("#### 🎥 Video Resources") | |
| for video in videos: | |
| st.markdown(f""" | |
| - **{video['title']}** | |
| - Type: {video['type']} | |
| - Duration: {video.get('duration', 'N/A')} | |
| - [Watch Video]({video['url']}) | |
| """) | |
| all_sessions = [] | |
| start_date = st.session_state.course_details['start_date'] | |
| sessions_per_week = st.session_state.course_details['sessions_per_week'] | |
| for module in st.session_state.final_structure['modules']: | |
| for submodule in module['submodules']: | |
| for session_idx, session in enumerate(submodule['sessions']): | |
| days_per_session = 7 / sessions_per_week | |
| print(days_per_session) | |
| session_date = start_date + timedelta(days=session_idx * days_per_session) | |
| # get external resources for this session | |
| external_resources = st.session_state.generated_resources['session_resources'][session_idx]['resources'] | |
| session_datetime = datetime.combine(session_date, datetime.min.time()) | |
| session_doc = { | |
| "session_id": str(ObjectId()), | |
| "title": session['session_title'], | |
| "session_learning_outcomes": session['session_learning_outcomes'], | |
| "date": session_datetime, | |
| "status": "Scheduled", | |
| "module_name": module['module_title'], | |
| "submodule_name": submodule['submodule_title'], | |
| "created_at": datetime.utcnow(), | |
| "pre_class": { | |
| "resources": [], | |
| "completion_required": True | |
| }, | |
| "in_class": { | |
| "quiz": [], | |
| "polls": [] | |
| }, | |
| "post_class": { | |
| "assignments": [] | |
| }, | |
| "external_resources": external_resources | |
| } | |
| all_sessions.append(session_doc) | |
| # Display 1st two sessions | |
| print(all_sessions[:2]) | |
| new_course_id = get_new_course_id() | |
| course_title = st.session_state.final_structure['course_title'] | |
| # if st.button("Save Course", type="primary", use_container_width=True): | |
| # try: | |
| # course_doc = { | |
| # "course_id": new_course_id, | |
| # "title": course_title, | |
| # "description": st.session_state.course_plan['course_description'], | |
| # "faculty": faculty_name, | |
| # "faculty_id": faculty_id, | |
| # "duration": f"{st.session_state.duration_weeks} weeks", | |
| # "sessions_per_week": st.session_state.sessions_per_week, | |
| # "start_date": datetime.combine(st.session_state.start_date, datetime.min.time()), | |
| # "created_at": datetime.utcnow(), | |
| # "sessions": all_sessions | |
| # } | |
| # # Insert into database | |
| # courses_collection.insert_one(course_doc) | |
| # st.success("Course successfully created!") | |
| # # Update faculty collection | |
| # faculty_collection.update_one( | |
| # {"_id": st.session_state.user_id}, | |
| # { | |
| # "$push": { | |
| # "courses_taught": { | |
| # "course_id": new_course_id, | |
| # "title": course_title, | |
| # } | |
| # } | |
| # } | |
| # ) | |
| # # Clear session state | |
| # st.session_state.course_plan = None | |
| # st.session_state.edit_mode = False | |
| # st.session_state.resources_map = {} | |
| # # Optional: Add a button to view the created course | |
| # if st.button("View Course"): | |
| # # Add navigation logic here | |
| # pass | |
| # except Exception as e: | |
| # st.error(f"Error saving course: {e}") | |
| # Final Save Button | |
| if st.button("Save Course", type="primary", use_container_width=True): | |
| try: | |
| # Create final course document | |
| course_doc = { | |
| "course_id": new_course_id, | |
| "title": st.session_state.final_structure['course_title'], | |
| "description": st.session_state.final_structure['course_description'], | |
| "course_outcomes": st.session_state.final_structure['learning_outcomes'], | |
| "faculty": st.session_state.course_details['faculty'], | |
| "faculty_id": faculty_id, | |
| "duration": f"{st.session_state.course_details['duration']} weeks", | |
| "sessions_per_week": st.session_state.course_details['sessions_per_week'], | |
| "start_date": datetime.combine(st.session_state.course_details['start_date'], datetime.min.time()), | |
| "created_at": datetime.utcnow(), | |
| "sessions": all_sessions, | |
| "full_course_structure": st.session_state.final_structure | |
| } | |
| # Insert into database | |
| courses_collection.insert_one(course_doc) | |
| # Update faculty collection | |
| faculty_collection.update_one( | |
| {"_id": st.session_state.user_id}, | |
| { | |
| "$push": { | |
| "courses_taught": { | |
| "course_id": new_course_id, | |
| "title": course_title, | |
| } | |
| } | |
| } | |
| ) | |
| # Show success message | |
| st.success("🎉 Course successfully created! You can now access it from your dashboard.") | |
| # Clear session state | |
| for key in ['course_details', 'course_outcomes', 'module_outcomes', | |
| 'submodule_outcomes', 'session_outcomes', 'final_structure', | |
| 'generated_resources', 'current_step']: | |
| if key in st.session_state: | |
| del st.session_state[key] | |
| except Exception as e: | |
| st.error(f"Error saving course: {e}") | |
| # Back button | |
| if st.button("⬅️ Back to Session Outcomes", use_container_width=True): | |
| st.session_state.current_step = 4 | |
| st.rerun() | |
| except Exception as e: | |
| st.error(f"Error in resource generation: {e}") | |
| from research_assistant_dashboard import display_research_assistant_dashboard | |
| from goals2 import display_analyst_dashboard | |
| def enroll_in_course(course_id, course_title, student): | |
| """Enroll a student in a course""" | |
| if student: | |
| courses = student.get("enrolled_courses", []) | |
| if course_id not in [course["course_id"] for course in courses]: | |
| course = courses_collection.find_one({"course_id": course_id}) | |
| if course: | |
| courses.append( | |
| { | |
| "course_id": course["course_id"], | |
| "title": course["title"], | |
| } | |
| ) | |
| students_collection.update_one( | |
| {"_id": st.session_state.user_id}, | |
| {"$set": {"enrolled_courses": courses}}, | |
| ) | |
| st.success(f"Enrolled in course {course_title}") | |
| # st.experimental_rerun() | |
| else: | |
| st.error("Course not found") | |
| else: | |
| st.warning("Already enrolled in this course") | |
| # def enroll_in_course_page(course_id): | |
| # """Enroll a student in a course""" | |
| # student = students_collection.find_one({"_id": st.session_state.user_id}) | |
| # course_title = courses_collection.find_one({"course_id": course_id})["title"] | |
| # course = courses_collection.find_one({"course_id": course_id}) | |
| # if course: | |
| # st.title(course["title"]) | |
| # st.subheader("Course Description:") | |
| # st.write(course["description"]) | |
| # st.write(f"Faculty: {course['faculty']}") | |
| # st.write(f"Duration: {course['duration']}") | |
| # st.title("Course Sessions") | |
| # for session in course["sessions"]: | |
| # st.write(f"Session: {session['title']}") | |
| # st.write(f"Date: {session['date']}") | |
| # st.write(f"Status: {session['status']}") | |
| # st.write("----") | |
| # else: | |
| # st.error("Course not found") | |
| # enroll_button = st.button("Enroll in Course", key="enroll_button", use_container_width=True) | |
| # if enroll_button: | |
| # enroll_in_course(course_id, course_title, student) | |
| def enroll_in_course_page(course_id): | |
| """Display an aesthetically pleasing course enrollment page""" | |
| student = students_collection.find_one({"_id": st.session_state.user_id}) | |
| course = courses_collection.find_one({"course_id": course_id}) | |
| if not course: | |
| st.error("Course not found") | |
| return | |
| # Create two columns for layout | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| # Course header section | |
| st.title(course["title"]) | |
| st.markdown(f"*{course['description']}*") | |
| # Course details in an expander | |
| with st.expander("Course Details", expanded=True): | |
| st.markdown(f"👨🏫 **Faculty:** {course['faculty']}") | |
| st.markdown(f"⏱️ **Duration:** {course['duration']}") | |
| # Sessions in a clean card-like format | |
| st.subheader("📚 Course Sessions") | |
| for idx, session in enumerate(course["sessions"], 1): | |
| with st.container(): | |
| st.markdown(f""" | |
| --- | |
| ### Session {idx}: {session['title']} | |
| 🗓️ **Date:** {session['date']} | |
| 📌 **Status:** {session['status']} | |
| """) | |
| with col2: | |
| with st.container(): | |
| st.markdown("### Ready to Learn?") | |
| st.markdown("Click below to enroll in this course") | |
| # Check if already enrolled | |
| courses = student.get("enrolled_courses", []) | |
| is_enrolled = course_id in [c["course_id"] for c in courses] | |
| if is_enrolled: | |
| st.info("✅ You are already enrolled in this course") | |
| else: | |
| enroll_button = st.button( | |
| "🎓 Enroll Now", | |
| key="enroll_button", | |
| use_container_width=True | |
| ) | |
| if enroll_button: | |
| enroll_in_course(course_id, course["title"], student) | |
| def show_available_courses(username, user_type, user_id): | |
| """Display available courses for enrollment""" | |
| st.title("Available Courses") | |
| courses = list(courses_collection.find({}, {"course_id": 1, "title": 1})) | |
| course_options = [ | |
| f"{course['title']} ({course['course_id']})" for course in courses | |
| ] | |
| selected_course = st.selectbox("Select a Course to Enroll", course_options) | |
| # if selected_courses: | |
| # for course in selected_courses: | |
| # course_id = course.split("(")[-1][:-1] | |
| # course_title = course.split(" (")[0] | |
| # enroll_in_course(course_id, course_title, user_id) | |
| # st.success("Courses enrolled successfully!") | |
| if selected_course: | |
| course_id = selected_course.split("(")[-1][:-1] | |
| enroll_in_course_page(course_id) | |
| def validate_email(email): | |
| """Validate email format and domain""" | |
| # Basic email pattern | |
| pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' | |
| if not re.match(pattern, email): | |
| return False, "Invalid email format" | |
| # You can add additional institution-specific validation here | |
| # For example, checking if the domain is from your institution | |
| # allowed_domains = ["spit.ac.in"] # Add more domains as needed | |
| # domain = email.split('@')[1] | |
| # if domain not in allowed_domains: | |
| # return False, "Please use your institutional email address" | |
| return True, "Valid email" | |
| def validate_phone(phone): | |
| """Validate phone number format""" | |
| # Assuming Indian phone numbers | |
| pattern = r'^[6-9]\d{9}$' | |
| if not re.match(pattern, phone): | |
| return False, "Invalid phone number format. Please enter a 10-digit Indian mobile number" | |
| return True, "Valid phone number" | |
| def extract_username(email): | |
| """Extract username from email""" | |
| return email.split('@')[0] | |
| def main_dashboard(): | |
| if st.session_state.user_type == "research_assistant": | |
| display_research_assistant_dashboard() | |
| elif st.session_state.user_type == "analyst": | |
| display_analyst_dashboard() | |
| else: | |
| selected_course_id = None | |
| create_session = False | |
| with st.sidebar: | |
| st.title(f"Welcome, {st.session_state.username}") | |
| if st.session_state.user_type == "student": | |
| st.title("Enrolled Courses") | |
| else: | |
| st.title("Your Courses") | |
| # Course selection | |
| enrolled_courses = get_courses( | |
| st.session_state.username, st.session_state.user_type | |
| ) | |
| # Enroll in Courses | |
| if st.session_state.user_type == "student": | |
| if st.button( | |
| "Enroll in a New Course", key="enroll_course", use_container_width=True | |
| ): | |
| st.session_state.show_enroll_course_page = True | |
| # if st.session_state.show_enroll_course_form: | |
| # courses = list(courses_collection.find({}, {"course_id": 1, "title": 1})) | |
| # course_options = [f"{course['title']} ({course['course_id']})" for course in courses] | |
| # course_to_enroll = st.selectbox("Available Courses", course_options) | |
| # st.session_state.course_to_enroll = course_to_enroll | |
| if st.session_state.user_type == "faculty": | |
| if st.button( | |
| "Create New Course", key="create_course", use_container_width=True | |
| ): | |
| st.session_state.show_create_course_form = True | |
| if not enrolled_courses: | |
| st.warning("No courses found") | |
| else: | |
| course_titles = [course["title"] for course in enrolled_courses] | |
| course_ids = [course["course_id"] for course in enrolled_courses] | |
| selected_course = st.selectbox("Select Course", course_titles) | |
| selected_course_id = course_ids[course_titles.index(selected_course)] | |
| print("Selected Course ID: ", selected_course_id) | |
| st.session_state.selected_course = selected_course | |
| st.session_state.selected_course_id = selected_course_id | |
| # Display course sessions | |
| sessions = get_sessions(selected_course_id, selected_course) | |
| st.title("Course Sessions") | |
| for i, session in enumerate(sessions, start=1): | |
| if st.button( | |
| f"Session {i}", key=f"session_{i}", use_container_width=True | |
| ): | |
| st.session_state.selected_session = session | |
| if st.session_state.user_type == "faculty": | |
| # Create new session | |
| # create_session = st.button("Create New Session Button", key="create_session", use_container_width=True) | |
| if st.button( | |
| "Create New Session", | |
| key="create_session", | |
| use_container_width=True, | |
| ): | |
| st.session_state.show_create_session_form = True | |
| if st.button("Logout", use_container_width=True): | |
| for key in st.session_state.keys(): | |
| del st.session_state[key] | |
| st.rerun() | |
| # if create_session: | |
| # create_session_form(selected_course_id) | |
| if st.session_state.get("show_create_course_form"): | |
| create_course_form(st.session_state.username, st.session_state.user_id) | |
| elif st.session_state.get("show_create_session_form"): | |
| create_session_form(selected_course_id) | |
| elif st.session_state.get("show_enroll_course_page"): | |
| show_available_courses(st.session_state.username, st.session_state.user_type, st.session_state.user_id) | |
| else: | |
| # Main content | |
| if "selected_session" in st.session_state: | |
| display_session_content( | |
| st.session_state.user_id, | |
| selected_course_id, | |
| st.session_state.selected_session, | |
| st.session_state.username, | |
| st.session_state.user_type, | |
| ) | |
| else: | |
| st.info("Select a session to view details") | |
| # # Main content | |
| # if 'selected_session' in st.session_state: | |
| # display_session_content(st.session_state.user_id, selected_course_id, st.session_state.selected_session, st.session_state.username, st.session_state.user_type) | |
| # if create_session: | |
| # create_session_form(selected_course_id) | |
| def main(): | |
| st.set_page_config(page_title="NOVAScholar", page_icon="📚", layout="wide") | |
| init_session_state() | |
| # modify_courses_collection_schema() | |
| if not st.session_state.authenticated: | |
| login_tab, register_tab = st.tabs(["Login", "Register"]) | |
| with register_tab: | |
| register_page() | |
| with login_tab: | |
| login_form() | |
| else: | |
| main_dashboard() | |
| if __name__ == "__main__": | |
| main() | |