diff --git a/requirements.txt b/requirements.txt index a1ae00e..bde7a63 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ requests msal +customtkinter diff --git a/sharepoint_gui.py b/sharepoint_gui.py new file mode 100644 index 0000000..eb05793 --- /dev/null +++ b/sharepoint_gui.py @@ -0,0 +1,145 @@ +import os +import threading +import logging +import customtkinter as ctk +from tkinter import filedialog, messagebox +import download_sharepoint # Importerer din eksisterende logik + +# --- Logging Handler for GUI --- +class TextboxHandler(logging.Handler): + def __init__(self, textbox): + super().__init__() + self.textbox = textbox + + def emit(self, record): + msg = self.format(record) + self.textbox.after(0, self.append_msg, msg) + + def append_msg(self, msg): + self.textbox.configure(state="normal") + self.textbox.insert("end", msg + "\n") + self.textbox.see("end") + self.textbox.configure(state="disabled") + +# --- Main App --- +class SharepointApp(ctk.CTk): + def __init__(self): + super().__init__() + + self.title("SharePoint Download Tool - UX") + self.geometry("900x750") + ctk.set_appearance_mode("dark") + ctk.set_default_color_theme("blue") + + # Layout + self.grid_columnconfigure(1, weight=1) + self.grid_rowconfigure(0, weight=1) + + # Sidebar for indstillinger + self.sidebar_frame = ctk.CTkFrame(self, width=350, corner_radius=0) + self.sidebar_frame.grid(row=0, column=0, sticky="nsew") + self.sidebar_frame.grid_rowconfigure(9, weight=1) + + self.logo_label = ctk.CTkLabel(self.sidebar_frame, text="Indstillinger", font=ctk.CTkFont(size=20, weight="bold")) + self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10)) + + # Input Felter + self.entries = {} + fields = [ + ("TENANT_ID", "Tenant ID"), + ("CLIENT_ID", "Client ID"), + ("CLIENT_SECRET", "Client Secret"), + ("SITE_URL", "Site URL"), + ("DOCUMENT_LIBRARY", "Library Navn"), + ("FOLDERS_TO_DOWNLOAD", "Mapper (komma-sep)"), + ("LOCAL_PATH", "Lokal Sti") + ] + + for i, (key, label) in enumerate(fields): + lbl = ctk.CTkLabel(self.sidebar_frame, text=label) + lbl.grid(row=i*2+1, column=0, padx=20, pady=(10, 0), sticky="w") + + entry = ctk.CTkEntry(self.sidebar_frame, width=280, placeholder_text=f"Indtast {label}") + if key == "CLIENT_SECRET": + entry.configure(show="*") + entry.grid(row=i*2+2, column=0, padx=20, pady=(0, 5)) + self.entries[key] = entry + + # Browse knap til lokal sti + self.browse_button = ctk.CTkButton(self.sidebar_frame, text="Vælg Mappe", command=self.browse_folder, height=32) + self.browse_button.grid(row=15, column=0, padx=20, pady=10) + + # Gem knap + self.save_button = ctk.CTkButton(self.sidebar_frame, text="Gem Indstillinger", command=self.save_settings, fg_color="transparent", border_width=2) + self.save_button.grid(row=16, column=0, padx=20, pady=10) + + # Højre side (Log og Status) + self.main_frame = ctk.CTkFrame(self, corner_radius=0, fg_color="transparent") + self.main_frame.grid(row=0, column=1, sticky="nsew", padx=20, pady=20) + self.main_frame.grid_rowconfigure(1, weight=1) + self.main_frame.grid_columnconfigure(0, weight=1) + + self.status_label = ctk.CTkLabel(self.main_frame, text="Status: Klar", font=ctk.CTkFont(size=16)) + self.status_label.grid(row=0, column=0, pady=(0, 10), sticky="w") + + self.log_textbox = ctk.CTkTextbox(self.main_frame, state="disabled") + self.log_textbox.grid(row=1, column=0, sticky="nsew") + + self.start_button = ctk.CTkButton(self.main_frame, text="Start Synkronisering", command=self.start_sync_thread, height=50, font=ctk.CTkFont(size=16, weight="bold")) + self.start_button.grid(row=2, column=0, pady=(20, 0), sticky="ew") + + # Initialisering + self.load_settings() + self.setup_logging() + + def setup_logging(self): + handler = TextboxHandler(self.log_textbox) + handler.setFormatter(logging.Formatter('%(asctime)s: %(message)s', datefmt='%H:%M:%S')) + download_sharepoint.logger.addHandler(handler) + + def browse_folder(self): + path = filedialog.askdirectory() + if path: + self.entries["LOCAL_PATH"].delete(0, "end") + self.entries["LOCAL_PATH"].insert(0, path) + + def load_settings(self): + if os.path.exists("connection_info.txt"): + config = download_sharepoint.load_config("connection_info.txt") + for key, entry in self.entries.items(): + val = config.get(key, "") + entry.insert(0, val) + + def save_settings(self): + config_lines = [] + for key, entry in self.entries.items(): + val = entry.get() + config_lines.append(f'{key} = "{val}"') + + with open("connection_info.txt", "w", encoding="utf-8") as f: + f.write("\n".join(config_lines)) + logger = logging.getLogger("sharepoint_gui") + # trigger a small log to show save happened + messagebox.showinfo("Succes", "Indstillinger er gemt i connection_info.txt") + + def start_sync_thread(self): + self.save_settings() + self.start_button.configure(state="disabled", text="Arbejder...") + self.status_label.configure(text="Status: Synkroniserer...", text_color="orange") + + thread = threading.Thread(target=self.run_sync, daemon=True) + thread.start() + + def run_sync(self): + try: + download_sharepoint.main() + self.status_label.configure(text="Status: Gennemført!", text_color="green") + except Exception as e: + self.status_label.configure(text=f"Status: Fejl!", text_color="red") + messagebox.showerror("Fejl", str(e)) + finally: + self.start_button.configure(state="normal", text="Start Synkronisering") + +if __name__ == "__main__": + app = SharepointApp() + app.mainloop()