Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Improve time to load org UI #2044

Merged
merged 8 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion frontend/src/components/screencast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ export class Screencast extends BtrixElement {
changedProperties: PropertyValues<this> & Map<string, unknown>,
) {
if (
changedProperties.get("appState.userOrg") ||
changedProperties.get("crawlId") ||
changedProperties.get("authToken")
) {
Expand Down
38 changes: 22 additions & 16 deletions frontend/src/components/ui/config-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import RegexColorize from "regex-colorize";
import { RelativeDuration } from "./relative-duration";

import type { CrawlConfig, Seed, SeedConfig } from "@/pages/org/types";
import type { AppSettings } from "@/types/app";
import type { Collection } from "@/types/collection";
import { isApiError } from "@/utils/api";
import { DEPTH_SUPPORTED_SCOPES } from "@/utils/crawler";
Expand Down Expand Up @@ -506,28 +507,33 @@ export class ConfigDetails extends LiteElement {

private async fetchAPIDefaults() {
try {
const resp = await fetch("/api/settings", {
headers: { "Content-Type": "application/json" },
});
if (!resp.ok) {
throw new Error(resp.statusText);
let settings: AppSettings;

if (!this.appState.settings) {
const resp = await fetch("/api/settings", {
headers: { "Content-Type": "application/json" },
});
if (!resp.ok) {
throw new Error(resp.statusText);
}
settings = (await resp.json()) as AppSettings;
} else {
settings = this.appState.settings;
}
const orgDefaults = {
...this.orgDefaults,
};
const data = (await resp.json()) as {
defaultBehaviorTimeSeconds: number;
defaultPageLoadTimeSeconds: number;
maxPagesPerCrawl: number;
};
if (data.defaultBehaviorTimeSeconds > 0) {
orgDefaults.behaviorTimeoutSeconds = data.defaultBehaviorTimeSeconds;

if (settings.defaultBehaviorTimeSeconds > 0) {
orgDefaults.behaviorTimeoutSeconds =
settings.defaultBehaviorTimeSeconds;
}
if (data.defaultPageLoadTimeSeconds > 0) {
orgDefaults.pageLoadTimeoutSeconds = data.defaultPageLoadTimeSeconds;
if (settings.defaultPageLoadTimeSeconds > 0) {
orgDefaults.pageLoadTimeoutSeconds =
settings.defaultPageLoadTimeSeconds;
}
if (data.maxPagesPerCrawl > 0) {
orgDefaults.maxPagesPerCrawl = data.maxPagesPerCrawl;
if (settings.maxPagesPerCrawl > 0) {
orgDefaults.maxPagesPerCrawl = settings.maxPagesPerCrawl;
}
this.orgDefaults = orgDefaults;
} catch (e) {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/features/accounts/account-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ export class AccountSettings extends LiteElement {
}),
});

AppStateService.updateUserInfo({
AppStateService.updateUser({
...this.userInfo,
name: newName,
});
Expand Down Expand Up @@ -381,7 +381,7 @@ export class AccountSettings extends LiteElement {
}),
});

AppStateService.updateUserInfo({
AppStateService.updateUser({
...this.userInfo,
email: newEmail,
});
Expand Down
42 changes: 19 additions & 23 deletions frontend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ export class App extends LiteElement {
this.authService.saveLogin(authState);
}
this.syncViewState();
if (authState) {
void this.updateUserInfo();
if (authState && !this.userInfo) {
void this.fetchAndUpdateUserInfo();
}
super.connectedCallback();

Expand All @@ -99,7 +99,10 @@ export class App extends LiteElement {
});

this.startSyncBrowserTabs();
void this.fetchAppSettings();

if (!this.appState.settings) {
void this.fetchAppSettings();
}
}

willUpdate(changedProperties: Map<string, unknown>) {
Expand Down Expand Up @@ -150,26 +153,14 @@ export class App extends LiteElement {
AppStateService.updateSettings(settings);
}

/**
* @deprecate Components should update user info directly through `AppStateService`
*/
private async updateUserInfo(e?: CustomEvent) {
private async fetchAndUpdateUserInfo(e?: CustomEvent) {
if (e) {
e.stopPropagation();
}
try {
const userInfo = await this.getUserInfo();
AppStateService.updateUserInfo(formatAPIUser(userInfo));
const orgs = userInfo.orgs;

if (
orgs.length &&
!this.userInfo!.isSuperAdmin &&
!this.appState.orgSlug
) {
const firstOrg = orgs[0].slug;
AppStateService.updateOrgSlug(firstOrg);
}
const user = await this.getUserInfo();

AppStateService.updateUser(formatAPIUser(user));
} catch (err) {
if ((err as Error | null | undefined)?.message === "Unauthorized") {
console.debug(
Expand Down Expand Up @@ -664,7 +655,6 @@ export class App extends LiteElement {
.viewStateData=${this.viewState.data}
.params=${this.viewState.params}
.maxScale=${this.appState.settings?.maxScale || DEFAULT_MAX_SCALE}
slug=${slug}
orgPath=${orgPath.split(slug)[1]}
orgTab=${orgTab as OrgTab}
></btrix-org>`;
Expand Down Expand Up @@ -817,7 +807,13 @@ export class App extends LiteElement {
this.onFirstLogin({ email: detail.username });
}

void this.updateUserInfo();
if (!this.userInfo) {
if (detail.user) {
AppStateService.updateUser(formatAPIUser(detail.user));
} else {
void this.fetchAndUpdateUserInfo();
}
}
}

onNeedLogin = (e: CustomEvent<NeedLoginEventDetail>) => {
Expand Down Expand Up @@ -851,7 +847,7 @@ export class App extends LiteElement {
};

onUserInfoChange(event: CustomEvent<Partial<UserInfo>>) {
AppStateService.updateUserInfo({
AppStateService.updateUser({
...this.userInfo,
...event.detail,
} as UserInfo);
Expand Down Expand Up @@ -955,7 +951,7 @@ export class App extends LiteElement {
if (data.value !== AuthService.storage.getItem()) {
if (data.value) {
this.authService.saveLogin(JSON.parse(data.value) as Auth);
void this.updateUserInfo();
void this.fetchAndUpdateUserInfo();
this.syncViewState();
} else {
this.clearUser();
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ export class Home extends LiteElement {
body: JSON.stringify(params),
});
const userInfo = await this.getUserInfo();
AppStateService.updateUserInfo(formatAPIUser(userInfo));
AppStateService.updateUser(formatAPIUser(userInfo));

this.notify({
message: msg(str`Created new org named "${params.name}".`),
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/pages/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import "./org";

import(/* webpackChunkName: "admin" */ "./admin");
import(/* webpackChunkName: "sign-up" */ "./sign-up");
import(/* webpackChunkName: "log-in" */ "./log-in");
import(/* webpackChunkName: "org" */ "./org");
import(/* webpackChunkName: "crawls" */ "./crawls");
import(/* webpackChunkName: "join" */ "./invite/join");
import(/* webpackChunkName: "verify" */ "./verify");
Expand Down
29 changes: 15 additions & 14 deletions frontend/src/pages/invite/accept.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AcceptInvite } from "./accept";
import type { OrgForm, OrgUpdatedDetail } from "@/pages/invite/ui/org-form";
import AuthService from "@/utils/AuthService";
import { AppStateService } from "@/utils/state";
import { formatAPIUser } from "@/utils/user";

const mockInviteInfo = {
inviterEmail: "inviter_fake_email@example.com",
Expand Down Expand Up @@ -224,6 +225,14 @@ describe("btrix-accept-invite", () => {
});

it("updates user app state on accept", async () => {
const user = {
id: "740d7b63-b257-4311-ba3f-adc46a5fafb8",
email: "fake@example.com",
name: "Fake User",
is_verified: false,
is_superuser: false,
orgs: [],
};
AppStateService.updateAuth(mockAuthState);
const el = await fixture<AcceptInvite>(
html`<btrix-accept-invite
Expand All @@ -233,16 +242,7 @@ describe("btrix-accept-invite", () => {
);

stub(el.navigate, "to");
stub(el, "_getCurrentUser").callsFake(async () =>
Promise.resolve({
id: "740d7b63-b257-4311-ba3f-adc46a5fafb8",
email: "fake@example.com",
name: "Fake User",
is_verified: false,
is_superuser: false,
orgs: [],
}),
);
stub(el, "_getCurrentUser").callsFake(async () => Promise.resolve(user));
stub(el.api, "fetch").callsFake(async () =>
Promise.resolve({
org: {
Expand All @@ -252,13 +252,14 @@ describe("btrix-accept-invite", () => {
},
}),
);
stub(AppStateService, "updateUserInfo");
stub(AppStateService, "updateOrgSlug");
stub(AppStateService, "updateUser");

await el._onAccept();

expect(AppStateService.updateUserInfo).to.have.callCount(1);
expect(AppStateService.updateOrgSlug).to.have.callCount(1);
expect(AppStateService.updateUser).to.have.been.calledWith(
formatAPIUser(user),
mockInviteInfo.orgSlug,
);
});

it("redirects to org dashboard on accept", async () => {
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/pages/invite/accept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,7 @@ export class AcceptInvite extends BtrixElement {
} else {
const user = await this._getCurrentUser();

AppStateService.updateUserInfo(formatAPIUser(user));
AppStateService.updateOrgSlug(org.slug);
AppStateService.updateUser(formatAPIUser(user), org.slug);

await this.updateComplete;

Expand Down
29 changes: 15 additions & 14 deletions frontend/src/pages/invite/ui/org-form.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { OrgForm } from "./org-form";

import AuthService from "@/utils/AuthService";
import { AppStateService } from "@/utils/state";
import { formatAPIUser } from "@/utils/user";

describe("btrix-org-form", () => {
beforeEach(() => {
Expand Down Expand Up @@ -116,32 +117,32 @@ describe("btrix-org-form", () => {

describe("#_renameOrg", () => {
it("updates user app state on success", async () => {
const user = {
id: "740d7b63-b257-4311-ba3f-adc46a5fafb8",
email: "fake@example.com",
name: "Fake User",
is_verified: false,
is_superuser: false,
orgs: [],
};
const el = await fixture<OrgForm>(
html`<btrix-org-form
newOrgId="e21ab647-2d0e-489d-97d1-88ac91774942"
></btrix-org-form>`,
);
stub(el.api, "fetch").callsFake(async () => Promise.resolve());
stub(el, "_getCurrentUser").callsFake(async () =>
Promise.resolve({
id: "740d7b63-b257-4311-ba3f-adc46a5fafb8",
email: "fake@example.com",
name: "Fake User",
is_verified: false,
is_superuser: false,
orgs: [],
}),
);
stub(AppStateService, "updateUserInfo");
stub(AppStateService, "updateOrgSlug");
stub(el, "_getCurrentUser").callsFake(async () => Promise.resolve(user));
stub(AppStateService, "updateUser");

await el._renameOrg("e21ab647-2d0e-489d-97d1-88ac91774942", {
name: "Fake Org Name 2",
slug: "fake-org-name-2",
});

expect(AppStateService.updateUserInfo).to.have.callCount(1);
expect(AppStateService.updateOrgSlug).to.have.callCount(1);
expect(AppStateService.updateUser).to.have.been.calledWith(
formatAPIUser(user),
"fake-org-name-2",
);
});

it("fires the correct event on success", async () => {
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/pages/invite/ui/org-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,7 @@ export class OrgForm extends BtrixElement {
try {
const user = await this._getCurrentUser();

AppStateService.updateUserInfo(formatAPIUser(user));
AppStateService.updateOrgSlug(data.slug);
AppStateService.updateUser(formatAPIUser(user), data.slug);
} catch (e) {
console.debug(e);
}
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/pages/log-in.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { isApiError } from "@/utils/api";
import type { ViewState } from "@/utils/APIRouter";
import AuthService from "@/utils/AuthService";
import LiteElement, { html } from "@/utils/LiteElement";
import { AppStateService } from "@/utils/state";
import { formatAPIUser } from "@/utils/user";

type FormContext = {
successMessage?: string;
Expand Down Expand Up @@ -338,6 +340,12 @@ export class LogInPage extends LiteElement {
}

async checkBackendInitialized() {
if (this.appState.settings) {
this.formStateService.send("BACKEND_INITIALIZED");

return;
}

const resp = await fetch("/api/settings");
if (resp.status === 200) {
this.formStateService.send("BACKEND_INITIALIZED");
Expand All @@ -360,6 +368,10 @@ export class LogInPage extends LiteElement {
try {
const data = await AuthService.login({ email: username, password });

AppStateService.updateUser(formatAPIUser(data.user));

await this.updateComplete;

this.dispatchEvent(
AuthService.createLoggedInEvent({
...data,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { choose } from "lit/directives/choose.js";
import { guard } from "lit/directives/guard.js";
import { until } from "lit/directives/until.js";
import { when } from "lit/directives/when.js";
import { throttle } from "lodash/fp";
import throttle from "lodash/fp/throttle";
import queryString from "query-string";

import stylesheet from "./archived-item-qa.stylesheet.css";
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/org/browser-profiles-detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { html, nothing, type TemplateResult } from "lit";
import { customElement, property, query, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { when } from "lit/directives/when.js";
import { capitalize } from "lodash/fp";
import capitalize from "lodash/fp/capitalize";
import queryString from "query-string";

import type { Profile, ProfileWorkflow } from "./types";
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/org/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class Dashboard extends LiteElement {
};

willUpdate(changedProperties: PropertyValues<this> & Map<string, unknown>) {
if (changedProperties.has("appState.userOrg") && this.orgId) {
if (changedProperties.has("appState.orgSlug") && this.orgId) {
void this.fetchMetrics();
}
}
Expand Down
Loading
Loading