import re from pymongo import MongoClient 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_alt import display_session_content 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_course 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 code_playground import display_code_playground 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({"$or": [{"full_name": username}, {"username": 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"] ) user_type = user_type.lower().replace(" ", "_") # 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({"$or": [{"full_name": username}, {"username": 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_collection.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_collection.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_collection.update_one( # {"course_id": course_id}, {"$push": {"sessions": new_session}} # ) # st.success("Session created successfully!") # st.session_state.show_create_session_form = 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 if "outcomes" not in st.session_state: st.session_state.outcomes = [] # List to store outcomes dynamically 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") st.subheader("Session Learning Outcomes") # Display all outcomes dynamically for idx, outcome in enumerate(st.session_state.outcomes): st.text_input(f"Outcome {idx + 1} Description", key=f"outcome_desc_{idx}") st.selectbox( f"Bloom's Taxonomy Level {idx + 1}", ["Remember", "Understand", "Apply", "Analyze", "Evaluate", "Create"], key=f"bloom_level_{idx}" ) # Button to add new outcome fields if st.form_submit_button("Add Outcome"): new_index = len(st.session_state.outcomes) st.session_state.outcomes.append( {"outcome_number": new_index + 1, "outcome_description": "", "bloom_taxanomy_level": ""} ) st.rerun() # Refresh the form to display new fields # Generate new session ID new_session_id = None course = courses_collection.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 # Submit session if st.form_submit_button("Create Session"): 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": []}, "session_learning_outcomes": [ { "outcome_number": idx + 1, "outcome_description": st.session_state[f"outcome_desc_{idx}"], "bloom_taxanomy_level": st.session_state[f"bloom_level_{idx}"] } for idx in range(len(st.session_state.outcomes)) ] } courses_collection.update_one({"course_id": course_id}, {"$push": {"sessions": new_session}}) st.success("Session created successfully!") st.session_state.outcomes = [] # Clear outcomes after submission st.session_state.show_create_session_form = False st.rerun() # 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: load_dotenv() MONGO_URI = os.getenv('MONGO_URI') client = MongoClient(MONGO_URI) db = client["novascholar_db"] subjective_tests_collection = db["subjective_tests"] resources_collection = db['resources'] quizzes_collection = db['quizzes'] chat_history_collection = db['chat_history'] polls_collection = db['polls'] def delete_session(course_id: str, session_id: str) -> bool: """Delete a session and all its associated data""" try: # Delete all resources for this session resources_collection.delete_many({ "course_id": course_id, "session_id": session_id }) # Delete all quizzes for this session quizzes_collection.delete_many({ "course_id": course_id, "session_id": session_id }) # Delete all subjective tests subjective_tests_collection.delete_many({ "course_id": course_id, "session_id": session_id }) # Delete chat history chat_history_collection.delete_many({ "course_id": course_id, "session_id": session_id }) # Delete session polls polls_collection.delete_many({ "course_id": course_id, "session_id": session_id }) # Finally remove session from course result = courses_collection.update_one( {"course_id": course_id}, {"$pull": {"sessions": {"session_id": session_id}}} ) return result.modified_count > 0 except Exception as e: print(f"Error deleting session: {e}") return False 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.lower().replace(" ", "_") 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") course_description = st.text_area("Course Description", placeholder="Enter a brief course description here") generate_button = st.form_submit_button("Generate Course Structure", use_container_width=True) if generate_button and course_name: create_course(course_name, duration_weeks, faculty_name, sessions_per_week, start_date, course_description, faculty_id) #update faculty list of courses # 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 # # 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}") 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})) # courses += list(courses_collection2.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("Delete a Session", key="delete_session", use_container_width=True): # session_id = st.text_input("Enter the Session ID to delete") st.session_state.show_delete_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) elif st.session_state.get("show_delete_session_form"): session_options = [f"{session['title']} (ID: {session['session_id']})" for session in sessions] session_id = st.selectbox("Select Session to Delete", session_options) session_id = session_id.split(" (ID: ")[-1][:-1] if st.button("Delete Session"): if delete_session(selected_course_id, session_id): st.success(f"Session {session_id} deleted successfully!") st.rerun() 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() st.info("Registrations are closed.") with login_tab: login_form() else: main_dashboard() if __name__ == "__main__": main()