Skip to content

Commit 32a44e0

Browse files
Merge pull request #67 from FaserF/new-feat-sapwizard
New feat: SAP packaging wizard
2 parents 2f915d0 + 6eeb69c commit 32a44e0

File tree

14 files changed

+439
-6
lines changed

14 files changed

+439
-6
lines changed

docs/.vitepress/config.mts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,17 @@ export default defineConfig({
8585
{ text: 'Script Manager', link: '/views/scripts' },
8686
{ text: 'Detection Tester', link: '/views/tester' },
8787
{ text: 'AI Helper', link: '/views/helper' },
88+
{ text: 'SAP Management', link: '/views/sap_wizard' },
8889
{ text: 'Settings', link: '/views/settings' }
8990
]
9091
},
92+
{
93+
text: 'Specialized Tools',
94+
collapsed: false,
95+
items: [
96+
{ text: 'SAP Installation Server', link: '/SAP' }
97+
]
98+
},
9199
{
92100
text: 'Enterprise & IT Pro',
93101
collapsed: false,

docs/SAP.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# SAP Management
2+
3+
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.
4+
5+
## Key Features
6+
7+
- **Automated Update Merging**: Easily integrate SAP GUI patches and add-ons using the `/UpdateServer` command-line interface.
8+
- **Logo Customization**: Automatically distribute custom company logos to all clients by integrated them into the installation server.
9+
- **Edge WebView2 Enforcement**: Force the use of Edge WebView2 as the default browser engine for SAP GUI transactions by patching the `SapGuiSetup.xml` configuration.
10+
- **Guided Multi-Step Wizard**: A specialized UI that walks you through the entire process from server selection to finalized packaging.
11+
12+
## Usage Guide
13+
14+
### 1. Select Installation Server
15+
Point SwitchCraft to the root directory of your SAP Installation Server. The tool will look for `NwSapSetupAdmin.exe` in the `Setup` subfolder.
16+
17+
### 2. Merge Updates
18+
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.
19+
20+
### 3. Customization
21+
- **Edge WebView2**: Check this option to ensure all clients use the modern WebView2 engine.
22+
- **Custom Logo**: Select a `.png` file to be used as the branding logo in the SAP GUI.
23+
24+
### 4. Finalize & Package
25+
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.
26+
27+
## Technical Details
28+
29+
The tool interacts with the SAP Setup infrastructure via:
30+
- **CLI**: `NwSapSetupAdmin.exe` for server updates and SFU compression.
31+
- **XML Patching**: Direct manipulation of `Setup\SapGuiSetup.xml` for specific preference overrides that are not exposed via standard CLI arguments.

docs/views/sap_wizard.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# SAP Management Wizard
2+
3+
The **SAP Management Wizard** is a guided tool designed to simplify the lifecycle management of SAP Installation Servers.
4+
5+
## View Components
6+
7+
### Server Selection
8+
The first step requires the path to a network share or local folder containing the SAP nwsetupadmin server.
9+
10+
### Update Manager
11+
Allows queuing multiple `.exe` patches for sequential merging.
12+
13+
### Customization Options
14+
- **WebView2 Toggle**: Corresponds to the `UseWebView2` parameter in the SAP configuration.
15+
- **Branding**: Automatically handles the copying and registration of custom logos.
16+
17+
## Best Practices
18+
- Always create a backup of your `Setup` directory before applying customizations.
19+
- Ensure you have administrative privileges on the folder where the installation server is hosted.
20+
- Test the resulting Single-File Installer on a clean machine before wide-scale distribution.

src/switchcraft/assets/lang/de.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1095,5 +1095,24 @@
10951095
"error_feature_demo_restricted": "Das Paketieren ist in der Web-Demo nicht verfügbar.",
10961096
"error_wine_missing": "Wine wird benötigt, um das Paketierungs-Werkzeug unter Linux auszuführen. Bitte installiere Wine.",
10971097
"demo_restriction_hint": "Die Funktion {feature}ist in der Web-Demo eingeschränkt. Für den vollen Funktionsumfang nutze bitte die Desktop-Version.",
1098-
"wine_missing_hint": "Diese Funktion erfordert eine Wine-Installation auf deinem Linux-System."
1098+
"wine_missing_hint": "Diese Funktion erfordert eine Wine-Installation auf deinem Linux-System.",
1099+
"sap_wizard_title": "SAP Management Wizard",
1100+
"sap_card_title": "SAP Management",
1101+
"sap_card_desc": "SAP Install Server Werkzeug",
1102+
"sap_step1_title": "1. SAP Installations-Server wählen",
1103+
"sap_step1_desc": "Wähle den Stammordner deines SAP nwsetupadmin Servers aus.",
1104+
"sap_step2_title": "2. Updates & Add-ons hinzufügen (Optional)",
1105+
"sap_step2_desc": "Wähle .exe Dateien aus, die in den Installations-Server integriert werden sollen.",
1106+
"sap_step3_title": "3. Anpassung",
1107+
"sap_step3_desc": "Konfiguriere Logo und Browser-Einstellungen.",
1108+
"sap_step4_title": "4. Zusammenfassung & Paketierung",
1109+
"sap_use_webview2": "Edge WebView2 als Standard (Empfohlen)",
1110+
"no_logo_selected": "Kein Logo ausgewählt",
1111+
"label_server": "Server",
1112+
"label_custom_logo": "Benutzerdefiniertes Logo",
1113+
"label_webview2": "Edge WebView2",
1114+
"btn_browse_folder": "Serverordner durchsuchen",
1115+
"btn_add_update": "Update EXE hinzufügen",
1116+
"btn_select_logo": "Custom Logo wählen",
1117+
"btn_apply_build": "Anwenden & Paketierung erstellen"
10991118
}

