Skip to content

Commit

Permalink
Save new workflow scope type preference (#2099)
Browse files Browse the repository at this point in the history
Resolves #2091

<!-- Fixes #issue_number -->

### Changes

Saves scope type chosen from "+ New Workflow" dropdown to local storage, as well as from within workflow editor when creating a new workflow (but not editing an existing one).
  • Loading branch information
SuaYoo authored Oct 3, 2024
1 parent bb6e703 commit 22435dd
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 37 deletions.
12 changes: 7 additions & 5 deletions frontend/src/features/crawl-workflows/new-workflow-dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { html } from "lit";
import { customElement, property } from "lit/decorators.js";

import { TailwindElement } from "@/classes/TailwindElement";
import type { FormState as WorkflowFormState } from "@/utils/workflow";
import { WorkflowScopeType } from "@/types/workflow";
import seededCrawlSvg from "~assets/images/new-crawl-config_Seeded-Crawl.svg";
import urlListSvg from "~assets/images/new-crawl-config_URL-List.svg";

export type SelectJobTypeEvent = CustomEvent<WorkflowFormState["scopeType"]>;
export type SelectJobTypeEvent = CustomEvent<
(typeof WorkflowScopeType)[keyof typeof WorkflowScopeType]
>;

/**
* @event select-job-type SelectJobTypeEvent
Expand All @@ -33,8 +35,8 @@ export class NewWorkflowDialog extends TailwindElement {
@click=${() => {
this.dispatchEvent(
new CustomEvent("select-job-type", {
detail: "page-list",
}) as SelectJobTypeEvent,
detail: WorkflowScopeType.PageList,
}),
);
}}
>
Expand Down Expand Up @@ -63,7 +65,7 @@ export class NewWorkflowDialog extends TailwindElement {
@click=${() => {
this.dispatchEvent(
new CustomEvent("select-job-type", {
detail: "prefix",
detail: WorkflowScopeType.Prefix,
}) as SelectJobTypeEvent,
);
}}
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/features/crawl-workflows/workflow-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import {
import { maxLengthValidator } from "@/utils/form";
import { getLocale } from "@/utils/localization";
import { isArchivingDisabled } from "@/utils/orgs";
import { AppStateService } from "@/utils/state";
import { regexEscape } from "@/utils/string";
import { tw } from "@/utils/tailwind";
import {
Expand Down Expand Up @@ -1712,6 +1713,13 @@ https://archiveweb.page/images/${"logo.svg"}`}
}
}

if (!this.configId) {
// Remember scope type for new workflows
AppStateService.partialUpdateUserPreferences({
newWorkflowScopeType: value,
});
}

this.updateFormState(formState);
}

Expand Down
7 changes: 7 additions & 0 deletions frontend/src/pages/org/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,13 @@ export class Org extends LiteElement {
@select-new-dialog=${this.onSelectNewDialog}
@select-job-type=${(e: SelectJobTypeEvent) => {
this.openDialogName = undefined;
if (e.detail !== this.appState.userPreferences?.newWorkflowScopeType) {
AppStateService.partialUpdateUserPreferences({
newWorkflowScopeType: e.detail,
});
}
this.navTo(`${this.orgBasePath}/workflows/new`, {
scopeType: e.detail,
});
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/pages/org/workflows-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,12 @@ export class WorkflowsList extends LiteElement {
<sl-button
variant="primary"
size="small"
href="${this.orgBasePath}/workflows/new"
?disabled=${this.org?.readOnly}
@click=${this.navLink}
@click=${() =>
this.navTo(`${this.orgBasePath}/workflows/new`, {
scopeType:
this.appState.userPreferences?.newWorkflowScopeType,
})}
>
<sl-icon slot="prefix" name="plus-lg"></sl-icon>
${msg("New Workflow")}</sl-button
Expand Down
59 changes: 31 additions & 28 deletions frontend/src/pages/org/workflows-new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,10 @@ import { ScopeType, type Seed, type WorkflowParams } from "./types";

import type { UserGuideEventMap } from "@/index";
import { pageNav, type Breadcrumb } from "@/layouts/pageHeader";
import { WorkflowScopeType } from "@/types/workflow";
import LiteElement, { html } from "@/utils/LiteElement";
import type { FormState as WorkflowFormState } from "@/utils/workflow";

const defaultValue = {
name: "",
description: null,
profileid: null,
schedule: "",
config: {
seeds: [],
scopeType: ScopeType.Page,
exclude: [],
behaviorTimeout: null,
pageLoadTimeout: null,
pageExtraDelay: null,
postLoadDelay: null,
useSitemap: false,
failOnFailedSeed: false,
userAgent: null,
},
tags: [],
crawlTimeout: null,
maxCrawlSize: null,
jobType: "custom",
scale: 1,
autoAddCollections: [],
crawlerChannel: "default",
proxyId: null,
} as WorkflowParams;

/**
* Usage:
* ```ts
Expand All @@ -59,6 +33,35 @@ export class WorkflowsNew extends LiteElement {
@property({ type: Object })
initialWorkflow?: WorkflowParams;

private get defaultNewWorkflow(): WorkflowParams {
return {
name: "",
description: null,
profileid: null,
schedule: "",
config: {
scopeType: (this.appState.userPreferences?.newWorkflowScopeType ||
WorkflowScopeType.Page) as ScopeType,
exclude: [],
behaviorTimeout: null,
pageLoadTimeout: null,
pageExtraDelay: null,
postLoadDelay: null,
useSitemap: false,
failOnFailedSeed: false,
userAgent: null,
},
tags: [],
crawlTimeout: null,
maxCrawlSize: null,
jobType: "custom",
scale: 1,
autoAddCollections: [],
crawlerChannel: "default",
proxyId: null,
};
}

private renderBreadcrumbs() {
const breadcrumbs: Breadcrumb[] = [
{
Expand Down Expand Up @@ -103,7 +106,7 @@ export class WorkflowsNew extends LiteElement {
</header>
${when(this.org, (org) => {
const initialWorkflow = mergeDeep(
defaultValue,
this.defaultNewWorkflow,
{
profileid: org.crawlingDefaults?.profileid,
config: {
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/types/user.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { z } from "zod";

import { accessCodeSchema } from "./org";
import { WorkflowScopeType } from "./workflow";

export const userOrgSchema = z.object({
default: z.boolean().optional(),
Expand Down Expand Up @@ -44,3 +45,8 @@ export const userInfoSchema = z.object({
orgs: z.array(userOrgSchema),
});
export type UserInfo = z.infer<typeof userInfoSchema>;

export const userPreferencesSchema = z.object({
newWorkflowScopeType: z.nativeEnum(WorkflowScopeType).optional(),
});
export type UserPreferences = z.infer<typeof userPreferencesSchema>;
35 changes: 33 additions & 2 deletions frontend/src/utils/state.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
/**
* Store and access application-wide state
*/
import { mergeDeep } from "immutable";
import { locked, options, transaction, use } from "lit-shared-state";

import { persist } from "./persist";

import { authSchema, type Auth } from "@/types/auth";
import type { OrgData } from "@/types/org";
import { userInfoSchema, type UserInfo, type UserOrg } from "@/types/user";
import {
userInfoSchema,
userPreferencesSchema,
type UserInfo,
type UserOrg,
type UserPreferences,
} from "@/types/user";
import type { AppSettings } from "@/utils/app";
import { isAdmin, isCrawler } from "@/utils/orgs";

Expand All @@ -28,11 +35,15 @@ export function makeAppStateService() {
@options(persist(window.sessionStorage))
userInfo: UserInfo | null = null;

@options(persist(window.localStorage))
userPreferences: UserPreferences | null = null;

// TODO persist here
auth: Auth | null = null;

// Store org slug in local storage in order to redirect
// to the most recently visited org on next log in
// TODO move to `userPreferences`
@options(persist(window.localStorage))
orgSlug: string | null = null;

Expand All @@ -52,7 +63,7 @@ export function makeAppStateService() {
)) ||
null;

if (!userOrg) {
if (appState.userInfo && !userOrg) {
console.debug("no user org matching slug in state");
}

Expand Down Expand Up @@ -113,6 +124,25 @@ export function makeAppStateService() {
}
}

@transaction()
@unlock()
partialUpdateUserPreferences(
userPreferences: Partial<AppState["userPreferences"]>,
) {
userPreferencesSchema.nullable().parse(userPreferences);

if (appState.userPreferences && userPreferences) {
appState.userPreferences = mergeDeep(
appState.userPreferences,
userPreferences,
);
} else {
appState.userPreferences = userPreferences;
}

console.log("appState.userPreferences:", appState.userPreferences);
}

@transaction()
@unlock()
updateOrgSlug(orgSlug: AppState["orgSlug"]) {
Expand Down Expand Up @@ -152,6 +182,7 @@ export function makeAppStateService() {
private _resetUser() {
appState.auth = null;
appState.userInfo = null;
appState.userPreferences = null;
appState.orgSlug = null;
appState.org = undefined;
}
Expand Down

0 comments on commit 22435dd

Please sign in to comment.