change UI, Filetree
This commit is contained in:
parent
3ce4ef970b
commit
b7bbd63bb3
@ -22,19 +22,15 @@ def main():
|
|||||||
|
|
||||||
init_state()
|
init_state()
|
||||||
|
|
||||||
left, right = st.columns([1, 3])
|
render_sidebar()
|
||||||
|
|
||||||
with left:
|
show_editor = st.session_state.get("show_Editor", False)
|
||||||
choice = render_sidebar()
|
show_chat = st.session_state.get("show_Chat", False)
|
||||||
|
|
||||||
with right:
|
if show_editor:
|
||||||
if "Chat with AI Assistant" in choice:
|
|
||||||
render_chat()
|
|
||||||
if "Code Editor" in choice:
|
|
||||||
render_editor()
|
render_editor()
|
||||||
#elif choice == "File Explorer":
|
if show_chat:
|
||||||
# st.subheader("File Explorer")
|
render_chat()
|
||||||
# st.info("File Explorer functionality is not implemented yet.")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@ -43,15 +43,19 @@ def render_editor():
|
|||||||
if not st.session_state.open_files:
|
if not st.session_state.open_files:
|
||||||
st.info("Please select a file to edit.")
|
st.info("Please select a file to edit.")
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
fm = FileManager()
|
fm = FileManager()
|
||||||
|
|
||||||
|
try:
|
||||||
|
active_index = st.session_state.open_files.index(st.session_state.active_file)
|
||||||
|
except (ValueError, KeyError):
|
||||||
|
active_index = 0
|
||||||
|
|
||||||
tab_names = [Path(f).name for f in st.session_state.open_files]
|
tab_names = [Path(f).name for f in st.session_state.open_files]
|
||||||
tabs = st.tabs(tab_names)
|
tabs = st.tabs(tab_names)
|
||||||
|
|
||||||
for idx, file_path in enumerate(st.session_state.open_files):
|
for idx, file_path in enumerate(st.session_state.open_files):
|
||||||
with tabs[idx]:
|
with tabs[idx]:
|
||||||
st.session_state.active_file = file_path
|
|
||||||
|
|
||||||
if file_path not in st.session_state.files_content:
|
if file_path not in st.session_state.files_content:
|
||||||
st.session_state.files_content[file_path] = fm.read_file(Path(file_path))
|
st.session_state.files_content[file_path] = fm.read_file(Path(file_path))
|
||||||
@ -65,13 +69,14 @@ def render_editor():
|
|||||||
key=f"code_editor_{file_path}",
|
key=f"code_editor_{file_path}",
|
||||||
auto_update=True,
|
auto_update=True,
|
||||||
height=400,
|
height=400,
|
||||||
tab_size=4,
|
# tab_size=4,
|
||||||
font_size=14,
|
# font_size=14,
|
||||||
show_gutter=True,
|
# show_gutter=True,
|
||||||
show_print_margin=False,
|
# show_print_margin=False,
|
||||||
wrap=True
|
# wrap=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if code != st.session_state.files_content[file_path]:
|
||||||
st.session_state.files_content[file_path] = code
|
st.session_state.files_content[file_path] = code
|
||||||
|
|
||||||
cols = st.columns([1, 1, 1, 1])
|
cols = st.columns([1, 1, 1, 1])
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import streamlit as st
|
import streamlit as st
|
||||||
|
from streamlit_arborist import tree_view
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from backend.managers.file_manager import FileManager
|
from backend.managers.file_manager import FileManager
|
||||||
|
|
||||||
@ -23,98 +24,45 @@ SUFFIX_MAP = {
|
|||||||
"default": "📄" # Unbekannt
|
"default": "📄" # Unbekannt
|
||||||
}
|
}
|
||||||
|
|
||||||
def render_filetree(tree, parent_path=Path()):
|
def build_arborist_tree(tree, parent_path=Path()):
|
||||||
|
nodes = []
|
||||||
|
|
||||||
for name, content in sorted(tree.items()):
|
for name, content in sorted(tree.items()):
|
||||||
full_path = parent_path / name
|
full_path = parent_path / name
|
||||||
|
node_id = str(full_path.as_posix())
|
||||||
|
|
||||||
if isinstance(content, dict): # Directory
|
if isinstance(content, dict):
|
||||||
disp_name = name if len(name) <= 13 else (name[:10] + "...")
|
nodes.append({
|
||||||
|
"id": node_id,
|
||||||
with st.expander(f"📁 {disp_name}", expanded=False):
|
"name": f"{name}",
|
||||||
render_filetree(content, full_path)
|
"children": build_arborist_tree(content, full_path)
|
||||||
with st.popover("+", key=f"popover_{full_path}"):
|
})
|
||||||
st.write(f"**Create in {name}**")
|
else:
|
||||||
action = st.radio("Action", ["New File", "New Folder"], key=f"radio_{full_path}", label_visibility="collapsed")
|
|
||||||
new_name = st.text_input("Name", key=f"input_{full_path}")
|
|
||||||
|
|
||||||
if st.button("Create", key=f"btn_{full_path}"):
|
|
||||||
if "/" in new_name or "\\" in new_name:
|
|
||||||
st.warning("Do not include slashes in names!")
|
|
||||||
elif new_name and action == "New Folder":
|
|
||||||
fm.create_folder(str(full_path), new_name)
|
|
||||||
st.success(f"Folder {new_name} created!")
|
|
||||||
st.rerun()
|
|
||||||
elif new_name and action == "New File":
|
|
||||||
fm.create_file(str(full_path), new_name)
|
|
||||||
st.success(f"File {new_name} created!")
|
|
||||||
st.rerun()
|
|
||||||
|
|
||||||
else: # File
|
|
||||||
suffix = Path(name).suffix
|
suffix = Path(name).suffix
|
||||||
icon = SUFFIX_MAP.get(suffix, SUFFIX_MAP["default"])
|
icon = SUFFIX_MAP.get(suffix, SUFFIX_MAP["default"])
|
||||||
disp_name = name if len(name) <= 13 else (name[:10] + "...")
|
|
||||||
|
|
||||||
col_file, col_opt = st.columns([0.85, 0.15], gap="small")
|
nodes.append({
|
||||||
|
"id": node_id,
|
||||||
|
"name": f"{icon} {name}",
|
||||||
|
"key": f"key_{node_id}"
|
||||||
|
})
|
||||||
|
|
||||||
with col_file:
|
return nodes
|
||||||
if st.button(f"{icon} {disp_name}", key=str(full_path)):
|
|
||||||
abs_path = fm.base_path / full_path
|
|
||||||
|
|
||||||
if str(abs_path) not in st.session_state.open_files:
|
def render_filetree_arborist(tree):
|
||||||
st.session_state.open_files.append(str(abs_path))
|
data = build_arborist_tree(tree)
|
||||||
|
|
||||||
st.session_state.active_file = str(abs_path)
|
selected = tree_view(
|
||||||
st.rerun()
|
data=data,
|
||||||
|
icons={"open": "📂", "closed": "📁"},
|
||||||
|
height=200,
|
||||||
|
selection=None,
|
||||||
|
select_internal_nodes=True,
|
||||||
|
open_by_default=False
|
||||||
|
)
|
||||||
|
|
||||||
with col_opt:
|
return selected
|
||||||
with st.popover("⋮", key=f"opt_{full_path}"):
|
|
||||||
|
|
||||||
delete_key = f"confirm_delete_{full_path}"
|
|
||||||
if delete_key not in st.session_state:
|
|
||||||
st.session_state[delete_key] = False
|
|
||||||
|
|
||||||
if st.button(" **Delete** 🗑️", key=f"del_{full_path}"):
|
|
||||||
st.session_state[delete_key] = True
|
|
||||||
|
|
||||||
if st.session_state[delete_key]:
|
|
||||||
st.warning(f"Delete {name}?")
|
|
||||||
|
|
||||||
confirm_col, deny_col = st.columns([1, 1], gap="small")
|
|
||||||
with confirm_col:
|
|
||||||
if st.button("✔", key=f"yes_{full_path}"):
|
|
||||||
try:
|
|
||||||
fm.delete_file(str(full_path))
|
|
||||||
st.session_state[delete_key] = False
|
|
||||||
st.rerun()
|
|
||||||
except Exception as e:
|
|
||||||
st.error(f"Error deleting file: {e}")
|
|
||||||
with deny_col:
|
|
||||||
if st.button("✖", key=f"cancel_{full_path}"):
|
|
||||||
st.session_state[delete_key] = False
|
|
||||||
|
|
||||||
rename_key = f"rename_mode_{full_path}"
|
|
||||||
if rename_key not in st.session_state:
|
|
||||||
st.session_state[rename_key] = False
|
|
||||||
|
|
||||||
if st.button("**Rename** ✏️", key=f"ren_{full_path}"):
|
|
||||||
st.session_state[rename_key] = True
|
|
||||||
|
|
||||||
if st.session_state[rename_key]:
|
|
||||||
new_name = st.text_input("New Name", key=f"input_ren_{full_path}")
|
|
||||||
|
|
||||||
apply_col, cancel_col = st.columns([1, 1], gap="small")
|
|
||||||
with apply_col:
|
|
||||||
if st.button("Apply", key=f"apply_ren_{full_path}"):
|
|
||||||
try:
|
|
||||||
fm.rename_file(str(full_path), new_name)
|
|
||||||
st.session_state[rename_key] = False
|
|
||||||
st.rerun()
|
|
||||||
except Exception as e:
|
|
||||||
st.error(f"Error renaming file: {e}")
|
|
||||||
|
|
||||||
with cancel_col:
|
|
||||||
if st.button("Cancel", key=f"cancel_ren_{full_path}"):
|
|
||||||
st.session_state[rename_key] = False
|
|
||||||
|
|
||||||
def render_sidebar():
|
def render_sidebar():
|
||||||
st.sidebar.title("Navigation")
|
st.sidebar.title("Navigation")
|
||||||
@ -129,11 +77,69 @@ def render_sidebar():
|
|||||||
add_more = st.container()
|
add_more = st.container()
|
||||||
|
|
||||||
with workspace:
|
with workspace:
|
||||||
|
with st.container(border=False):
|
||||||
if not tree:
|
if not tree:
|
||||||
st.info("Workspace is empty.")
|
st.info("Workspace is empty.")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
render_filetree(tree)
|
selected = render_filetree_arborist(tree)
|
||||||
|
|
||||||
|
if selected:
|
||||||
|
selected_path = selected.get("id")
|
||||||
|
|
||||||
|
if st.session_state.last_selected != selected_path:
|
||||||
|
st.session_state.last_selected = selected_path
|
||||||
|
abs_path = fm.base_path / selected_path
|
||||||
|
|
||||||
|
if abs_path.is_file():
|
||||||
|
if str(abs_path) not in st.session_state.open_files:
|
||||||
|
st.session_state.open_files.append(str(abs_path))
|
||||||
|
|
||||||
|
st.session_state.active_file = str(abs_path)
|
||||||
|
st.rerun()
|
||||||
|
|
||||||
|
elif abs_path.is_dir():
|
||||||
|
st.session_state.selected_folder = str(abs_path)
|
||||||
|
selected_folder = st.session_state.selected_folder
|
||||||
|
with st.popover(
|
||||||
|
f"📁 {Path(selected_folder).name}",
|
||||||
|
use_container_width=True,
|
||||||
|
key=f"{selected_folder}_popover_options"):
|
||||||
|
action = st.radio(
|
||||||
|
"Action",
|
||||||
|
["New File", "New Folder"],
|
||||||
|
key=f"radio_folder_options",
|
||||||
|
label_visibility="collapsed")
|
||||||
|
|
||||||
|
new_name = st.text_input("Name", key=f"input_folder_options")
|
||||||
|
|
||||||
|
btn_cols = st.columns([1,1,1])
|
||||||
|
with btn_cols[0]:
|
||||||
|
if st.button("Create", key=f"btn_create_subfile_or_subfolder"):
|
||||||
|
if "/" in new_name or "\\" in new_name:
|
||||||
|
st.warning("Do not include slashes in names!")
|
||||||
|
elif new_name:
|
||||||
|
if action == "New Folder":
|
||||||
|
fm.create_folder(selected_path, new_name)
|
||||||
|
else:
|
||||||
|
fm.create_file(selected_path, new_name)
|
||||||
|
st.success(f"{action} created!")
|
||||||
|
st.session_state.selected_folder = None
|
||||||
|
st.rerun()
|
||||||
|
|
||||||
|
with btn_cols[1]:
|
||||||
|
if st.button("Cancel", key=f"cancel_folder_options"):
|
||||||
|
st.session_state.selected_folder = None
|
||||||
|
st.rerun()
|
||||||
|
|
||||||
|
with btn_cols[2]:
|
||||||
|
if st.button("Delete Folder", key=f"delete_folder"):
|
||||||
|
try:
|
||||||
|
fm.delete_folder(selected_path)
|
||||||
|
st.success(f"Folder '{Path(selected_folder).name}' deleted successfully!")
|
||||||
|
st.session_state.selected_folder = None
|
||||||
|
st.rerun()
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"Error deleting folder: {e}")
|
||||||
|
|
||||||
with add_more:
|
with add_more:
|
||||||
with st.popover("⚙️ Explorer_Options", key=f"popover_options"):
|
with st.popover("⚙️ Explorer_Options", key=f"popover_options"):
|
||||||
@ -160,13 +166,10 @@ def render_sidebar():
|
|||||||
|
|
||||||
with navigation_section:
|
with navigation_section:
|
||||||
st.sidebar.subheader("Options")
|
st.sidebar.subheader("Options")
|
||||||
options = ["Code Editor", "Chat with AI Assistant"]
|
st.sidebar.checkbox("Code Editor", key="show_Editor")
|
||||||
choice = []
|
st.sidebar.checkbox("Chat with AI Assistant", key="show_Chat")
|
||||||
|
|
||||||
for option in options:
|
return
|
||||||
if st.sidebar.checkbox(option):
|
|
||||||
choice.append(option)
|
|
||||||
return choice
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
render_sidebar()
|
render_sidebar()
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
import streamlit as st
|
import streamlit as st
|
||||||
|
|
||||||
def init_state():
|
def init_state():
|
||||||
# Sidebar state initialization
|
# Sidebar
|
||||||
|
if "last_selected" not in st.session_state:
|
||||||
|
st.session_state.last_selected = None
|
||||||
|
|
||||||
|
if "selected_folder" not in st.session_state:
|
||||||
|
st.session_state.selected_folder = None
|
||||||
|
|
||||||
# Editor state initialization
|
# Editor state initialization
|
||||||
if "open_files" not in st.session_state:
|
if "open_files" not in st.session_state:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user