Skip to content
Open
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,6 @@ credentials/
temp/
firestore_data/

*.pem
*.pem

.tanstack
5 changes: 2 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@
"editor.defaultFormatter": "ms-python.black-formatter"
},
"npm.packageManager": "npm",
"typescript.enablePromptUseWorkspaceTsdk": true,
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
Expand Down Expand Up @@ -79,5 +77,6 @@
"jest.nodeEnv": {
"NODE_OPTIONS": "--experimental-vm-modules"
},
"testing.automaticallyOpenTestResults": "openOnTestFailure"
"testing.automaticallyOpenTestResults": "openOnTestFailure",
"eslint.format.enable": true
}
5 changes: 3 additions & 2 deletions frontend/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports = {
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended"
],
ignorePatterns: ["dist", ".eslintrc.cjs"],
ignorePatterns: ["dist", ".eslintrc.cjs", "routeTree.gen.ts"],
parser: "@typescript-eslint/parser",
plugins: ["react-refresh"],
rules: {
Expand All @@ -15,6 +15,7 @@ module.exports = {
{ allowConstantExport: true }
],
"@typescript-eslint/no-explicit-any": "off",
"eslint/no-fallthrough": "off"
// noFallthroughCasesInSwitch in tsconfig handles this
"no-fallthrough": "off"
}
};
10,144 changes: 5,346 additions & 4,798 deletions frontend/package-lock.json

Large diffs are not rendered by default.

