Fix in-app link UX (#132)

closes #130, closes #113
This commit is contained in:
sua yoo 2022-01-31 17:36:50 -08:00 committed by GitHub
parent adb5c835f2
commit d7f58c964c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 26 deletions

View File

@ -1,4 +1,5 @@
import type { TemplateResult } from "lit"; import type { TemplateResult } from "lit";
import { render } from "lit";
import { state, query } from "lit/decorators.js"; import { state, query } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
import { msg, localized } from "@lit/localize"; import { msg, localized } from "@lit/localize";
@ -491,6 +492,9 @@ export class App extends LiteElement {
}; };
} }
/**
* Show global toast alert
*/
onNotify(event: NotifyEvent) { onNotify(event: NotifyEvent) {
event.stopPropagation(); event.stopPropagation();
@ -502,7 +506,8 @@ export class App extends LiteElement {
duration = 5000, duration = 5000,
} = event.detail; } = event.detail;
const alert = Object.assign(document.createElement("sl-alert"), { const container = document.createElement("sl-alert");
const alert = Object.assign(container, {
type: type, type: type,
closable: true, closable: true,
duration: duration, duration: duration,
@ -512,16 +517,16 @@ export class App extends LiteElement {
// "--sl-panel-border-width: 0px", // "--sl-panel-border-width: 0px",
"--sl-spacing-large: var(--sl-spacing-medium)", "--sl-spacing-large: var(--sl-spacing-medium)",
].join(";"), ].join(";"),
innerHTML: `
<sl-icon name="${icon}" slot="icon"></sl-icon>
<span>
${title ? `<strong>${title}</strong>` : ""}
${message ? `<div>${message}</div>` : ""}
</span>
`,
}); });
render(
html`
<sl-icon name="${icon}" slot="icon"></sl-icon>
${title ? html`<strong>${title}</strong>` : ""}
${message ? html`<div>${message}</div>` : ""}
`,
container
);
document.body.append(alert); document.body.append(alert);
alert.toast(); alert.toast();
} }

View File

