-
Notifications
You must be signed in to change notification settings - Fork 2
DocumentLibraryView #408
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
base: main
Are you sure you want to change the base?
DocumentLibraryView #408
Conversation
9077f7f
to
9cf48bf
Compare
…meter from detail view
Note Reviews pausedUse the following commands to manage reviews:
WalkthroughThe changes encompass several areas across the codebase. Unit tests have been added for managing survey files, specifically to verify file querying and deletion behaviors using mocked external modules. New helper functions have been introduced for querying all survey files and deleting survey result files, along with corresponding TypeScript interfaces. Enhancements have been made to the 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (21)
src/helpers/query-all-survey-files.ts (4)
33-33
: Consider removingasync
from theforEach
callback.This callback does not await any asynchronous operation, so marking it as
async
can be misleading and might cause confusion if future modifications introduce asynchronous steps that won’t be properly awaited.
38-38
: Use optional chaining for cleaner and safer expressions.Repetitive checks like
x && x.answers && x.answers[0]
can be replaced with optional chaining to reduce complexity. For instance, change:- const fileName = fileNameResults && fileNameResults.answers ? fileNameResults.answers[0] : ""; + const fileName = fileNameResults?.answers?.[0] ?? "";Apply similar changes for the date, title,
fileNameResultID
,type
, andnotes
to improve readability.Also applies to: 44-44, 46-47, 49-49, 51-51
🧰 Tools
🪛 Biome (1.9.4)
[error] 38-38: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
91-94
: Avoid mixingasync/await
with.then(...)
.Currently, the function is declared as
async
, yet a promise chain handles the result. For better consistency and clarity, either removeasync
and return the promise, or useawait
fully. For example:-export async function queryAllSurveyFiles(props: SurveyUploadedFileQueryParameters): Promise<SurveyUploadedFile[]> { - return await queryAllSurveyAnswers(queryParameters).then((surveyAnswers: SurveyAnswer[]) => { - return groupSurveyAnswersByResults(surveyAnswers); - }); +export async function queryAllSurveyFiles(props: SurveyUploadedFileQueryParameters): Promise<SurveyUploadedFile[]> { + const surveyAnswers = await queryAllSurveyAnswers(queryParameters); + return groupSurveyAnswersByResults(surveyAnswers); }
101-106
: Consider re-throwing errors to allow callers to handle them.Currently, errors are only logged without providing feedback to the caller about failure. Re-throwing or returning an error value ensures upstream code can respond appropriately:
}).catch((error) => { console.error('Error deleting survey results', error); console.error('The survey must be configured to support result deletion'); + throw error; });
src/components/view/DocumentLibraryView/DocumentLibraryView.previewData.ts (1)
23-23
: Use deterministic dates if you rely on snapshot testing.Generating random dates can produce inconsistent test snapshots. If you want consistent outputs, consider using a fixed date or a predictable seed for the random calculation.
src/components/view/DocumentLibraryView/DocumentLibraryView.stories.tsx (1)
33-46
: Consider adding error state story.While the current stories cover Default, Loading, and Live states, consider adding an error state story to demonstrate how the component handles failures.
export const Error: Story = { args: { ...defaultProps, preview: 'PreviewError' }, render: render };src/components/view/DocumentDetailView/DocumentDetailView.previewData.ts (1)
24-36
: Refactor preview data for better maintainability.Consider extracting common properties into a base object to reduce duplication and improve maintainability.
const basePreviewData: Partial<DocumentDetail> = { surveyResultId: "12345", fileCategory: "test category", showDownload: false, fileKey: "file key" }; const previewPdfData: DocumentDetail = { ...basePreviewData, title: "Sample Portrait PDF", fileName: "PDF32000_2008.pdf", // ... other specific properties } as DocumentDetail;Also applies to: 38-50, 52-64, 66-78, 80-92, 94-106, 108-120
src/components/view/DocumentLibraryView/DocumentLibraryView.tsx (2)
104-112
: Improve sorting logic readability and type safety.The sorting logic in
buildFileList
could be more readable and type-safe.Consider using a more structured approach:
function buildFileList(files: SurveyUploadedFile[], selectedSegment: "date" | "name" | "type") { + const sortingStrategies = { + date: (a: SurveyUploadedFile, b: SurveyUploadedFile) => b.date.getTime() - a.date.getTime(), + name: (a: SurveyUploadedFile, b: SurveyUploadedFile) => a.title.localeCompare(b.title), + type: (a: SurveyUploadedFile, b: SurveyUploadedFile) => a.type.localeCompare(b.type) + }; + const sortingStrategy = sortingStrategies[selectedSegment]; - const sortedFiles = files.sort((a, b) => { - if (selectedSegment === "date") { - return a.date > b.date ? -1 : 1; - } else if (selectedSegment === "name") { - return a.title < b.title ? -1 : 1; - } else { - return a.type < b.type ? -1 : 1; - } - }); + const sortedFiles = [...files].sort(sortingStrategy);
122-124
: Consider adding cleanup in useInitializeView.The
useInitializeView
hook might need cleanup if the component unmounts during initialization.Add cleanup:
useInitializeView(() => { + let mounted = true; initialize(); + return () => { + mounted = false; + }; }, [], []);src/components/view/DocumentDetailView/DocumentDetailView.tsx (1)
22-27
: Consider making DocumentDetail properties optional.The
DocumentDetail
interface extendsSurveyUploadedFile
but some properties might not be available when file is not found.Make properties optional:
export interface DocumentDetail extends SurveyUploadedFile { - presignedDocUrl: string, - presignedImageUrl: string, + presignedDocUrl?: string, + presignedImageUrl?: string, showDownload: boolean, fileKey: string }__tests__/helpers/query-all-survey-files.test.ts (2)
83-87
: Add test for concurrent file operations.The test doesn't verify behavior during concurrent delete operations.
Add concurrent operation test:
test("should handle concurrent delete operations correctly", async () => { const deletePromises = [ deleteSurveyResultFiles("test-id-1", "test-file-key-1"), deleteSurveyResultFiles("test-id-2", "test-file-key-2") ]; await Promise.all(deletePromises); expect(MyDataHelps.deleteSurveyResult).toHaveBeenCalledTimes(2); expect(MyDataHelps.deleteFile).toHaveBeenCalledTimes(2); });
89-94
: Add retry mechanism test.The test doesn't verify retry behavior for transient failures.
Add retry test:
test("should retry failed operations", async () => { (MyDataHelps.deleteSurveyResult as jest.Mock) .mockRejectedValueOnce(new Error("Transient error")) .mockResolvedValueOnce(undefined); await deleteSurveyResultFiles("test-id", "test-file-key"); expect(MyDataHelps.deleteSurveyResult).toHaveBeenCalledTimes(2); });src/helpers/strings-en.ts (1)
526-533
: Consider adding more descriptive error messages.The error message for file loading failure could be more specific.
Enhance error messages:
- "file-not-loaded": "The file could not be loaded. Please contact support.", + "file-not-loaded": "Unable to load the file. This could be due to network issues or the file may have been deleted. Please try again or contact support if the problem persists.", + "file-load-network-error": "Network error while loading the file. Please check your connection and try again.", + "file-load-permission-error": "You don't have permission to access this file.",src/helpers/strings-pt.ts (1)
525-533
: Well-structured localization implementation!The localization implementation follows best practices:
- Consistent string keys across all language files
- Type-safe implementation using TypeScript
- Clear and maintainable organization of UI strings
Consider adding JSDoc comments for the string keys to help other developers understand their context and usage.
Also applies to: 526-533, 526-533
src/helpers/strings-fr.ts (1)
526-533
: LGTM! Consider adding a period to the error message.The French translations for document-related functionality are accurate and well-structured. Consider adding a period at the end of the error message for consistency with other error messages in the file.
Apply this diff to add a period to the error message:
- "file-not-loaded": "Le fichier n'a pas pu être chargé. Veuillez contacter le support.", + "file-not-loaded": "Le fichier n'a pas pu être chargé. Veuillez contacter le support."src/components/view/DocumentDetailView/DocumentDetailView.css (6)
1-8
: Consider using CSS variables for better maintainability.The container styles look good, but consider using CSS variables for values that might need to be adjusted across different themes or breakpoints.
Apply this diff to use CSS variables:
.mdhui-survey-answer-file-container { max-width: 600px; margin: auto; - padding: 16px; - border-radius: 8px; + padding: var(--mdhui-spacing-4, 16px); + border-radius: var(--mdhui-border-radius-2, 8px); background: #f9f9f9; - box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1); + box-shadow: var(--mdhui-box-shadow-1, 0px 4px 10px rgba(0, 0, 0, 0.1)); }
10-19
: Consider a more responsive height approach.Using a fixed viewport height percentage might cause issues on mobile devices. Consider using a min-height or a more responsive approach.
Apply this diff to make the height more responsive:
.mdhui-survey-answer-file-preview-container { width: 100%; - height: 55vh; + min-height: 300px; + height: min(55vh, 600px); display: flex; align-items: center; justify-content: center; background: #fff; - border-radius: 8px; + border-radius: var(--mdhui-border-radius-2, 8px); overflow: hidden; }
32-37
: Consider using CSS variables for spacing.The file name styles look good, but consider using CSS variables for consistency with other spacing values.
Apply this diff to use CSS variables:
.mdhui-survey-answer-file-document-file-name { display: flex; justify-content: center; - margin-top: 10px; + margin-top: var(--mdhui-spacing-2-5, 10px); }
38-41
: Consider using CSS variables for padding.Consider using CSS variables for consistent spacing across the application.
Apply this diff to use CSS variables:
.mdhui-survey-answer-file-document-details-parent { - padding: 10px; + padding: var(--mdhui-spacing-2-5, 10px); }
42-45
: Consider using CSS variables for spacing and font size.The use of em units for font size is good for accessibility. Consider using CSS variables for consistent spacing and typography.
Apply this diff to use CSS variables:
.mdhui-survey-answer-file-document-details { - font-size: .88em; - margin: 5px; + font-size: var(--mdhui-font-size-sm, .88em); + margin: var(--mdhui-spacing-1-25, 5px); }
47-53
: Consider using CSS variables for spacing.The button container styles are well-structured. Consider using CSS variables for consistent spacing.
Apply this diff to use CSS variables:
.mdhui-survey-answer-file-download-button { display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; - margin-bottom: 10px; + margin-bottom: var(--mdhui-spacing-2-5, 10px); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
__tests__/helpers/query-all-survey-files.test.ts
(1 hunks)src/components/view/DocumentDetailView/DocumentDetailView.css
(1 hunks)src/components/view/DocumentDetailView/DocumentDetailView.previewData.ts
(1 hunks)src/components/view/DocumentDetailView/DocumentDetailView.stories.tsx
(1 hunks)src/components/view/DocumentDetailView/DocumentDetailView.tsx
(1 hunks)src/components/view/DocumentDetailView/index.ts
(1 hunks)src/components/view/DocumentLibraryView/DocumentLibraryView.previewData.ts
(1 hunks)src/components/view/DocumentLibraryView/DocumentLibraryView.stories.tsx
(1 hunks)src/components/view/DocumentLibraryView/DocumentLibraryView.tsx
(1 hunks)src/components/view/DocumentLibraryView/index.ts
(1 hunks)src/components/view/index.ts
(1 hunks)src/helpers/index.ts
(1 hunks)src/helpers/query-all-survey-files.ts
(1 hunks)src/helpers/strings-de.ts
(1 hunks)src/helpers/strings-en.ts
(1 hunks)src/helpers/strings-es.ts
(1 hunks)src/helpers/strings-fr.ts
(1 hunks)src/helpers/strings-it.ts
(1 hunks)src/helpers/strings-nl.ts
(1 hunks)src/helpers/strings-pl.ts
(1 hunks)src/helpers/strings-pt.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- src/components/view/DocumentDetailView/index.ts
- src/components/view/DocumentLibraryView/index.ts
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/view/DocumentDetailView/DocumentDetailView.tsx
[error] 128-128: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 151-151: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
src/helpers/query-all-survey-files.ts
[error] 38-38: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 44-44: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 46-46: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 47-47: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 49-49: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 51-51: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (15)
src/helpers/index.ts (1)
11-11
: Export additions look good.These exports expand the helper module’s interface without issues.
src/components/view/DocumentLibraryView/DocumentLibraryView.previewData.ts (1)
5-12
: Good use of a preview helper function.Providing multiple sample files with different types and notes is handy for testing and demonstrations.
src/components/view/DocumentLibraryView/DocumentLibraryView.stories.tsx (1)
23-31
: Props naming follows a clear pattern.The props follow a consistent naming convention with clear identifiers for different document attributes. This makes the component's configuration intuitive and maintainable.
src/components/view/index.ts (1)
8-9
: Exports are correctly placed and follow consistent pattern.The new exports maintain alphabetical ordering and follow the same syntax as other exports in the file.
src/components/view/DocumentDetailView/DocumentDetailView.stories.tsx (2)
31-59
: Excellent coverage of different file types.The stories comprehensively cover various file types (PDF, Text, Image, CSV, Video, Unsupported) which is great for testing and documentation.
71-89
:✅ Verification successful
Verify the hardcoded surveyResultIds.
The live examples use hardcoded surveyResultIds. Ensure these IDs are:
- Not tied to sensitive or production data
- Will remain valid for testing purposes
🏁 Script executed:
#!/bin/bash # Check if these IDs exist in any configuration or test data files rg -l "2e3f7062-87e8-ef11-bafe-0affe8024cad|97477698-85e9-ef11-bafe-0affe8024cad|ad6d89b3-a1ef-ef11-bafe-0affe8024cad|a90c0337-cfe4-ef11-bafe-0affe8024cad"Length of output: 227
Hardcoded surveyResultIds verification complete.
The search confirms that the IDs used in the story file
src/components/view/DocumentDetailView/DocumentDetailView.stories.tsx
(2e3f7062-87e8-ef11-bafe-0affe8024cad, 97477698-85e9-ef11-bafe-0affe8024cad, ad6d89b3-a1ef-ef11-bafe-0affe8024cad, and a90c0337-cfe4-ef11-bafe-0affe8024cad) appear only in test story examples. There’s no indication that they are tied to any sensitive or production data. Please confirm that these IDs will remain valid for testing purposes over time.src/helpers/strings-nl.ts (1)
525-532
: Dutch translations look good!The added translations are accurate, maintain consistent tone, and follow Dutch language conventions for UI strings.
src/helpers/strings-pl.ts (1)
526-533
: Polish translations look good!The added translations are accurate, maintain consistent tone, and follow Polish language conventions for UI strings.
src/helpers/strings-pt.ts (1)
526-533
: Portuguese translations look good!The added translations are accurate, maintain consistent tone, and follow Portuguese language conventions for UI strings.
src/helpers/strings-es.ts (1)
526-533
: Well-structured Spanish translations for document management!The translations are accurate, use standard Spanish UI terminology, and maintain consistent meaning with English terms. Good security practice in the error handling message directing users to support.
src/helpers/strings-it.ts (1)
526-533
: Well-structured Italian translations for document management!The translations are accurate, use standard Italian UI terminology, and maintain consistent meaning with English terms. Good security practice in the error handling message directing users to support.
src/helpers/strings-de.ts (2)
526-533
: Well-structured German translations for document management!The translations are accurate, use standard German UI terminology, and maintain consistent meaning with English terms. Good security practice in the error handling message directing users to support.
526-533
: Excellent localization implementation across all language files!The implementation demonstrates several good practices:
- Consistent structure and messaging across all language files
- Security-conscious error handling directing users to support
- Use of standard UI terminology in each language
- Clear and user-friendly delete confirmation dialogs
src/components/view/DocumentDetailView/DocumentDetailView.css (2)
21-27
: LGTM!The preview content styles are well-structured and responsive.
28-30
: LGTM!The image preview styles use the appropriate object-fit property to maintain aspect ratio.
type: "Test Results", | ||
notes: "These are some notes for a sample PDF", | ||
date: new Date(), | ||
presignedDocUrl: "https://freelawlibrary.org/wp-content/uploads/2022/10/The-Constitution-Full-Text-The-National-Constitution-Center.pdf", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Security: Validate and secure external URLs.
The preview data uses external URLs which could pose several risks:
- URLs might become unavailable
- Content might change without notice
- External dependencies for testing
Consider:
- Using local assets for testing
- Implementing URL validation
- Adding fallback content
Also applies to: 46-46, 61-61, 88-88, 102-102, 116-116
🏁 Script executed:
#!/bin/bash
# Test URL availability and content type
for url in \
"https://freelawlibrary.org/wp-content/uploads/2022/10/The-Constitution-Full-Text-The-National-Constitution-Center.pdf" \
"https://www.gutenberg.org/cache/epub/42671/pg42671.txt" \
"https://careevolution.com/wp-content/themes/careevolution-2023/assets/images/logo.svg" \
"https://people.sc.fsu.edu/~jburkardt/data/csv/airtravel.csv" \
"https://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"
do
echo "Checking $url"
curl -sI "$url" | head -n 1
done
Length of output: 3536
Security Concern: External URLs in Preview Data
Although our tests show that the current external URLs (e.g., the presigned document URL returning HTTP/2 200) are accessible, relying on external resources for preview data poses inherent risks. These URLs might change or become unavailable without notice, which could lead to unexpected behavior or broken previews.
Recommendations:
- Local Assets: Where feasible, replace external URLs with local assets to ensure reliable testing and consistent behavior.
- URL Validation & Fallbacks: Implement a mechanism to validate the URL content dynamically and provide fallback content if the external resource is unreachable or returns an unexpected status (e.g., the BigBuckBunny URL returned a 302 redirect).
These concerns apply not only at line 32 in src/components/view/DocumentDetailView/DocumentDetailView.previewData.ts
but also at the similar occurrences on lines 46, 61, 88, 102, and 116.
const onUploadClick = () => { | ||
setLoading(true); | ||
MyDataHelps.startSurvey(props.uploadDocumentSurveyName); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling for startSurvey call.
The onUploadClick
function doesn't handle potential errors from MyDataHelps.startSurvey
.
Add error handling:
const onUploadClick = () => {
setLoading(true);
- MyDataHelps.startSurvey(props.uploadDocumentSurveyName);
+ MyDataHelps.startSurvey(props.uploadDocumentSurveyName).catch(error => {
+ console.error('Failed to start survey:', error);
+ setLoading(false);
+ });
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const onUploadClick = () => { | |
setLoading(true); | |
MyDataHelps.startSurvey(props.uploadDocumentSurveyName); | |
} | |
const onUploadClick = () => { | |
setLoading(true); | |
MyDataHelps.startSurvey(props.uploadDocumentSurveyName).catch(error => { | |
console.error('Failed to start survey:', error); | |
setLoading(false); | |
}); | |
} |
src/components/view/DocumentLibraryView/DocumentLibraryView.tsx
Outdated
Show resolved
Hide resolved
src/components/view/DocumentLibraryView/DocumentLibraryView.tsx
Outdated
Show resolved
Hide resolved
src/components/view/DocumentLibraryView/DocumentLibraryView.tsx
Outdated
Show resolved
Hide resolved
async function downloadFile() { | ||
const deviceInfo = await MyDataHelps.getDeviceInfo(); | ||
|
||
if (!deviceInfo || deviceInfo.platform == "Web") { | ||
window.open(documentDetail?.presignedDocUrl ?? documentDetail?.presignedImageUrl, "_blank"); | ||
} else { | ||
(window as any).webkit.messageHandlers.OpenFile.postMessage({ url: documentDetail?.presignedDocUrl ?? documentDetail?.presignedImageUrl }); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve cross-platform compatibility in downloadFile.
The downloadFile
function assumes iOS-specific message handler.
Add platform-specific handling:
async function downloadFile() {
const deviceInfo = await MyDataHelps.getDeviceInfo();
+ const fileUrl = documentDetail?.presignedDocUrl ?? documentDetail?.presignedImageUrl;
+ if (!fileUrl) return;
if (!deviceInfo || deviceInfo.platform == "Web") {
- window.open(documentDetail?.presignedDocUrl ?? documentDetail?.presignedImageUrl, "_blank");
+ window.open(fileUrl, "_blank");
} else {
- (window as any).webkit.messageHandlers.OpenFile.postMessage({ url: documentDetail?.presignedDocUrl ?? documentDetail?.presignedImageUrl });
+ if (deviceInfo.platform === "iOS") {
+ (window as any).webkit.messageHandlers.OpenFile.postMessage({ url: fileUrl });
+ } else if (deviceInfo.platform === "Android") {
+ (window as any).Android.openFile(fileUrl);
+ }
}
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async function downloadFile() { | |
const deviceInfo = await MyDataHelps.getDeviceInfo(); | |
if (!deviceInfo || deviceInfo.platform == "Web") { | |
window.open(documentDetail?.presignedDocUrl ?? documentDetail?.presignedImageUrl, "_blank"); | |
} else { | |
(window as any).webkit.messageHandlers.OpenFile.postMessage({ url: documentDetail?.presignedDocUrl ?? documentDetail?.presignedImageUrl }); | |
} | |
} | |
async function downloadFile() { | |
const deviceInfo = await MyDataHelps.getDeviceInfo(); | |
const fileUrl = documentDetail?.presignedDocUrl ?? documentDetail?.presignedImageUrl; | |
if (!fileUrl) return; | |
if (!deviceInfo || deviceInfo.platform === "Web") { | |
window.open(fileUrl, "_blank"); | |
} else { | |
if (deviceInfo.platform === "iOS") { | |
(window as any).webkit.messageHandlers.OpenFile.postMessage({ url: fileUrl }); | |
} else if (deviceInfo.platform === "Android") { | |
(window as any).Android.openFile(fileUrl); | |
} | |
} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (6)
src/components/view/DocumentDetailView/DocumentDetailView.stories.tsx (2)
22-30
: Add JSDoc comments to document the base props.The
uploadDocumentSurveyProps
object contains several result identifiers that would benefit from documentation explaining their purpose and expected values. Additionally, consider documenting the 'auto' colorScheme behavior.Add JSDoc comments like this:
+/** + * Base props for document upload survey stories. + * @property {string} colorScheme - Controls the component's color theme ('auto'|'light'|'dark'). + * @property {string} surveyResultId - Unique identifier for the survey result. + * @property {string} fileResultIdentifier - Field identifier for the uploaded file. + * @property {string} typeResultIdentifier - Field identifier for the document type. + * @property {string} nameResultIdentifier - Field identifier for the document name. + * @property {string} dateResultIdentifier - Field identifier for the document date. + * @property {string} notesResultIdentifier - Field identifier for document notes. + */ const uploadDocumentSurveyProps: DocumentDetailViewProps = {
32-70
: Use constants for preview values.The preview values are currently hardcoded strings. Consider defining an enum or constants to ensure type safety and maintainability.
Create a constants file or enum:
// previewTypes.ts export enum PreviewType { PDF = 'PreviewPdf', TEXT = 'PreviewText', IMAGE = 'PreviewImage', CSV = 'PreviewCsvFile', VIDEO = 'PreviewMp4', UNKNOWN = 'PreviewUnknown', LOADING = 'PreviewLoading', FILE_NOT_FOUND = 'PreviewFileNotFound' }Then update the stories:
- args: { ...uploadDocumentSurveyProps, preview: 'PreviewPdf' }, + args: { ...uploadDocumentSurveyProps, preview: PreviewType.PDF },src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.previewData.ts (1)
1-7
: Consider using an enum or constant for document types.The document types are hardcoded strings which could lead to maintenance issues. Consider:
- Using an enum to ensure type safety
- Moving these strings to a centralized constants file for reusability
+export enum DocumentType { + InsuranceCard = "Insurance Card", + MammogramResults = "Mammogram Results", + BloodTestResults = "Blood Test Results" +} + export function getPreviewData(): string[] { return [ - "Insurance Card", - "Mammogram Results", - "Blood Test Results", + DocumentType.InsuranceCard, + DocumentType.MammogramResults, + DocumentType.BloodTestResults, ]; }src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.stories.tsx (2)
26-34
: Consider adding JSDoc comments for defaultProps.The defaultProps object contains important configuration that would benefit from documentation explaining the purpose of each identifier.
+/** + * Default configuration for DocumentLibraryPreview stories + * @property {string} uploadDocumentSurveyName - Name of the survey for document uploads + * @property {string} fileResultIdentifier - Identifier for the file result + * @property {string} typeResultIdentifier - Identifier for the document type + * @property {string} nameResultIdentifier - Identifier for the document name + * @property {string} dateResultIdentifier - Identifier for the document date + * @property {string} notesResultIdentifier - Identifier for document notes + * @property {string} documentViewBaseUrl - Base URL for document viewing + */ const defaultProps: DocumentLibraryPreviewProps = {
36-54
: Consider adding test cases for error scenarios.The stories cover basic use cases but lack scenarios for error handling, such as:
- Network errors during file upload
- Invalid document types
- Maximum file size exceeded
export const NetworkError: Story = { args: { ...defaultProps, preview: 'PreviewError' }, render: render };src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.tsx (1)
10-20
: Consider adding validation for required props.The interface doesn't indicate which props are required vs optional. Consider:
- Adding proper type annotations
- Using Zod or similar for runtime validation
export interface DocumentLibraryPreviewProps { preview?: "PreviewNoDocuments" | "PreviewDocuments" | "PreviewLoading", - uploadDocumentSurveyName: string, - fileResultIdentifier: string, - typeResultIdentifier: string, - nameResultIdentifier: string, - dateResultIdentifier: string, - notesResultIdentifier: string, - documentViewBaseUrl: string, + uploadDocumentSurveyName: string & { _brand: 'NonEmptyString' }, + fileResultIdentifier: string & { _brand: 'NonEmptyString' }, + typeResultIdentifier: string & { _brand: 'NonEmptyString' }, + nameResultIdentifier: string & { _brand: 'NonEmptyString' }, + dateResultIdentifier: string & { _brand: 'NonEmptyString' }, + notesResultIdentifier: string & { _brand: 'NonEmptyString' }, + documentViewBaseUrl: string & { _brand: 'ValidURL' }, innerRef?: React.Ref<HTMLDivElement>; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.css
(1 hunks)src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.previewData.ts
(1 hunks)src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.stories.tsx
(1 hunks)src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.tsx
(1 hunks)src/components/view/DocumentDetailView/DocumentDetailView.stories.tsx
(1 hunks)src/components/view/DocumentLibraryView/DocumentLibraryView.stories.tsx
(1 hunks)src/helpers/strings-de.ts
(1 hunks)src/helpers/strings-en.ts
(1 hunks)src/helpers/strings-es.ts
(1 hunks)src/helpers/strings-fr.ts
(1 hunks)src/helpers/strings-it.ts
(1 hunks)src/helpers/strings-nl.ts
(1 hunks)src/helpers/strings-pl.ts
(1 hunks)src/helpers/strings-pt.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.css
🚧 Files skipped from review as they are similar to previous changes (2)
- src/components/view/DocumentLibraryView/DocumentLibraryView.stories.tsx
- src/helpers/strings-it.ts
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.tsx
[error] 77-77: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🔇 Additional comments (6)
src/helpers/strings-en.ts (1)
526-539
: LGTM! The English translations are clear and consistent.The new document management strings follow a consistent style and provide clear, user-friendly messages.
src/helpers/strings-nl.ts (1)
525-538
: LGTM! The Dutch translations are accurate and consistent.The translations maintain appropriate formality using "je" and follow Dutch language conventions.
src/helpers/strings-pl.ts (1)
526-539
: LGTM! The Polish translations are accurate and consistent.The translations follow Polish language conventions and maintain appropriate formality.
src/helpers/strings-pt.ts (1)
526-539
: LGTM! The Portuguese translations are accurate and consistent.The translations follow Portuguese language conventions and maintain appropriate formality.
src/helpers/strings-de.ts (1)
526-539
: LGTM! German translations are accurate and consistent.The translations use correct German terminology for document management actions, maintaining consistency between related terms (e.g., "Hochladen" for upload actions).
src/components/view/DocumentDetailView/DocumentDetailView.stories.tsx (1)
1-18
: LGTM! Well-structured Storybook configuration.The imports and metadata are properly configured following Storybook best practices. The fullscreen layout is appropriate for a document viewer component.
export const Live: Story = { | ||
args: { ...uploadDocumentSurveyProps, surveyResultId: '2e3f7062-87e8-ef11-bafe-0affe8024cad' }, | ||
render: render | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Replace hardcoded UUID in Live story.
The Live story uses a hardcoded UUID which could make the story brittle and difficult to maintain. Consider using a mock service or a more maintainable approach.
Options to consider:
- Use a mock service worker (MSW) to intercept API calls
- Create a helper function that generates valid test IDs
- Document the UUID's source and purpose if it must be hardcoded
Example using MSW:
import { rest } from 'msw'
import { setupServer } from 'msw/node'
const server = setupServer(
rest.get('/api/survey-result/:id', (req, res, ctx) => {
return res(
ctx.json({
// mock response data
})
)
})
)
export const Live: Story = {
args: { ...uploadDocumentSurveyProps, surveyResultId: 'test-survey-result' },
parameters: {
msw: {
handlers: [server]
}
}
}
queryAllSurveyFiles({ ...params }).then((uploadedFiles: SurveyUploadedFile[]) => { | ||
const sortedFiles = uploadedFiles.sort((a, b) => { | ||
return a.date > b.date ? -1 : 1; | ||
}); | ||
|
||
const top3Files = sortedFiles.slice(0, 3).map((file: SurveyUploadedFile, index: number) => | ||
file.title | ||
); | ||
setSurveyFiles(top3Files); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling for queryAllSurveyFiles.
The promise chain lacks error handling which could lead to unhandled rejections.
- queryAllSurveyFiles({ ...params }).then((uploadedFiles: SurveyUploadedFile[]) => {
+ queryAllSurveyFiles({ ...params })
+ .then((uploadedFiles: SurveyUploadedFile[]) => {
const sortedFiles = uploadedFiles.sort((a, b) => {
return a.date > b.date ? -1 : 1;
});
const top3Files = sortedFiles.slice(0, 3).map((file: SurveyUploadedFile, index: number) =>
file.title
);
setSurveyFiles(top3Files);
- });
+ })
+ .catch((error) => {
+ console.error('Failed to query survey files:', error);
+ setSurveyFiles([]);
+ });
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
queryAllSurveyFiles({ ...params }).then((uploadedFiles: SurveyUploadedFile[]) => { | |
const sortedFiles = uploadedFiles.sort((a, b) => { | |
return a.date > b.date ? -1 : 1; | |
}); | |
const top3Files = sortedFiles.slice(0, 3).map((file: SurveyUploadedFile, index: number) => | |
file.title | |
); | |
setSurveyFiles(top3Files); | |
}); | |
} | |
queryAllSurveyFiles({ ...params }) | |
.then((uploadedFiles: SurveyUploadedFile[]) => { | |
const sortedFiles = uploadedFiles.sort((a, b) => { | |
return a.date > b.date ? -1 : 1; | |
}); | |
const top3Files = sortedFiles.slice(0, 3).map((file: SurveyUploadedFile, index: number) => | |
file.title | |
); | |
setSurveyFiles(top3Files); | |
}) | |
.catch((error) => { | |
console.error('Failed to query survey files:', error); | |
setSurveyFiles([]); | |
}); |
src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
package.json (1)
3-3
: Correct the version string spelling.The version string currently reads
"2.68.1-DocumentLibaryView.0"
, but based on the PR objectives and component naming, it appears the intended name should be"DocumentLibraryView"
rather than"DocumentLibaryView"
. Please update the spelling to maintain consistency and avoid confusion.- "version": "2.68.1-DocumentLibaryView.0", + "version": "2.68.1-DocumentLibraryView.0",
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (3)
package.json
(1 hunks)src/components/container/DocumentLibraryPreview/index.ts
(1 hunks)src/components/container/index.ts
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/components/container/DocumentLibraryPreview/index.ts
🔇 Additional comments (1)
src/components/container/index.ts (1)
17-17
: LGTM! Export follows consistent patterns.The new export for
DocumentLibraryPreview
is correctly placed in alphabetical order and follows the established export pattern in the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.tsx (2)
45-55
:⚠️ Potential issueAdd error handling for queryAllSurveyFiles.
The promise chain lacks error handling which could lead to unhandled rejections.
- queryAllSurveyFiles({ ...params }).then((uploadedFiles: SurveyUploadedFile[]) => { + queryAllSurveyFiles({ ...params }) + .then((uploadedFiles: SurveyUploadedFile[]) => { const sortedFiles = uploadedFiles.sort((a, b) => { return a.date > b.date ? -1 : 1; }); const top3Files = sortedFiles.slice(0, 3).map((file: SurveyUploadedFile, index: number) => file.title ); setSurveyFiles(top3Files); - }); + }) + .catch((error) => { + console.error('Failed to query survey files:', error); + setSurveyFiles([]); + });
75-91
:⚠️ Potential issueFix React children prop issue.
The static analysis tool correctly identified an issue with passing children as a prop.
- <Action title={` ${language("uploaded-documents")}`} - className="font-size" - indicatorPosition="default" - subtitle={surveyFiles.length === 0 - ? language("upload-documents-subtitle") - : ""} - children={surveyFiles.length > 0 - ? surveyFiles.map((file, index) => <div className="file-title" key={index}>{file}</div>) - : undefined - } - titleIcon={<FontAwesomeSvgIcon icon={faCamera} />} - indicatorValue={surveyFiles.length > 0 ? surveyFiles.length.toString() : undefined} - indicator={surveyFiles.length === 0 - ? <Button variant="default" fullWidth={false} onClick={noop}>{language("upload-button")}</Button> - : undefined} - /> + <Action + title={` ${language("uploaded-documents")}`} + className="font-size" + indicatorPosition="default" + subtitle={surveyFiles.length === 0 + ? language("upload-documents-subtitle") + : ""} + titleIcon={<FontAwesomeSvgIcon icon={faCamera} />} + indicatorValue={surveyFiles.length > 0 ? surveyFiles.length.toString() : undefined} + indicator={surveyFiles.length === 0 + ? <Button variant="default" fullWidth={false} onClick={onPreviewClick}>{language("upload-button")}</Button> + : undefined} + > + {surveyFiles.length > 0 + ? surveyFiles.map((file, index) => <div className="file-title" key={index}>{file}</div>) + : undefined} + </Action>🧰 Tools
🪛 Biome (1.9.4)
[error] 82-82: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (2)
package.json
(2 hunks)src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.tsx
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- package.json
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.tsx
[error] 82-82: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🔇 Additional comments (3)
src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.tsx (3)
1-21
: LGTM! Well-structured imports and interface definition.The imports are organized logically, and the interface is comprehensive with clear prop types.
23-34
: LGTM! Clean state management and preview mode handling.The state initialization and preview mode handling are well-implemented with clear conditional logic.
57-69
: LGTM! Well-implemented event handlers.The event handlers have clear conditional logic and proper initialization.
src/components/container/DocumentLibraryPreview/DocumentLibraryPreview.tsx
Outdated
Show resolved
Hide resolved
46148c8
to
94f8fda
Compare
82b248e
to
9c761eb
Compare
f92d34c
to
b679caf
Compare
b66c090
to
4f97e8b
Compare
26b9591
to
0cd7830
Compare
0278a11
to
4c712fa
Compare
4c712fa
to
6161bcd
Compare
8e9f34a
to
8131c9f
Compare
Overview
This PR has 3 components.
Components
Full spec here
Security
REMINDER: All file contents are public.
Describe briefly what security risks you considered, why they don't apply, or how they've been mitigated.
Checklist
Testing
Documentation
Consider "Squash and merge" as needed to keep the commit history reasonable on
main
.Reviewers
Assign to the appropriate reviewer(s). Minimally, a second set of eyes is needed ensure no non-public information is published. Consider also including: