feat(dashboard): add HTML gallery and image compare tools - #447
feat(dashboard): add HTML gallery and image compare tools#447tembo[bot] wants to merge 2 commits into
Conversation
Co-authored-by: Dominik <68947960+mezotv@users.noreply.github.com>
|
React Doctor found 22 issues in 3 files · 4 errors & 18 warnings · score 72 / 100 (Needs work) · vs Errors
18 warnings
Reviewed by React Doctor for commit |
| const { data, isLoading } = useQuery(listQueryOptions); | ||
| const documents: HtmlDocument[] = data?.documents ?? []; | ||
|
|
||
| const invalidate = useCallback( |
There was a problem hiding this comment.
React Doctor · react-doctor/react-compiler-no-manual-memoization (warning)
This useCallback is dead weight, since React Compiler already caches every function here. Delete it.
Fix → Delete the useMemo / useCallback / memo call and use the plain value or component. React Compiler caches it for you.
| [queryClient] | ||
| ); | ||
|
|
||
| const uploadMutation = useMutation({ |
There was a problem hiding this comment.
React Doctor · react-doctor/query-mutation-missing-invalidation (warning)
useMutation with no cache update leaves your users looking at stale data after it runs.
Fix → Add onSuccess: () => queryClient.invalidateQueries({ queryKey: ['...'] }) so cached data stays in sync after the mutation
| mutationFn: async (files: File[]) => { | ||
| let uploaded = 0; | ||
| for (const file of files) { | ||
| const content = await file.text(); |
There was a problem hiding this comment.
React Doctor · react-doctor/async-await-in-loop (warning)
This makes the for…of loop slow because each await runs one after another, so collect the independent calls & run them together with await Promise.all(items.map(...))
Fix → Collect the items, then use await Promise.all(items.map(...)) so independent work runs at the same time
| }, | ||
| }); | ||
|
|
||
| const deleteMutation = useMutation({ |
There was a problem hiding this comment.
React Doctor · react-doctor/query-mutation-missing-invalidation (warning)
useMutation with no cache update leaves your users looking at stale data after it runs.
Fix → Add onSuccess: () => queryClient.invalidateQueries({ queryKey: ['...'] }) so cached data stays in sync after the mutation
| }, | ||
| }); | ||
|
|
||
| const handleFiles = useCallback( |
There was a problem hiding this comment.
React Doctor · react-doctor/react-compiler-no-manual-memoization (warning)
This useCallback is dead weight, since React Compiler already caches every function here. Delete it.
Fix → Delete the useMemo / useCallback / memo call and use the plain value or component. React Compiler caches it for you.
| beforeRef.current = before; | ||
| afterRef.current = after; | ||
|
|
||
| const handleSelect = useCallback((side: Side, file: File) => { |
There was a problem hiding this comment.
React Doctor · react-doctor/react-compiler-no-manual-memoization (warning)
This useCallback is dead weight, since React Compiler already caches every function here. Delete it.
Fix → Delete the useMemo / useCallback / memo call and use the plain value or component. React Compiler caches it for you.
| }); | ||
| }, []); | ||
|
|
||
| const handleClear = useCallback((side: Side) => { |
There was a problem hiding this comment.
React Doctor · react-doctor/react-compiler-no-manual-memoization (warning)
This useCallback is dead weight, since React Compiler already caches every function here. Delete it.
Fix → Delete the useMemo / useCallback / memo call and use the plain value or component. React Compiler caches it for you.
| setSimilarity(null); | ||
| }, []); | ||
|
|
||
| useEffect(() => { |
There was a problem hiding this comment.
React Doctor · react-doctor/no-cascading-set-state (warning)
5 setState calls in one useEffect redraw your screen each time they run together.
Fix → Combine related updates in useReducer so one effect does not redraw the screen once per setState call.
|
|
||
| useEffect(() => { | ||
| if (!(before && after)) { | ||
| setSimilarity(null); |
There was a problem hiding this comment.
React Doctor · react-hooks-js/set-state-in-effect (error)
This component misses React Compiler's automatic memoization & re-renders more than it should: Calling setState synchronously within an effect can trigger cascading renders. Rewrite the flagged code so the compiler can optimize it.
Fix → Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:
- Update external systems with the latest state from React.
- Subscribe for updates from some external system, calling setState in a callback function when external state changes.
Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).
| [] | ||
| ); | ||
|
|
||
| const updatePosition = useCallback((clientX: number) => { |
There was a problem hiding this comment.
React Doctor · react-doctor/react-compiler-no-manual-memoization (warning)
This useCallback is dead weight, since React Compiler already caches every function here. Delete it.
Fix → Delete the useMemo / useCallback / memo call and use the plain value or component. React Compiler caches it for you.
Description
Adds two new workspace tools to the dashboard, each available from the sidebar (under Workspace).
1. HTML Gallery (
/[slug]/gallery).htmlfiles (drag-and-drop or file picker) and view them all on one page as live, sandboxediframepreviews in a gallery grid.text/html, which Figma's "paste from HTML" converts into native layers on paste.html_documentstable. HTML content is kept in the DB (rather than R2) so previews and the copy feature work without any object-storage round-trip or CORS setup. 5MB/file cap.2. Image Compare (
/[slug]/image-compare)Implementation notes
html_documents+ relations, with generated migration0043_whole_ultimo.sql.html(list/create/deleteMany), registered in the dashboard router and scoped to the active organization via the existingauthorizedProcedure+ membership checks.HTML Gallery,Image Compare) using Hugeicons.page.tsx/page-client.tsx/loading.tsx/skeleton.tsxconvention.Screenshot/Recording (if applicable)
N/A — UI follows existing dashboard page/card conventions.
Checklist
Summary by cubic
Adds two new workspace tools: HTML Gallery and Image Compare. Speeds up reviews with secure HTML previews you can paste into Figma, plus a fast pixel similarity check.
New Features
/[slug]/gallery).html/.htmfiles and see live, sandboxed previews in a grid.text/htmlclipboard).html_documentstable (5MB/file)./[slug]/image-compare)Migration
html_documentsand indexes).Written for commit 79a2013. Summary will update on new commits.