Create browser profile UI (#211)
This commit is contained in:
parent
d2653ae835
commit
f5993e8ad8
@ -431,6 +431,7 @@ export class App extends LiteElement {
|
|||||||
case "archiveNewResourceTab":
|
case "archiveNewResourceTab":
|
||||||
case "archiveCrawl":
|
case "archiveCrawl":
|
||||||
case "browserProfile":
|
case "browserProfile":
|
||||||
|
case "browser":
|
||||||
case "crawlTemplate":
|
case "crawlTemplate":
|
||||||
case "crawlTemplateEdit":
|
case "crawlTemplateEdit":
|
||||||
return html`<btrix-archive
|
return html`<btrix-archive
|
||||||
@ -444,6 +445,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}
|
||||||
browserProfileId=${this.viewState.params.browserProfileId}
|
browserProfileId=${this.viewState.params.browserProfileId}
|
||||||
|
browserId=${this.viewState.params.browserId}
|
||||||
crawlConfigId=${this.viewState.params.crawlConfigId}
|
crawlConfigId=${this.viewState.params.crawlConfigId}
|
||||||
crawlId=${this.viewState.params.crawlId}
|
crawlId=${this.viewState.params.crawlId}
|
||||||
?isAddingMember=${this.viewState.route === "archiveAddMember"}
|
?isAddingMember=${this.viewState.route === "archiveAddMember"}
|
||||||
|
@ -8,7 +8,10 @@ import { Profile } from "./types";
|
|||||||
/**
|
/**
|
||||||
* Usage:
|
* Usage:
|
||||||
* ```ts
|
* ```ts
|
||||||
* <btrix-browser-profiles-list></btrix-browser-profiles-list>
|
* <btrix-browser-profiles-list
|
||||||
|
* authState=${authState}
|
||||||
|
* archiveId=${archiveId}
|
||||||
|
* ></btrix-browser-profiles-list>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@localized()
|
@localized()
|
||||||
@ -17,20 +20,74 @@ export class BrowserProfilesList extends LiteElement {
|
|||||||
authState!: AuthState;
|
authState!: AuthState;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
archiveId?: string;
|
archiveId!: string;
|
||||||
|
|
||||||
|
@property({ type: Boolean })
|
||||||
|
showCreateDialog = false;
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
browserProfiles?: Profile[];
|
browserProfiles?: Profile[];
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private isCreateFormVisible = false;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private isSubmitting = false;
|
||||||
|
|
||||||
|
/** Profile creation only works in Chromium-based browsers */
|
||||||
|
private isBrowserCompatible = Boolean((window as any).chrome);
|
||||||
|
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
this.fetchCrawls();
|
if (this.showCreateDialog) {
|
||||||
|
this.isCreateFormVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fetchBrowserProfiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html` ${this.renderTable()} `;
|
return html`<header class="mb-3 text-right">
|
||||||
|
<a
|
||||||
|
href=${`/archives/${this.archiveId}/browser-profiles/new`}
|
||||||
|
class="inline-block bg-primary hover:bg-indigo-400 text-white text-center font-medium leading-none rounded px-3 py-2 transition-colors"
|
||||||
|
role="button"
|
||||||
|
@click=${this.navLink}
|
||||||
|
>
|
||||||
|
<sl-icon
|
||||||
|
class="inline-block align-middle mr-2"
|
||||||
|
name="plus-lg"
|
||||||
|
></sl-icon
|
||||||
|
><span class="inline-block align-middle mr-2 text-sm"
|
||||||
|
>${msg("New Browser Profile")}</span
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
${this.renderTable()}
|
||||||
|
|
||||||
|
<sl-dialog
|
||||||
|
label=${msg(str`New Browser Profile`)}
|
||||||
|
?open=${this.showCreateDialog}
|
||||||
|
@sl-request-close=${this.hideDialog}
|
||||||
|
@sl-show=${() => (this.isCreateFormVisible = true)}
|
||||||
|
@sl-after-hide=${() => (this.isCreateFormVisible = false)}
|
||||||
|
>
|
||||||
|
${this.isBrowserCompatible
|
||||||
|
? ""
|
||||||
|
: html`
|
||||||
|
<div class="mb-4">
|
||||||
|
<btrix-alert type="warning" class="text-sm">
|
||||||
|
${msg(
|
||||||
|
"Browser profile creation is only supported in Chromium-based browsers (such as Chrome) at this time. Please re-open this page in a compatible browser to proceed."
|
||||||
|
)}
|
||||||
|
</btrix-alert>
|
||||||
|
</div>
|
||||||
|
`}
|
||||||
|
${this.isCreateFormVisible ? this.renderCreateForm() : ""}
|
||||||
|
</sl-dialog> `;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTable() {
|
private renderTable() {
|
||||||
return html`
|
return html`
|
||||||
<div role="table">
|
<div role="table">
|
||||||
<div class="mb-2 px-4" role="rowgroup">
|
<div class="mb-2 px-4" role="rowgroup">
|
||||||
@ -90,10 +147,132 @@ export class BrowserProfilesList extends LiteElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderCreateForm() {
|
||||||
|
return html`<sl-form @sl-submit=${this.onSubmit}>
|
||||||
|
<div class="grid gap-5">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
id="startingUrlLabel"
|
||||||
|
class="text-sm leading-normal"
|
||||||
|
style="margin-bottom: var(--sl-spacing-3x-small)"
|
||||||
|
>${msg("Starting URL")}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="flex">
|
||||||
|
<sl-select
|
||||||
|
class="grow-0 mr-1"
|
||||||
|
name="urlPrefix"
|
||||||
|
value="https://"
|
||||||
|
hoist
|
||||||
|
?disabled=${!this.isBrowserCompatible}
|
||||||
|
@sl-hide=${this.stopProp}
|
||||||
|
@sl-after-hide=${this.stopProp}
|
||||||
|
>
|
||||||
|
<sl-menu-item value="http://">http://</sl-menu-item>
|
||||||
|
<sl-menu-item value="https://">https://</sl-menu-item>
|
||||||
|
</sl-select>
|
||||||
|
<sl-input
|
||||||
|
class="grow"
|
||||||
|
name="url"
|
||||||
|
placeholder=${msg("example.com")}
|
||||||
|
autocomplete="off"
|
||||||
|
aria-labelledby="startingUrlLabel"
|
||||||
|
?disabled=${!this.isBrowserCompatible}
|
||||||
|
required
|
||||||
|
>
|
||||||
|
</sl-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary class="text-sm text-neutral-500 font-medium cursor-pointer">
|
||||||
|
${msg("More options")}
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="p-3">
|
||||||
|
<sl-select
|
||||||
|
name="baseId"
|
||||||
|
label=${msg("Extend Profile")}
|
||||||
|
help-text=${msg("Extend an existing browser profile.")}
|
||||||
|
clearable
|
||||||
|
?disabled=${!this.isBrowserCompatible}
|
||||||
|
@sl-hide=${this.stopProp}
|
||||||
|
@sl-after-hide=${this.stopProp}
|
||||||
|
>
|
||||||
|
${this.browserProfiles?.map(
|
||||||
|
(profile) => html`
|
||||||
|
<sl-menu-item value=${profile.id}
|
||||||
|
>${profile.name}</sl-menu-item
|
||||||
|
>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</sl-select>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<div class="text-right">
|
||||||
|
<sl-button @click=${this.hideDialog}>${msg("Cancel")}</sl-button>
|
||||||
|
<sl-button
|
||||||
|
type="primary"
|
||||||
|
submit
|
||||||
|
?disabled=${!this.isBrowserCompatible || this.isSubmitting}
|
||||||
|
?loading=${this.isSubmitting}
|
||||||
|
>
|
||||||
|
${msg("Start Browser")}
|
||||||
|
</sl-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</sl-form>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private hideDialog() {
|
||||||
|
this.navTo(`/archives/${this.archiveId}/browser-profiles`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSubmit(event: { detail: { formData: FormData } }) {
|
||||||
|
this.isSubmitting = true;
|
||||||
|
|
||||||
|
const { formData } = event.detail;
|
||||||
|
const url = formData.get("url") as string;
|
||||||
|
const params = {
|
||||||
|
url: `${formData.get("urlPrefix")}${url.substring(url.indexOf(",") + 1)}`,
|
||||||
|
baseId: formData.get("baseId"),
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await this.apiFetch(
|
||||||
|
`/archives/${this.archiveId}/profiles/browser`,
|
||||||
|
this.authState!,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.notify({
|
||||||
|
message: msg("Starting up browser for profile creation."),
|
||||||
|
type: "success",
|
||||||
|
icon: "check2-circle",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.navTo(
|
||||||
|
`/archives/${this.archiveId}/browser-profiles/profile/browser/${data.browserid}`
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
this.isSubmitting = false;
|
||||||
|
|
||||||
|
this.notify({
|
||||||
|
message: msg("Sorry, couldn't create browser profile at this time."),
|
||||||
|
type: "danger",
|
||||||
|
icon: "exclamation-octagon",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch browser profiles and update internal state
|
* Fetch browser profiles and update internal state
|
||||||
*/
|
*/
|
||||||
private async fetchCrawls(): Promise<void> {
|
private async fetchBrowserProfiles(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const data = await this.getProfiles();
|
const data = await this.getProfiles();
|
||||||
|
|
||||||
@ -108,10 +287,6 @@ export class BrowserProfilesList extends LiteElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getProfiles(): Promise<Profile[]> {
|
private async getProfiles(): Promise<Profile[]> {
|
||||||
if (!this.archiveId) {
|
|
||||||
throw new Error(`Archive ID ${typeof this.archiveId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await this.apiFetch(
|
const data = await this.apiFetch(
|
||||||
`/archives/${this.archiveId}/profiles`,
|
`/archives/${this.archiveId}/profiles`,
|
||||||
this.authState!
|
this.authState!
|
||||||
@ -119,6 +294,15 @@ export class BrowserProfilesList extends LiteElement {
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop propgation of sl-select events.
|
||||||
|
* Prevents bug where sl-dialog closes when dropdown closes
|
||||||
|
* https://github.com/shoelace-style/shoelace/issues/170
|
||||||
|
*/
|
||||||
|
private stopProp(e: CustomEvent) {
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("btrix-browser-profiles-list", BrowserProfilesList);
|
customElements.define("btrix-browser-profiles-list", BrowserProfilesList);
|
||||||
|
337
frontend/src/pages/archive/browser-profiles-new.ts
Normal file
337
frontend/src/pages/archive/browser-profiles-new.ts
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
import { state, property } from "lit/decorators.js";
|
||||||
|
import { msg, localized, str } from "@lit/localize";
|
||||||
|
import { ref } from "lit/directives/ref.js";
|
||||||
|
|
||||||
|
import type { AuthState } from "../../utils/AuthService";
|
||||||
|
import LiteElement, { html } from "../../utils/LiteElement";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage:
|
||||||
|
* ```ts
|
||||||
|
* <btrix-browser-profiles-new
|
||||||
|
* authState=${authState}
|
||||||
|
* archiveId=${archiveId}
|
||||||
|
* browserId=${browserId}
|
||||||
|
* ></btrix-browser-profiles-new>
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
@localized()
|
||||||
|
export class BrowserProfilesNew extends LiteElement {
|
||||||
|
@property({ type: Object })
|
||||||
|
authState!: AuthState;
|
||||||
|
|
||||||
|
@property({ type: String })
|
||||||
|
archiveId!: string;
|
||||||
|
|
||||||
|
@property({ type: String })
|
||||||
|
browserId!: string;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private browserUrl?: string;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private isSubmitting = false;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private hasFetchError = false;
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private isFullscreen = false;
|
||||||
|
|
||||||
|
private pollTimerId?: number;
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
|
||||||
|
document.addEventListener("fullscreenchange", this.onFullscreenChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
window.clearTimeout(this.pollTimerId);
|
||||||
|
document.removeEventListener("fullscreenchange", this.onFullscreenChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
firstUpdated() {
|
||||||
|
this.fetchBrowser();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<div id="browserProfileInstructions" class="mb-5">
|
||||||
|
<p class="text-sm text-neutral-500">
|
||||||
|
${msg(
|
||||||
|
"Interact with the browser to record your browser profile. When you’re finished interacting, name and save the profile."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="interactive-browser" aria-live="polite">
|
||||||
|
${this.hasFetchError
|
||||||
|
? html`
|
||||||
|
<btrix-alert type="danger">
|
||||||
|
${msg(
|
||||||
|
html`The interactive browser is not available. Try creating a
|
||||||
|
new browser profile.
|
||||||
|
<a
|
||||||
|
class="font-medium underline"
|
||||||
|
href=${`/archives/${this.archiveId}/browser-profiles/new`}
|
||||||
|
@click=${this.navLink}
|
||||||
|
>Create New</a
|
||||||
|
>`
|
||||||
|
)}
|
||||||
|
</btrix-alert>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<div class="lg:flex bg-white">
|
||||||
|
<div class="grow lg:rounded-l overflow-hidden">
|
||||||
|
${this.browserUrl
|
||||||
|
? this.renderBrowser()
|
||||||
|
: html`
|
||||||
|
<div
|
||||||
|
class="aspect-video bg-slate-50 flex items-center justify-center text-4xl"
|
||||||
|
>
|
||||||
|
<sl-spinner></sl-spinner>
|
||||||
|
</div>
|
||||||
|
`}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="rounded-b lg:rounded-b-none lg:rounded-r border p-2 shadow-inner"
|
||||||
|
>
|
||||||
|
${document.fullscreenEnabled
|
||||||
|
? html`
|
||||||
|
<div class="mb-4 text-right">
|
||||||
|
<sl-button
|
||||||
|
type="neutral"
|
||||||
|
size="small"
|
||||||
|
@click=${() =>
|
||||||
|
this.isFullscreen
|
||||||
|
? document.exitFullscreen()
|
||||||
|
: this.enterFullscreen("interactive-browser")}
|
||||||
|
>
|
||||||
|
${this.isFullscreen
|
||||||
|
? html`
|
||||||
|
<sl-icon
|
||||||
|
slot="prefix"
|
||||||
|
name="fullscreen-exit"
|
||||||
|
label=${msg("Exit fullscreen")}
|
||||||
|
></sl-icon>
|
||||||
|
${msg("Exit")}
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<sl-icon
|
||||||
|
slot="prefix"
|
||||||
|
name="arrows-fullscreen"
|
||||||
|
label=${msg("Fullscreen")}
|
||||||
|
></sl-icon>
|
||||||
|
${msg("Go Fullscreen")}
|
||||||
|
`}
|
||||||
|
</sl-button>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
|
||||||
|
<div class="p-2">${this.renderForm()}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderForm() {
|
||||||
|
return html`<sl-form @sl-submit=${this.onSubmit}>
|
||||||
|
<div class="grid gap-5">
|
||||||
|
<sl-input
|
||||||
|
name="name"
|
||||||
|
label=${msg("Name")}
|
||||||
|
placeholder=${msg("Example (example.com)", {
|
||||||
|
desc: "Example browser profile name",
|
||||||
|
})}
|
||||||
|
autocomplete="off"
|
||||||
|
value="My Profile"
|
||||||
|
?disabled=${!this.browserUrl}
|
||||||
|
required
|
||||||
|
></sl-input>
|
||||||
|
|
||||||
|
<sl-textarea
|
||||||
|
name="description"
|
||||||
|
label=${msg("Description")}
|
||||||
|
help-text=${msg("Optional profile description")}
|
||||||
|
placeholder=${msg("Example (example.com) login profile", {
|
||||||
|
desc: "Example browser profile name",
|
||||||
|
})}
|
||||||
|
rows="2"
|
||||||
|
autocomplete="off"
|
||||||
|
?disabled=${!this.browserUrl}
|
||||||
|
></sl-textarea>
|
||||||
|
|
||||||
|
<div class="text-right">
|
||||||
|
<sl-button
|
||||||
|
type="primary"
|
||||||
|
submit
|
||||||
|
?disabled=${!this.browserUrl || this.isSubmitting}
|
||||||
|
?loading=${this.isSubmitting}
|
||||||
|
>
|
||||||
|
${msg("Save Profile")}
|
||||||
|
</sl-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</sl-form>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderBrowser() {
|
||||||
|
return html`
|
||||||
|
<iframe
|
||||||
|
class="w-full ${this.isFullscreen ? "h-screen" : "aspect-video"}"
|
||||||
|
title=${msg("Interactive browser for creating browser profile")}
|
||||||
|
src=${this.browserUrl!}
|
||||||
|
${ref((el) => this.onIframeRef(el as HTMLIFrameElement))}
|
||||||
|
></iframe>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch browser profiles and update internal state
|
||||||
|
*/
|
||||||
|
private async fetchBrowser(): Promise<void> {
|
||||||
|
try {
|
||||||
|
await this.checkBrowserStatus();
|
||||||
|
} catch (e) {
|
||||||
|
this.hasFetchError = true;
|
||||||
|
|
||||||
|
this.notify({
|
||||||
|
message: msg("Sorry, couldn't create browser profile at this time."),
|
||||||
|
type: "danger",
|
||||||
|
icon: "exclamation-octagon",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether temporary browser is up
|
||||||
|
**/
|
||||||
|
private async checkBrowserStatus() {
|
||||||
|
const result = await this.getBrowser();
|
||||||
|
|
||||||
|
if (result.detail === "waiting_for_browser") {
|
||||||
|
this.pollTimerId = window.setTimeout(
|
||||||
|
() => this.checkBrowserStatus(),
|
||||||
|
5 * 1000
|
||||||
|
);
|
||||||
|
} else if (result.url) {
|
||||||
|
this.browserUrl = result.url;
|
||||||
|
|
||||||
|
this.pingBrowser();
|
||||||
|
} else {
|
||||||
|
console.debug("Unknown checkBrowserStatus state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getBrowser(): Promise<{
|
||||||
|
detail?: string;
|
||||||
|
url?: string;
|
||||||
|
}> {
|
||||||
|
const data = await this.apiFetch(
|
||||||
|
`/archives/${this.archiveId}/profiles/browser/${this.browserId}`,
|
||||||
|
this.authState!
|
||||||
|
);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ping temporary browser every minute to keep it alive
|
||||||
|
**/
|
||||||
|
private async pingBrowser() {
|
||||||
|
await this.apiFetch(
|
||||||
|
`/archives/${this.archiveId}/profiles/browser/${this.browserId}/ping`,
|
||||||
|
this.authState!,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.pollTimerId = window.setTimeout(() => this.pingBrowser(), 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async onSubmit(event: { detail: { formData: FormData } }) {
|
||||||
|
this.isSubmitting = true;
|
||||||
|
|
||||||
|
if (this.isFullscreen) {
|
||||||
|
await document.exitFullscreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { formData } = event.detail;
|
||||||
|
const params = {
|
||||||
|
name: formData.get("name"),
|
||||||
|
description: formData.get("description"),
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await this.apiFetch(
|
||||||
|
`/archives/${this.archiveId}/profiles/browser/${this.browserId}/commit`,
|
||||||
|
this.authState!,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.notify({
|
||||||
|
message: msg("Successfully created browser profile."),
|
||||||
|
type: "success",
|
||||||
|
icon: "check2-circle",
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO nav to detail page
|
||||||
|
// this.navTo(
|
||||||
|
// `/archives/${this.archiveId}/browser-profiles/profile/${data.id}`
|
||||||
|
// );
|
||||||
|
this.navTo(`/archives/${this.archiveId}/browser-profiles`);
|
||||||
|
} catch (e) {
|
||||||
|
this.isSubmitting = false;
|
||||||
|
|
||||||
|
this.notify({
|
||||||
|
message: msg("Sorry, couldn't create browser profile at this time."),
|
||||||
|
type: "danger",
|
||||||
|
icon: "exclamation-octagon",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private onIframeRef(el: HTMLIFrameElement) {
|
||||||
|
el.addEventListener("load", () => {
|
||||||
|
// TODO see if we can make this work locally without CORs errors
|
||||||
|
el.contentWindow?.localStorage.setItem("uiTheme", '"default"');
|
||||||
|
el.contentWindow?.localStorage.setItem(
|
||||||
|
"InspectorView.screencastSplitViewState",
|
||||||
|
'{"vertical":{"size":241}}'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter fullscreen mode
|
||||||
|
* @param id ID of element to fullscreen
|
||||||
|
*/
|
||||||
|
private async enterFullscreen(id: string) {
|
||||||
|
try {
|
||||||
|
document.getElementById(id)!.requestFullscreen({
|
||||||
|
// Show browser navigation controls
|
||||||
|
navigationUI: "show",
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private onFullscreenChange = () => {
|
||||||
|
if (document.fullscreenElement) {
|
||||||
|
this.isFullscreen = true;
|
||||||
|
} else {
|
||||||
|
this.isFullscreen = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("btrix-browser-profiles-new", BrowserProfilesNew);
|
@ -69,7 +69,7 @@ export class CrawlTemplatesList extends LiteElement {
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href=${`/archives/${this.archiveId}/crawl-templates/new`}
|
href=${`/archives/${this.archiveId}/crawl-templates/new`}
|
||||||
class="col-span-1 bg-slate-50 border border-indigo-200 hover:border-indigo-400 text-primary text-center font-medium rounded px-6 py-4 transition-colors"
|
class="col-span-1 bg-slate-50 border border-indigo-200 hover:border-primary text-primary text-center font-medium rounded px-6 py-4 transition-colors"
|
||||||
@click=${this.navLink}
|
@click=${this.navLink}
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
@ -81,7 +81,7 @@ export class CrawlTemplatesList extends LiteElement {
|
|||||||
class="inline-block align-middle mr-2 ${this.crawlTemplates.length
|
class="inline-block align-middle mr-2 ${this.crawlTemplates.length
|
||||||
? "text-sm"
|
? "text-sm"
|
||||||
: "font-medium"}"
|
: "font-medium"}"
|
||||||
>${msg("Create New Crawl Template")}</span
|
>${msg("New Crawl Template")}</span
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -156,8 +156,8 @@ export class CrawlTemplatesNew extends LiteElement {
|
|||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<h2 class="text-xl font-bold mb-3">${msg("New Crawl Template")}</h2>
|
<h2 class="text-xl font-medium mb-3">${msg("New Crawl Template")}</h2>
|
||||||
<p>
|
<p class="text-neutral-500 text-sm">
|
||||||
${msg(
|
${msg(
|
||||||
"Configure a new crawl template. You can choose to run a crawl immediately upon saving this template."
|
"Configure a new crawl template. You can choose to run a crawl immediately upon saving this template."
|
||||||
)}
|
)}
|
||||||
@ -225,9 +225,7 @@ export class CrawlTemplatesNew extends LiteElement {
|
|||||||
<sl-input
|
<sl-input
|
||||||
name="name"
|
name="name"
|
||||||
label=${msg("Name")}
|
label=${msg("Name")}
|
||||||
help-text=${msg(
|
help-text=${msg("Name your template to easily identify it later.")}
|
||||||
"Required. Name your template to easily identify it later."
|
|
||||||
)}
|
|
||||||
placeholder=${msg("Example (example.com) Weekly Crawl", {
|
placeholder=${msg("Example (example.com) Weekly Crawl", {
|
||||||
desc: "Example crawl template name",
|
desc: "Example crawl template name",
|
||||||
})}
|
})}
|
||||||
|
@ -15,6 +15,7 @@ import "./crawl-detail";
|
|||||||
import "./crawls-list";
|
import "./crawls-list";
|
||||||
import "./browser-profiles-detail";
|
import "./browser-profiles-detail";
|
||||||
import "./browser-profiles-list";
|
import "./browser-profiles-list";
|
||||||
|
import "./browser-profiles-new";
|
||||||
|
|
||||||
export type ArchiveTab =
|
export type ArchiveTab =
|
||||||
| "crawls"
|
| "crawls"
|
||||||
@ -45,6 +46,9 @@ export class Archive extends LiteElement {
|
|||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
browserProfileId?: string;
|
browserProfileId?: string;
|
||||||
|
|
||||||
|
@property({ type: String })
|
||||||
|
browserId?: string;
|
||||||
|
|
||||||
@property({ type: String })
|
@property({ type: String })
|
||||||
crawlId?: string;
|
crawlId?: string;
|
||||||
|
|
||||||
@ -270,9 +274,18 @@ export class Archive extends LiteElement {
|
|||||||
></btrix-browser-profiles-detail>`;
|
></btrix-browser-profiles-detail>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.browserId) {
|
||||||
|
return html`<btrix-browser-profiles-new
|
||||||
|
.authState=${this.authState!}
|
||||||
|
.archiveId=${this.archiveId!}
|
||||||
|
.browserId=${this.browserId}
|
||||||
|
></btrix-browser-profiles-new>`;
|
||||||
|
}
|
||||||
|
|
||||||
return html`<btrix-browser-profiles-list
|
return html`<btrix-browser-profiles-list
|
||||||
.authState=${this.authState!}
|
.authState=${this.authState!}
|
||||||
.archiveId=${this.archiveId!}
|
.archiveId=${this.archiveId!}
|
||||||
|
?showCreateDialog=${this.isNewResourceTab}
|
||||||
></btrix-browser-profiles-list>`;
|
></btrix-browser-profiles-list>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ export const ROUTES = {
|
|||||||
archiveAddMember: "/archives/:id/:tab/add-member",
|
archiveAddMember: "/archives/:id/:tab/add-member",
|
||||||
archiveCrawl: "/archives/:id/:tab/crawl/:crawlId",
|
archiveCrawl: "/archives/:id/:tab/crawl/:crawlId",
|
||||||
browserProfile: "/archives/:id/:tab/profile/:browserProfileId",
|
browserProfile: "/archives/:id/:tab/profile/:browserProfileId",
|
||||||
|
browser: "/archives/:id/:tab/profile/browser/:browserId",
|
||||||
crawlTemplate: "/archives/:id/:tab/config/:crawlConfigId",
|
crawlTemplate: "/archives/:id/:tab/config/:crawlConfigId",
|
||||||
crawlTemplateEdit: "/archives/:id/:tab/config/:crawlConfigId?edit",
|
crawlTemplateEdit: "/archives/:id/:tab/config/:crawlConfigId?edit",
|
||||||
users: "/users",
|
users: "/users",
|
||||||
|
Loading…
Reference in New Issue
Block a user