Untitled

mail@pastecode.io avatar
unknown
python
5 days ago
9.3 kB
1
Indexable
Never
import os
import json
import streamlit as st
import reveal_slides as rs  # Import the reveal_slides module


class SlideComponent:
    def __init__(self, content: str, config: dict, initial_state: dict):
        self.content = content
        self.config = config
        self.initial_state = initial_state

    def render(self):
        return rs.slides(
            self.content,
            # height=self.config.get('height', 600),
            height=self.config.get('height', '100%'),
            theme=self.config.get('theme', 'black'),
            config=self.config,
            initial_state=self.initial_state,
            markdown_props={"data-separator-vertical": "^--$"},
            key=f"slides_{self.config.get('base_font_size', 24)}_{self.config.get('heading_scale', 1.5)}"
        )


class LessonPresenter:
    def __init__(self, content: dict):
        self.content = content
        self.set_subject_content(None)
        self.callback_func = None  # Callback function placeholder

    def set_subject_content(self, subject: str):
        if subject is None:
            self.subject = {"subject": "Unknown", "lessons": []}
            return

        for s in self.content.get("subjects", []):
            if s.get("subject", "").lower() == subject.lower():
                self.subject = s
                return
        print(f"Warning: Subject '{subject}' not found in JSON data")
        self.subject = {"subject": "Unknown", "lessons": []}

    def json_to_slides(self) -> str:
        subject_name = self.subject.get('subject', 'Unknown Subject')
        slides = f"# Subject Matter: {subject_name}\nPresentation By ClassPilot\n---\n"
        
        for lesson in self.subject.get("lessons", []):
            slides += f"## {lesson.get('title', 'Untitled Lesson')}\n---\n"
            for page in lesson.get("pages", []):
                slides += f"\n### {page.get('title', 'Untitled Page')}\n"
                for subtitle in page.get("subtitles", []):
                    slides += f"#### {subtitle}\n"
                slides += f"{page.get('content', '')}\n---\n"
        
        if not self.subject.get("lessons"):
            slides += "## No lessons available for this subject\n---\n"
        
        slides += "# End\n## Good Luck!"
        return slides

    def update_page(self, selected_lesson: str, selected_page: str, new_title: str, new_subtitles: str, new_content: str) -> bool:
        lesson_data = next((l for l in self.subject.get("lessons", []) if l["title"] == selected_lesson), None)
        if lesson_data:
            page_data = next((p for p in lesson_data.get("pages", []) if p["title"] == selected_page), None)
            if page_data:
                page_data["title"] = new_title
                page_data["subtitles"] = new_subtitles.split("\n")
                page_data["content"] = new_content
                
                # Save the updated content
                if self.save_content():
                    # Call the callback function if provided
                    if self.callback_func:
                        self.callback_func(self.content)
                    return True
        return False

    def set_callback_func(self, func):
        self.callback_func = func

    def create_slide_component(self, content: str, config: dict, initial_state: dict):
        full_content = self.generate_custom_css(config.get('base_font_size', 24), config.get('heading_scale', 1.5)) + content
        return SlideComponent(full_content, config, initial_state)

    def generate_custom_css(self, base_font_size: int, heading_scale: float) -> str:
        return f"""
        <style>
        .reveal .slides section {{
            height: 100%;
            overflow-y: auto !important;
            overflow-x: hidden !important;
        }}
        .reveal {{
            height: 100% !important;
            font-size: {base_font_size}px !important;
        }}
        .reveal .slides {{
            height: 100% !important;
        }}
        .reveal h1 {{ font-size: {base_font_size * heading_scale}px !important; }}
        .reveal h2 {{ font-size: {base_font_size * (heading_scale * 0.9)}px !important; }}
        .reveal h3 {{ font-size: {base_font_size * (heading_scale * 0.8)}px !important; }}
        .reveal p, .reveal li {{ font-size: {base_font_size}px !important; }}
        .reveal .slides section {{ color: #f0f0f0 !important; }}
        .reveal pre {{
            box-shadow: none !important;
            background-color: rgba(0,0,0,0.3) !important;
            margin: 15px 0 !important;
            padding: 10px !important;
            border-radius: 5px !important;
        }}
        .reveal pre code {{
            max-height: 400px !important;
            font-size: {base_font_size * 0.7}px !important;
            line-height: 1.3em !important;
            padding: 0 !important;
        }}
        .hljs {{ background: transparent !important; }}
        .reveal.white pre, .reveal.beige pre {{ background-color: rgba(0,0,0,0.05) !important; }}
        .reveal.white pre code, .reveal.beige pre code {{ color: #333 !important; }}
        .reveal.black pre, .reveal.league pre, .reveal.night pre {{ background-color: rgba(255,255,255,0.1) !important; }}
        .reveal.black pre code, .reveal.league pre code, .reveal.night pre code {{ color: #f0f0f0 !important; }}
        </style>
        """
    def save_content(self):
        current_dir = os.path.dirname(os.path.abspath(__file__))
        json_path = os.path.join(current_dir, '..', '..', 'utils', 'data', 'lesson_plans.json')
        json_path = os.path.normpath(json_path)
        
        try:
            with open(json_path, 'w') as f:
                json.dump(self.content, f, indent=2)
            print("Content saved successfully")
            return True
        except Exception as e:
            print(f"Error saving content: {str(e)}")
            return False

