Skip to content

Commit

Permalink
dedicated UI routes for tags
Browse files Browse the repository at this point in the history
  • Loading branch information
sdumetz committed Oct 25, 2024
1 parent 4b005fb commit c18dbfa
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 133 deletions.
2 changes: 1 addition & 1 deletion source/ui/MainView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default class MainView extends router(i18n(withUser(LitElement))){
@route()
static "/ui/" =({search})=> html`<home-page .compact=${(search as URLSearchParams).has("compact")}></home-page>`;
@route()
static "/ui/tags/" = ()=>html`<tags-screen></tags-screen>`;
static "/ui/tags/.*" = ()=>html`<tags-screen></tags-screen>`;
@route()
static "/ui/scenes/" =({search: qs})=> html`<corpus-list .match=${(qs as URLSearchParams).get("search")} .compact=${(qs as URLSearchParams).has("compact")}></corpus-list>`;
@route()
Expand Down
2 changes: 1 addition & 1 deletion source/ui/composants/TagList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(){
Expand Down
131 changes: 0 additions & 131 deletions source/ui/screens/Tags.ts

This file was deleted.

92 changes: 92 additions & 0 deletions source/ui/screens/Tags/TagView.ts
Original file line number Diff line number Diff line change
@@ -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<string | number | symbol, unknown>): 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`<div class="section">
<h4>${this.tag}</h4>
<div>
${this.scenes.map(scene=>{
return html`<scene-card
cardStyle="list"
name=${scene.name}
.thumb=${scene.thumb}
.time=${scene.mtime}
access=${(("access" in scene)?((this.user?.isAdministrator)?"admin":scene.access.user): "none")}
></scene-card>`
})}
</div>
</div>`;
}
}
91 changes: 91 additions & 0 deletions source/ui/screens/Tags/index.ts
Original file line number Diff line number Diff line change
@@ -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`<tag-view tag=${params.tag}></tag-view>`;

@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<string | number | symbol, unknown>): 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`
<h2>Tags</h2>
<div class="section">
${this.tags.length?html`
<tag-list @click=${this.handleTagClick} .tags=${this.tags.map(this.formatTag)} .selected=${selection}></tag-list>
`:html`No tags found on this instance. Head over to the <a href="/ui/scenes/">search</a> page to create tags`}
</div>
${this.renderContent()}
`;
}
}

0 comments on commit c18dbfa

Please sign in to comment.