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("
", unsafe_allow_html=True) # Add gap between sessions # # st.markdown(f"### 📖 {sub_module['title']}") # st.markdown(f'

📖 Chapter {sub_idx + 1}: {sub_module["title"]}

', 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("
", 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'

📚 Session Resources

', unsafe_allow_html=True) # # Readings Tab # if resources.get('readings'): # st.markdown(f'
📖 External Resources
', 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'
📚 Reference Books
', 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'
🔗 Additional Study Resources
', 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()