changeset 5:75b54be050bc

show one subdir of archive at once, with folders and parents-breadcrumbs
author drewp@bigasterisk.com
date Thu, 30 Mar 2023 20:39:40 -0700
parents c8a41359505c
children ccfea3625cf6
files src/VideoPage.ts video.py
diffstat 2 files changed, 74 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/VideoPage.ts	Sat Mar 25 16:01:56 2023 -0700
+++ b/src/VideoPage.ts	Thu Mar 30 20:39:40 2023 -0700
@@ -1,35 +1,92 @@
 import { LitElement, html, css } from "lit";
-import { customElement } from "lit/decorators.js";
+import { customElement, property } from "lit/decorators.js";
 export { VideoSection } from "./VideoSection";
 
 interface VideoFile {
   webRelPath: string;
   label: string;
 }
+interface Subdir {
+  label: string;
+  path: string;
+}
+
+function subdirQuery(subdir: string): string {
+  return "subdir=" + encodeURIComponent(subdir);
+}
 
 @customElement("video-page")
 export class VideoPage extends LitElement {
   videos: VideoFile[];
+  subdirs: Subdir[];
+  @property() pathSegs: { label: string; subdir: string }[];
   constructor() {
     super();
     this.videos = [];
+    this.subdirs = [];
+    this.pathSegs = [];
     this.loadVideos();
   }
+  updatePathSegs(subdir: string) {
+    this.pathSegs = [{ label: "TOP", subdir: "/" }];
+    if (subdir != "/") {
+      let acc = "";
+      const segs = subdir.split("/");
+      segs.splice(0, 1); // the root
+      for (let seg of segs) {
+        acc += "/" + seg;
+        this.pathSegs.push({ label: seg, subdir: acc });
+      }
+    }
+  }
   async loadVideos() {
-    const resp = await (await fetch("api/videos")).json();
+    const u = new URL(location.href);
+    const subdir = u.searchParams.get("subdir") || "/";
+    this.updatePathSegs(subdir);
+    const resp = await (await fetch("api/videos?" + subdirQuery(subdir))).json();
     this.videos = resp.videos as VideoFile[];
-    this.requestUpdate()
+    this.subdirs = resp.subdirs as Subdir[];
+    this.requestUpdate();
   }
-  static styles=[css`
-
-  `]
+  static styles = [
+    css`
+      a {
+        color: white;
+        font-size: 20px;
+      }
+      #path-segs > span {
+        color: white;
+        padding: 11px;
+        display: inline-block;
+        background: #4ea1bd21;
+        margin: 5px;
+        border-top-left-radius: 29px;
+      }
+      #path-segs > span:after {
+        content: " >";
+        font-size: 33px;
+        vertical-align: middle;
+        color: gray;
+      }
+      .subdir {
+        vertical-align: top;
+        color: white;
+        padding: 11px;
+        display: inline-block;
+        width: 300px;
+        background: #4ea1bd21;
+        margin: 5px;
+        border-bottom-right-radius: 29px;
+      }
+    `,
+  ];
   // allow only 1 to play. embiggen like pbskids does.
   render() {
     return html`
-      <video-section title="tl1" manifest="/tl1.webm"></video-section>
-      <video-section title="Henry Sugar" manifest="files/henry-sugar/manifest.mpd"></video-section>
-      <video-section title="Henry Sugar bloopers" manifest="files/henry-sugar-bloopers/manifest.mpd"></video-section>
-      ${this.videos.map((v)=>html`<video-section title="${v.label}" manifest=${v.webRelPath}></video-section>`)}
+      <div id="path-segs">${this.pathSegs.map((seg) => html`<span><a href="./?${subdirQuery(seg.subdir)}">${seg.label}</a></span>`)}</div>
+
+      ${this.subdirs.map((s) => html`<div class="subdir"><a href="${"./?" + subdirQuery(s.path)}">${s.label}</a></div>`)}
+      ${this.videos.map((v) => html`<video-section title="${v.label}" manifest=${v.webRelPath}></video-section>`)}
     `;
   }
 }
--- a/video.py	Sat Mar 25 16:01:56 2023 -0700
+++ b/video.py	Thu Mar 30 20:39:40 2023 -0700
@@ -1,15 +1,13 @@
-import asyncio
 import logging
-from typing import List
-from pathlib import Path
-import uvicorn
+
 from prometheus_client import Gauge
 from starlette.applications import Starlette
 from starlette.requests import Request
 from starlette.responses import HTMLResponse, JSONResponse
 from starlette.routing import Route
 from starlette_exporter import PrometheusMiddleware, handle_metrics
-from video_service import findAll
+
+from video_service import findInDir, findSubdirs
 
 logging.basicConfig(level=logging.DEBUG)
 log = logging.getLogger()
@@ -20,11 +18,14 @@
 
 
 def videos(req: Request) -> JSONResponse:
+    subdir = req.query_params.get('subdir', '/')  # danger user input
     return JSONResponse({
         "videos": [{
             'webRelPath': vf.webRelPath,
             'label': vf.label,
-        } for vf in findAll()]
+        } for vf in findInDir(subdir)],
+        "subdirs":
+        list(findSubdirs(subdir)),
     })