web/elements: add new API to store attributes in URL, use for table and tabs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
c363b1cfde
commit
465898c7d0
9
Makefile
9
Makefile
|
@ -81,3 +81,12 @@ migrate:
|
||||||
|
|
||||||
run:
|
run:
|
||||||
go run -v cmd/server/main.go
|
go run -v cmd/server/main.go
|
||||||
|
|
||||||
|
web: web-lint-fix web-lint
|
||||||
|
|
||||||
|
web-lint-fix:
|
||||||
|
cd web && npm run prettier
|
||||||
|
|
||||||
|
web-lint:
|
||||||
|
cd web && npm run lint
|
||||||
|
cd web && npm run lit-analyse
|
||||||
|
|
|
@ -9,6 +9,7 @@ import PFTabs from "@patternfly/patternfly/components/Tabs/tabs.css";
|
||||||
import PFGlobal from "@patternfly/patternfly/patternfly-base.css";
|
import PFGlobal from "@patternfly/patternfly/patternfly-base.css";
|
||||||
|
|
||||||
import { CURRENT_CLASS, ROUTE_SEPARATOR } from "../constants";
|
import { CURRENT_CLASS, ROUTE_SEPARATOR } from "../constants";
|
||||||
|
import { getURLParams, updateURLParams } from "./router/RouteMatch";
|
||||||
|
|
||||||
@customElement("ak-tabs")
|
@customElement("ak-tabs")
|
||||||
export class Tabs extends LitElement {
|
export class Tabs extends LitElement {
|
||||||
|
@ -65,9 +66,9 @@ export class Tabs extends LitElement {
|
||||||
|
|
||||||
onClick(slot?: string): void {
|
onClick(slot?: string): void {
|
||||||
this.currentPage = slot;
|
this.currentPage = slot;
|
||||||
const currentUrl = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR)[0];
|
updateURLParams({
|
||||||
const newUrl = `#${currentUrl};${slot}`;
|
page: slot,
|
||||||
history.replaceState(undefined, "", newUrl);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTab(page: Element): TemplateResult {
|
renderTab(page: Element): TemplateResult {
|
||||||
|
@ -81,18 +82,20 @@ export class Tabs extends LitElement {
|
||||||
|
|
||||||
render(): TemplateResult {
|
render(): TemplateResult {
|
||||||
const pages = Array.from(this.querySelectorAll("[slot^='page-']"));
|
const pages = Array.from(this.querySelectorAll("[slot^='page-']"));
|
||||||
|
if (window.location.hash.includes(ROUTE_SEPARATOR)) {
|
||||||
|
const params = getURLParams();
|
||||||
|
if ("page" in params) {
|
||||||
|
if (this.querySelector(`[slot='${params.page}']`) !== null) {
|
||||||
|
// To update the URL to match with the current slot
|
||||||
|
this.currentPage = params.page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!this.currentPage) {
|
if (!this.currentPage) {
|
||||||
if (pages.length < 1) {
|
if (pages.length < 1) {
|
||||||
return html`<h1>${t`no tabs defined`}</h1>`;
|
return html`<h1>${t`no tabs defined`}</h1>`;
|
||||||
}
|
}
|
||||||
let wantedPage = pages[0].attributes.getNamedItem("slot")?.value;
|
const wantedPage = pages[0].attributes.getNamedItem("slot")?.value;
|
||||||
if (window.location.hash.includes(ROUTE_SEPARATOR)) {
|
|
||||||
const urlParts = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR);
|
|
||||||
if (this.querySelector(`[slot='${urlParts[1]}']`) !== null) {
|
|
||||||
// To update the URL to match with the current slot
|
|
||||||
wantedPage = urlParts[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.onClick(wantedPage);
|
this.onClick(wantedPage);
|
||||||
}
|
}
|
||||||
return html`<div class="pf-c-tabs ${this.vertical ? "pf-m-vertical pf-m-box" : ""}">
|
return html`<div class="pf-c-tabs ${this.vertical ? "pf-m-vertical pf-m-box" : ""}">
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { TemplateResult } from "lit";
|
import { TemplateResult } from "lit";
|
||||||
|
|
||||||
|
import { ROUTE_SEPARATOR } from "../../constants";
|
||||||
import { Route } from "./Route";
|
import { Route } from "./Route";
|
||||||
|
|
||||||
export class RouteMatch {
|
export class RouteMatch {
|
||||||
|
@ -22,3 +23,44 @@ export class RouteMatch {
|
||||||
)}>`;
|
)}>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getURLParam<T>(key: string, fallback: T): T {
|
||||||
|
const params = getURLParams();
|
||||||
|
if (key in params) {
|
||||||
|
return params[key] as T;
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getURLParams(): { [key: string]: unknown } {
|
||||||
|
const params = {};
|
||||||
|
if (window.location.hash.includes(ROUTE_SEPARATOR)) {
|
||||||
|
const urlParts = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR, 2);
|
||||||
|
const rawParams = decodeURIComponent(urlParts[1]);
|
||||||
|
try {
|
||||||
|
return JSON.parse(rawParams);
|
||||||
|
} catch {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setURLParams(params: { [key: string]: unknown }, replace = true): void {
|
||||||
|
const paramsString = JSON.stringify(params);
|
||||||
|
const currentUrl = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR)[0];
|
||||||
|
const newUrl = `#${currentUrl};${encodeURIComponent(paramsString)}`;
|
||||||
|
if (replace) {
|
||||||
|
history.replaceState(undefined, "", newUrl);
|
||||||
|
} else {
|
||||||
|
history.pushState(undefined, "", newUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateURLParams(params: { [key: string]: unknown }, replace = true): void {
|
||||||
|
const currentParams = getURLParams();
|
||||||
|
for (const key in params) {
|
||||||
|
currentParams[key] = params[key] as string;
|
||||||
|
}
|
||||||
|
setURLParams(currentParams, replace);
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { groupBy } from "../../utils";
|
||||||
import "../EmptyState";
|
import "../EmptyState";
|
||||||
import "../chips/Chip";
|
import "../chips/Chip";
|
||||||
import "../chips/ChipGroup";
|
import "../chips/ChipGroup";
|
||||||
|
import { getURLParams, updateURLParams } from "../router/RouteMatch";
|
||||||
import "./TablePagination";
|
import "./TablePagination";
|
||||||
import "./TableSearch";
|
import "./TableSearch";
|
||||||
|
|
||||||
|
@ -355,6 +356,9 @@ export abstract class Table<T> extends LitElement {
|
||||||
composed: true,
|
composed: true,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
updateURLParams({
|
||||||
|
search: value,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
</ak-table-search>`;
|
</ak-table-search>`;
|
||||||
|
@ -393,6 +397,10 @@ export abstract class Table<T> extends LitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated(): void {
|
firstUpdated(): void {
|
||||||
|
const params = getURLParams();
|
||||||
|
if ("search" in params) {
|
||||||
|
this.search = params.search;
|
||||||
|
}
|
||||||
this.fetch();
|
this.fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import "../../elements/buttons/SpinnerButton";
|
||||||
import "../../elements/forms/DeleteBulkForm";
|
import "../../elements/forms/DeleteBulkForm";
|
||||||
import "../../elements/forms/ModalForm";
|
import "../../elements/forms/ModalForm";
|
||||||
import "../../elements/forms/ProxyForm";
|
import "../../elements/forms/ProxyForm";
|
||||||
|
import { getURLParam, updateURLParams } from "../../elements/router/RouteMatch";
|
||||||
import { TableColumn } from "../../elements/table/Table";
|
import { TableColumn } from "../../elements/table/Table";
|
||||||
import { TablePage } from "../../elements/table/TablePage";
|
import { TablePage } from "../../elements/table/TablePage";
|
||||||
import { groupBy } from "../../utils";
|
import { groupBy } from "../../utils";
|
||||||
|
@ -45,7 +46,7 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
|
||||||
order = "name";
|
order = "name";
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
hideManaged = false;
|
hideManaged = getURLParam<boolean>("hideManaged", true);
|
||||||
|
|
||||||
async apiEndpoint(page: number): Promise<AKResponse<PropertyMapping>> {
|
async apiEndpoint(page: number): Promise<AKResponse<PropertyMapping>> {
|
||||||
return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllList({
|
return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllList({
|
||||||
|
@ -171,6 +172,9 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> {
|
||||||
this.hideManaged = !this.hideManaged;
|
this.hideManaged = !this.hideManaged;
|
||||||
this.page = 1;
|
this.page = 1;
|
||||||
this.fetch();
|
this.fetch();
|
||||||
|
updateURLParams({
|
||||||
|
hideManaged: this.hideManaged,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<label class="pf-c-check__label" for="hide-managed"
|
<label class="pf-c-check__label" for="hide-managed"
|
||||||
|
|
|
@ -16,6 +16,7 @@ import "../../elements/forms/DeleteBulkForm";
|
||||||
import "../../elements/forms/ModalForm";
|
import "../../elements/forms/ModalForm";
|
||||||
import { MessageLevel } from "../../elements/messages/Message";
|
import { MessageLevel } from "../../elements/messages/Message";
|
||||||
import { showMessage } from "../../elements/messages/MessageContainer";
|
import { showMessage } from "../../elements/messages/MessageContainer";
|
||||||
|
import { getURLParam, updateURLParams } from "../../elements/router/RouteMatch";
|
||||||
import { TableColumn } from "../../elements/table/Table";
|
import { TableColumn } from "../../elements/table/Table";
|
||||||
import { TablePage } from "../../elements/table/TablePage";
|
import { TablePage } from "../../elements/table/TablePage";
|
||||||
import { first } from "../../utils";
|
import { first } from "../../utils";
|
||||||
|
@ -46,7 +47,7 @@ export class UserListPage extends TablePage<User> {
|
||||||
order = "last_login";
|
order = "last_login";
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
hideServiceAccounts = true;
|
hideServiceAccounts = getURLParam<boolean>("hideServiceAccounts", true);
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return super.styles.concat(PFDescriptionList);
|
return super.styles.concat(PFDescriptionList);
|
||||||
|
@ -284,6 +285,9 @@ export class UserListPage extends TablePage<User> {
|
||||||
this.hideServiceAccounts = !this.hideServiceAccounts;
|
this.hideServiceAccounts = !this.hideServiceAccounts;
|
||||||
this.page = 1;
|
this.page = 1;
|
||||||
this.fetch();
|
this.fetch();
|
||||||
|
updateURLParams({
|
||||||
|
hideServiceAccounts: this.hideServiceAccounts,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<label class="pf-c-check__label" for="hide-service-accounts">
|
<label class="pf-c-check__label" for="hide-service-accounts">
|
||||||
|
|
Reference in New Issue