static: rewrite API Fetching to make API Version upgrades easier
This commit is contained in:
parent
f83087d04d
commit
c7b6eac33d
6
passbook/static/static/dist/main.js
vendored
6
passbook/static/static/dist/main.js
vendored
File diff suppressed because one or more lines are too long
2
passbook/static/static/dist/main.js.map
vendored
2
passbook/static/static/dist/main.js.map
vendored
File diff suppressed because one or more lines are too long
|
@ -1,3 +1,5 @@
|
|||
import { DefaultClient } from "./client";
|
||||
|
||||
export class Application {
|
||||
pk?: string;
|
||||
name?: string;
|
||||
|
@ -11,8 +13,6 @@ export class Application {
|
|||
policies?: string[];
|
||||
|
||||
static get(slug: string): Promise<Application> {
|
||||
return fetch(`/api/v2beta/core/applications/${slug}/`)
|
||||
.then((r) => r.json())
|
||||
.then((r) => <Application>r);
|
||||
return DefaultClient.fetch<Application>("core", "applications", slug);
|
||||
}
|
||||
}
|
||||
|
|
30
passbook/static/static/src/api/client.ts
Normal file
30
passbook/static/static/src/api/client.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { NotFoundError, RequestError } from "./errors";
|
||||
|
||||
export const VERSION = "v2beta";
|
||||
|
||||
export class Client {
|
||||
private makeUrl(...url: string[]): string {
|
||||
return `/api/${VERSION}/${url.join("/")}/`;
|
||||
}
|
||||
|
||||
fetch<T>(...url: string[]): Promise<T> {
|
||||
return fetch(this.makeUrl(...url))
|
||||
.then((r) => {
|
||||
if (r.status > 300) {
|
||||
switch (r.status) {
|
||||
case 404:
|
||||
throw new NotFoundError(
|
||||
`URL ${this.makeUrl(...url)} not found`
|
||||
);
|
||||
default:
|
||||
throw new RequestError(r.statusText);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
})
|
||||
.then((r) => r.json())
|
||||
.then((r) => <T>r);
|
||||
}
|
||||
}
|
||||
|
||||
export const DefaultClient = new Client();
|
|
@ -1,10 +1,10 @@
|
|||
export interface Config {
|
||||
branding_logo: string;
|
||||
branding_title: string;
|
||||
}
|
||||
import { DefaultClient } from "./client";
|
||||
|
||||
export function getConfig(): Promise<Config> {
|
||||
return fetch("/api/v2beta/root/config/")
|
||||
.then((r) => r.json())
|
||||
.then((r) => <Config>r);
|
||||
export class Config {
|
||||
branding_logo?: string;
|
||||
branding_title?: string;
|
||||
|
||||
static get(): Promise<Config> {
|
||||
return DefaultClient.fetch<Config>("root", "config");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export class NotFoundError extends Error {}
|
||||
export class RequestError extends Error {}
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
export function tokenByIdentifier(identifier: string): Promise<string> {
|
||||
return fetch(`/api/v2beta/core/tokens/${identifier}/view_key/`)
|
||||
.then((r) => r.json())
|
||||
.then((r) => r["key"]);
|
||||
import { DefaultClient } from "./client";
|
||||
|
||||
interface TokenResponse {
|
||||
key: string;
|
||||
}
|
||||
|
||||
export function tokenByIdentifier(identifier: string): Promise<string> {
|
||||
return DefaultClient.fetch<TokenResponse>(
|
||||
"core",
|
||||
"tokens",
|
||||
identifier,
|
||||
"view_key"
|
||||
).then((r) => r.key);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
export interface User {
|
||||
pk: number;
|
||||
username: string;
|
||||
name: string;
|
||||
is_superuser: boolean;
|
||||
email: boolean;
|
||||
avatar: string;
|
||||
}
|
||||
import { Primitive } from "lit-html/lib/parts";
|
||||
import { DefaultClient } from "./client";
|
||||
|
||||
export function me(): Promise<User> {
|
||||
return fetch("/api/v2beta/core/users/me/")
|
||||
.then((r) => r.json())
|
||||
.then((r) => <User>r);
|
||||
export class User {
|
||||
pk?: number;
|
||||
username?: string;
|
||||
name?: string;
|
||||
is_superuser?: boolean;
|
||||
email?: boolean;
|
||||
avatar?: string;
|
||||
|
||||
static me(): Promise<User> {
|
||||
return DefaultClient.fetch<User>("core", "users", "me");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ export class Messages extends LitElement {
|
|||
console.debug(`passbook/messages: closed ws connection: ${e}`);
|
||||
setTimeout(() => {
|
||||
console.debug(
|
||||
`passbook/messages: reconnecting ws in ${this.retryDelay}`
|
||||
`passbook/messages: reconnecting ws in ${this.retryDelay}ms`
|
||||
);
|
||||
this.connect();
|
||||
}, this.retryDelay);
|
||||
|
@ -67,7 +67,7 @@ export class Messages extends LitElement {
|
|||
this.messageSocket.addEventListener("error", (e) => {
|
||||
console.warn(`passbook/messages: error ${e}`);
|
||||
this.retryDelay = this.retryDelay * 2;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/* Fetch messages which were stored in the session.
|
||||
|
@ -90,9 +90,7 @@ export class Messages extends LitElement {
|
|||
}
|
||||
|
||||
renderMessage(message: Message) {
|
||||
const container = <HTMLElement>(
|
||||
this.querySelector(".pf-c-alert-group")!
|
||||
);
|
||||
const container = <HTMLElement>this.querySelector(".pf-c-alert-group")!;
|
||||
const id = ID("pb-message");
|
||||
const el = document.createElement("template");
|
||||
el.innerHTML = `<li id=${id} class="pf-c-alert-group__item">
|
||||
|
|
|
@ -13,7 +13,7 @@ import NavStyle from "@patternfly/patternfly/components/Nav/nav.css";
|
|||
// @ts-ignore
|
||||
import GlobalsStyle from "@patternfly/patternfly/base/patternfly-globals.css";
|
||||
|
||||
import { me, User } from "../api/user";
|
||||
import { User } from "../api/user";
|
||||
|
||||
export interface SidebarItem {
|
||||
name: string;
|
||||
|
@ -166,7 +166,7 @@ export class Sidebar extends LitElement {
|
|||
|
||||
constructor() {
|
||||
super();
|
||||
me().then((u) => (this.user = u));
|
||||
User.me().then((u) => (this.user = u));
|
||||
this.activePath = window.location.hash.slice(1, Infinity);
|
||||
window.addEventListener("hashchange", (e) => {
|
||||
this.activePath = window.location.hash.slice(1, Infinity);
|
||||
|
|
|
@ -3,7 +3,7 @@ import { css, customElement, html, LitElement, property } from "lit-element";
|
|||
import PageStyle from "@patternfly/patternfly/components/Page/page.css";
|
||||
// @ts-ignore
|
||||
import GlobalsStyle from "@patternfly/patternfly/base/patternfly-globals.css";
|
||||
import { Config, getConfig } from "../api/config";
|
||||
import { Config } from "../api/config";
|
||||
|
||||
@customElement("pb-sidebar-brand")
|
||||
export class SidebarBrand extends LitElement {
|
||||
|
@ -37,7 +37,7 @@ export class SidebarBrand extends LitElement {
|
|||
|
||||
constructor() {
|
||||
super();
|
||||
getConfig().then((c) => (this.config = c));
|
||||
Config.get().then((c) => (this.config = c));
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
// Fetch from data-attributes
|
||||
document.querySelectorAll("[data-pb-fetch-fill]").forEach((el) => {
|
||||
const url = el.dataset.pbFetchFill;
|
||||
const key = el.dataset.pbFetchKey;
|
||||
fetch(url)
|
||||
.then((r) => r.json())
|
||||
.then((r) => {
|
||||
el.textContent = r[key];
|
||||
el.value = r[key];
|
||||
});
|
||||
});
|
||||
|
||||
// Modal
|
||||
document.querySelectorAll("[data-target='modal']").forEach((m) => {
|
||||
m.addEventListener("click", (e) => {
|
||||
const parentContainer = e.target.closest('[data-target="modal"]');
|
||||
const modalId = parentContainer.attributes["data-modal"].value;
|
||||
document.querySelector(`#${modalId}`).removeAttribute("hidden");
|
||||
});
|
||||
});
|
||||
document.querySelectorAll(".pf-c-modal-box [data-modal-close]").forEach((b) => {
|
||||
b.addEventListener("click", (e) => {
|
||||
const parentContainer = e.target.closest(".pf-c-backdrop");
|
||||
parentContainer.setAttribute("hidden", true);
|
||||
});
|
||||
});
|
||||
|
||||
// Make Checkbox label click trigger checkbox toggle
|
||||
document.querySelectorAll(".pf-c-check__label").forEach((checkLabel) => {
|
||||
checkLabel.addEventListener("click", (e) => {
|
||||
const checkbox = e.target.parentElement.querySelector(
|
||||
"input[type=checkbox]"
|
||||
);
|
||||
checkbox.checked = !checkbox.checked;
|
||||
});
|
||||
});
|
||||
|
||||
// Hamburger Menu
|
||||
document
|
||||
.querySelectorAll(".pf-c-page__header-brand-toggle>button")
|
||||
.forEach((toggle) => {
|
||||
toggle.addEventListener("click", (e) => {
|
||||
const sidebar = document.querySelector(".pf-c-page__sidebar");
|
||||
if (sidebar.classList.contains("pf-m-expanded")) {
|
||||
// Sidebar already expanded
|
||||
sidebar.classList.remove("pf-m-expanded");
|
||||
sidebar.style.zIndex = 0;
|
||||
} else {
|
||||
// Sidebar not expanded yet
|
||||
sidebar.classList.add("pf-m-expanded");
|
||||
sidebar.style.zIndex = 200;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Collapsable Menus in Sidebar
|
||||
document
|
||||
.querySelectorAll(".pf-m-expandable>.pf-c-nav__link")
|
||||
.forEach((menu) => {
|
||||
menu.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
menu.parentElement.classList.toggle("pf-m-expanded");
|
||||
});
|
||||
});
|
|
@ -1,7 +1,5 @@
|
|||
import "construct-style-sheets-polyfill";
|
||||
|
||||
import "./legacy.js";
|
||||
|
||||
import "./elements/ActionButton";
|
||||
import "./elements/AdminLoginsChart";
|
||||
import "./elements/CodeMirror";
|
||||
|
|
Reference in a new issue