web: port library page to clientside, router performance improvements
This commit is contained in:
@ -49,8 +49,9 @@ export class Route {
|
||||
export const SLUG_REGEX = "[-a-zA-Z0-9_]+";
|
||||
export const ROUTES: Route[] = [
|
||||
// Prevent infinite Shell loops
|
||||
new Route(new RegExp(`^/$`)).redirect("/-/overview/"),
|
||||
new Route(new RegExp(`^#.*`)).redirect("/-/overview/"),
|
||||
new Route(new RegExp(`^/$`)).redirect("/library/"),
|
||||
new Route(new RegExp(`^#.*`)).redirect("/library/"),
|
||||
new Route(new RegExp(`^/library/$`), html`<pb-library></pb-library>`),
|
||||
new Route(new RegExp(`^/applications/$`), html`<h1>test</h1>`),
|
||||
new Route(new RegExp(`^/applications/(?<slug>${SLUG_REGEX})/$`)).then((args) => {
|
||||
return html`<pb-application-view .args=${args}></pb-application-view>`;
|
||||
@ -114,7 +115,7 @@ export class RouterOutlet extends LitElement {
|
||||
return;
|
||||
}
|
||||
let matchedRoute: RouteMatch | null = null;
|
||||
ROUTES.forEach((route) => {
|
||||
ROUTES.some((route) => {
|
||||
console.debug(`passbook/router: matching ${activeUrl} against ${route.url}`);
|
||||
const match = route.url.exec(activeUrl);
|
||||
if (match != null) {
|
||||
@ -122,7 +123,7 @@ export class RouterOutlet extends LitElement {
|
||||
matchedRoute.arguments = match;
|
||||
matchedRoute.fullUrl = activeUrl;
|
||||
console.debug(`passbook/router: found match ${matchedRoute}`);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!matchedRoute) {
|
||||
|
||||
@ -5,12 +5,12 @@ import { COMMON_STYLES } from "../../common/styles";
|
||||
import { Table } from "../../elements/table/Table";
|
||||
|
||||
@customElement("pb-bound-policies-list")
|
||||
export class BoundPoliciesList extends Table {
|
||||
export class BoundPoliciesList extends Table<any> {
|
||||
@property()
|
||||
target?: string;
|
||||
|
||||
apiEndpoint(page: number): Promise<PBResponse> {
|
||||
return DefaultClient.fetch<PBResponse>(["policies", "bindings"], {
|
||||
apiEndpoint(page: number): Promise<PBResponse<any>> {
|
||||
return DefaultClient.fetch<PBResponse<any>>(["policies", "bindings"], {
|
||||
target: this.target!,
|
||||
ordering: "order",
|
||||
page: page,
|
||||
|
||||
108
web/src/pages/applications/LibraryPage.ts
Normal file
108
web/src/pages/applications/LibraryPage.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import { css, customElement, html, LitElement, property, TemplateResult } from "lit-element";
|
||||
import { Application } from "../../api/application";
|
||||
import { DefaultClient, PBResponse } from "../../api/client";
|
||||
import { COMMON_STYLES } from "../../common/styles";
|
||||
import { truncate } from "../../utils";
|
||||
|
||||
@customElement("pb-library")
|
||||
export class ApplicationViewPage extends LitElement {
|
||||
@property()
|
||||
apps?: PBResponse<Application>;
|
||||
|
||||
static get styles() {
|
||||
return COMMON_STYLES.concat(
|
||||
css`
|
||||
img.pf-icon {
|
||||
max-height: 24px;
|
||||
}
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
Application.list().then((r) => (this.apps = r));
|
||||
}
|
||||
|
||||
renderEmptyState() {
|
||||
return html` <div class="pf-c-empty-state pf-m-full-height">
|
||||
<div class="pf-c-empty-state__content">
|
||||
<i class="fas fa-cubes pf-c-empty-state__icon" aria-hidden="true"></i>
|
||||
<h1 class="pf-c-title pf-m-lg">{% trans 'No Applications available.' %}</h1>
|
||||
<div class="pf-c-empty-state__body">
|
||||
{% trans "Either no applications are defined, or you don't have access to any."
|
||||
%}
|
||||
</div>
|
||||
{% if perms.passbook_core.add_application %}
|
||||
<a
|
||||
href="{% url 'passbook_admin:application-create' %}"
|
||||
class="pf-c-button pf-m-primary"
|
||||
type="button"
|
||||
>
|
||||
{% trans 'Create Application' %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
renderApp(app: Application): TemplateResult {
|
||||
return html` <a href="${app.launch_url}" class="pf-c-card pf-m-hoverable pf-m-compact">
|
||||
<div class="pf-c-card__header">
|
||||
${app.meta_icon
|
||||
? html`<img
|
||||
class="app-icon pf-c-avatar"
|
||||
src="${app.meta_icon}"
|
||||
alt="Application Icon"
|
||||
/>`
|
||||
: html`<i class="pf-icon pf-icon-arrow"></i>`}
|
||||
</div>
|
||||
<div class="pf-c-card__title">
|
||||
<p id="card-1-check-label">${app.name}</p>
|
||||
<div class="pf-c-content">
|
||||
<small>${app.meta_publisher}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-card__body">${truncate(app.meta_description, 35)}</div>
|
||||
</a>`;
|
||||
}
|
||||
|
||||
renderLoading() {
|
||||
return html`<div class="pf-c-empty-state pf-m-full-height">
|
||||
<div class="pf-c-empty-state__content">
|
||||
<div class="pf-l-bullseye">
|
||||
<div class="pf-l-bullseye__item">
|
||||
<span
|
||||
class="pf-c-spinner pf-m-xl"
|
||||
role="progressbar"
|
||||
aria-valuetext="Loading..."
|
||||
>
|
||||
<span class="pf-c-spinner__clipper"></span>
|
||||
<span class="pf-c-spinner__lead-ball"></span>
|
||||
<span class="pf-c-spinner__tail-ball"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<main role="main" class="pf-c-page__main" tabindex="-1" id="main-content">
|
||||
<section class="pf-c-page__main-section pf-m-light">
|
||||
<div class="pf-c-content">
|
||||
<h1>
|
||||
<i class="pf-icon pf-icon-applications"></i>
|
||||
Applications
|
||||
</h1>
|
||||
</div>
|
||||
</section>
|
||||
${this.apps
|
||||
? html`<section class="pf-c-page__main-section">
|
||||
<div class="pf-l-gallery pf-m-gutter">
|
||||
${this.apps.results.map((app) => this.renderApp(app))}
|
||||
</div>
|
||||
</section>`
|
||||
: this.renderLoading()}
|
||||
</main>`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user