36 changes: 19 additions & 17 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,45 @@
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
"build": "vite build && tsc --noEmit",
"preview": "vite preview",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
},
"dependencies": {
"@blueprintjs/core": "^6.0.0",
"@blueprintjs/icons": "^6.0.0",
"@blueprintjs/select": "^6.0.0",
"@tailwindcss/vite": "^4.1.11",
"@tailwindcss/vite": "^4.2.4",
"@tanstack/react-query": "^5.87.0",
"@tanstack/react-router": "^1.121.12",
"@tanstack/react-router-devtools": "^1.121.12",
"dotenv": "^16.3.1",
"immer": "^10.2.0",
"@tanstack/react-start": "^1.167.63",
"dotenv": "^17.4.2",
"immer": "^11.1.6",
"minisearch": "^7.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript-parsec": "^0.3.4",
"zod": "^4.1.11"
},
"devDependencies": {
"@types/jest": "^29.5.8",
"@types/node": "^20.10.6",
"@tanstack/router-plugin": "^1.167.33",
"@types/jest": "^30.0.0",
"@types/node": "^25.6.0",
"@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.55.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"jest": "^29.7.0",
"@typescript-eslint/eslint-plugin": "^8.59.2",
"@typescript-eslint/parser": "^8.59.2",
"@vitejs/plugin-react": "^6.0.1",
"eslint": "^10.3.0",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.2",
"jest": "^30.3.0",
"jest-environment-jsdom": "^30.2.0",
"sass": "^1.69.5",
"ts-jest": "^29.1.1",
"tsx": "^4.7.0",
"typescript": "^5.2.2",
"vite": "^6.3.5"
"typescript": "^6.0.3",
"vite": "^8.0.10"
}
}
6 changes: 4 additions & 2 deletions frontend/src/cards/card-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import { apiPost } from "../api/api";
import { queryClient } from "../query-client";
import { ElementObj, hasUserAccess } from "../api/models";
import { useMemo } from "react";
import { useSearch } from "@tanstack/react-router";
import { useRouter, useSearch } from "@tanstack/react-router";
import { showErrorToast, showSuccessToast } from "../common/toaster";
import { toLibraryPath, useLibrary } from "../api/library";
import { getAppErrorHandler } from "../api/errors";
import { libraryQueryMatchKey } from "../queries";
import { router } from "../router";
import {
ElementPath,
InstancePath,
Expand All @@ -23,6 +22,8 @@ export function useSetVisibilityMutation(
isVisible: boolean
) {
const library = useLibrary();
const router = useRouter();

return useMutation({
mutationKey: ["set-element-visibility"],
mutationFn: async () => {
Expand Down Expand Up @@ -66,6 +67,7 @@ export function useIsElementHidden(element: ElementObj): boolean {

export function useReloadThumbnailMutation(path: InstancePath | ElementPath) {
const library = useLibrary();
const router = useRouter();

const apiPath = isElementPath(path)
? toElementApiPath(path)
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/cards/element-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
MenuDivider,
MenuItem
} from "@blueprintjs/core";
import { useNavigate, useSearch } from "@tanstack/react-router";
import { useNavigate, useRouter, useSearch } from "@tanstack/react-router";
import { PropsWithChildren, ReactNode } from "react";
import { ElementObj, ElementType, LibraryObj } from "../api/models";
import { SearchHit } from "../search/search";
Expand Down Expand Up @@ -39,7 +39,6 @@ import { showSuccessToast } from "../common/toaster";
import { toLibraryPath, useLibrary } from "../api/library";
import { getAppErrorHandler } from "../api/errors";
import { getQueryUpdater } from "../common/utils";
import { router } from "../router";

interface ElementCardProps extends PropsWithChildren {
element: ElementObj;
Expand Down Expand Up @@ -155,6 +154,7 @@ export function ElementAdminContextMenu(props: ElementAdminContextMenuProps) {

const library = useLibrary();
const search = useSearch({ from: "/app" });
const router = useRouter();

const setVisibilityMutation = useSetVisibilityMutation(
element.documentId,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/favorites/favorite-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import { apiDelete, apiPost } from "../api/api";
import { ElementObj, LibraryUserData } from "../api/models";
import { toUserApiPath } from "../api/path";
import { queryClient } from "../query-client";
import { useSearch } from "@tanstack/react-router";
import { router } from "../router";
import { useRouter, useSearch } from "@tanstack/react-router";
import { handleAppError, HandledError } from "../api/errors";
import { getQueryUpdater } from "../common/utils";
import { toLibraryPath, useLibrary } from "../api/library";
Expand Down Expand Up @@ -53,6 +52,7 @@ function updateFavorites(
function useUpdateFavoritesMutation(isFavorite: boolean) {
const search = useSearch({ from: "/app" });
const library = useLibrary();
const router = useRouter();

return useMutation<null, Error, UpdateFavoritesArgs>({
mutationKey: ["update-favorite", isFavorite],
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/favorites/favorite-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import {
MenuDivider,
MenuItem
} from "@blueprintjs/core";
import { useNavigate, useSearch } from "@tanstack/react-router";
import {
useNavigate,
useRouteContext,
useRouter,
useSearch
} from "@tanstack/react-router";
import { MenuType } from "../overlays/menu-params";
import { FavoriteButton, FavoriteElementItem } from "./favorite-button";
import {
Expand All @@ -25,7 +30,6 @@ import { useIsAssemblyInPartStudio } from "../insert/insert-hooks";
import { ChangeOrderItems } from "../cards/change-order";
import { toUserApiPath } from "../api/path";
import { useUiState } from "../api/ui-state";
import { router } from "../router";
import { AppPopup, useOpenAlert } from "../overlays/popup-params";
import { getAppErrorHandler } from "../api/errors";
import { useLibraryUserDataQuery } from "../queries";
Expand Down Expand Up @@ -171,6 +175,8 @@ function FavoriteContextMenu(props: FavoriteContextMenuProps): ReactNode {
function useSetFavoriteOrderMutation() {
const userPath = useSearch({ from: "/app" });
const library = useLibrary();
const router = useRouter();

return useMutation({
mutationKey: ["set-favorite-order"],
mutationFn: async (favoriteOrder: string[]) => {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/favorites/favorite-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
MenuDialogProps,
useHandleCloseDialog
} from "../overlays/menu-params";
import { useSearch } from "@tanstack/react-router";
import { useRouter, useSearch } from "@tanstack/react-router";
import { useMutation } from "@tanstack/react-query";
import { apiPost } from "../api/api";
import { showErrorToast, showSuccessToast } from "../common/toaster";
Expand All @@ -23,7 +23,6 @@ import { AppInternalErrorState } from "../common/app-zero-state";
import { HeartIcon } from "./favorite-button";
import { toUserApiPath } from "../api/path";
import { queryClient } from "../query-client";
import { router } from "../router";
import { Configuration } from "../insert/configuration-models";
import { libraryUserDataQueryMatchKey, useLibraryQuery } from "../queries";
import { getQueryUpdater } from "../common/utils";
Expand All @@ -48,6 +47,7 @@ function FavoriteMenuDialog(
const { favoriteId, defaultConfiguration } = props;

const search = useSearch({ from: "/app" });
const router = useRouter();
const library = useLibrary();
const elements = useLibraryQuery().data?.elements;

Expand Down
14 changes: 9 additions & 5 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { createRoot } from "react-dom/client";
import { IconPaths, Icons } from "@blueprintjs/icons";

// Router
import { RouterProvider } from "@tanstack/react-router";
import { router } from "./router";
import { createRouter, RouterProvider } from "@tanstack/react-router";
import { routeTree } from "./routeTree.gen";

// Used to make static assets work in dev
import "vite/modulepreload-polyfill";
Expand Down Expand Up @@ -36,13 +36,17 @@ Icons.setLoaderOptions({

FocusStyleManager.onlyShowFocusOnTabs();

const router = createRouter({ routeTree, scrollRestoration: true });

declare module "@tanstack/react-router" {
interface Register {
router: typeof router;
}
}

const rootElement: HTMLElement = document.getElementById("root")!;
const root = createRoot(rootElement);
// Note: We can't use React StrictMode because it breaks Blueprint portals and hence, ContextMenus
root.render(<RouterProvider router={router} />);

if (!rootElement.innerHTML) {
const root = createRoot(rootElement);
root.render(<RouterProvider router={router} />);
}
7 changes: 4 additions & 3 deletions frontend/src/navbar/settings-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from "@blueprintjs/core";
import { Dispatch, ReactNode, useMemo, useState } from "react";
import { MenuType, useHandleCloseDialog } from "../overlays/menu-params";
import { useNavigate, useSearch } from "@tanstack/react-router";
import { useNavigate, useRouter, useSearch } from "@tanstack/react-router";
import { showErrorToast, showSuccessToast } from "../common/toaster";
import { useMutation } from "@tanstack/react-query";
import { apiPost } from "../api/api";
Expand All @@ -30,7 +30,6 @@ import { ItemRenderer, Select } from "@blueprintjs/select";
import { capitalize, getQueryUpdater } from "../common/utils";
import { buildSearchDb } from "../search/search";
import { toUserApiPath } from "../api/path";
import { router } from "../router";
import { OpenUrlButton } from "../common/open-url-button";
import { RequireAccessLevel } from "../api/access-level";
import { FEEDBACK_FORM_URL } from "../common/url";
Expand Down Expand Up @@ -60,7 +59,7 @@ function SettingsMenuDialog(): ReactNode {

const search = useSearch({ from: "/app" });

let adminSettings = null;
let adminSettings: ReactNode = null;
// Unlike all other checks, this one uses maxAccessLevel so you can still switch from user to admin
if (hasMemberAccess(search.maxAccessLevel)) {
adminSettings = (
Expand Down Expand Up @@ -101,6 +100,7 @@ function SettingsMenuDialog(): ReactNode {
function UserSettings(): ReactNode {
const search = useSearch({ from: "/app" });
const settings = useUserData().settings;
const router = useRouter();

const settingsMutation = useMutation({
mutationKey: updateSettingsKey(search),
Expand Down Expand Up @@ -366,6 +366,7 @@ export function ReloadDocumentsButton(
const hideFormGroup = props.hideFormGroup ?? false;

const library = useLibrary();
const router = useRouter();

const mutation = useMutation({
mutationKey: ["reload-documents"],
Expand Down
Loading