Add initial crawl template form (#80)
This commit is contained in:
parent
b3ca501a19
commit
b2088f5634
@ -23,7 +23,7 @@
|
|||||||
border: solid var(--sl-input-border-width) var(--sl-input-border-color);
|
border: solid var(--sl-input-border-width) var(--sl-input-border-color);
|
||||||
border-radius: var(--sl-input-border-radius-medium);
|
border-radius: var(--sl-input-border-radius-medium);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
padding: var(--sl-input-spacing-medium);
|
padding: 0 var(--sl-input-spacing-medium);
|
||||||
cursor: inherit;
|
cursor: inherit;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
transition: var(--sl-transition-fast) border,
|
transition: var(--sl-transition-fast) border,
|
||||||
|
@ -33,6 +33,9 @@ export class Input extends LiteElement {
|
|||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
|
||||||
|
@property()
|
||||||
|
value?: any;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
autocomplete?: any;
|
autocomplete?: any;
|
||||||
|
|
||||||
@ -60,6 +63,7 @@ export class Input extends LiteElement {
|
|||||||
: ifDefined(this.type as any)}
|
: ifDefined(this.type as any)}
|
||||||
autocomplete=${ifDefined(this.autocomplete)}
|
autocomplete=${ifDefined(this.autocomplete)}
|
||||||
placeholder=${ifDefined(this.placeholder)}
|
placeholder=${ifDefined(this.placeholder)}
|
||||||
|
value=${ifDefined(this.value)}
|
||||||
?required=${Boolean(this.required)}
|
?required=${Boolean(this.required)}
|
||||||
/>
|
/>
|
||||||
${this.togglePassword
|
${this.togglePassword
|
||||||
|
@ -197,7 +197,7 @@ export class App extends LiteElement {
|
|||||||
return html`
|
return html`
|
||||||
<div class="bg-gray-900 text-gray-50">
|
<div class="bg-gray-900 text-gray-50">
|
||||||
<nav
|
<nav
|
||||||
class="max-w-screen-xl mx-auto p-2 box-border flex items-center justify-between"
|
class="max-w-screen-lg mx-auto p-2 box-border flex items-center justify-between"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<a href="/archives" @click="${this.navLink}"
|
<a href="/archives" @click="${this.navLink}"
|
||||||
@ -268,7 +268,7 @@ export class App extends LiteElement {
|
|||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
const appLayout = (template: TemplateResult) => html`
|
const appLayout = (template: TemplateResult) => html`
|
||||||
<div class="w-full max-w-screen-xl mx-auto p-2 md:py-8 box-border">
|
<div class="w-full max-w-screen-lg mx-auto p-2 md:py-8 box-border">
|
||||||
${template}
|
${template}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@ -367,6 +367,7 @@ export class App extends LiteElement {
|
|||||||
|
|
||||||
case "archive":
|
case "archive":
|
||||||
case "archiveAddMember":
|
case "archiveAddMember":
|
||||||
|
case "archiveNewResourceTab":
|
||||||
return appLayout(html`<btrix-archive
|
return appLayout(html`<btrix-archive
|
||||||
class="w-full"
|
class="w-full"
|
||||||
@navigate=${this.onNavigateTo}
|
@navigate=${this.onNavigateTo}
|
||||||
@ -376,6 +377,7 @@ export class App extends LiteElement {
|
|||||||
archiveId=${this.viewState.params.id}
|
archiveId=${this.viewState.params.id}
|
||||||
archiveTab=${this.viewState.params.tab as ArchiveTab}
|
archiveTab=${this.viewState.params.tab as ArchiveTab}
|
||||||
?isAddingMember=${this.viewState.route === "archiveAddMember"}
|
?isAddingMember=${this.viewState.route === "archiveAddMember"}
|
||||||
|
?isNewResourceTab=${this.viewState.route === "archiveNewResourceTab"}
|
||||||
></btrix-archive>`);
|
></btrix-archive>`);
|
||||||
|
|
||||||
case "accountSettings":
|
case "accountSettings":
|
||||||
@ -462,6 +464,8 @@ export class App extends LiteElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onNavigateTo(event: NavigateEvent) {
|
onNavigateTo(event: NavigateEvent) {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
this.navigate(event.detail);
|
this.navigate(event.detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
240
frontend/src/pages/archive/crawl-templates.ts
Normal file
240
frontend/src/pages/archive/crawl-templates.ts
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
import { state, property } from "lit/decorators.js";
|
||||||
|
import { msg, localized } from "@lit/localize";
|
||||||
|
|
||||||
|
import type { AuthState } from "../../utils/AuthService";
|
||||||
|
import LiteElement, { html } from "../../utils/LiteElement";
|
||||||
|
|
||||||
|
type CrawlTemplate = any; // TODO
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
name: `Example crawl ${Date.now()}`, // TODO remove placeholder
|
||||||
|
runNow: true,
|
||||||
|
schedule: "@weekly",
|
||||||
|
// crawlTimeoutMinutes: 0,
|
||||||
|
seedUrls: "",
|
||||||
|
scopeType: "prefix",
|
||||||
|
// limit: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
@localized()
|
||||||
|
export class CrawlTemplates extends LiteElement {
|
||||||
|
@property({ type: Object })
|
||||||
|
authState!: AuthState;
|
||||||
|
|
||||||
|
@property({ type: String })
|
||||||
|
archiveId!: string;
|
||||||
|
|
||||||
|
@property({ type: Boolean })
|
||||||
|
isNew!: boolean;
|
||||||
|
|
||||||
|
@property({ type: Array })
|
||||||
|
crawlTemplates?: CrawlTemplate[];
|
||||||
|
|
||||||
|
@state()
|
||||||
|
isRunNow: boolean = initialValues.runNow;
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.isNew) {
|
||||||
|
return this.renderNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.renderList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderNew() {
|
||||||
|
return html`
|
||||||
|
<h2 class="text-xl font-bold">${msg("New Crawl Template")}</h2>
|
||||||
|
<p>
|
||||||
|
${msg(
|
||||||
|
"Configure a new crawl template. You can choose to run a crawl immediately upon saving this template."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<main class="mt-4">
|
||||||
|
<sl-form @sl-submit=${this.onSubmit}>
|
||||||
|
<div class="border rounded-lg md:grid grid-cols-4">
|
||||||
|
<div class="col-span-1 p-4 md:p-8 md:border-b">
|
||||||
|
<h3 class="text-lg font-medium">${msg("Basic settings")}</h3>
|
||||||
|
</div>
|
||||||
|
<section class="col-span-3 p-4 md:p-8 border-b grid gap-5">
|
||||||
|
<div>
|
||||||
|
<sl-input
|
||||||
|
name="name"
|
||||||
|
label=${msg("Name")}
|
||||||
|
placeholder=${msg("Example (example.com) Weekly Crawl", {
|
||||||
|
desc: "Example crawl template name",
|
||||||
|
})}
|
||||||
|
autocomplete="off"
|
||||||
|
value=${initialValues.name}
|
||||||
|
required
|
||||||
|
></sl-input>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-end">
|
||||||
|
<!-- TODO schedule time -->
|
||||||
|
<div>
|
||||||
|
<sl-select
|
||||||
|
name="schedule"
|
||||||
|
label=${msg("Schedule")}
|
||||||
|
value=${initialValues.schedule}
|
||||||
|
>
|
||||||
|
<sl-menu-item value="">None</sl-menu-item>
|
||||||
|
<sl-menu-item value="@daily">Daily</sl-menu-item>
|
||||||
|
<sl-menu-item value="@weekly">Weekly</sl-menu-item>
|
||||||
|
<sl-menu-item value="@monthly">Monthly</sl-menu-item>
|
||||||
|
</sl-select>
|
||||||
|
</div>
|
||||||
|
<!-- <div>
|
||||||
|
<btrix-input
|
||||||
|
name="scheduleTime"
|
||||||
|
type="time"
|
||||||
|
></btrix-input>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<sl-switch
|
||||||
|
name="runNow"
|
||||||
|
?checked=${initialValues.runNow}
|
||||||
|
@sl-change=${(e: any) => (this.isRunNow = e.target.checked)}
|
||||||
|
>${msg("Run immediately")}</sl-switch
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<sl-input
|
||||||
|
name="crawlTimeoutMinutes"
|
||||||
|
label=${msg("Time limit")}
|
||||||
|
placeholder=${msg("unlimited")}
|
||||||
|
type="number"
|
||||||
|
>
|
||||||
|
<span slot="suffix">${msg("minutes")}</span>
|
||||||
|
</sl-input>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="col-span-1 p-4 md:p-8 md:border-b">
|
||||||
|
<h3 class="text-lg font-medium">${msg("Pages")}</h3>
|
||||||
|
</div>
|
||||||
|
<section class="col-span-3 p-4 md:p-8 border-b grid gap-5">
|
||||||
|
<div>
|
||||||
|
<sl-textarea
|
||||||
|
name="seedUrls"
|
||||||
|
label=${msg("Seed URLs")}
|
||||||
|
helpText=${msg("Separated by a new line, space or comma")}
|
||||||
|
placeholder=${msg(
|
||||||
|
`https://webrecorder.net\nhttps://example.com`,
|
||||||
|
{
|
||||||
|
desc: "Example seed URLs",
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
help-text=${msg(
|
||||||
|
"Separate URLs with a new line, space or comma."
|
||||||
|
)}
|
||||||
|
rows="3"
|
||||||
|
value=${initialValues.seedUrls}
|
||||||
|
required
|
||||||
|
></sl-textarea>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<sl-select
|
||||||
|
name="scopeType"
|
||||||
|
label=${msg("Scope type")}
|
||||||
|
value=${initialValues.scopeType}
|
||||||
|
>
|
||||||
|
<sl-menu-item value="page">Page</sl-menu-item>
|
||||||
|
<sl-menu-item value="page-spa">Page SPA</sl-menu-item>
|
||||||
|
<sl-menu-item value="prefix">Prefix</sl-menu-item>
|
||||||
|
<sl-menu-item value="host">Host</sl-menu-item>
|
||||||
|
<sl-menu-item value="any">Any</sl-menu-item>
|
||||||
|
</sl-select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<sl-input
|
||||||
|
name="limit"
|
||||||
|
label=${msg("Page limit")}
|
||||||
|
type="number"
|
||||||
|
placeholder=${msg("unlimited")}
|
||||||
|
>
|
||||||
|
<span slot="suffix">${msg("pages")}</span>
|
||||||
|
</sl-input>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="col-span-4 p-4 md:p-8 text-center">
|
||||||
|
${this.isRunNow
|
||||||
|
? html`
|
||||||
|
<p class="text-sm mb-3">
|
||||||
|
${msg("A crawl will start immediately on save.")}
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
|
||||||
|
<sl-button type="primary" submit
|
||||||
|
>${msg("Save Crawl Template")}</sl-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</sl-form>
|
||||||
|
</main>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderList() {
|
||||||
|
return html`
|
||||||
|
<div class="text-center">
|
||||||
|
<sl-button
|
||||||
|
@click=${() =>
|
||||||
|
this.navTo(`/archives/${this.archiveId}/crawl-templates/new`)}
|
||||||
|
>
|
||||||
|
<sl-icon slot="prefix" name="plus-square-dotted"></sl-icon>
|
||||||
|
${msg("Create new crawl template")}
|
||||||
|
</sl-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
${this.crawlTemplates?.map(
|
||||||
|
(template) => html`<div>${template.id}</div>`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async onSubmit(event: { detail: { formData: FormData } }) {
|
||||||
|
if (!this.authState) return;
|
||||||
|
|
||||||
|
const { formData } = event.detail;
|
||||||
|
|
||||||
|
const crawlTimeoutMinutes = formData.get("crawlTimeoutMinutes");
|
||||||
|
const pageLimit = formData.get("limit");
|
||||||
|
const seedUrlsStr = formData.get("seedUrls");
|
||||||
|
const params = {
|
||||||
|
name: formData.get("name"),
|
||||||
|
schedule: formData.get("schedule"),
|
||||||
|
runNow: this.isRunNow,
|
||||||
|
crawlTimeout: crawlTimeoutMinutes ? +crawlTimeoutMinutes * 60 : 0,
|
||||||
|
config: {
|
||||||
|
seeds: (seedUrlsStr as string).trim().replace(/,/g, " ").split(/\s+/g),
|
||||||
|
scopeType: formData.get("scopeType"),
|
||||||
|
limit: pageLimit ? +pageLimit : 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(params);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.apiFetch(
|
||||||
|
`/archives/${this.archiveId}/crawlconfigs/`,
|
||||||
|
this.authState,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
console.debug("success");
|
||||||
|
|
||||||
|
this.navTo(`/archives/${this.archiveId}/crawl-templates`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,18 @@
|
|||||||
import { state, property } from "lit/decorators.js";
|
import { state, property } from "lit/decorators.js";
|
||||||
import { msg, localized, str } from "@lit/localize";
|
import { msg, localized, str } from "@lit/localize";
|
||||||
|
|
||||||
import type { AuthState } from "../utils/AuthService";
|
import type { AuthState } from "../../utils/AuthService";
|
||||||
import type { CurrentUser } from "../types/user";
|
import type { CurrentUser } from "../../types/user";
|
||||||
import type { ArchiveData } from "../utils/archives";
|
import type { ArchiveData } from "../../utils/archives";
|
||||||
import LiteElement, { html } from "../utils/LiteElement";
|
import LiteElement, { html } from "../../utils/LiteElement";
|
||||||
import { needLogin } from "../utils/auth";
|
import { needLogin } from "../../utils/auth";
|
||||||
import { isOwner } from "../utils/archives";
|
import { isOwner } from "../../utils/archives";
|
||||||
|
import { CrawlTemplates } from "./crawl-templates";
|
||||||
|
|
||||||
export type ArchiveTab = "settings" | "members";
|
customElements.define("btrix-crawl-templates", CrawlTemplates);
|
||||||
|
|
||||||
|
export type ArchiveTab = "crawl-templates" | "settings" | "members";
|
||||||
|
type CrawlTemplate = any; // TODO
|
||||||
|
|
||||||
const defaultTab = "settings";
|
const defaultTab = "settings";
|
||||||
|
|
||||||
@ -30,9 +34,16 @@ export class Archive extends LiteElement {
|
|||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
isAddingMember: boolean = false;
|
isAddingMember: boolean = false;
|
||||||
|
|
||||||
|
/** Whether new resource is being added in tab */
|
||||||
|
@property({ type: Boolean })
|
||||||
|
isNewResourceTab: boolean = false;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private archive?: ArchiveData;
|
private archive?: ArchiveData;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private crawlTemplates?: CrawlTemplate[];
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private successfullyInvitedEmail?: string;
|
private successfullyInvitedEmail?: string;
|
||||||
|
|
||||||
@ -50,8 +61,18 @@ export class Archive extends LiteElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updated(changedProperties: any) {
|
async updated(changedProperties: any) {
|
||||||
if (changedProperties.has("isAddingMember") && this.isAddingMember) {
|
if (
|
||||||
|
changedProperties.has("archiveTab") &&
|
||||||
|
this.archiveTab === "crawl-templates" &&
|
||||||
|
!this.isNewResourceTab
|
||||||
|
) {
|
||||||
|
this.crawlTemplates = await this.getCrawlTemplates();
|
||||||
|
|
||||||
|
if (!this.crawlTemplates.length) {
|
||||||
|
this.navTo(`/archives/${this.archiveId}/crawl-templates/new`);
|
||||||
|
}
|
||||||
|
} else if (changedProperties.has("isAddingMember") && this.isAddingMember) {
|
||||||
this.successfullyInvitedEmail = undefined;
|
this.successfullyInvitedEmail = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,7 +86,7 @@ export class Archive extends LiteElement {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const showMembers = Boolean(this.archive.users);
|
const showMembersTab = Boolean(this.archive.users);
|
||||||
|
|
||||||
return html`<article class="grid gap-4">
|
return html`<article class="grid gap-4">
|
||||||
<nav class="font-medium text-sm text-gray-500">
|
<nav class="font-medium text-sm text-gray-500">
|
||||||
@ -81,13 +102,19 @@ export class Archive extends LiteElement {
|
|||||||
|
|
||||||
<main>
|
<main>
|
||||||
<sl-tab-group @sl-tab-show=${this.updateUrl}>
|
<sl-tab-group @sl-tab-show=${this.updateUrl}>
|
||||||
|
<sl-tab
|
||||||
|
slot="nav"
|
||||||
|
panel="crawl-templates"
|
||||||
|
?active=${this.archiveTab === "crawl-templates"}
|
||||||
|
>${msg("Crawl Templates")}</sl-tab
|
||||||
|
>
|
||||||
<sl-tab
|
<sl-tab
|
||||||
slot="nav"
|
slot="nav"
|
||||||
panel="settings"
|
panel="settings"
|
||||||
?active=${this.archiveTab === "settings"}
|
?active=${this.archiveTab === "settings"}
|
||||||
>${msg("Settings")}</sl-tab
|
>${msg("Settings")}</sl-tab
|
||||||
>
|
>
|
||||||
${showMembers
|
${showMembersTab
|
||||||
? html`<sl-tab
|
? html`<sl-tab
|
||||||
slot="nav"
|
slot="nav"
|
||||||
panel="members"
|
panel="members"
|
||||||
@ -101,7 +128,12 @@ export class Archive extends LiteElement {
|
|||||||
?active=${this.archiveTab === "settings"}
|
?active=${this.archiveTab === "settings"}
|
||||||
>${this.renderSettings()}</sl-tab-panel
|
>${this.renderSettings()}</sl-tab-panel
|
||||||
>
|
>
|
||||||
${showMembers
|
<sl-tab-panel
|
||||||
|
name="crawl-templates"
|
||||||
|
?active=${this.archiveTab === "crawl-templates"}
|
||||||
|
>${this.renderCrawlTemplates()}</sl-tab-panel
|
||||||
|
>
|
||||||
|
${showMembersTab
|
||||||
? html`<sl-tab-panel
|
? html`<sl-tab-panel
|
||||||
name="members"
|
name="members"
|
||||||
?active=${this.archiveTab === "members"}
|
?active=${this.archiveTab === "members"}
|
||||||
@ -120,6 +152,19 @@ export class Archive extends LiteElement {
|
|||||||
return html` TODO `;
|
return html` TODO `;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderCrawlTemplates() {
|
||||||
|
if (!this.isNewResourceTab && !this.crawlTemplates) {
|
||||||
|
return html` TODO `;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`<btrix-crawl-templates
|
||||||
|
.authState=${this.authState!}
|
||||||
|
.archiveId=${this.archiveId!}
|
||||||
|
.crawlTemplates=${this.crawlTemplates}
|
||||||
|
.isNew=${this.isNewResourceTab}
|
||||||
|
></btrix-crawl-templates>`;
|
||||||
|
}
|
||||||
|
|
||||||
private renderMembers() {
|
private renderMembers() {
|
||||||
if (!this.archive!.users) return;
|
if (!this.archive!.users) return;
|
||||||
|
|
||||||
@ -205,6 +250,15 @@ export class Archive extends LiteElement {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getCrawlTemplates(): Promise<CrawlTemplate[]> {
|
||||||
|
const data = await this.apiFetch(
|
||||||
|
`/archives/${this.archiveId}/crawlconfigs`,
|
||||||
|
this.authState!
|
||||||
|
);
|
||||||
|
|
||||||
|
return data.crawl_configs;
|
||||||
|
}
|
||||||
|
|
||||||
onInviteSuccess(
|
onInviteSuccess(
|
||||||
event: CustomEvent<{ inviteEmail: string; isExistingUser: boolean }>
|
event: CustomEvent<{ inviteEmail: string; isExistingUser: boolean }>
|
||||||
) {
|
) {
|
@ -12,6 +12,7 @@ export const ROUTES = {
|
|||||||
accountSettings: "/account/settings",
|
accountSettings: "/account/settings",
|
||||||
archives: "/archives",
|
archives: "/archives",
|
||||||
archive: "/archives/:id/:tab",
|
archive: "/archives/:id/:tab",
|
||||||
|
archiveNewResourceTab: "/archives/:id/:tab/new",
|
||||||
archiveAddMember: "/archives/:id/:tab/add-member",
|
archiveAddMember: "/archives/:id/:tab/add-member",
|
||||||
users: "/users",
|
users: "/users",
|
||||||
usersInvite: "/users/invite",
|
usersInvite: "/users/invite",
|
||||||
|
@ -38,6 +38,9 @@ import(
|
|||||||
import(
|
import(
|
||||||
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/spinner/spinner"
|
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/spinner/spinner"
|
||||||
);
|
);
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/switch/switch"
|
||||||
|
);
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/tab/tab"
|
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/tab/tab"
|
||||||
);
|
);
|
||||||
@ -47,5 +50,8 @@ import(
|
|||||||
import(
|
import(
|
||||||
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/tab-panel/tab-panel"
|
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/tab-panel/tab-panel"
|
||||||
);
|
);
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "shoelace" */ "@shoelace-style/shoelace/dist/components/textarea/textarea"
|
||||||
|
);
|
||||||
|
|
||||||
setBasePath("/shoelace");
|
setBasePath("/shoelace");
|
||||||
|
@ -15,9 +15,7 @@ export type ViewState = {
|
|||||||
// e.g. "/redirect?url"
|
// e.g. "/redirect?url"
|
||||||
params: { [key: string]: string };
|
params: { [key: string]: string };
|
||||||
};
|
};
|
||||||
export type NavigateEvent = {
|
export interface NavigateEvent extends CustomEvent {}
|
||||||
detail: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class APIRouter {
|
export default class APIRouter {
|
||||||
routes: Routes;
|
routes: Routes;
|
||||||
|
@ -11,7 +11,9 @@ export default class LiteElement extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
navTo(url: string) {
|
navTo(url: string) {
|
||||||
this.dispatchEvent(new CustomEvent("navigate", { detail: url }));
|
this.dispatchEvent(
|
||||||
|
new CustomEvent("navigate", { detail: url, bubbles: true })
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
navLink(event: Event) {
|
navLink(event: Event) {
|
||||||
|
Loading…
Reference in New Issue
Block a user