import { nothing } from "lit"; import { property, state } from "lit/decorators.js"; import { CLIENT_CONTEXT, requestNavigation, setupComponentSubscriptions, } from "@helpers"; import { TemsObjectsHandler } from "@helpers/components/temsObjectsHandler"; import type { Container, LiveOrbit, PropertiesPicker, ProxyValue, Resource, UnknownResource, } from "@src/tems.d.ts"; export default class extends TemsObjectsHandler { constructor({ defaultRoute = false, setupSubscriptions = true, ignoreRouter = false, } = {}) { super(); const attach = () => { this._attach(defaultRoute, setupSubscriptions, ignoreRouter).then( (attach: boolean) => { if (attach) { this.requestUpdate(); } }, ); }; if (document.readyState !== "complete") { document.addEventListener("DOMContentLoaded", attach); } else { attach(); } } @property({ attribute: "default-data-src", reflect: true }) defaultDataSrc?: string; @property({ attribute: "data-src", reflect: true }) dataSrc?: string; @property({ attribute: "nested-field" }) nestedField?: string; @property({ attribute: "uniq" }) uniq?: string; @property({ attribute: "route" }) route: string | undefined; @property({ attribute: false }) cherryPickedProperties: PropertiesPicker[] = []; @state() orbit: LiveOrbit | undefined; @state() currentRoute = ""; protected async _attach( defaultRoute: boolean, setupSubscriptions: boolean, ignoreRouter: boolean ) { if (!this.orbit) { if (window.orbit) { this.orbit = window.orbit; if (setupSubscriptions) { setupComponentSubscriptions({ component: this, defaultRoute: defaultRoute, ignoreRouter: ignoreRouter, }); if (this.route) { this.component = this.orbit.getComponentFromRoute(this.route); if (this.component) { this.orbit.components.map((c) => { if (c.uniq === this.component.uniq) { c.instance = this; } return c; }); } } await this._afterAttach(); return Promise.resolve(true); } } } return Promise.resolve(false); } async _afterAttach() { return Promise.resolve(); } _navigate(e: Event) { window.sibRouter.previousRoute = this.currentRoute; window.sibRouter.previousResource = window.sibRouter.currentResource; const navigator = e.target?.closest("[navigation-target]"); let target = navigator.getAttribute("navigation-target"); const subrouter = navigator.getAttribute("navigation-subrouter"); const resource = navigator.getAttribute("navigation-resource"); const rdfType = navigator.getAttribute("navigation-rdf-type"); if (rdfType) { const compatibleComponents = window.orbit?.components?.filter( (c) => c?.routeAttributes?.["rdf-type"] === rdfType ); if (compatibleComponents) target = compatibleComponents[0]?.uniq; } if (target) { requestNavigation( (window.orbit ? window.orbit.getRoute(target, true) : target) + (subrouter ? `-${subrouter}` : ""), resource ); } e.preventDefault(); } _normalizeLdpContains(value: Resource[] | Resource): Resource[] { if (!Array.isArray(value) && value !== null) { return [value]; } return value; } async _expandContainer( value: Resource[], recursive = true ): Promise { const expandedContainer: UnknownResource[] = []; for (const entry of value) { const line = await this._getProxyValue(entry, recursive); if (line) expandedContainer.push(line); } return expandedContainer; } async _getProperties( resource: Resource, recursive = true, targetProperties: PropertiesPicker[] = this.cherryPickedProperties ) { const properties = await resource.properties; const response: Resource = { "@id": resource["@id"], "@type": resource["@type"], "@context": resource.serverContext, _originalResource: resource, }; for (const prop of targetProperties) { if (properties?.includes(prop.key)) { response[prop.value] = await resource.get(prop.key); if (prop.expand) { response[prop.value] = await this._getProxyValue( response[prop.value], recursive, targetProperties ); } if (prop.cast) { response[prop.value] = prop.cast(response[prop.value]); } } } return await this._responseAdaptator(response); } async _getProxyValue( resource: | string | Resource | ProxyValue | Resource>>, recursive = true, targetProperties: PropertiesPicker[] = this.cherryPickedProperties ) { try { if (resource) { let target = resource; if (typeof resource === "string") { target = await window.sibStore.getData(resource, CLIENT_CONTEXT); } if (typeof resource !== "string" && resource.isFullResource) { if (!resource.isFullResource?.()) { target = await window.sibStore.getData( resource["@id"], CLIENT_CONTEXT ); } } if (typeof resource !== "string" && !resource.isFullResource) { // Edge case when calling getProxyValue with an already // fetched resource with server search, not a proxy (target as Resource).properties = Object.keys(target); (target as Resource).get = (property: any) => (target as Resource)[property]; } if (!target) return { _originalResource: target }; if (typeof target === "object" && target !== null) { if (target["ldp:contains"]) { const value = this._normalizeLdpContains(target["ldp:contains"]); return await this._expandContainer(value, recursive); } return await this._getProperties(target, recursive, targetProperties); } } return; } catch (e) { if (import.meta.env.DEV) console.error(e); } } async _responseAdaptator(response: Resource) { return Promise.resolve(response); } gatekeeper() { if ( !this.orbit || (!this.noRouter && this.route && this.currentRoute && !this.route.startsWith(this.currentRoute)) ) { return nothing; } if (!this.dataSrc) { if (this.defaultDataSrc && this.route) { requestNavigation(this.route, this.defaultDataSrc); this.dataSrc = this.defaultDataSrc; } return nothing; } } }