diff --git a/frontend/src/index.ts b/frontend/src/index.ts index 45a152e3..39b079c5 100644 --- a/frontend/src/index.ts +++ b/frontend/src/index.ts @@ -172,7 +172,9 @@ export class App extends LiteElement { window.history.pushState( this.viewState, "", - `${this.viewState.pathname}${url.hash}${url.search}` + `${this.viewState.pathname.replace(url.search, "")}${url.hash}${ + url.search + }` ); } diff --git a/frontend/src/pages/archive/browser-profiles-detail.ts b/frontend/src/pages/archive/browser-profiles-detail.ts index da4fe1c0..7d44a81e 100644 --- a/frontend/src/pages/archive/browser-profiles-detail.ts +++ b/frontend/src/pages/archive/browser-profiles-detail.ts @@ -23,13 +23,23 @@ export class BrowserProfilesDetail extends LiteElement { profileId!: string; @state() - private profile: Partial = { - id: "2", - name: "Twitter Webrecorder", - description: "Et netus et malesuada fames.", - created: new Date().toUTCString(), - origins: ["https://twitter.com", "https://twitter.com/webrecorder_io"], - }; + private profile?: Profile; + + @property({ type: Boolean }) + showCreateDialog = false; + + @state() + private isCreateFormVisible = false; + + @state() + private isSubmitting = false; + + /** Profile creation only works in Chromium-based browsers */ + private isBrowserCompatible = Boolean((window as any).chrome); + + firstUpdated() { + this.fetchProfile(); + } render() { return html`
@@ -48,9 +58,212 @@ export class BrowserProfilesDetail extends LiteElement {
-
-

${this.profile.name}

-
`; +
+

+ ${this.profile?.name || + html``} +

+
+ ${this.profile + ? html` (this.showCreateDialog = true)} + > + ${msg("Launch Browser Profile")}` + : html``} +
+
+ +
+
+
+
${msg("Description")}
+
+ ${this.profile + ? this.profile.description || + html`${msg("None")}` + : ""} +
+
+
+
+ ${msg("Created at")} +
+
+ ${this.profile + ? html` + + ` + : ""} +
+
+
+
${msg("Visited URLs")}
+
+
    + ${this.profile?.origins.map((url) => html`
  • ${url}
  • `)} +
+
+
+
+
+ + (this.isCreateFormVisible = true)} + @sl-after-hide=${() => (this.isCreateFormVisible = false)} + > +
+ ${this.isBrowserCompatible + ? "" + : html` + + ${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." + )} + + `} +
+ ${this.isCreateFormVisible ? this.renderCreateForm() : ""} +
`; + } + + private renderCreateForm() { + return html` +
+ + ${this.profile?.origins.map( + (origin) => html` + ${origin} + ` + )} + + +
+ ${msg("Cancel")} + + ${msg("Start Browser")} + +
+
+
`; + } + + private hideDialog() { + this.showCreateDialog = false; + } + + async onSubmit(event: { detail: { formData: FormData } }) { + if (!this.profile) return; + + this.isSubmitting = true; + + const { formData } = event.detail; + const url = formData.get("url") as string; + const params = { + url, + profileId: this.profile.id, + }; + + 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."), + type: "success", + icon: "check2-circle", + }); + + this.navTo( + `/archives/${this.archiveId}/browser-profiles/profile/browser/${ + data.browserid + }?name=${window.encodeURIComponent( + this.profile.name + )}&description=${window.encodeURIComponent( + this.profile.description || "" + )}&profileId=${window.encodeURIComponent(this.profile.id)}` + ); + } 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 profile and update internal state + */ + private async fetchProfile(): Promise { + try { + const data = await this.getProfile(); + + this.profile = data; + } catch (e) { + this.notify({ + message: msg("Sorry, couldn't retrieve browser profiles at this time."), + type: "danger", + icon: "exclamation-octagon", + }); + } + } + + private async getProfile(): Promise { + const data = await this.apiFetch( + `/archives/${this.archiveId}/profiles/${this.profileId}`, + this.authState! + ); + + 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(); } } diff --git a/frontend/src/pages/archive/browser-profiles-list.ts b/frontend/src/pages/archive/browser-profiles-list.ts index c4f84200..acd68d3c 100644 --- a/frontend/src/pages/archive/browser-profiles-list.ts +++ b/frontend/src/pages/archive/browser-profiles-list.ts @@ -126,7 +126,9 @@ export class BrowserProfilesList extends LiteElement { private renderItem(data: Profile) { return html`
@@ -191,7 +193,7 @@ export class BrowserProfilesList extends LiteElement {
= {}; + private pollTimerId?: number; connectedCallback() { @@ -52,12 +61,39 @@ export class BrowserProfilesNew extends LiteElement { } firstUpdated() { + const params = new URLSearchParams(window.location.search); + this.params = { + name: params.get("name") || msg("My Profile"), + description: params.get("description") || "", + profileId: params.get("profileId") || null, + }; + this.fetchBrowser(); } render() { return html` -
+ + +

${msg( "Interact with the browser to record your browser profile. When you’re finished interacting, name and save the profile." @@ -83,19 +119,19 @@ export class BrowserProfilesNew extends LiteElement { ` : html`

-
+
${this.browserUrl ? this.renderBrowser() : html`
`}
${document.fullscreenEnabled ? html` @@ -130,7 +166,21 @@ export class BrowserProfilesNew extends LiteElement { ` : ""} -
${this.renderForm()}
+
+ ${this.params.profileId + ? html` +
+ ${msg( + html`Viewing + ${this.params.name}` + )} +
+ ` + : ""} + ${this.renderForm()} +
`} @@ -148,7 +198,7 @@ export class BrowserProfilesNew extends LiteElement { desc: "Example browser profile name", })} autocomplete="off" - value="My Profile" + value=${this.params.name || ""} ?disabled=${!this.browserUrl} required > @@ -162,10 +212,21 @@ export class BrowserProfilesNew extends LiteElement { })} rows="2" autocomplete="off" + value=${this.params.description || ""} ?disabled=${!this.browserUrl} >
+ + ${msg("Cancel")} + + { // TODO see if we can make this work locally without CORs errors + const sidebarWidth = 288; try { //el.style.width = "132%"; el.contentWindow?.localStorage.setItem("uiTheme", '"default"'); el.contentWindow?.localStorage.setItem( "InspectorView.screencastSplitViewState", - '{"vertical":{"size":241}}' + `{"vertical":{"size":${sidebarWidth}}}` ); } catch (e) {} }); diff --git a/frontend/src/pages/archive/crawl-templates-detail.ts b/frontend/src/pages/archive/crawl-templates-detail.ts index f0564d4d..e00e7c58 100644 --- a/frontend/src/pages/archive/crawl-templates-detail.ts +++ b/frontend/src/pages/archive/crawl-templates-detail.ts @@ -123,7 +123,7 @@ export class CrawlTemplatesDetail extends LiteElement { `} ` - : html``} + : html``}
${msg("Crawl Template")}
@@ -591,10 +591,10 @@ export class CrawlTemplatesDetail extends LiteElement {
${msg("Browser Profile")}
${this.crawlTemplate ? html` - ${this.crawlTemplate.profileid + ${this.crawlTemplate.profileId ? html`