-
Notifications
You must be signed in to change notification settings - Fork 1
New feat: SAP packaging wizard #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # SAP Management | ||
|
|
||
| SwitchCraft provides specialized tools for managing SAP Installation Servers (`nwsetupadmin`). This tool automates common administrative tasks like merging updates, customizing the GUI appearance, and forcing browser preferences. | ||
|
|
||
| ## Key Features | ||
|
|
||
| - **Automated Update Merging**: Easily integrate SAP GUI patches and add-ons using the `/UpdateServer` command-line interface. | ||
| - **Logo Customization**: Automatically distribute custom company logos to all clients by integrated them into the installation server. | ||
| - **Edge WebView2 Enforcement**: Force the use of Edge WebView2 as the default browser engine for SAP GUI transactions by patching the `SapGuiSetup.xml` configuration. | ||
| - **Guided Multi-Step Wizard**: A specialized UI that walks you through the entire process from server selection to finalized packaging. | ||
|
|
||
| ## Usage Guide | ||
|
|
||
| ### 1. Select Installation Server | ||
| Point SwitchCraft to the root directory of your SAP Installation Server. The tool will look for `NwSapSetupAdmin.exe` in the `Setup` subfolder. | ||
|
|
||
| ### 2. Merge Updates | ||
| Select one or more SAP update executables. SwitchCraft will execute the merge process in the background, ensuring your server is up to date with the latest patches. | ||
|
|
||
| ### 3. Customization | ||
| - **Edge WebView2**: Check this option to ensure all clients use the modern WebView2 engine. | ||
| - **Custom Logo**: Select a `.png` file to be used as the branding logo in the SAP GUI. | ||
|
|
||
| ### 4. Finalize & Package | ||
| Once customized, you can trigger the creation of a **Single-File Installer (SFU)**. This creates a self-extracting executable that contains only the necessary components for a silent, standalone deployment. | ||
|
|
||
| ## Technical Details | ||
|
|
||
| The tool interacts with the SAP Setup infrastructure via: | ||
| - **CLI**: `NwSapSetupAdmin.exe` for server updates and SFU compression. | ||
| - **XML Patching**: Direct manipulation of `Setup\SapGuiSetup.xml` for specific preference overrides that are not exposed via standard CLI arguments. | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,23 @@ | ||||||
| # SAP Management Wizard | ||||||
|
|
||||||
| The **SAP Management Wizard** is a guided tool designed to simplify the lifecycle management of SAP Installation Servers. | ||||||
|
|
||||||
|  | ||||||
|
||||||
|  | |
|  |
🤖 Prompt for AI Agents
In `@docs/views/sap_wizard.md` at line 5, The markdown references a missing image
and uses the wrong VitePress path: replace the existing reference string "! [SAP
Wizard Screenshot](/docs/public/img/sap_wizard.png)" by adding the actual
sap_wizard.png into docs/public/img/ (or your chosen docs public asset folder)
and update the markdown to use the VitePress-served path "/img/sap_wizard.png"
(i.e., change the image link to ""); ensure the file name matches exactly
(sap_wizard.png) and commit both the image and the updated
docs/views/sap_wizard.md line.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1095,5 +1095,24 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "error_feature_demo_restricted": "Das Paketieren ist in der Web-Demo nicht verfügbar.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "error_wine_missing": "Wine wird benötigt, um das Paketierungs-Werkzeug unter Linux auszuführen. Bitte installiere Wine.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "demo_restriction_hint": "Die Funktion {feature}ist in der Web-Demo eingeschränkt. Für den vollen Funktionsumfang nutze bitte die Desktop-Version.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "wine_missing_hint": "Diese Funktion erfordert eine Wine-Installation auf deinem Linux-System." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "wine_missing_hint": "Diese Funktion erfordert eine Wine-Installation auf deinem Linux-System.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_wizard_title": "SAP Management Wizard", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_card_title": "SAP Management", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_card_desc": "SAP Install Server Werkzeug", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_step1_title": "1. SAP Installations-Server wählen", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_step1_desc": "Wähle den Stammordner deines SAP nwsetupadmin Servers aus.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_step2_title": "2. Updates & Add-ons hinzufügen (Optional)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_step2_desc": "Wähle .exe Dateien aus, die in den Installations-Server integriert werden sollen.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_step3_title": "3. Anpassung", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_step3_desc": "Konfiguriere Logo und Browser-Einstellungen.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_step4_title": "4. Zusammenfassung & Paketierung", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sap_use_webview2": "Edge WebView2 als Standard (Empfohlen)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "no_logo_selected": "Kein Logo ausgewählt", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "label_server": "Server", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "label_custom_logo": "Benutzerdefiniertes Logo", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "label_webview2": "Edge WebView2", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "btn_browse_folder": "Serverordner durchsuchen", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "btn_add_update": "Update EXE hinzufügen", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "btn_select_logo": "Custom Logo wählen", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "btn_apply_build": "Anwenden & Paketierung erstellen" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1098
to
+1117
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider fully localizing the new SAP strings. 💬 Optional wording adjustments- "sap_wizard_title": "SAP Management Wizard",
+ "sap_wizard_title": "SAP-Verwaltungsassistent",
...
- "btn_select_logo": "Custom Logo wählen",
+ "btn_select_logo": "Benutzerdefiniertes Logo wählen",📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| import flet as ft | ||
| import logging | ||
| import os | ||
| from pathlib import Path | ||
| from switchcraft.gui_modern.utils.view_utils import ViewMixin | ||
| from switchcraft.utils.i18n import i18n | ||
| from switchcraft.services.sap_service import SapService | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| class SapWizardView(ft.Column, ViewMixin): | ||
| """ | ||
| Wizard-style UI for SAP Installation Server management. | ||
| Handles merging updates, customization, and packaging. | ||
| """ | ||
|
|
||
| def __init__(self, page: ft.Page): | ||
| super().__init__(expand=True, scroll=ft.ScrollMode.AUTO) | ||
| self.app_page = page | ||
| self.sap_service = SapService() | ||
|
|
||
| # State | ||
| self.server_path = "" | ||
| self.update_files = [] | ||
| self.logo_path = "" | ||
| self.use_webview2 = True | ||
|
|
||
| self.current_step = 1 | ||
| self.content_area = ft.Container(expand=True) | ||
| self.controls = [ | ||
| ft.Text(i18n.get("sap_wizard_title") or "SAP Management Wizard", size=24, weight=ft.FontWeight.BOLD), | ||
| ft.Divider(), | ||
| self.content_area, | ||
| self._build_nav_buttons() | ||
| ] | ||
|
|
||
| self._show_step(1) | ||
|
|
||
| def _show_step(self, step_num): | ||
| self.current_step = step_num | ||
| if step_num == 1: | ||
| self.content_area.content = self._build_step_1() | ||
| elif step_num == 2: | ||
| self.content_area.content = self._build_step_2() | ||
| elif step_num == 3: | ||
| self.content_area.content = self._build_step_3() | ||
| elif step_num == 4: | ||
| self.content_area.content = self._build_step_4() | ||
| self.update() | ||
|
|
||
| def _build_step_1(self): | ||
| """Step 1: Select SAP Installation Server path.""" | ||
| def on_pick_server(e: ft.FilePickerResultEvent): | ||
| if e.path: | ||
| self.server_path = e.path | ||
| path_text.value = e.path | ||
| self.update() | ||
|
|
||
| path_text = ft.Text(self.server_path or "No path selected", italic=True) | ||
| fp = ft.FilePicker(on_result=on_pick_server) | ||
| self.app_page.overlay.append(fp) | ||
|
|
||
| return ft.Column([ | ||
| ft.Text(i18n.get("sap_step1_title") or "1. Select SAP Installation Server", size=18, weight=ft.FontWeight.BOLD), | ||
| ft.Text(i18n.get("sap_step1_desc") or "Point to the root folder of your SAP nwsetupadmin server."), | ||
| ft.Row([ | ||
| ft.ElevatedButton(i18n.get("btn_browse_folder") or "Browse Server Folder", icon=ft.Icons.FOLDER_OPEN, on_click=lambda _: fp.get_directory_path()), | ||
| path_text | ||
| ]) | ||
| ]) | ||
|
Comment on lines
+51
to
+71
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FilePicker accumulates in overlay on repeated navigation. Each call to Proposed fix - initialize FilePicker in __init__ def __init__(self, page: ft.Page):
super().__init__(expand=True, scroll=ft.ScrollMode.AUTO)
self.app_page = page
self.sap_service = SapService()
# State
self.server_path = ""
self.update_files = []
self.logo_path = ""
self.use_webview2 = True
+ # FilePicker for server selection
+ self.server_picker = ft.FilePicker(on_result=self._on_pick_server)
+ self.app_page.overlay.append(self.server_picker)
+
self.current_step = 1Then update 🤖 Prompt for AI Agents |
||
|
|
||
| def _build_step_2(self): | ||
| """Step 2: Add Updates/Add-ons.""" | ||
| return ft.Column([ | ||
| ft.Text(i18n.get("sap_step2_title") or "2. Add Updates & Add-ons (Optional)", size=18, weight=ft.FontWeight.BOLD), | ||
| ft.Text(i18n.get("sap_step2_desc") or "Select .exe files to merge into the installation server."), | ||
| ft.ElevatedButton(i18n.get("btn_add_update") or "Add Update EXE", icon=ft.Icons.ADD, on_click=lambda _: self._show_snack("Not implemented in stub")), | ||
| ft.ListView(expand=True, height=100) # Placeholder for file list | ||
| ]) | ||
|
|
||
| def _build_step_3(self): | ||
| """Step 3: Customization.""" | ||
| return ft.Column([ | ||
| ft.Text(i18n.get("sap_step3_title") or "3. Customization", size=18, weight=ft.FontWeight.BOLD), | ||
| ft.Checkbox(label=i18n.get("sap_use_webview2") or "Default to Edge WebView2 (Recommended)", value=self.use_webview2, on_change=lambda e: setattr(self, 'use_webview2', e.control.value)), | ||
| ft.Row([ | ||
| ft.ElevatedButton(i18n.get("btn_select_logo") or "Select Custom Logo", icon=ft.Icons.IMAGE), | ||
| ft.Text(i18n.get("no_logo_selected") or "No logo selected", italic=True) | ||
| ]) | ||
| ]) | ||
|
|
||
| def _build_step_4(self): | ||
| """Step 4: Summary & Packaging.""" | ||
| return ft.Column([ | ||
| ft.Text(i18n.get("sap_step4_title") or "4. Summary & Packaging", size=18, weight=ft.FontWeight.BOLD), | ||
| ft.Text(f"{i18n.get('label_server') or 'Server'}: {self.server_path}"), | ||
| ft.Text(f"{i18n.get('label_custom_logo') or 'Custom Logo'}: {'Yes' if self.logo_path else 'No'}"), | ||
| ft.Text(f"{i18n.get('label_webview2') or 'Edge WebView2'}: {'Enabled' if self.use_webview2 else 'Disabled'}"), | ||
| ft.Divider(), | ||
| ft.ElevatedButton(i18n.get("btn_apply_build") or "Apply & Build Packaging", icon=ft.Icons.BUILD_CIRCLE, bgcolor="PRIMARY", color="WHITE", on_click=self._on_finalize) | ||
| ]) | ||
|
|
||
| def _build_nav_buttons(self): | ||
| return ft.Row([ | ||
| ft.TextButton(i18n.get("btn_back") or "Back", on_click=lambda _: self._show_step(self.current_step - 1) if self.current_step > 1 else None), | ||
| ft.ElevatedButton(i18n.get("btn_next") or "Next", on_click=lambda _: self._show_step(self.current_step + 1) if self.current_step < 4 else None) | ||
| ], alignment=ft.MainAxisAlignment.END) | ||
|
|
||
| def _on_finalize(self, _): | ||
| if not self.server_path: | ||
| self._show_snack("Please select a server path first.", color="RED") | ||
| return | ||
|
|
||
| try: | ||
| self.sap_service.customize_server(self.server_path, self.logo_path, self.use_webview2) | ||
| self._show_snack("SAP Server customized successfully!", color="GREEN") | ||
| # In a real app, we would now trigger the packaging process | ||
| except Exception as e: | ||
| self._show_snack(f"Error: {e}", color="RED") | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor grammar fix in Logo Customization bullet.
“by integrated them” → “by integrating them”.
✏️ Suggested edit
📝 Committable suggestion
🤖 Prompt for AI Agents