Enhance API response in portal files listing: streamline JSON structure by consolidating repeated code, improve error handling for directory checks, and add portal files directory information to the response. Update HTML template to display the server directory path dynamically.
This commit is contained in:
@@ -615,17 +615,24 @@ def _save_portal_descriptions(descriptions):
|
|||||||
def api_portal_files_list():
|
def api_portal_files_list():
|
||||||
"""List one level: root or contents of path=... (folders and files)."""
|
"""List one level: root or contents of path=... (folders and files)."""
|
||||||
subpath = request.args.get("path", "").strip().strip("/")
|
subpath = request.args.get("path", "").strip().strip("/")
|
||||||
|
base_url = request.host_url.rstrip("/") + "/files/"
|
||||||
|
empty = {"items": [], "base_url": base_url, "descriptions": {}, "current_path": subpath, "portal_files_dir": str(PORTAL_FILES_DIR)}
|
||||||
if ".." in subpath or "\\" in subpath:
|
if ".." in subpath or "\\" in subpath:
|
||||||
return jsonify({"items": [], "base_url": request.host_url.rstrip("/") + "/files/", "descriptions": {}, "current_path": ""})
|
return jsonify(empty)
|
||||||
if not PORTAL_FILES_DIR.is_dir():
|
if not PORTAL_FILES_DIR.is_dir():
|
||||||
return jsonify({"items": [], "base_url": request.host_url.rstrip("/") + "/files/", "descriptions": {}, "current_path": ""})
|
try:
|
||||||
|
PORTAL_FILES_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
if not PORTAL_FILES_DIR.is_dir():
|
||||||
|
return jsonify(empty)
|
||||||
list_dir = (PORTAL_FILES_DIR / subpath).resolve() if subpath else PORTAL_FILES_DIR
|
list_dir = (PORTAL_FILES_DIR / subpath).resolve() if subpath else PORTAL_FILES_DIR
|
||||||
try:
|
try:
|
||||||
list_dir.relative_to(PORTAL_FILES_DIR.resolve())
|
list_dir.relative_to(PORTAL_FILES_DIR.resolve())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return jsonify({"items": [], "base_url": request.host_url.rstrip("/") + "/files/", "descriptions": {}, "current_path": subpath})
|
return jsonify({**empty, "current_path": subpath})
|
||||||
if not list_dir.is_dir():
|
if not list_dir.is_dir():
|
||||||
return jsonify({"items": [], "base_url": request.host_url.rstrip("/") + "/files/", "descriptions": {}, "current_path": subpath})
|
return jsonify({**empty, "current_path": subpath})
|
||||||
items = []
|
items = []
|
||||||
for p in sorted(list_dir.iterdir(), key=lambda x: (not x.is_dir(), x.name.lower())):
|
for p in sorted(list_dir.iterdir(), key=lambda x: (not x.is_dir(), x.name.lower())):
|
||||||
if ".." in p.name or p.name.startswith("."):
|
if ".." in p.name or p.name.startswith("."):
|
||||||
@@ -639,8 +646,7 @@ def api_portal_files_list():
|
|||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
descriptions = _load_portal_descriptions()
|
descriptions = _load_portal_descriptions()
|
||||||
base = request.host_url.rstrip("/") + "/files/"
|
return jsonify({"items": items, "base_url": base_url, "descriptions": descriptions, "current_path": subpath, "portal_files_dir": str(PORTAL_FILES_DIR)})
|
||||||
return jsonify({"items": items, "base_url": base, "descriptions": descriptions, "current_path": subpath})
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/portal-files/descriptions", methods=["GET", "PATCH"])
|
@app.route("/api/portal-files/descriptions", methods=["GET", "PATCH"])
|
||||||
|
|||||||
@@ -72,7 +72,8 @@
|
|||||||
<button type="button" class="btn btn-outline btn-sm" id="uploadBtn">Upload file</button>
|
<button type="button" class="btn btn-outline btn-sm" id="uploadBtn">Upload file</button>
|
||||||
<input type="file" id="uploadInput" style="display:none;" />
|
<input type="file" id="uploadInput" style="display:none;" />
|
||||||
</div>
|
</div>
|
||||||
<p class="mono" style="font-size:0.8rem; margin-bottom:0.75rem;">Served at <strong id="baseUrl">/files/</strong> — use in cloud-init e.g. <code>curl -fsSL "http://SERVER/files/first-boot/splash.png" -o /tmp/splash.png</code></p>
|
<p class="mono" style="font-size:0.8rem; margin-bottom:0.5rem;">Served at <strong id="baseUrl">/files/</strong> — use in cloud-init e.g. <code>curl -fsSL "http://SERVER/files/first-boot/splash.png" -o /tmp/splash.png</code></p>
|
||||||
|
<p class="mono" style="font-size:0.75rem; color:var(--text-muted); margin-bottom:0.75rem;">Directory on server: <strong id="portalDir">—</strong></p>
|
||||||
<table>
|
<table>
|
||||||
<thead><tr><th>Name</th><th>Type</th><th>Size</th><th>Description</th><th>Actions</th></tr></thead>
|
<thead><tr><th>Name</th><th>Type</th><th>Size</th><th>Description</th><th>Actions</th></tr></thead>
|
||||||
<tbody id="portalBody"></tbody>
|
<tbody id="portalBody"></tbody>
|
||||||
@@ -121,6 +122,7 @@
|
|||||||
descriptions = data.descriptions || {};
|
descriptions = data.descriptions || {};
|
||||||
currentPath = data.current_path || '';
|
currentPath = data.current_path || '';
|
||||||
document.getElementById('baseUrl').textContent = baseUrl + (currentPath ? currentPath + '/' : '');
|
document.getElementById('baseUrl').textContent = baseUrl + (currentPath ? currentPath + '/' : '');
|
||||||
|
document.getElementById('portalDir').textContent = data.portal_files_dir || '—';
|
||||||
buildBreadcrumb();
|
buildBreadcrumb();
|
||||||
|
|
||||||
var tbody = document.getElementById('portalBody');
|
var tbody = document.getElementById('portalBody');
|
||||||
|
|||||||
Reference in New Issue
Block a user