src/switchcraft/assets/lang/en.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1095,5 +1095,24 @@
10951095
"error_feature_demo_restricted": "Packaging is not available in the Web Demo.",
10961096
"error_wine_missing": "Wine is required to run the Packaging Tool on Linux. Please install Wine.",
10971097
"demo_restriction_hint": "The feature {feature}is restricted in the Web Demo. For full functionality, please use the Desktop version.",
1098-
"wine_missing_hint": "This feature requires Wine to be installed on your Linux system."
1098+
"wine_missing_hint": "This feature requires Wine to be installed on your Linux system.",
1099+
"sap_wizard_title": "SAP Management Wizard",
1100+
"sap_card_title": "SAP Management",
1101+
"sap_card_desc": "SAP Install Server tool",
1102+
"sap_step1_title": "1. Select SAP Installation Server",
1103+
"sap_step1_desc": "Point to the root folder of your SAP nwsetupadmin server.",
1104+
"sap_step2_title": "2. Add Updates & Add-ons (Optional)",
1105+
"sap_step2_desc": "Select .exe files to merge into the installation server.",
1106+
"sap_step3_title": "3. Customization",
1107+
"sap_step3_desc": "Configure logo and browser preferences.",
1108+
"sap_step4_title": "4. Summary & Packaging",
1109+
"sap_use_webview2": "Default to Edge WebView2 (Recommended)",
1110+
"no_logo_selected": "No logo selected",
1111+
"label_server": "Server",
1112+
"label_custom_logo": "Custom Logo",
1113+
"label_webview2": "Edge WebView2",
1114+
"btn_browse_folder": "Browse Server Folder",
1115+
"btn_add_update": "Add Update EXE",
1116+
"btn_select_logo": "Select Custom Logo",
1117+
"btn_apply_build": "Apply & Build Packaging"
10991118
}

src/switchcraft/gui_modern/app.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,9 @@ def build_ui(self):
10761076
ft.NavigationRailDestination(
10771077
icon=ft.Icons.POLICY_OUTLINED, selected_icon=ft.Icons.POLICY, label=i18n.get("settings_policies") or "Policies"
10781078
), # 21 Policies
1079+
ft.NavigationRailDestination(
1080+
icon=ft.Icons.BUSINESS, selected_icon=ft.Icons.BUSINESS, label=i18n.get("sap_card_title") or "SAP Management"
1081+
), # 22 SAP Magic
10791082
]
10801083

10811084

