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