feat: Workflow form collapsible section enhancements (#2381)
Resolves https://github.com/webrecorder/browsertrix/issues/2359 ## Changes - Track when a workflow form section is opened - Hide workflow form section navigation on small screens --------- Co-authored-by: Ilya Kreymer <ikreymer@users.noreply.github.com> Co-authored-by: Emma Segal-Grossman <hi@emma.cafe> Co-authored-by: Ilya Kreymer <ikreymer@gmail.com>
This commit is contained in:
parent
3ca68bf1d2
commit
8db80f5570
@ -5,8 +5,6 @@ import { ifDefined } from "lit/directives/if-defined.js";
|
||||
import { TailwindElement } from "@/classes/TailwindElement";
|
||||
|
||||
const DEFAULT_PANEL_ID = "default-panel";
|
||||
// postcss-lit-disable-next-line
|
||||
export const TWO_COL_SCREEN_MIN_CSS = css`64.5rem`;
|
||||
|
||||
const tabTagName = "btrix-tab-list-tab" as const;
|
||||
|
||||
@ -58,12 +56,6 @@ export class TabList extends TailwindElement {
|
||||
--track-width: 4px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: ${TWO_COL_SCREEN_MIN_CSS}) {
|
||||
.navWrapper {
|
||||
overflow: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
grid-area: header;
|
||||
font-size: var(--sl-font-size-large);
|
||||
@ -94,12 +86,6 @@ export class TabList extends TailwindElement {
|
||||
margin-left: var(--track-width);
|
||||
}
|
||||
|
||||
@media only screen and (min-width: ${TWO_COL_SCREEN_MIN_CSS}) {
|
||||
.tablist {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.track {
|
||||
display: none;
|
||||
position: absolute;
|
||||
@ -118,13 +104,6 @@ export class TabList extends TailwindElement {
|
||||
border-radius: var(--track-width);
|
||||
background-color: var(--sl-color-primary-500);
|
||||
}
|
||||
|
||||
@media only screen and (min-width: ${TWO_COL_SCREEN_MIN_CSS}) {
|
||||
.show-indicator .track,
|
||||
.show-indicator .indicator {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// ID of active tab
|
||||
@ -178,7 +157,9 @@ export class TabList extends TailwindElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<div class="navWrapper min-w-0">${this.renderNav()}</div>`;
|
||||
return html`<div class="min-w-0 lg:overflow-hidden">
|
||||
${this.renderNav()}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
renderNav() {
|
||||
@ -193,11 +174,14 @@ export class TabList extends TailwindElement {
|
||||
? "hide-indicator"
|
||||
: "show-indicator"} -mx-3 overflow-x-hidden px-3"
|
||||
>
|
||||
<div class="track" role="presentation">
|
||||
<div class="indicator" role="presentation"></div>
|
||||
<div class="track lg:block" role="presentation">
|
||||
<div class="indicator lg:block" role="presentation"></div>
|
||||
</div>
|
||||
|
||||
<ul class="tablist -mx-3 overflow-x-auto px-3" role="tablist">
|
||||
<ul
|
||||
class="tablist -mx-3 overflow-x-auto px-3 lg:flex-col"
|
||||
role="tablist"
|
||||
>
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -59,9 +59,11 @@ import { panel } from "@/layouts/panel";
|
||||
import infoTextStrings from "@/strings/crawl-workflows/infoText";
|
||||
import scopeTypeLabels from "@/strings/crawl-workflows/scopeType";
|
||||
import sectionStrings from "@/strings/crawl-workflows/section";
|
||||
import { AnalyticsTrackEvent } from "@/trackEvents";
|
||||
import { ScopeType, type Seed, type WorkflowParams } from "@/types/crawler";
|
||||
import type { UnderlyingFunction } from "@/types/utils";
|
||||
import { NewWorkflowOnlyScopeType } from "@/types/workflow";
|
||||
import { track } from "@/utils/analytics";
|
||||
import { isApiError } from "@/utils/api";
|
||||
import { DEPTH_SUPPORTED_SCOPES, isPageScopeType } from "@/utils/crawler";
|
||||
import {
|
||||
@ -69,6 +71,7 @@ import {
|
||||
humanizeNextDate,
|
||||
humanizeSchedule,
|
||||
} from "@/utils/cron";
|
||||
import { makeCurrentTargetHandler, stopProp } from "@/utils/events";
|
||||
import { formValidator, maxLengthValidator } from "@/utils/form";
|
||||
import localize from "@/utils/localize";
|
||||
import { isArchivingDisabled } from "@/utils/orgs";
|
||||
@ -234,6 +237,7 @@ export class WorkflowEditor extends BtrixElement {
|
||||
threshold: 0.2, // stricter; default is 0.6
|
||||
});
|
||||
|
||||
private readonly handleCurrentTarget = makeCurrentTargetHandler(this);
|
||||
private readonly checkFormValidity = formValidator(this);
|
||||
private readonly validateNameMax = maxLengthValidator(50);
|
||||
private readonly validateDescriptionMax = maxLengthValidator(350);
|
||||
@ -405,7 +409,10 @@ export class WorkflowEditor extends BtrixElement {
|
||||
};
|
||||
|
||||
return html`
|
||||
<btrix-tab-list tab=${ifDefined(this.progressState?.activeTab)}>
|
||||
<btrix-tab-list
|
||||
class="hidden lg:block"
|
||||
tab=${ifDefined(this.progressState?.activeTab)}
|
||||
>
|
||||
${STEPS.map(button)}
|
||||
</btrix-tab-list>
|
||||
`;
|
||||
@ -436,13 +443,17 @@ export class WorkflowEditor extends BtrixElement {
|
||||
activeTab: name,
|
||||
});
|
||||
}}
|
||||
@sl-show=${() => {
|
||||
@sl-show=${this.handleCurrentTarget(() => {
|
||||
this.pauseObserve();
|
||||
this.updateProgressState({
|
||||
activeTab: name,
|
||||
});
|
||||
}}
|
||||
@sl-hide=${(e: SlHideEvent) => {
|
||||
|
||||
track(AnalyticsTrackEvent.ExpandWorkflowFormSection, {
|
||||
section: name,
|
||||
});
|
||||
})}
|
||||
@sl-hide=${this.handleCurrentTarget((e: SlHideEvent) => {
|
||||
const el = e.currentTarget as SlDetails;
|
||||
|
||||
// Check if there's any invalid elements before hiding
|
||||
@ -461,12 +472,19 @@ export class WorkflowEditor extends BtrixElement {
|
||||
invalidEl.focus();
|
||||
invalidEl.checkValidity();
|
||||
}
|
||||
}}
|
||||
@sl-after-show=${this.resumeObserve}
|
||||
@sl-after-hide=${this.resumeObserve}
|
||||
})}
|
||||
@sl-after-show=${this.handleCurrentTarget(this.resumeObserve)}
|
||||
@sl-after-hide=${this.handleCurrentTarget(this.resumeObserve)}
|
||||
>
|
||||
<div slot="expand-icon" class="flex items-center">
|
||||
<sl-tooltip content=${msg("Show section")} hoist>
|
||||
<sl-tooltip
|
||||
content=${msg("Show section")}
|
||||
hoist
|
||||
@sl-show=${stopProp}
|
||||
@sl-hide=${stopProp}
|
||||
@sl-after-show=${stopProp}
|
||||
@sl-after-hide=${stopProp}
|
||||
>
|
||||
<sl-icon name="chevron-down" class="size-5"></sl-icon>
|
||||
</sl-tooltip>
|
||||
</div>
|
||||
@ -477,6 +495,10 @@ export class WorkflowEditor extends BtrixElement {
|
||||
<sl-tooltip
|
||||
content=${msg("Please fix all errors in this section")}
|
||||
hoist
|
||||
@sl-show=${stopProp}
|
||||
@sl-hide=${stopProp}
|
||||
@sl-after-show=${stopProp}
|
||||
@sl-after-hide=${stopProp}
|
||||
>
|
||||
<sl-icon
|
||||
name="exclamation-lg"
|
||||
|
@ -3,7 +3,17 @@
|
||||
*/
|
||||
|
||||
export enum AnalyticsTrackEvent {
|
||||
/**
|
||||
* Generic
|
||||
*/
|
||||
PageView = "pageview",
|
||||
/**
|
||||
* Collections
|
||||
*/
|
||||
CopyShareCollectionLink = "Copy share collection link",
|
||||
DownloadPublicCollection = "Download public collection",
|
||||
/**
|
||||
* Workflows
|
||||
*/
|
||||
ExpandWorkflowFormSection = "Expand workflow form section",
|
||||
}
|
||||
|
@ -8,9 +8,10 @@
|
||||
import { AnalyticsTrackEvent } from "../trackEvents";
|
||||
|
||||
export type AnalyticsTrackProps = {
|
||||
org_slug: string | null;
|
||||
collection_slug?: string | null;
|
||||
org_slug?: string | null;
|
||||
logged_in?: boolean;
|
||||
collection_slug?: string;
|
||||
section?: string;
|
||||
};
|
||||
|
||||
declare global {
|
||||
|
38
frontend/src/utils/events.ts
Normal file
38
frontend/src/utils/events.ts
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Ignore events bubbling from children. Common use case would be
|
||||
* ignoring @sl-hide events from tooltips within a dialog.
|
||||
*
|
||||
* @example Usage:
|
||||
* ```
|
||||
* <btrix-element
|
||||
* @sl-hide=${makeCurrentTargetHandler(this)(() => console.log("Only current target!"))}
|
||||
* >
|
||||
* </btrix-element>
|
||||
* ```
|
||||
*/
|
||||
export function makeCurrentTargetHandler(t: EventTarget) {
|
||||
const currentTargetHandler: <T extends Event = CustomEvent>(
|
||||
handler: (event: T) => void,
|
||||
) => (event: T) => void = (handler) => (e) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
handler.bind(t)(e);
|
||||
}
|
||||
};
|
||||
|
||||
return currentTargetHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop propgation shorthand.
|
||||
*
|
||||
* @example Usage:
|
||||
* ```
|
||||
* <btrix-element
|
||||
* @sl-show=${stopProp}
|
||||
* >
|
||||
* </btrix-element>
|
||||
* ```
|
||||
*/
|
||||
export function stopProp(e: Event) {
|
||||
e.stopPropagation();
|
||||
}
|
Loading…
Reference in New Issue
Block a user