From c18dbfa275fb6c6f1ea15291b788dd48120cf8f2 Mon Sep 17 00:00:00 2001 From: Sebastien DUMETZ Date: Fri, 25 Oct 2024 16:31:42 +0200 Subject: [PATCH] dedicated UI routes for tags --- source/ui/MainView.ts | 2 +- source/ui/composants/TagList.ts | 2 +- source/ui/screens/Tags.ts | 131 ------------------------------ source/ui/screens/Tags/TagView.ts | 92 +++++++++++++++++++++ source/ui/screens/Tags/index.ts | 91 +++++++++++++++++++++ 5 files changed, 185 insertions(+), 133 deletions(-) delete mode 100644 source/ui/screens/Tags.ts create mode 100644 source/ui/screens/Tags/TagView.ts create mode 100644 source/ui/screens/Tags/index.ts diff --git a/source/ui/MainView.ts b/source/ui/MainView.ts index fd75cd29..cdf0f719 100644 --- a/source/ui/MainView.ts +++ b/source/ui/MainView.ts @@ -34,7 +34,7 @@ export default class MainView extends router(i18n(withUser(LitElement))){ @route() static "/ui/" =({search})=> html``; @route() - static "/ui/tags/" = ()=>html``; + static "/ui/tags/.*" = ()=>html``; @route() static "/ui/scenes/" =({search: qs})=> html``; @route() diff --git a/source/ui/composants/TagList.ts b/source/ui/composants/TagList.ts index 00df495a..bb708b73 100644 --- a/source/ui/composants/TagList.ts +++ b/source/ui/composants/TagList.ts @@ -33,7 +33,7 @@ export default class TagList extends LitElement{ private onClick = (index :number, ev :Event)=>{ ev.preventDefault(); ev.stopPropagation(); - this.dispatchEvent(new CustomEvent("click", {detail: this.tags[index]})); + this.dispatchEvent(new CustomEvent("click", {detail: {name: this.tags[index], index}})); } render(){ diff --git a/source/ui/screens/Tags.ts b/source/ui/screens/Tags.ts deleted file mode 100644 index 7b86ffed..00000000 --- a/source/ui/screens/Tags.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { LitElement, customElement, html, property } from "lit-element"; - -import Notification from "../composants/Notification"; - -import "../composants/TagList"; -import "../composants/SceneCard"; -import Notifications from "../composants/Notification"; -import { Scene } from "../state/withScenes"; -import { withUser } from "../state/auth"; - -export interface Tag{ - name :string; - size :number; -} - - -@customElement("tags-screen") -export default class TagsScreen extends withUser(LitElement){ - - @property({attribute: false, type: Array}) - tags :Tag[] = []; - - @property({attribute:false, type: Number}) - selected :number = -1; - - @property({attribute:false, type: Array}) - scenes :Scene[] = []; - - #c:AbortController = new AbortController(); - - constructor() - { - super(); - } - createRenderRoot() { - return this; - } - - public connectedCallback(): void { - super.connectedCallback(); - this.fetchTags(); - } - - - public disconnectedCallback(): void { - this.#c.abort(); - } - - - public update(changedProperties: Map): void { - if(changedProperties.has("selected")){ - this.fetchTag(); - } - super.update(changedProperties); - } - - - async fetchTags(){ - const signal = this.#c.signal; - await fetch(`/tags`, {signal}).then(async (r)=>{ - if(!r.ok) throw new Error(`[${r.status}]: ${r.statusText}`); - let body = await r.json(); - if(signal.aborted) return; - this.tags = body; - }).catch((e)=> { - if(e.name == "AbortError") return; - console.error(e); - Notification.show(`Failed to fetch scene scene: ${e.message}`, "error"); - }); - } - - async fetchTag(){ - this.scenes = []; - if(this.selected === -1 ) return; - const signal = this.#c.signal; - await fetch(`/tags/${encodeURIComponent(this.tags[this.selected].name)}`, {signal}).then(async (r)=>{ - if(!r.ok) throw new Error(`[${r.status}]: ${r.statusText}`); - let body = await r.json(); - if(signal.aborted) return; - this.scenes = body; - console.log("Scenes : ", this.scenes); - }).catch((e)=> { - if(e.name == "AbortError") return; - console.error(e); - Notification.show(`Failed to fetch scene scene: ${e.message}`, "error"); - }); - } - - handleTagClick = (e:CustomEvent)=>{ - const tagText = e.detail; - const tagIndex = this.tags.findIndex((t)=> this.formatTag(t) === tagText); - if(tagIndex === -1) return Notifications.show(`Can't find tag matching ${tagText}`, "error"); - if(this.selected === tagIndex){ - this.selected = -1; - return; - } - this.selected = tagIndex; - } - - formatTag({name, size}:Tag){ - return `${name} (${size})`; - } - - render(){ - console.log("Tags :", this.tags); - return html`
-

Tags

-
- ${this.tags.length?html` - - `:html`No tags found on this instance. Head over to the search page to create tags`} -
- - ${this.selected != -1? html`
-

${this.tags[this.selected].name}

-
- ${this.scenes.map(scene=>{ - return html`` - })} -
-
`:null} -
`; - } -} \ No newline at end of file diff --git a/source/ui/screens/Tags/TagView.ts b/source/ui/screens/Tags/TagView.ts new file mode 100644 index 00000000..e512e27b --- /dev/null +++ b/source/ui/screens/Tags/TagView.ts @@ -0,0 +1,92 @@ +import { LitElement, customElement, html, property } from "lit-element"; + +import Notification from "../../composants/Notification"; + +import "../../composants/TagList"; +import "../../composants/SceneCard"; + +import { withUser } from "../../state/auth"; +import { Scene } from "../../state/withScenes"; + +export interface Tag{ + name :string; + size :number; +} + + +@customElement("tag-view") +export default class TagView extends withUser(LitElement){ + + @property({attribute: true, type: String}) + tag :string; + + @property({attribute:false, type: Array}) + scenes :Scene[] = []; + + #c:AbortController = new AbortController(); + + constructor() + { + super(); + } + createRenderRoot() { + return this; + } + + public connectedCallback(): void { + super.connectedCallback(); + } + + + public disconnectedCallback(): void { + this.#c.abort(); + } + + + public update(changedProperties: Map): void { + if(changedProperties.has("tag")){ + this.fetchTag(); + } + super.update(changedProperties); + } + + + async fetchTag(){ + this.scenes = []; + const signal = this.#c.signal; + await fetch(`/tags/${encodeURIComponent(this.tag)}`, {signal}).then(async (r)=>{ + if(!r.ok) throw new Error(`[${r.status}]: ${r.statusText}`); + let body = await r.json(); + if(signal.aborted) return; + this.scenes = body; + console.log("Scenes : ", this.scenes); + }).catch((e)=> { + if(e.name == "AbortError") return; + console.error(e); + Notification.show(`Failed to fetch scene scene: ${e.message}`, "error"); + }); + } + + formatTag({name, size}:Tag){ + return `${name} (${size})`; + } + + render(){ + console.log("Render tag : ", this.tag); + return html`
+

${this.tag}

+
+ ${this.scenes.map(scene=>{ + return html`` + })} +
+
`; + } +} \ No newline at end of file diff --git a/source/ui/screens/Tags/index.ts b/source/ui/screens/Tags/index.ts new file mode 100644 index 00000000..28cd4172 --- /dev/null +++ b/source/ui/screens/Tags/index.ts @@ -0,0 +1,91 @@ +import { LitElement, customElement, html, property } from "lit-element"; + +import Notification from "../../composants/Notification"; + +import "../../composants/TagList"; +import "../../composants/SceneCard"; +import { withUser } from "../../state/auth"; +import { navigate, route, router } from "../../state/router"; + +import "./TagView"; + + +export interface Tag{ + name :string; + size :number; +} + + +@customElement("tags-screen") +export default class TagsScreen extends router(withUser(LitElement)){ + path="/ui/tags/"; + @route() + static "/" = ()=> null; + @route() + static "/:tag/" = ({params})=> html``; + + @property({attribute: false, type: Array}) + tags :Tag[] = []; + + #c:AbortController = new AbortController(); + + constructor() + { + super(); + } + createRenderRoot() { + return this; + } + + public connectedCallback(): void { + super.connectedCallback(); + this.fetchTags(); + } + + + public disconnectedCallback(): void { + this.#c.abort(); + } + + + public update(changedProperties: Map): void { + super.update(changedProperties); + } + + + async fetchTags(){ + const signal = this.#c.signal; + await fetch(`/tags`, {signal}).then(async (r)=>{ + if(!r.ok) throw new Error(`[${r.status}]: ${r.statusText}`); + let body = await r.json(); + if(signal.aborted) return; + this.tags = body; + }).catch((e)=> { + if(e.name == "AbortError") return; + console.error(e); + Notification.show(`Failed to fetch scene scene: ${e.message}`, "error"); + }); + } + + + handleTagClick = (e:CustomEvent<{name:string, index:number}>)=>{ + navigate(this, `${this.path}${encodeURIComponent(this.tags[e.detail.index].name)}`); + } + + formatTag({name, size}:Tag){ + return `${name} (${size})`; + } + + render(){ + const selection = this.tags.findIndex((t)=>this.isActive(`${encodeURIComponent(t.name)}`)) + return html` +

Tags

+
+ ${this.tags.length?html` + + `:html`No tags found on this instance. Head over to the search page to create tags`} +
+ ${this.renderContent()} + `; + } +} \ No newline at end of file