@ -415,11 +415,14 @@ export class CrawlTemplatesDetail extends LiteElement {
this.notify({ this.notify({
message: msg( message: msg(
str`Started crawl from <strong>${ html`Started crawl from <strong>${this.crawlTemplate!.name}</strong>.
this.crawlTemplate!.name <br />
}</strong>. <br /><a class="underline hover:no-underline" href="/archives/${ <a
this.archiveId class="underline hover:no-underline"
}/crawls/crawl/${data.started}">View crawl</a>` href="/archives/${this.archiveId}/crawls/crawl/${data.started}"
@click=${this.navLink.bind(this)}
>View crawl</a
>`
), ),
type: "success", type: "success",
icon: "check2-circle", icon: "check2-circle",

View File

@ -47,7 +47,6 @@ export class CrawlTemplatesList extends LiteElement {
message: msg("Sorry, couldn't retrieve crawl templates at this time."), message: msg("Sorry, couldn't retrieve crawl templates at this time."),
type: "danger", type: "danger",
icon: "exclamation-octagon", icon: "exclamation-octagon",
duration: 10000,
}); });
} }
} }
@ -379,7 +378,7 @@ export class CrawlTemplatesList extends LiteElement {
); );
this.notify({ this.notify({
message: msg(str`Deleted <strong>${template.name}</strong>.`), message: msg(html`Deleted <strong>${template.name}</strong>.`),
type: "success", type: "success",
icon: "check2-circle", icon: "check2-circle",
}); });
@ -415,7 +414,13 @@ export class CrawlTemplatesList extends LiteElement {
this.notify({ this.notify({
message: msg( message: msg(
str`Started crawl from <strong>${template.name}</strong>. <br /><a class="underline hover:no-underline" href="/archives/${this.archiveId}/crawls/crawl/${data.started}">View crawl</a>` html`Started crawl from <strong>${template.name}</strong>. <br />
<a
class="underline hover:no-underline"
href="/archives/${this.archiveId}/crawls/crawl/${data.started}"
@click=${this.navLink.bind(this)}
>View crawl</a
>`
), ),
type: "success", type: "success",
icon: "check2-circle", icon: "check2-circle",

View File

@ -543,7 +543,14 @@ export class CrawlTemplatesNew extends LiteElement {
this.notify({ this.notify({
message: data.run_now_job message: data.run_now_job
? msg( ? msg(
str`Crawl running with new template. <br /><a class="underline hover:no-underline" href="/archives/${this.archiveId}/crawls/crawl/${data.started}">View crawl</a>` html`Crawl running with new template. <br />
<a
class="underline hover:no-underline"
href="/archives/${this
.archiveId}/crawls/crawl/${data.started}"
@click=${this.navLink.bind(this)}
>View crawl</a
>`
) )
: msg("Crawl template created."), : msg("Crawl template created."),
type: "success", type: "success",

View File

@ -46,7 +46,6 @@ export class CrawlTemplatesList extends LiteElement {
message: msg("Sorry, couldn't retrieve crawl templates at this time."), message: msg("Sorry, couldn't retrieve crawl templates at this time."),
type: "danger", type: "danger",
icon: "exclamation-octagon", icon: "exclamation-octagon",
duration: 10000,
}); });
} }
} }
@ -119,7 +118,7 @@ export class CrawlTemplatesList extends LiteElement {
); );
this.notify({ this.notify({
message: msg(str`Deleted <strong>${template.name}</strong>.`), message: msg(html`Deleted <strong>${template.name}</strong>.`),
type: "success", type: "success",
icon: "check2-circle", icon: "check2-circle",
}); });
@ -155,7 +154,13 @@ export class CrawlTemplatesList extends LiteElement {
this.notify({ this.notify({
message: msg( message: msg(
str`Started crawl from <strong>${template.name}</strong>. <br /><a class="underline hover:no-underline" href="/archives/${this.archiveId}/crawls/crawl/${data.started}">View crawl</a>` html`Started crawl from <strong>${template.name}</strong>. <br />
<a
class="underline hover:no-underline"
href="/archives/${this.archiveId}/crawls/crawl/${data.started}"
@click=${this.navLink.bind(this)}
>View crawl</a
>`
), ),
type: "success", type: "success",
icon: "check2-circle", icon: "check2-circle",

View File

@ -242,7 +242,17 @@ export class CrawlsList extends LiteElement {
title=${crawl.configName || crawl.cid} title=${crawl.configName || crawl.cid}
> >
<div class="col-span-12 md:col-span-5"> <div class="col-span-12 md:col-span-5">
<div class="font-medium mb-1">${crawl.configName || crawl.cid}</div> <div class="font-medium mb-1">
<a
href=${`/archives/${this.archiveId}/crawls/crawl/${crawl.id}`}
@click=${(e: any) => {
e.stopPropagation();
this.navLink(e);
}}
>
${crawl.configName || crawl.cid}
</a>
</div>
<div class="text-0-700 text-sm whitespace-nowrap truncate"> <div class="text-0-700 text-sm whitespace-nowrap truncate">
<sl-format-date <sl-format-date
date=${`${crawl.started}Z` /** Z for UTC */} date=${`${crawl.started}Z` /** Z for UTC */}

View File

@ -1,4 +1,5 @@
import { LitElement, html } from "lit"; import { LitElement, html } from "lit";
import type { TemplateResult } from "lit";
import type { Auth } from "../utils/AuthService"; import type { Auth } from "../utils/AuthService";
import { APIError } from "./api"; import { APIError } from "./api";
@ -14,10 +15,23 @@ export interface NotifyEvent extends CustomEvent {
detail: { detail: {
/** /**
* Notification message body. * Notification message body.
* Can contain HTML. * Example:
* HTML is rendered as-is without sanitation * ```ts
* message: html`<strong>Look!</strong>`
* ```
*
* Note: In order for `this` methods to work, you'll
* need to bind `this` or use a fat arrow function.
* For example:
* ```ts
* message: html`<button @click=${this.onClick.bind(this)}>Go!</button>`
* ```
* Or:
* ```ts
* message: html`<button @click=${(e) => this.onClick(e)}>Go!</button>`
* ```
**/ **/
message: string; message: string | TemplateResult;
/** Notification title */ /** Notification title */
title?: string; title?: string;
/** Shoelace icon name */ /** Shoelace icon name */
@ -50,7 +64,17 @@ export default class LiteElement extends LitElement {
* ``` * ```
* @param event Click event * @param event Click event
*/ */
navLink(event: Event): void { navLink(event: MouseEvent, href?: string): void {
// Detect keypress for opening in a new tab
if (
event.ctrlKey ||
event.shiftKey ||
event.metaKey ||
(event.button && event.button == 1)
) {
return;
}
event.preventDefault(); event.preventDefault();
const evt: NavigateEvent = new CustomEvent("navigate", { const evt: NavigateEvent = new CustomEvent("navigate", {