import os import json import streamlit as st import streamlit.components.v1 as components from streamlit_javascript import st_javascript # pip install streamlit-javascript SETTINGS_FILE = "settings.json" # --- Helper functions for persistence --- def load_settings(): if os.path.exists(SETTINGS_FILE): with open(SETTINGS_FILE, "r") as f: return json.load(f) else: # Create a default settings structure default = { "decks": [ { "name": "Deck 1", "columns": [ { "id": 1, "title": "Column 1", "size": "medium", "order": "latest", "advanced_search": False }, { "id": 2, "title": "Column 2", "size": "medium", "order": "top", "advanced_search": False }, { "id": 3, "title": "Column 3", "size": "medium", "order": "latest", "advanced_search": False } ] } ] } save_settings(default) return default def save_settings(settings): with open(SETTINGS_FILE, "w") as f: json.dump(settings, f, indent=2) def get_new_column_id(deck): # Return a new id that is 1 higher than the max id in the deck’s columns if deck["columns"]: return max(col["id"] for col in deck["columns"]) + 1 else: return 1 # --- Initialize session state --- if "settings" not in st.session_state: st.session_state.settings = load_settings() if "current_deck_index" not in st.session_state: st.session_state.current_deck_index = 0 def update_order(new_order): # new_order is expected to be a list of column IDs (as numbers) deck = st.session_state.settings["decks"][st.session_state.current_deck_index] # Build a dictionary mapping id -> column col_dict = {col["id"]: col for col in deck["columns"]} # Reorder based on new_order list new_cols = [] for cid in new_order: # Make sure the id exists if cid in col_dict: new_cols.append(col_dict[cid]) deck["columns"] = new_cols save_settings(st.session_state.settings) st.success("Column order saved.") def edit_column(deck_index, col_index, new_props): st.session_state.settings["decks"][deck_index]["columns"][col_index].update(new_props) save_settings(st.session_state.settings) def delete_column(deck_index, col_index): del st.session_state.settings["decks"][deck_index]["columns"][col_index] save_settings(st.session_state.settings) def add_column(deck_index, title): deck = st.session_state.settings["decks"][deck_index] new_id = get_new_column_id(deck) new_col = { "id": new_id, "title": title, "size": "medium", "order": "latest", "advanced_search": False } deck["columns"].append(new_col) save_settings(st.session_state.settings) # --- Sidebar: Deck selection and management --- st.sidebar.title("Decks Sidebar") decks = [deck["name"] for deck in st.session_state.settings["decks"]] selected_deck_name = st.sidebar.selectbox("Select a Deck", decks, index=st.session_state.current_deck_index) # Update current deck index based on selection st.session_state.current_deck_index = decks.index(selected_deck_name) # Allow adding a new deck with st.sidebar.expander("Manage Decks"): new_deck_name = st.text_input("New deck name", key="new_deck_name") if st.button("Add Deck"): new_deck = {"name": new_deck_name or f"Deck {len(decks)+1}", "columns": []} st.session_state.settings["decks"].append(new_deck) save_settings(st.session_state.settings) st.experimental_rerun() st.markdown("[Change Display Settings](#)") st.markdown("[Discover Keyboard Shortcuts](#)") st.markdown("[Take the Tour Again](#)") # --- Main area: Display columns with drag-and-drop --- current_deck = st.session_state.settings["decks"][st.session_state.current_deck_index] st.header(f"Columns in {current_deck['name']}") # Build HTML for the draggable column list. # Each li includes a data-id (the column id) and displays its title. # On drag end, we update a global JS variable window.currentOrder. html_code = f"""