114 improve project overview page - #115
Conversation
…m/InfinityBowman/corates into 114-improve-project-overview-page
WalkthroughThis PR introduces PDF metadata extraction during upload and Google Drive import, propagates studyId through the import flow, refactors error handling in Google Drive integration, updates completion-status filtering for dual-reviewer studies, integrates a PDF metadata editing modal, and performs minor code simplifications and styling adjustments across multiple components. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Component as ProjectView/<br/>StudyPdfSection
participant Store as projectActionsStore
participant PDF as PDF Utils
participant DOI as DOI API
participant Firebase as Firebase
User->>Component: Upload/Import PDF
Component->>Store: handleUpload() or<br/>handleGoogleDriveImport()
Store->>PDF: extractPdfMetadata(arrayBuffer)
PDF->>PDF: extractPdfTitle()
PDF->>PDF: extractPdfDoi()
PDF->>DOI: fetchFromDOI(doi)
DOI-->>PDF: {firstAuthor,<br/>publicationYear, journal}
PDF-->>Store: {title, doi, firstAuthor,<br/>publicationYear, journal}
Store->>Firebase: addPdfToStudy(file,<br/>pdfMetadata)
Firebase-->>Store: PDF record created
Store-->>Component: Success callback
Component->>Component: Update UI
Component-->>User: Display PDF with<br/>extracted metadata
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
corates | 81072e3 | Commit Preview URL | Dec 20 2025, 07:29 AM |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
packages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsx (1)
337-497: Consider consolidating ReviewerPoolSection props.The
ReviewerPoolSectioncomponent receives 9 distinct properties (title, pool, available, total, isValid, onAdd, onRemove, onUpdatePercent, onDistributeEvenly), which exceeds the recommended maximum of 1–5 props per component. While this is an internal component, consolidating this state or extracting pool management logic into a shared primitive could improve maintainability.For example, you could create a custom hook/primitive for pool operations and pass a single pool state object, or use Solid context to provide pool callbacks globally within this component's scope.
packages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsx (1)
140-140: Remove diagnostic console.log.This debug statement should be removed before merging to production.
Proposed fix
- console.log('picked', picked, studyId); await props.onPick?.(picked, studyId);packages/web/src/api/google-drive.js (1)
52-52: Remove diagnostic console.log.This debug statement should be removed before merging to production.
Proposed fix
- console.log('importing from google drive', fileId, projectId, studyId); const response = await fetch(`${API_BASE}/api/google-drive/import`, {packages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsx (1)
77-85: Consider user-facing error for missing studyId.The guard correctly prevents passing an undefined studyId downstream, but only logs to console. Users won't know why their import failed. Consider showing a toast notification.
Proposed improvement
const handleGoogleDriveImportSuccess = (file, studyId) => { // Use studyId from callback if provided, otherwise fall back to state const targetStudyId = studyId || googleDriveTargetStudyId(); if (!targetStudyId) { console.error('No study ID available for Google Drive import'); + showToast.error('Import Failed', 'Unable to determine target study'); return; } projectActionsStore.pdf.handleGoogleDriveImport(targetStudyId, file); };packages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx (1)
30-30: Remove diagnostic console.log.This debug statement should be removed before merging to production.
Proposed fix
try { - console.log('importing from google drive', file.id, projectId(), studyId); setImporting(true);packages/web/src/stores/projectActionsStore/pdfs.js (1)
47-48: Dead code: condition will never be true.At line 37,
metadata.doiis set whenextractedDoiis truthy. Since we're inside theif (extractedDoi)block (line 40),metadata.doiis already assigned. The conditionif (!metadata.doi)will always be false.If the intent is to prefer
refData.doiover the extracted DOI when available, the logic should be inverted. Otherwise, these lines can be removed.Option A: Prefer refData.doi when available
- if (!metadata.doi) metadata.doi = refData.doi || extractedDoi; + if (refData.doi) metadata.doi = refData.doi;Option B: Remove dead code if extracted DOI is preferred
- // Use extracted DOI if refData doesn't have one - if (!metadata.doi) metadata.doi = refData.doi || extractedDoi;
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (18)
packages/web/src/api/google-drive.js(7 hunks)packages/web/src/components/charts/AMSTARDistribution.jsx(1 hunks)packages/web/src/components/charts/AMSTARRobvis.jsx(1 hunks)packages/web/src/components/checklist-ui/compare/NotesCompareSection.jsx(2 hunks)packages/web/src/components/project-ui/ProjectDashboard.jsx(0 hunks)packages/web/src/components/project-ui/ProjectView.jsx(1 hunks)packages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsx(1 hunks)packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsx(1 hunks)packages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsx(4 hunks)packages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsx(1 hunks)packages/web/src/components/project-ui/completed-tab/CompletedTab.jsx(1 hunks)packages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsx(2 hunks)packages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx(2 hunks)packages/web/src/components/project-ui/overview-tab/ChartSection.jsx(2 hunks)packages/web/src/components/project-ui/overview-tab/OverviewTab.jsx(3 hunks)packages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsx(1 hunks)packages/web/src/stores/projectActionsStore/pdfs.js(7 hunks)packages/web/src/stores/projectActionsStore/studies.js(2 hunks)
💤 Files with no reviewable changes (1)
- packages/web/src/components/project-ui/ProjectDashboard.jsx
🧰 Additional context used
📓 Path-based instructions (11)
**/*
📄 CodeRabbit inference engine (.cursorrules)
Do not use emojis in code, comments, documentation, or commit messages
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/api/google-drive.jspackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/stores/projectActionsStore/pdfs.jspackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/stores/projectActionsStore/studies.jspackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
packages/web/src/**/*.{jsx,tsx,js,ts}
📄 CodeRabbit inference engine (.cursorrules)
packages/web/src/**/*.{jsx,tsx,js,ts}: For UI icons, use thesolid-iconslibrary or SVGs only. Do not use emojis
Import stores directly where needed instead of passing values through multiple components
When you need to compute a value based on props or state in SolidJS, usecreateMemoto ensure it updates reactively
For complex state or state objects in SolidJS, use Solid'screateStorefor better performance and reactivity
You may create reusable logic in 'primitives' (hooks) that can be shared across components to keep components clean and focused on rendering
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/api/google-drive.jspackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/stores/projectActionsStore/pdfs.jspackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/stores/projectActionsStore/studies.jspackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
packages/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
packages/**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Use aliases for imports when appropriate to improve readability
Prefer using config files rather than hardcoding values
Keep files small, focused, and modular. If a file exceeds a high number of lines, consider refactoring by extracting sub-modules into a folder with index.jsx and helper components, moving complex logic into separate utility files or primitives, or splitting large forms into section components
Each file should handle one coherent responsibility
Use Zod for schema and input validation
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/api/google-drive.jspackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/stores/projectActionsStore/pdfs.jspackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/stores/projectActionsStore/studies.jspackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
packages/web/src/components/**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
packages/web/src/components/**/*.{jsx,tsx}: Use responsive design principles for UI components
Use Zag.js for UI components and design system
Zag components exist inpackages/web/src/components/zag/*and should be reused; check the README.md in that folder for a list of existing components before adding new components and when debugging
Components should receive at most 1–5 props, and only for local configuration, not shared state
If a component would need more than 5 props, move the shared data into an external store, a primitive, or Solid context
Components should be lean and focused and should not implement business logic; move business logic into stores, utilities, or primitives
Never have a component act as a 'God component' coordinating multiple large concerns
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
packages/web/src/**/*.{jsx,tsx,js,ts,css}
📄 CodeRabbit inference engine (.cursorrules)
Ensure browser compatibility for all frontend code (Safari is usually problematic)
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/api/google-drive.jspackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/stores/projectActionsStore/pdfs.jspackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/stores/projectActionsStore/studies.jspackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
packages/web/src/components/**/*.{jsx,tsx,js}
📄 CodeRabbit inference engine (.cursorrules)
Group related components in subdirectories with an
index.jsbarrel export
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
packages/web/src/**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
packages/web/src/**/*.{jsx,tsx}: Do NOT prop-drill application state. Shared or cross-feature state must live in external stores under packages/web/src/stores/ or relative to the component file
Do not destructure props in SolidJS components as it breaks reactivity. Instead, access props directly from the props object or wrap them in a function to ensure they are always up-to-date
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
packages/web/src/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
packages/web/src/**/*.{js,jsx,ts,tsx}: For UI icons, use thesolid-iconslibrary or SVGs only. Do not use emojis
Ensure browser compatibility for all frontend code (Safari is usually problematic)
Keep files small, focused, and modular. If a file exceeds a high number of lines, consider refactoring by extracting sub-modules into a folder with index.jsx and helper components, moving complex logic into separate utility files or primitives, or splitting large forms into section components
Do NOT prop-drill application state. Shared or cross-feature state must live in external stores under packages/web/src/stores/ or relative to the component file
UsecreateMemofor derived values to ensure they update reactively
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/api/google-drive.jspackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/stores/projectActionsStore/pdfs.jspackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/stores/projectActionsStore/studies.jspackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Use aliases for imports when appropriate to improve readability
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/api/google-drive.jspackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/stores/projectActionsStore/pdfs.jspackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/stores/projectActionsStore/studies.jspackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
packages/web/src/components/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
packages/web/src/components/**/*.{js,jsx,ts,tsx}: Use responsive design principles for UI components
Group related components in subdirectories with an index.js barrel export
Use Zag.js for UI components and design system
Zag component exist inpackages/web/src/components/zag/*and should be reused. Check the README.md in that folder for a list of existing components before adding new components and when debugging
Components should receive at most 1–5 props, and only for local configuration, not shared state. If a component would need more than 5 props, move the shared data into an external store, a primitive, or Solid context
Do not destructure props in SolidJS components as it breaks reactivity. Instead, access props directly from the props object or wrap them in a function to ensure they are always up-to-date
Components should be lean and focused. They should not implement business logic; move that into stores, utilities, or primitives
Never have a component act as a God component coordinating multiple large concerns
Files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsxpackages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsxpackages/web/src/components/project-ui/completed-tab/CompletedTab.jsxpackages/web/src/components/project-ui/ProjectView.jsxpackages/web/src/components/project-ui/overview-tab/ChartSection.jsxpackages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsxpackages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsxpackages/web/src/components/charts/AMSTARRobvis.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsxpackages/web/src/components/project-ui/overview-tab/OverviewTab.jsxpackages/web/src/components/checklist-ui/compare/NotesCompareSection.jsxpackages/web/src/components/charts/AMSTARDistribution.jsxpackages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsxpackages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx
packages/web/src/stores/**/*.{js,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use Solid's
createStorefor complex state or state objects for better performance and reactivity
Files:
packages/web/src/stores/projectActionsStore/pdfs.jspackages/web/src/stores/projectActionsStore/studies.js
🧠 Learnings (3)
📚 Learning: 2025-12-19T12:38:18.491Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-19T12:38:18.491Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : Do not destructure props in SolidJS components as it breaks reactivity. Instead, access props directly from the props object or wrap them in a function to ensure they are always up-to-date
Applied to files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsx
📚 Learning: 2025-12-19T14:49:49.717Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-19T14:49:49.717Z
Learning: Applies to packages/web/src/components/**/*.{js,jsx,ts,tsx} : Do not destructure props in SolidJS components as it breaks reactivity. Instead, access props directly from the props object or wrap them in a function to ensure they are always up-to-date
Applied to files:
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsx
📚 Learning: 2025-12-19T12:38:18.491Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-19T12:38:18.491Z
Learning: Applies to packages/web/src/components/**/*.{jsx,tsx} : Use responsive design principles for UI components
Applied to files:
packages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsx
🧬 Code graph analysis (8)
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsx (2)
packages/web/src/stores/projectActionsStore/index.js (3)
projectActionsStore(145-145)study(112-112)packages/web/src/components/project-ui/all-studies-tab/EditPdfMetadataModal.jsx (1)
EditPdfMetadataModal(16-192)
packages/web/src/api/google-drive.js (1)
packages/web/src/lib/error-utils.js (1)
parseApiError(23-37)
packages/web/src/components/project-ui/ProjectView.jsx (3)
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCardHeader.jsx (1)
studyName(47-47)packages/web/src/api/pdf-api.js (1)
uploadPdf(40-70)packages/web/src/primitives/pdfCache.js (1)
cachePdf(111-138)
packages/web/src/stores/projectActionsStore/pdfs.js (4)
packages/web/src/lib/pdfUtils.js (2)
extractPdfTitle(69-71)extractPdfDoi(216-218)packages/web/src/lib/referenceLookup.js (1)
fetchFromDOI(139-170)packages/web/src/api/pdf-api.js (1)
downloadPdf(79-93)packages/web/src/primitives/pdfCache.js (1)
cachePdf(111-138)
packages/web/src/components/charts/AMSTARRobvis.jsx (1)
packages/web/src/components/charts/AMSTARDistribution.jsx (1)
colorMapGreyscale(82-87)
packages/web/src/components/project-ui/overview-tab/OverviewTab.jsx (3)
packages/web/src/components/project-ui/completed-tab/CompletedTab.jsx (2)
completedStudies(19-32)studies(17-17)packages/web/src/primitives/useProject/index.js (1)
studies(166-166)packages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsx (1)
isSingleReviewer(16-16)
packages/web/src/components/project-ui/all-studies-tab/AllStudiesTab.jsx (2)
packages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsx (1)
studyId(36-36)packages/web/src/stores/projectActionsStore/index.js (1)
projectActionsStore(145-145)
packages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx (2)
packages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsx (1)
studyId(36-36)packages/web/src/api/google-drive.js (1)
importFromGoogleDrive(51-68)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Workers Builds: corates
🔇 Additional comments (18)
packages/web/src/components/project-ui/overview-tab/ReviewerAssignment.jsx (1)
428-428: Visual polish looks good.The addition of
shadow-smenhances the visual hierarchy and complements the broader UI refinements in the Overview tab.packages/web/src/components/checklist-ui/compare/NotesCompareSection.jsx (2)
55-55: LGTM - Clean consolidation.The single-line arrow function maintains the same logic and reactivity while improving code conciseness.
107-109: LGTM - Cleaner formatting.The single-line array expression maintains identical logic (conditional entries with filter and join) while being more compact and readable.
packages/web/src/components/project-ui/completed-tab/CompletedStudyCard.jsx (1)
19-27: LGTM! Consistent dual-reviewer completion criteria.The filter logic correctly distinguishes between single and dual-reviewer studies. For dual-reviewer studies, requiring both
isReconciledandstatus === 'completed'ensures only fully reconciled and completed checklists are displayed. This aligns with the updated completion logic applied consistently across CompletedTab.jsx, OverviewTab.jsx, and ChartSection.jsx.packages/web/src/components/project-ui/overview-tab/OverviewTab.jsx (3)
45-53: LGTM! Consistent completed studies calculation.The
completedStudiescalculation correctly implements the dual-status requirement for dual-reviewer studies, matching the logic in CompletedTab.jsx (lines 19-31) and other related components. Using.some()to check for at least one qualifying checklist is appropriate.
103-114: LGTM! Improved visual distinction with color scheme.The tile styling changes improve the visual hierarchy:
- Amber theme for "In Progress" studies
- Blue theme for "Completed" studies
This provides better visual distinction between different study states and makes the dashboard more intuitive.
205-205: LGTM! Minor text refinement.The heading change from "Charts" to "Figures" is a minor text refinement that uses more academically appropriate terminology.
packages/web/src/components/project-ui/completed-tab/CompletedTab.jsx (1)
19-31: LGTM! Consistent dual-reviewer completion logic.The updated
completedStudiesmemo correctly requires bothisReconciledandstatus === 'completed'for dual-reviewer studies. This aligns with the filtering logic applied across CompletedStudyCard.jsx (line 26), ChartSection.jsx (line 172), and OverviewTab.jsx (line 52), ensuring consistent completion criteria throughout the application.packages/web/src/components/project-ui/overview-tab/ChartSection.jsx (1)
149-173: LGTM! Clear filtering logic with helpful comments.The filtering logic correctly implements the dual-status requirement for dual-reviewer studies and is consistent with changes in CompletedTab.jsx, CompletedStudyCard.jsx, and OverviewTab.jsx. The comments clearly document the intended behavior.
For the edge case of studies with no reviewers assigned: the logic treats them as dual-reviewer studies (since
isSingleReviewer = study.reviewer1 && !study.reviewer2evaluates to false), requiring reconciled checklists to be included. This is safe because the reconciliation system requires both reviewers to be present forisReconciledto ever be true, so studies without reviewers will naturally be filtered out.packages/web/src/api/google-drive.js (1)
6-6: LGTM: Centralized error handling.The refactor to use
parseApiErrorprovides consistent error handling across all API calls. This improves maintainability and ensures uniform error response parsing.Also applies to: 19-20, 37-38, 63-64, 81-82, 107-108
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsx (1)
12-12: LGTM: EditPdfMetadataModal integration.The modal integration is clean, with appropriate local state management. The flow correctly opens the modal with the selected PDF and delegates saves to the store.
Also applies to: 21-22, 84-90, 178-185
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyCard.jsx (1)
28-28: LGTM: Correct SolidJS reactivity pattern.The changes correctly use direct prop access instead of destructuring, maintaining reactivity. This aligns with the coding guidelines and learnings for SolidJS components.
Based on learnings, direct prop access ensures props remain reactive in SolidJS.
Also applies to: 31-31, 37-38, 40-40, 47-47
packages/web/src/stores/projectActionsStore/studies.js (1)
178-191: LGTM: PDF metadata extraction during upload.The metadata extraction is well-integrated with appropriate error handling. Failures are logged but don't block the upload flow, ensuring robustness. The extracted metadata (title, firstAuthor, publicationYear, journal, doi) is correctly passed to the PDF record with safe null fallbacks.
Also applies to: 203-207
packages/web/src/components/project-ui/ProjectView.jsx (1)
94-101: LGTM: Metadata extraction and study creation flow.The changes correctly:
- Derive study name from filename with appropriate fallback
- Extract and map PDF metadata fields to the PDF record
- Handle metadata errors gracefully with cleanup of orphaned files
The error handling pattern ensures that if metadata processing fails after upload, the uploaded file is properly cleaned up to avoid orphaned resources.
Also applies to: 108-127
packages/web/src/components/project-ui/google-drive/GoogleDrivePickerModal.jsx (1)
21-22: LGTM: studyId propagation through import flow.The changes correctly propagate studyId through the Google Drive import flow:
- Accessor functions maintain reactivity for props
- studyId is passed from modal to launcher and back through the callback
- Both file and studyId are correctly passed to onImportSuccess
Also applies to: 24-24, 32-32, 38-38, 64-64
packages/web/src/stores/projectActionsStore/pdfs.js (3)
7-8: LGTM!Imports are appropriate for the new metadata extraction functionality and use the expected aliases.
156-175: LGTM!Clean integration of metadata extraction into the upload flow. The
|| nullfallbacks ensure consistent shape, and the guard at line 28 handles the case wherearrayBuffermight be null.
237-290: LGTM!The async conversion and metadata extraction integration look good. The graceful degradation when download fails (continuing without metadata) is appropriate, and the cleanup on error maintains consistency.
| // https://dev.to/finnhvman/grayscale-color-palette-with-equal-contrast-ratios-2pgl | ||
| const colorMapGreyscale = { | ||
| yes: '#1f2937', | ||
| 'partial yes': '#6b7280', | ||
| no: '#d1d5db', | ||
| 'no ma': '#f3f4f6', | ||
| yes: '#1b1b1b', | ||
| 'partial yes': '#484848', | ||
| no: '#727272', | ||
| 'no ma': '#a2a2a2', | ||
| }; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Extract color maps to a shared constants file.
Both AMSTARRobvis.jsx and AMSTARDistribution.jsx define identical greyscale color maps. This duplication violates the DRY principle and makes maintenance harder—future color adjustments would need to be applied in multiple places.
Proposed refactor
Create a new shared constants file:
// packages/web/src/components/charts/amstarColorMaps.js
// https://dev.to/finnhvman/grayscale-color-palette-with-equal-contrast-ratios-2pgl
export const AMSTAR_COLOR_MAP_DEFAULT = {
yes: '#10b981',
'partial yes': '#facc15',
no: '#ef4444',
'no ma': '#9ca3af',
};
export const AMSTAR_COLOR_MAP_GREYSCALE = {
yes: '#1b1b1b',
'partial yes': '#484848',
no: '#727272',
'no ma': '#a2a2a2',
};Then import in both chart components:
import { onCleanup, createEffect, createSignal } from 'solid-js';
import * as d3 from 'd3';
+import { AMSTAR_COLOR_MAP_DEFAULT, AMSTAR_COLOR_MAP_GREYSCALE } from './amstarColorMaps';And replace the local definitions:
- const colorMapDefault = {
- yes: '#10b981',
- 'partial yes': '#facc15',
- no: '#ef4444',
- 'no ma': '#9ca3af',
- };
-
- // https://dev.to/finnhvman/grayscale-color-palette-with-equal-contrast-ratios-2pgl
- const colorMapGreyscale = {
- yes: '#1b1b1b',
- 'partial yes': '#484848',
- no: '#727272',
- 'no ma': '#a2a2a2',
- };
-
- const colorMap = () => (greyscale() ? colorMapGreyscale : colorMapDefault);
+ const colorMap = () => (greyscale() ? AMSTAR_COLOR_MAP_GREYSCALE : AMSTAR_COLOR_MAP_DEFAULT);Apply the same changes to AMSTARDistribution.jsx.
As per coding guidelines, keep files modular and avoid duplication.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/web/src/components/charts/AMSTARRobvis.jsx around lines 99-105 there
is a duplicated greyscale color map; extract both greyscale and default AMSTAR
color maps into a new shared constants module (suggested path:
packages/web/src/components/charts/amstarColorMaps.js), export named maps
(AMSTAR_COLOR_MAP_DEFAULT and AMSTAR_COLOR_MAP_GREYSCALE), then replace the
local colorMapGreyscale definition with an import from that module and do the
same change in AMSTARDistribution.jsx so both components consume the shared
constants and the local duplicated definitions are removed.
| const handleSaveMetadata = async (studyId, pdfId, metadata) => { | ||
| projectActionsStore.pdf.updateMetadata(studyId, pdfId, metadata); | ||
| }; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find projectActionsStore definition
fd -t f "projectActionsStore" --search-path packages/web/src 2>/dev/null | head -20Repository: InfinityBowman/corates
Length of output: 48
🏁 Script executed:
#!/bin/bash
# Search for updateMetadata in the codebase
rg "updateMetadata" packages/web/src -A 5 -B 2 --type ts --type tsx --type js --type jsx 2>/dev/null | head -100Repository: InfinityBowman/corates
Length of output: 48
🏁 Script executed:
#!/bin/bash
# Look at StudyPdfSection.jsx directly, especially around lines 88-90
if [ -f "packages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsx" ]; then
cat -n packages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsx | sed -n '80,100p'
fiRepository: InfinityBowman/corates
Length of output: 750
🏁 Script executed:
#!/bin/bash
# Search for projectActionsStore definition and updateMetadata method
rg "updateMetadata" packages/web/src -A 10 -B 3 --type ts --type tsx --type js --type jsx 2>/dev/nullRepository: InfinityBowman/corates
Length of output: 48
🏁 Script executed:
#!/bin/bash
# Find where handleSaveMetadata is called (likely the modal)
rg "handleSaveMetadata" packages/web/src -B 5 -A 5 --type ts --type tsx --type js --type jsx 2>/dev/nullRepository: InfinityBowman/corates
Length of output: 48
🏁 Script executed:
#!/bin/bash
# Find projectActionsStore or similar store definitions
fd "store" packages/web/src --search-path packages/web/src/stores 2>/dev/null | head -20Repository: InfinityBowman/corates
Length of output: 48
🏁 Script executed:
#!/bin/bash
# List files in stores directory
ls -la packages/web/src/stores/ 2>/dev/null | head -30Repository: InfinityBowman/corates
Length of output: 454
🏁 Script executed:
#!/bin/bash
# Search for updateMetadata more broadly across all file types
find packages/web/src -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) -exec grep -l "updateMetadata" {} \; 2>/dev/nullRepository: InfinityBowman/corates
Length of output: 203
🏁 Script executed:
#!/bin/bash
# Search for projectActionsStore
find packages/web/src -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) -exec grep -l "projectActionsStore" {} \; 2>/dev/null | head -10Repository: InfinityBowman/corates
Length of output: 776
🏁 Script executed:
#!/bin/bash
# Read the pdfs.js file which contains updateMetadata
cat packages/web/src/stores/projectActionsStore/pdfs.jsRepository: InfinityBowman/corates
Length of output: 9980
🏁 Script executed:
#!/bin/bash
# Find the modal component that uses handleSaveMetadata
grep -r "handleSaveMetadata" packages/web/src --include="*.jsx" --include="*.tsx" -B 10 -A 10Repository: InfinityBowman/corates
Length of output: 3998
🏁 Script executed:
#!/bin/bash
# List all files in projectActionsStore directory
ls -la packages/web/src/stores/projectActionsStore/Repository: InfinityBowman/corates
Length of output: 611
🏁 Script executed:
#!/bin/bash
# Find the EditPdfMetadataModal
find packages/web/src -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) -exec grep -l "EditPdfMetadataModal" {} \;Repository: InfinityBowman/corates
Length of output: 231
🏁 Script executed:
#!/bin/bash
# Search for the modal component definition
find packages/web/src -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) | xargs grep -l "export.*EditPdfMetadataModal\|function EditPdfMetadataModal\|const EditPdfMetadataModal"Repository: InfinityBowman/corates
Length of output: 145
🏁 Script executed:
#!/bin/bash
# Read the EditPdfMetadataModal component
cat packages/web/src/components/project-ui/all-studies-tab/EditPdfMetadataModal.jsxRepository: InfinityBowman/corates
Length of output: 6919
Remove unnecessary async declaration from handleSaveMetadata.
The handleSaveMetadata handler is declared as async but doesn't await anything. The underlying updateMetadata method is synchronous and directly calls Y.js operations. Either remove the async keyword or wrap the call if actual async error handling becomes necessary in the future.
🤖 Prompt for AI Agents
In
packages/web/src/components/project-ui/all-studies-tab/study-card/StudyPdfSection.jsx
around lines 88 to 90, the handler handleSaveMetadata is declared async but
performs only a synchronous call to projectActionsStore.pdf.updateMetadata;
remove the async keyword from the function declaration to avoid misleading async
semantics (or if you intend to handle async behavior, convert the updateMetadata
call to return a Promise and await it). Ensure the function signature is updated
accordingly and any callers are unaffected.
| // eslint-disable-next-line solid/reactivity | ||
| let studyId = props.studyId; |
There was a problem hiding this comment.
Reactivity issue: studyId won't update if props change.
The let studyId = props.studyId assignment captures the initial value but won't update if props.studyId changes. In SolidJS, this creates a stale closure. When handleOpenPicker executes later, it may pass an outdated studyId to the callback.
Recommended fix: access props.studyId directly
- // eslint-disable-next-line solid/reactivity
- let studyId = props.studyId;Then update line 141:
- await props.onPick?.(picked, studyId);
+ await props.onPick?.(picked, props.studyId);As per coding guidelines, props should be accessed directly to ensure reactivity in SolidJS components.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
packages/web/src/components/project-ui/google-drive/GoogleDrivePickerLauncher.jsx
around lines 35-36, the component assigns let studyId = props.studyId which
captures the initial value and becomes stale if props change; update the code to
stop copying props into a local variable and instead reference props.studyId
directly wherever studyId is used (e.g., in handleOpenPicker and callbacks) so
the component uses the reactive prop value; remove the local let studyId
declaration to avoid the stale closure.
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.