Add Path Mapping UI with Simple Mapping and Regex Rules modes

- Updated frontend/types.ts with new types: ReplacementRule, PathMappingRules, PathMappingMode, PathMappingConfig
- Replaced StrategySelector.tsx with new UI featuring:
  - Simple Mapping tab for local/cloud path pairs
  - Regex Rules tab with 4 rule groups (localPre, localPost, remotePre, remotePost)
  - MappingGroupEditor sub-component for editing rule lists
- Updated App.tsx to use PathMappingConfig state instead of RegexReplacement[]
- Updated api.ts to handle new PathMappingConfig structure
- Updated backend config.py with path_mapping field support
- Added /api/settings/path-mapping endpoint in main.py

Co-authored-by: Koha9 <36852125+Koha9@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-11-30 22:11:29 +00:00
parent c18ff5b2ef
commit 350f1d97e6
6 changed files with 567 additions and 188 deletions
+36
View File
@@ -92,9 +92,28 @@ class RegexRule(BaseModel):
replacement: str = ""
class ReplacementRule(BaseModel):
search: str
replace: str = ""
class RegexRulesGroup(BaseModel):
local_pre: list[ReplacementRule] = []
local_post: list[ReplacementRule] = []
remote_pre: list[ReplacementRule] = []
remote_post: list[ReplacementRule] = []
class PathMappingPayload(BaseModel):
mode: str = "SIMPLE"
simple: list[ReplacementRule] = []
regex: RegexRulesGroup = RegexRulesGroup()
class SyncSettingsResponse(BaseModel):
sync_mode: str
path_rules: list[RegexRule]
path_mapping: dict | None = None
local_path: str
library_name: str | None = None
server_url: str | None = None
@@ -352,6 +371,7 @@ async def get_settings():
return SyncSettingsResponse(
sync_mode=server_config.sync_mode,
path_rules=rules,
path_mapping=server_config.path_mapping,
local_path=server_config.local_path,
library_name=server_config.library_name,
server_url=server_config.url,
@@ -380,6 +400,22 @@ async def update_regex_rules(payload: RegexRulePayload):
return {"rules": payload.rules}
@app.put("/api/settings/path-mapping")
async def update_path_mapping(payload: PathMappingPayload):
path_mapping_dict = {
"mode": payload.mode,
"simple": [{"search": rule.search, "replace": rule.replace} for rule in payload.simple],
"regex": {
"local_pre": [{"search": rule.search, "replace": rule.replace} for rule in payload.regex.local_pre],
"local_post": [{"search": rule.search, "replace": rule.replace} for rule in payload.regex.local_post],
"remote_pre": [{"search": rule.search, "replace": rule.replace} for rule in payload.regex.remote_pre],
"remote_post": [{"search": rule.search, "replace": rule.replace} for rule in payload.regex.remote_post],
}
}
server_config.set_and_save_config(path_mapping=path_mapping_dict)
return {"path_mapping": server_config.path_mapping}
@app.put("/api/settings/library")
async def update_library(payload: LibrarySelection):
server_config.set_and_save_config(library_name=payload.library_name)