@@ -1779,6 +1782,12 @@ def _f():
17791782
from switchcraft.gui_modern.views.wingetcreate_view import WingetCreateView
17801783
return WingetCreateView(self.page)
17811784
load_view(_f)
1785+
elif idx == NavIndex.SAP_WIZARD:
1786+
# SAP Management
1787+
def _f():
1788+
from switchcraft.gui_modern.views.sap_wizard_view import SapWizardView
1789+
return SapWizardView(self.page)
1790+
load_view(_f)
17821791

17831792
else:
17841793
# Dynamic Addons

src/switchcraft/gui_modern/nav_constants.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class NavIndex:
4646
EXCHANGE = 20 # Exchange Online View
4747

4848
SETTINGS_POLICIES = 21 # Settings tab index 3 (Policies)
49+
SAP_WIZARD = 22 # SAP Management Wizard
4950

5051

5152
# Mapping from NavIndex to sidebar category for reference
@@ -58,7 +59,7 @@ class NavIndex:
5859
"Tools": [
5960
NavIndex.ANALYZER, NavIndex.HELPER, NavIndex.SCRIPTS,
6061
NavIndex.MACOS, NavIndex.PACKAGING_WIZARD, NavIndex.DETECTION_TESTER,
61-
NavIndex.WINGET_CREATE
62+
NavIndex.WINGET_CREATE, NavIndex.SAP_WIZARD
6263
],
6364
"System": [
6465
NavIndex.SETTINGS, NavIndex.SETTINGS_UPDATES,

src/switchcraft/gui_modern/views/category_view.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
"Help & Resources": "desc_help",
3939
"Hilfe & Ressourcen": "desc_help",
4040
"Policies": "desc_policies",
41-
"Richtlinien": "desc_policies"
41+
"Richtlinien": "desc_policies",
42+
"SAP Management": "sap_card_desc",
43+
"SAP-Management": "sap_card_desc"
4244
}
4345

4446
class CategoryView(ft.Container):

