fix: Backslash-Support im File-Explorer für Chat und Benutzerverwaltung

WorkspaceHelper gibt native Pfade zurück, Frontend-Logik unterstützt beide Separatoren.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
MelekiandClaude Opus 4.6 committed 2026-04-17 10:41:32 +02:00
1 parent 1526891cd9
commit 4e2815ebd3
3 files changed
+12 -9

No files matched your search

+2 -3
View File
@@ -27,12 +27,11 @@ public static class WorkspaceHelper
} }
/// <summary> /// <summary>
/// Gibt den relativen Pfad zurück – immer mit Forward-Slashes (für Agent-Output/API). /// Gibt den relativen Pfad zurück – mit nativen Separatoren (Backslash auf Windows, / auf Linux).
/// </summary> /// </summary>
internal static string GetRelativePath(string relativeTo, string path) internal static string GetRelativePath(string relativeTo, string path)
{ {
var rel = Path.GetRelativePath(relativeTo, path); return Path.GetRelativePath(relativeTo, path);
return IsWindows ? rel.Replace('\\', '/') : rel;
} }
/// <summary> /// <summary>
+1 -1
View File
@@ -701,7 +701,7 @@
<input type="password" id="adminPassword" placeholder="Passwort" autocomplete="new-password"> <input type="password" id="adminPassword" placeholder="Passwort" autocomplete="new-password">
<label>Standard-Pfad</label> <label>Standard-Pfad</label>
<div class="input-with-btn"> <div class="input-with-btn">
<input type="text" id="adminDefaultPath" placeholder="z.B. /home/user/projects" autocomplete="off"> <input type="text" id="adminDefaultPath" autocomplete="off">
<button type="button" id="adminDefaultPathBrowse" class="icon-btn"><i class="fa fa-folder"></i></button> <button type="button" id="adminDefaultPathBrowse" class="icon-btn"><i class="fa fa-folder"></i></button>
</div> </div>
<div class="admin-checkbox-row"> <div class="admin-checkbox-row">
+9 -5
View File
@@ -73,7 +73,8 @@ function openFileExplorer(opts = {}) {
// Zum Verzeichnis der initialFile navigieren, oder Root // Zum Verzeichnis der initialFile navigieren, oder Root
if (_feState.initialFile) { if (_feState.initialFile) {
const filePath = _feState.initialFile; const filePath = _feState.initialFile;
const dir = filePath.includes('/') ? filePath.substring(0, filePath.lastIndexOf('/')) : ''; const lastSep = Math.max(filePath.lastIndexOf('/'), filePath.lastIndexOf('\\'));
const dir = lastSep >= 0 ? filePath.substring(0, lastSep) : '';
feLoadDir(dir); feLoadDir(dir);
} else { } else {
feLoadDir(''); feLoadDir('');
@@ -128,7 +129,8 @@ async function feLoadDir(path) {
upItem.innerHTML = '<i class="fa fa-folder"></i> ..'; upItem.innerHTML = '<i class="fa fa-folder"></i> ..';
upItem.addEventListener('click', () => { upItem.addEventListener('click', () => {
_feState.history.push(path); _feState.history.push(path);
const parent = path.includes('/') ? path.substring(0, path.lastIndexOf('/')) : ''; const lastSep = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
const parent = lastSep >= 0 ? path.substring(0, lastSep) : '';
feLoadDir(parent); feLoadDir(parent);
}); });
sidebar.appendChild(upItem); sidebar.appendChild(upItem);
@@ -490,7 +492,7 @@ function openFolderBrowser(opts = {}) {
mode: 'folder', mode: 'folder',
onSelect: opts.onSelect || null, onSelect: opts.onSelect || null,
currentAbsPath: opts.startPath || '/', currentAbsPath: opts.startPath || '/',
basePath: (opts.basePath || '').replace(/\/+$/, '') || null, basePath: (opts.basePath || '').replace(/[\\/]+$/, '') || null,
history: [] history: []
}; };
@@ -635,7 +637,8 @@ async function fbCreateDir() {
return; return;
} }
const absPath = _feState.currentAbsPath.replace(/\/$/, '') + '/' + dirName; const sep = _feState.currentAbsPath.includes('\\') ? '\\' : '/';
const absPath = _feState.currentAbsPath.replace(/[\\/]+$/, '') + sep + dirName;
try { try {
const resp = await fetch(`/api/workspace/browse/mkdir?path=${encodeURIComponent(absPath)}`, { method: 'POST' }); const resp = await fetch(`/api/workspace/browse/mkdir?path=${encodeURIComponent(absPath)}`, { method: 'POST' });
@@ -664,7 +667,8 @@ async function feCreateDir() {
return; return;
} }
const newPath = _feState.currentPath ? _feState.currentPath + '/' + dirName : dirName; const sep = _feState.currentPath.includes('\\') ? '\\' : '/';
const newPath = _feState.currentPath ? _feState.currentPath + sep + dirName : dirName;
try { try {
const url = _feApiUrl('mkdir', `path=${encodeURIComponent(newPath)}`); const url = _feApiUrl('mkdir', `path=${encodeURIComponent(newPath)}`);