def load_content():
    current_dir = os.path.dirname(os.path.abspath(__file__))
    json_path = os.path.join(current_dir, '..', '..', 'utils', 'data', 'lesson_plans.json')
    json_path = os.path.normpath(json_path)

    try:
        with open(json_path, 'r') as f:
            content = json.load(f)
        print("JSON file loaded successfully")
    except FileNotFoundError:
        print(f"Error: Could not find the file at {json_path}")
        content = {"subjects": []}
    except json.JSONDecodeError:
        print(f"Error: The file at {json_path} is not a valid JSON file")
        content = {"subjects": []}

    return content


def create_editor_screen(presenter: LessonPresenter):
    st.title("Lesson Presentation System")

    subjects = [s["subject"] for s in presenter.content["subjects"]]
    selected_subject = st.sidebar.selectbox("Select Subject", subjects)
    presenter.set_subject_content(selected_subject)

    with st.expander("Edit Page Content", expanded=False):
        lessons = [l["title"] for l in presenter.subject.get("lessons", [])]
        selected_lesson = st.selectbox("Select Lesson", lessons)
        selected_lesson_data = next((l for l in presenter.subject.get("lessons", []) if l["title"] == selected_lesson), None)

        if selected_lesson_data:
            pages = [p["title"] for p in selected_lesson_data.get("pages", [])]
            selected_page = st.selectbox("Select Page", pages)
            selected_page_data = next((p for p in selected_lesson_data.get("pages", []) if p["title"] == selected_page), None)

            if selected_page_data:
                new_title = st.text_input("Edit Page Title", selected_page_data["title"])
                new_subtitles = st.text_area("Edit Subtitles (one per line)", "\n".join(selected_page_data.get("subtitles", [])))
                new_content = st.text_area("Edit Page Content", selected_page_data["content"], height=300)
                
                if st.button("Update Page"):
                    if presenter.update_page(selected_lesson, selected_page, new_title, new_subtitles, new_content):
                        st.success("Page updated and saved successfully!")
                        st.rerun()
                    else:
                        st.error("Failed to update and save page. Please check your input.")

    st.sidebar.header("Slide Design")
    config = {
        "base_font_size": st.sidebar.number_input("Base Font Size (px)", value=24, min_value=10, max_value=50, step=1),
        "heading_scale": st.sidebar.slider("Heading Scale", min_value=1.0, max_value=3.0, value=1.5, step=0.1),
        "theme": st.sidebar.selectbox("Theme", ["black", "white", "league", "beige", "sky", "night", "serif", "simple", "solarized"], index=0),
        "height": st.sidebar.number_input("Container Height", value=600, step=50),
        "scrollable": True,
    }

    slides_component = presenter.create_slide_component(presenter.json_to_slides(), config, initial_state={})
    slides_component.render()

def main():
    content = load_content()
    presenter = LessonPresenter(content)

    create_editor_screen(presenter)


if __name__ == "__main__":
    main()

Leave a Comment