src/switchcraft/gui_modern/views/home_view.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ def _build_content(self):
208208
ft.Row([
209209
self._create_action_card(i18n.get("home_card_analyzer_title") or "Analyzer", i18n.get("home_card_analyzer_desc") or "Deep Scan Installers", ft.Icons.SEARCH, NavIndex.ANALYZER, "CYAN"),
210210
self._create_action_card(i18n.get("home_card_wizard_title") or "Wizard", i18n.get("home_card_wizard_desc") or "Packaging Wizard", ft.Icons.AUTO_FIX_HIGH, NavIndex.PACKAGING_WIZARD, "PURPLE"),
211+
self._create_action_card(i18n.get("sap_card_title") or "SAP Management", i18n.get("sap_card_desc") or "SAP Install Server tool", ft.Icons.BUSINESS, NavIndex.SAP_WIZARD, "BLUE"),
211212
self._create_action_card(i18n.get("home_card_winget_title") or "Winget", i18n.get("home_card_winget_desc") or "Browse Store", ft.Icons.SHOP_TWO, NavIndex.WINGET, "BLUE"),
212213
], wrap=True, spacing=15),
213214

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import flet as ft
2+
import logging
3+
import os
4+
from pathlib import Path
5+
from switchcraft.gui_modern.utils.view_utils import ViewMixin
6+
from switchcraft.utils.i18n import i18n
7+
from switchcraft.services.sap_service import SapService
8+
9+
logger = logging.getLogger(__name__)
10+
11+
class SapWizardView(ft.Column, ViewMixin):
12+
"""
13+
Wizard-style UI for SAP Installation Server management.
14+
Handles merging updates, customization, and packaging.
15+
"""
16+
17+
def __init__(self, page: ft.Page):
18+
super().__init__(expand=True, scroll=ft.ScrollMode.AUTO)
19+
self.app_page = page
20+
self.sap_service = SapService()
21+
22+
# State
23+
self.server_path = ""
24+
self.update_files = []
25+
self.logo_path = ""
26+
self.use_webview2 = True
27+
28+
self.current_step = 1
29+
self.content_area = ft.Container(expand=True)
30+
self.controls = [
31+
ft.Text(i18n.get("sap_wizard_title") or "SAP Management Wizard", size=24, weight=ft.FontWeight.BOLD),
32+
ft.Divider(),
33+
self.content_area,
34+
self._build_nav_buttons()
35+
]
36+
37+
self._show_step(1)
38+
39+
def _show_step(self, step_num):
40+
self.current_step = step_num
41+
if step_num == 1:
42+
self.content_area.content = self._build_step_1()
43+
elif step_num == 2:
44+
self.content_area.content = self._build_step_2()
45+
elif step_num == 3:
46+
self.content_area.content = self._build_step_3()
47+
elif step_num == 4:
48+
self.content_area.content = self._build_step_4()
49+
self.update()
50+
51+
def _build_step_1(self):
52+
"""Step 1: Select SAP Installation Server path."""
53+
def on_pick_server(e: ft.FilePickerResultEvent):
54+
if e.path:
55+
self.server_path = e.path
56+
path_text.value = e.path
57+
self.update()
58+
59+
path_text = ft.Text(self.server_path or "No path selected", italic=True)
60+
fp = ft.FilePicker()
61+
fp.on_result = on_pick_server
62+
self.app_page.overlay.append(fp)
63+
64+
return ft.Column([
65+
ft.Text(i18n.get("sap_step1_title") or "1. Select SAP Installation Server", size=18, weight=ft.FontWeight.BOLD),
66+
ft.Text(i18n.get("sap_step1_desc") or "Point to the root folder of your SAP nwsetupadmin server."),
67+
ft.Row([
68+
ft.ElevatedButton(i18n.get("btn_browse_folder") or "Browse Server Folder", icon=ft.Icons.FOLDER_OPEN, on_click=lambda _: fp.get_directory_path()),
69+
path_text
70+
])
71+
])
72+
73+
def _build_step_2(self):
74+
"""Step 2: Add Updates/Add-ons."""
75+
return ft.Column([
76+
ft.Text(i18n.get("sap_step2_title") or "2. Add Updates & Add-ons (Optional)", size=18, weight=ft.FontWeight.BOLD),
77+
ft.Text(i18n.get("sap_step2_desc") or "Select .exe files to merge into the installation server."),
78+
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")),
79+
ft.ListView(expand=True, height=100) # Placeholder for file list
80+
])
81+
82+
def _build_step_3(self):
83+
"""Step 3: Customization."""
84+
return ft.Column([
85+
ft.Text(i18n.get("sap_step3_title") or "3. Customization", size=18, weight=ft.FontWeight.BOLD),
86+
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)),
87+
ft.Row([
88+
ft.ElevatedButton(i18n.get("btn_select_logo") or "Select Custom Logo", icon=ft.Icons.IMAGE),
89+
ft.Text(i18n.get("no_logo_selected") or "No logo selected", italic=True)
90+
])
91+
])
92+
93+
def _build_step_4(self):
94+
"""Step 4: Summary & Packaging."""
95+
return ft.Column([
96+
ft.Text(i18n.get("sap_step4_title") or "4. Summary & Packaging", size=18, weight=ft.FontWeight.BOLD),
97+
ft.Text(f"{i18n.get('label_server') or 'Server'}: {self.server_path}"),
98+
ft.Text(f"{i18n.get('label_custom_logo') or 'Custom Logo'}: {'Yes' if self.logo_path else 'No'}"),
99+
ft.Text(f"{i18n.get('label_webview2') or 'Edge WebView2'}: {'Enabled' if self.use_webview2 else 'Disabled'}"),
100+
ft.Divider(),
101+
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)
102+
])
103+
104+
def _build_nav_buttons(self):
105+
return ft.Row([
106+
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),
107+
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)
108+
], alignment=ft.MainAxisAlignment.END)
109+
110+
def _on_finalize(self, _):
111+
if not self.server_path:
112+
self._show_snack("Please select a server path first.", color="RED")
113+
return
114+
115+
try:
116+
self.sap_service.customize_server(self.server_path, self.logo_path, self.use_webview2)
117+
self._show_snack("SAP Server customized successfully!", color="GREEN")
118+
# In a real app, we would now trigger the packaging process
119+
except Exception as e:
120+
self._show_snack(f"Error: {e}", color="RED")

0 commit comments

Comments
 (0)