From 232ab85cc7e5a36c2396f82b4d577e916c6a895b Mon Sep 17 00:00:00 2001 From: Martin Tranberg Date: Wed, 1 Apr 2026 08:43:33 +0200 Subject: [PATCH] feat: add StartGuideDialog for initial Azure configuration and conditional MSAL initialization --- sharepoint_browser.py | 116 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 2 deletions(-) diff --git a/sharepoint_browser.py b/sharepoint_browser.py index ea61047..7619439 100644 --- a/sharepoint_browser.py +++ b/sharepoint_browser.py @@ -437,6 +437,104 @@ class SettingsDialog(wx.Dialog): def on_cancel(self, event): self.EndModal(wx.ID_CANCEL) +class StartGuideDialog(wx.Dialog): + def __init__(self, parent, current_settings): + lang = current_settings.get("language", "da") + title = "Velkommen til SharePoint Explorer" if lang == "da" else "Welcome to SharePoint Explorer" + super().__init__(parent, title=title, size=(600, 650)) + + self.settings = current_settings.copy() + self.lang = lang + self.InitUI() + self.Center() + + def InitUI(self): + panel = wx.Panel(self) + vbox = wx.BoxSizer(wx.VERTICAL) + + # Titel + title_lbl = wx.StaticText(panel, label="Opsætning af SharePoint Explorer" if self.lang == "da" else "SharePoint Explorer Setup") + title_font = title_lbl.GetFont() + title_font.MakeBold() + title_font.SetPointSize(14) + title_lbl.SetFont(title_font) + vbox.Add(title_lbl, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 15) + + # Guide tekst + guide_text_da = ( + "For at programmet kan forbinde til din Microsoft 365, skal du oprette en App Registrering i Azure Portal.\n\n" + "Følg disse trin:\n" + "1. Gå til portal.azure.com og log ind med din administrator konto.\n" + "2. Søg efter 'App registrations' og klik på 'New registration'.\n" + "3. Giv den et navn (f.eks. 'SharePoint Explorer') og vælg 'Accounts in any organizational directory' (eller 'Accounts in this organizational directory only' hvis det kun er internt).\n" + "4. Vælg 'Public client/native (mobile & desktop)' under Redirect URI og skriv:\n https://login.microsoftonline.com/common/oauth2/nativeclient\n" + "5. Klik 'Register'.\n\n" + "Giv tilladelser (API permissions):\n" + "1. Klik på 'API permissions' i menuen til venstre.\n" + "2. Klik 'Add a permission' -> 'Microsoft Graph' -> 'Delegated permissions'.\n" + "3. Tilføj følgende: Files.ReadWrite.All, Sites.Read.All, og User.Read.\n" + "4. Husk at klikke 'Grant admin consent' hvis nødvendigt.\n" + "5. Under 'Authentication' i menuen til venstre, sørg for at 'Allow public client flows' er aktiveret (slået til) i bunden af siden.\n\n" + "Kopier nu disse to værdier fra 'Overview' siden og sæt ind herunder:" + ) + guide_ctrl = wx.TextCtrl(panel, value=guide_text_da, style=wx.TE_MULTILINE | wx.TE_READONLY | wx.BORDER_NONE) + guide_ctrl.SetBackgroundColour(panel.GetBackgroundColour()) + font = guide_ctrl.GetFont() + font.SetPointSize(10) + guide_ctrl.SetFont(font) + vbox.Add(guide_ctrl, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 20) + + # Input felter + grid = wx.FlexGridSizer(2, 2, 10, 10) + grid.AddGrowableCol(1, 1) + + lbl_client = wx.StaticText(panel, label="App (Client) ID:") + self.client_id_ctrl = wx.TextCtrl(panel, value="") + grid.Add(lbl_client, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5) + grid.Add(self.client_id_ctrl, 1, wx.EXPAND) + + lbl_tenant = wx.StaticText(panel, label="Directory (Tenant) ID:") + self.tenant_id_ctrl = wx.TextCtrl(panel, value="") + grid.Add(lbl_tenant, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 5) + grid.Add(self.tenant_id_ctrl, 1, wx.EXPAND) + + vbox.Add(grid, 0, wx.EXPAND | wx.ALL, 20) + + # Gem/Annuller + btn_box = wx.BoxSizer(wx.HORIZONTAL) + save_btn = wx.Button(panel, label="Gem Indstillinger" if self.lang == "da" else "Save Settings", size=(150, 40)) + save_btn.SetBackgroundColour(wx.Colour(0, 120, 215)) + save_btn.SetForegroundColour(wx.WHITE) + save_btn.Bind(wx.EVT_BUTTON, self.on_save) + + cancel_btn = wx.Button(panel, label="Afslut" if self.lang == "da" else "Exit", size=(100, 40)) + cancel_btn.Bind(wx.EVT_BUTTON, self.on_cancel) + + btn_box.Add(save_btn, 0, wx.RIGHT, 10) + btn_box.Add(cancel_btn, 0) + + vbox.Add(btn_box, 0, wx.ALIGN_RIGHT | wx.ALL, 15) + + panel.SetSizer(vbox) + + def on_save(self, event): + cid = self.client_id_ctrl.GetValue().strip() + tid = self.tenant_id_ctrl.GetValue().strip() + + if not cid or not tid: + wx.MessageBox("Begge felter skal udfyldes for at fortsætte." if self.lang == "da" else "Both fields are required.", "Fejl", wx.OK | wx.ICON_ERROR) + return + + self.settings["client_id"] = cid + self.settings["tenant_id"] = tid + + save_settings(self.settings) + wx.MessageBox("Nye indstillinger gemt. Programmet genstarter for at anvende de nye ID'er." if self.lang == "da" else "Settings saved. App will restart.", "Succes", wx.OK | wx.ICON_INFORMATION) + self.EndModal(wx.ID_OK) + + def on_cancel(self, event): + self.EndModal(wx.ID_CANCEL) + class SharePointApp(wx.Frame): def __init__(self): self.lang = CURRENT_LANG @@ -483,7 +581,12 @@ class SharePointApp(wx.Frame): # Threading/Sync til filredigering # MSAL Cache - self.msal_app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY) + self.msal_app = None + if is_configured(settings): + try: + self.msal_app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY) + except Exception as e: + print(f"MSAL Init Error: {e}") self.InitUI() self.Centre() @@ -497,7 +600,16 @@ class SharePointApp(wx.Frame): # Start indlæsning (Check for konfiguration) if not is_configured(settings): - wx.CallAfter(self.on_settings_clicked, None) + wx.CallAfter(self.show_start_guide) + + def show_start_guide(self): + dlg = StartGuideDialog(self, settings) + if dlg.ShowModal() == wx.ID_OK: + import sys + os.execl(sys.executable, sys.executable, *sys.argv) + else: + self.Close() + dlg.Destroy() def get_txt(self, key, **kwargs): text = STRINGS[self.lang].get(key, key) if kwargs: