This commit is contained in:
leart-ramushi 2026-05-21 21:59:57 +02:00
parent ee38227d34
commit 57ba9eaf0b
3 changed files with 107 additions and 96 deletions

View File

@ -1,49 +1,23 @@
import os
from pathlib import Path from pathlib import Path
class FileManager: class FileManager:
""" """
Verwaltet das Laden, Speichern und Auflisten von Code-Dateien inklusive Ordnerstruktur [1] Handles file reading and writing
""" """
def __init__(self, root_path="."): def __init__(self, root_path="."):
self.root_path = Path(root_path).resolve() self.root_path = Path(root_path).resolve()
def list_files(self, current_path=None):
"""
Gibt eine verschachtelte Struktur zurück, um Ordner und Dateien darzustellen [1]
"""
if current_path is None:
current_path = self.root_path
elif not isinstance(current_path, Path):
current_path = Path(current_path)
items = []
try:
for item in current_path.iterdir():
if item.is_dir():
items.append({"type": "folder", "name": item.name, "path": str(item)})
elif item.is_file() and item.suffix in {'.py', '.js', '.html', '.css', '.md'}:
items.append({"type": "file", "name": item.name, "path": str(item)})
except PermissionError:
pass
return items
def read_file(self, file_path): def read_file(self, file_path):
"""
Liest und gibt den Inhalt einer Datei zurück [1]
"""
try: try:
with open(file_path, 'r', encoding='utf-8') as f: with open(file_path, "r", encoding="utf-8") as f:
return f.read() return f.read()
except Exception as e: except Exception:
return None return ""
def save_file(self, file_path, content): def save_file(self, file_path, content):
"""
Schreibt Inhalt in eine Datei [1]
"""
try: try:
with open(file_path, 'w', encoding='utf-8') as f: with open(file_path, "w", encoding="utf-8") as f:
f.write(content) f.write(content)
return True return True
except Exception: except Exception:

View File

@ -1,21 +1,45 @@
import sys import sys
import os import os
project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) from pathlib import Path
import streamlit as st
from streamlit_tree_select import tree_select
# project path fix
project_root = os.path.abspath(os.path.dirname(__file__))
if project_root not in sys.path: if project_root not in sys.path:
sys.path.insert(0, project_root) sys.path.insert(0, project_root)
import streamlit as st # backend
from backend.file_manager import FileManager
from ui.navigation import FileNavigation
# Backend-Imports # your existing modules (keep yours as-is)
from src.backend.file_manager import FileManager from backend.chat_manager import ChatManager
from src.backend.chat_manager import ChatManager from backend.execution_engine import ExecutionEngine
from src.backend.execution_engine import ExecutionEngine from ui.editor import CodeEditor
from ui.chat import ChatInterface
from ui.output import OutputDisplay
def render_sidebar():
st.sidebar.title("📁 File Explorer")
navigation = FileNavigation()
tree_data = navigation.build_tree()
with st.sidebar:
selection = tree_select(
tree_data,
check_model="leaf",
only_leaf_checkboxes=True
)
if selection and selection.get("checked"):
return selection["checked"][0]
return None
# UI-Imports
from src.ui.navigation import FileNavigation
from src.ui.editor import CodeEditor
from src.ui.chat import ChatInterface
from src.ui.output import OutputDisplay
def main(): def main():
st.set_page_config( st.set_page_config(
@ -24,49 +48,49 @@ def main():
layout="wide" layout="wide"
) )
# Initialisiere Manager-Klassen
file_manager = FileManager() file_manager = FileManager()
chat_manager = ChatManager() chat_manager = ChatManager()
execution_engine = ExecutionEngine() execution_engine = ExecutionEngine()
if "selected_file" not in st.session_state: if "selected_file" not in st.session_state:
st.session_state.selected_file = None st.session_state.selected_file = None
if "file_history" not in st.session_state:
st.session_state.file_history = []
# Sidebar für Dateinavigation # --- SIDEBAR ---
st.sidebar.title("📁 Datei-Explorer") selected_file = render_sidebar()
st.sidebar.subheader("Wähle eine Datei aus")
navigation = FileNavigation() if selected_file:
file_list = navigation.list_files() st.session_state.selected_file = selected_file
if file_list:
selected_file = st.sidebar.selectbox("Dateien", file_list)
if selected_file:
content = file_manager.read_file(selected_file)
st.session_state.selected_file = selected_file
col1, col2 = st.columns([3, 2])
with col1:
editor = CodeEditor()
editor.display_code(content)
if st.button("💾 Speichern"):
file_manager.save_file(selected_file, content)
st.success("Datei gespeichert!")
with col2:
chat = ChatInterface()
chat.display_chat(chat_manager)
output = OutputDisplay()
output.display_execution(execution_engine)
st.sidebar.markdown("---") st.sidebar.markdown("---")
st.sidebar.caption("AISE501 AI in Software Engineering") st.sidebar.caption("AISE501 AI in Software Engineering")
# --- MAIN AREA ---
if st.session_state.selected_file:
content = file_manager.read_file(st.session_state.selected_file)
col1, col2 = st.columns([3, 2])
with col1:
st.subheader(f"Editing: {Path(st.session_state.selected_file).name}")
editor = CodeEditor()
editor.display_code(content)
if st.button("💾 Save"):
file_manager.save_file(st.session_state.selected_file, content)
st.success("File saved!")
with col2:
chat = ChatInterface()
chat.display_chat(chat_manager)
output = OutputDisplay()
output.display_execution(execution_engine)
else:
st.info("Select a file from the sidebar explorer 👈")
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -1,30 +1,43 @@
import os
from pathlib import Path from pathlib import Path
class FileNavigation: class FileNavigation:
""" """
Navigation für die Dateiauswahl in der Sidebar [1] Builds a VS Code-like file tree for streamlit_tree_select
""" """
def __init__(self): def __init__(self):
self.supported_extensions = {'.py', '.js', '.html', '.css', '.json', '.md'} self.supported_extensions = {'.py', '.js', '.html', '.css', '.json', '.md'}
def list_files(self, path=None): def build_tree(self, path=None):
"""
Listet alle Code-Dateien im aktuellen Verzeichnis auf [1]
"""
if path is None: if path is None:
path = Path.cwd() path = Path.cwd()
file_list = [] path = Path(path)
for root, dirs, files in os.walk(path):
for file in files: def build_node(current_path: Path):
if os.path.splitext(file)[1] in self.supported_extensions: is_dir = current_path.is_dir()
file_list.append(file)
return sorted(file_list) node = {
"label": ("📁 " if is_dir else "📄 ") + current_path.name,
def get_full_path(self, filename): "value": str(current_path),
""" }
Gibt den vollständigen Pfad der Datei zurück
""" if is_dir:
return Path(filename) children = []
try:
for item in sorted(
current_path.iterdir(),
key=lambda x: (not x.is_dir(), x.name.lower())
):
if item.is_dir() or item.suffix in self.supported_extensions:
children.append(build_node(item))
except PermissionError:
pass
node["children"] = children
return node
# IMPORTANT: must return a LIST
return [build_node(path)]