-
Notifications
You must be signed in to change notification settings - Fork 1k
improvement: uploaded documents visible to viewer in the location the… #1773
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?
improvement: uploaded documents visible to viewer in the location the… #1773
Conversation
@AshishViradiya153 is attempting to deploy a commit to the mftsio Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughThis update introduces a document approval workflow for externally uploaded documents. It modifies the data model to track approval status, adds API endpoints for document approval, extends backend queries to include approval metadata, and updates frontend components to display approval status, restrict access to pending documents, and allow admins to approve uploads. State management and UI feedback for document approval are also implemented. Changes
Sequence Diagram(s)Document Upload and Approval FlowsequenceDiagram
participant Viewer
participant ViewerUploadComponent
participant API (Upload Route)
participant DB
participant Admin
participant API (Approve Route)
participant SWR/UI
Viewer->>ViewerUploadComponent: Upload document
ViewerUploadComponent->>API (Upload Route): POST /links/[id]/upload
API (Upload Route)->>DB: Create Document, DocumentUpload (requireApproval: true)
DB-->>API (Upload Route): Document, requireApproval
API (Upload Route)-->>ViewerUploadComponent: {document, requireApproval}
ViewerUploadComponent-->>Viewer: onSuccess callback
Viewer->>SWR/UI: UI shows "Pending Approval" badge
Admin->>UI: Sees document with "Approve" action
Admin->>API (Approve Route): POST /teams/[teamId]/documents/[id]/approve
API (Approve Route)->>DB: Set requireApproval=false, approvedAt, approvedBy, approvedStatus=APPROVED
API (Approve Route)-->>Admin: Success response
API (Approve Route)->>SWR/UI: Trigger mutate/revalidation
SWR/UI-->>UI: UI updates, document becomes accessible
Estimated code review effort4 (60–120 minutes)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
npm error Exit handler never called! ✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. 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: 1
🧹 Nitpick comments (5)
components/viewer-upload-component.tsx (1)
68-74
: Address static analysis hint for optional chainingThe response parsing and validation logic is sound, but the static analysis tool correctly identifies that line 70 could use optional chaining for better safety.
Apply this diff to improve null safety:
- if (document && document.id && Array.isArray(document.versions)) { + if (document?.id && Array.isArray(document?.versions)) {pages/api/teams/[teamId]/datarooms/[id]/documents/[documentId]/approve.ts (1)
14-37
: Authentication is thorough but consider additional authorization.The session validation and user/team verification are well-implemented. However, consider adding explicit checks for document approval permissions within the team context.
Consider adding a permission check:
+ // Check if user has approval permissions in this team + const teamMember = await prisma.teamMember.findUnique({ + where: { + userId_teamId: { + userId: user.id, + teamId: teamId, + }, + }, + select: { role: true }, + }); + + if (!teamMember || teamMember.role === 'VIEWER') { + return res.status(403).json({ message: "Insufficient permissions" }); + }prisma/schema/schema.prisma (2)
582-585
: Review the approval workflow fields.The approval-related fields are well-designed:
requireApproval
defaults totrue
for security-first approachapprovedAt
andapprovedBy
provide audit trailapprovedStatus
uses the new enum with appropriate defaultConsider making
approvedBy
a proper foreign key reference to ensure data integrity.-approvedBy String? // userId +approvedBy String? +approver User? @relation(fields: [approvedBy], references: [id], onDelete: SetNull)
112-112
: Clarify the purpose of ignoredDomains field.The new
ignoredDomains
field lacks documentation. Consider adding a comment to explain its purpose and usage.-ignoredDomains String[] // Domains that are ignored for the team +ignoredDomains String[] @default([]) // Domains that are ignored for notifications, validations, or other team-specific operationscomponents/view/viewer/dataroom-viewer.tsx (1)
333-366
: Review the handleUploadSuccess callback implementation.The callback correctly transforms the uploaded document data and updates both document list and count. However, there are a few considerations:
- The
canDownload
andcanView
are hardcoded tofalse
, which may be intentional for pending approval documents.- The
orderIndex
is set todocuments.length
, which could cause ordering issues if documents are filtered or sorted differently.Consider making the access permissions more explicit:
- canDownload: false, - canView: false, + canDownload: !newDocument.requireApproval, + canView: !newDocument.requireApproval,And for ordering, consider using a more robust approach:
- orderIndex: documents.length, + orderIndex: Math.max(...documents.map(d => d.orderIndex || 0), 0) + 1,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
app/api/links/[id]/upload/route.ts
(2 hunks)app/api/views-dataroom/route.ts
(3 hunks)components/datarooms/dataroom-document-card.tsx
(6 hunks)components/documents/document-card.tsx
(6 hunks)components/view/dataroom/dataroom-view.tsx
(4 hunks)components/view/dataroom/document-card.tsx
(8 hunks)components/view/dataroom/document-upload-modal.tsx
(3 hunks)components/view/viewer/dataroom-viewer.tsx
(6 hunks)components/viewer-upload-component.tsx
(2 hunks)lib/api/links/link-data.ts
(2 hunks)lib/swr/use-dataroom.ts
(1 hunks)lib/types.ts
(2 hunks)lib/utils/document-approve.ts
(1 hunks)pages/api/links/generate-index.ts
(1 hunks)pages/api/teams/[teamId]/datarooms/[id]/documents/[documentId]/approve.ts
(1 hunks)pages/api/teams/[teamId]/datarooms/[id]/documents/index.ts
(1 hunks)pages/api/teams/[teamId]/datarooms/[id]/folders/documents/[...name].ts
(1 hunks)pages/api/teams/[teamId]/documents/[id]/approve.ts
(1 hunks)pages/api/teams/[teamId]/documents/index.ts
(1 hunks)pages/api/teams/[teamId]/folders/documents/[...name].ts
(1 hunks)prisma/migrations/20250721091745_approved_docs/migration.sql
(1 hunks)prisma/schema/schema.prisma
(5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
components/view/dataroom/document-upload-modal.tsx (1)
components/view/viewer/dataroom-viewer.tsx (1)
DocumentVersion
(47-54)
app/api/views-dataroom/route.ts (1)
lib/api/links/link-data.ts (1)
fetchUploadDocumentsCount
(395-411)
components/documents/document-card.tsx (2)
lib/utils/document-approve.ts (1)
approveDocument
(27-59)components/ui/badge.tsx (1)
Badge
(48-48)
components/datarooms/dataroom-document-card.tsx (2)
lib/utils/document-approve.ts (1)
approveDocument
(27-59)components/ui/badge.tsx (1)
Badge
(48-48)
components/view/dataroom/document-card.tsx (3)
lib/utils.ts (1)
cn
(18-20)lib/utils/get-file-icon.tsx (1)
fileIcon
(13-70)components/ui/badge.tsx (1)
Badge
(48-48)
lib/utils/document-approve.ts (1)
context/team-context.tsx (1)
TeamContextType
(16-22)
🪛 Biome (1.9.4)
components/viewer-upload-component.tsx
[error] 70-70: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (60)
pages/api/teams/[teamId]/documents/index.ts (1)
115-119
: LGTM! Consistent approval status integration.The addition of
uploadedDocument.requireApproval
to the document query aligns well with the document approval workflow implementation. This ensures the approval status is available for UI components to conditionally render approval-related features.pages/api/teams/[teamId]/folders/documents/[...name].ts (1)
76-80
: LGTM! Consistent pattern implementation.The addition of
uploadedDocument.requireApproval
follows the same pattern as other document query endpoints, ensuring approval status is available for folder document listings.lib/swr/use-dataroom.ts (1)
287-289
: LGTM! Type definition correctly reflects API changes.The addition of the optional
uploadedDocument
field withrequireApproval
boolean aligns with the backend API changes and properly handles the case where documents may not have uploaded document records.pages/api/teams/[teamId]/datarooms/[id]/folders/documents/[...name].ts (1)
93-97
: LGTM! Maintains consistency across dataroom document queries.The inclusion of
uploadedDocument.requireApproval
in the dataroom folder document query maintains consistency with the approval workflow implementation across all document-related API endpoints.pages/api/teams/[teamId]/datarooms/[id]/documents/index.ts (1)
78-82
: LGTM! Consistent approval field addition.The addition of the
requireApproval
field selection from theuploadedDocument
relation is consistent with the broader document approval workflow. This enriches the API response with approval metadata that frontend components need to display approval status.components/view/dataroom/dataroom-view.tsx (2)
46-46
: LGTM! Proper type definition for upload count.The addition of the optional
uploadDocumentsCount
property to theDEFAULT_DATAROOM_VIEW_TYPE
is correctly typed and aligns with the approval workflow feature.
147-147
: LGTM! Consistent state management implementation.The
uploadDocumentsCount
is properly extracted from the API response and included in the state update. This follows the established pattern used for other view data properties.Also applies to: 183-183
app/api/links/[id]/upload/route.ts (2)
135-152
: LGTM! Efficient metadata capture from upload creation.The DocumentUpload creation now properly captures the returned object with the
requireApproval
field. Usingselect
to fetch only the needed field is efficient and follows best practices.
154-158
: LGTM! Enhanced API response with approval metadata.The enriched response provides frontend components with the necessary approval status and folder context. This enables proper handling of the upload approval workflow in the UI.
lib/types.ts (1)
27-29
: LGTM! Consistent type definitions for approval workflow.The optional
uploadedDocument
properties with therequireApproval
boolean field are consistently added to both interfaces. This provides proper type safety for the document approval feature while maintaining backward compatibility.Also applies to: 141-143
lib/api/links/link-data.ts (2)
142-146
: LGTM! Consistent field selection for approval metadata.The addition of
uploadedDocument.requireApproval
field selection follows the established pattern and enriches the dataroom link data with the necessary approval information for UI components.
395-411
: LGTM! Efficient upload count utility function.The new
fetchUploadDocumentsCount
function is well-implemented with proper TypeScript typing and efficient Prisma count query. The filtering byteamId
,dataroomId
, andviewerId
provides appropriate data scoping for tracking viewer-specific upload counts.app/api/views-dataroom/route.ts (3)
30-30
: LGTM: Import statement is correctly addedThe import for
fetchUploadDocumentsCount
is properly imported from the expected location.
656-667
: Good error handling for upload documents countThe try-catch block properly handles potential failures when fetching upload documents count without affecting the main response. The fallback to 0 and console logging are appropriate defensive programming practices.
680-680
: Response object correctly enriched with upload countThe
uploadDocumentsCount
is appropriately added to the return object for DATAROOM_VIEW requests, enabling frontend components to display the count of uploaded documents.components/view/dataroom/document-upload-modal.tsx (4)
4-6
: Well-structured imports for the approval workflowThe imports are correctly structured to support the new document approval functionality, including proper type definitions and toast notifications.
Also applies to: 18-18
31-36
: Excellent type definition for upload callbackThe
onUploadSuccess
callback is properly typed with the extended Document type including versions and requireApproval flag, ensuring type safety across the approval workflow.
40-51
: Well-implemented success handler with user feedbackThe
handleUploadSuccess
function properly:
- Calls the optional callback with uploaded document data
- Closes the modal
- Provides clear user feedback about pending approval
The toast message clearly communicates the approval requirement to users.
84-84
: Proper callback integration with upload componentThe
onSuccess
prop correctly passes the success handler to theViewerUploadComponent
, maintaining the callback chain for the approval workflow.components/datarooms/dataroom-document-card.tsx (4)
11-11
: Imports properly structured for approval functionalityThe CheckIcon, approveDocument utility, and Badge component imports are correctly added to support the document approval feature.
Also applies to: 23-23, 40-40
116-123
: Clean approval handler implementationThe
handleApproveDocument
function is well-implemented:
- Properly async with error handling delegated to the utility function
- Clean parameter passing with all required context
- Follows the established pattern of other handlers in the component
220-228
: Effective visual indicator for pending approvalThe conditional Badge rendering provides clear visual feedback to users when documents require approval. The placement next to the document name is intuitive and the conditional logic properly checks both external upload status and approval requirement.
291-303
: Well-structured conditional menu item for approvalThe approval menu item is properly:
- Conditionally rendered based on external upload and approval status
- Using appropriate icon and descriptive text
- Preventing event propagation to avoid card navigation
- Calling the correct handler function
The logical conditions ensure the menu item only appears when relevant.
pages/api/teams/[teamId]/documents/[id]/approve.ts (5)
9-11
: Proper HTTP method validationThe method check correctly restricts access to POST requests only, which is appropriate for a state-changing operation like document approval.
13-37
: Comprehensive authentication and authorizationThe authentication flow properly:
- Verifies user session exists
- Validates team existence
- Confirms user exists in the system
- Returns appropriate 401/404 status codes
This ensures only authenticated users from valid teams can approve documents.
38-49
: Thorough document validation before approvalThe validation logic correctly:
- Checks document exists and belongs to the team
- Verifies the document has an uploaded document record
- Confirms the document actually requires approval
This prevents approval of documents that don't need it or don't exist.
51-60
: Complete approval data updateThe database update properly sets all relevant approval fields:
requireApproval: false
to mark as approvedapprovedAt: new Date()
for timestamp trackingapprovedBy: user.id
for audit trailapprovedStatus: "APPROVED"
for explicit statusThis provides comprehensive audit information for the approval action.
62-66
: Appropriate error handling and loggingThe try-catch block provides proper error handling with console logging for debugging and returns a generic 500 error to avoid exposing internal details.
components/viewer-upload-component.tsx (2)
3-3
: Proper imports for document type integrationThe Document and DocumentVersion imports are correctly added to support the typed callback functionality.
Also applies to: 10-10
21-26
: Well-typed callback interfaceThe
onSuccess
callback is properly typed with the extended Document type including versions and requireApproval flag, ensuring type safety in the upload workflow.components/documents/document-card.tsx (4)
10-10
: Imports look good.The new imports for
CheckIcon
,approveDocument
, andBadge
are correctly added and used throughout the component for the document approval functionality.Also applies to: 28-28, 49-49
120-126
: Function implementation is correct.The
handleApproveDocument
function properly calls the approval utility with the required parameters and correctly omits thedataroomId
since this component is used outside of dataroom contexts.
284-288
: Badge implementation is well-designed.The conditional rendering of the "Need approval" badge provides clear visual feedback and uses appropriate styling. The optional chaining safely handles the case where
uploadedDocument
might not exist.
394-404
: Dropdown menu item implementation is solid.The conditional approval menu item is well-implemented with proper event handling, appropriate iconography, and clear text. The event propagation handling prevents interference with other UI interactions.
prisma/migrations/20250721091745_approved_docs/migration.sql (3)
7-8
: Enum definition is well-designed.The
DocumentApprovalStatus
enum covers all necessary states for the approval workflow with clear, descriptive values.
11-14
: Column additions are well-designed.The new approval-related columns properly support the workflow with appropriate nullable fields, sensible defaults, and the correct data types for tracking approval metadata.
4-4
: Please verify there are no duplicatedocumentId
values before applying this migration.The new unique index on
DocumentUpload(documentId)
will fail if any duplicates exist. To check against your current data, run in your database:SELECT "documentId", COUNT(*) AS cnt FROM "DocumentUpload" GROUP BY "documentId" HAVING COUNT(*) > 1;Ensure this returns zero rows before proceeding.
pages/api/teams/[teamId]/datarooms/[id]/documents/[documentId]/approve.ts (3)
6-11
: Request handling follows best practices.The parameter extraction and HTTP method validation are properly implemented with appropriate TypeScript typing and security considerations.
39-67
: Document validation is comprehensive and secure.The validation properly ensures the document exists in the specified dataroom, requires approval, and includes all necessary relation data. The composite key lookup and approval status checks are well-implemented.
69-88
: Approval update logic is well-implemented.The database update properly sets all approval fields atomically, includes audit trail information, and has appropriate error handling. The additional
teamId
filter in the where clause adds an extra layer of security.lib/utils/document-approve.ts (4)
1-10
: Type definitions and imports are well-designed.The imports are appropriate and the
ApproveDocumentParams
type correctly defines all necessary parameters with proper optional fields for different usage contexts.
12-25
: Helper function correctly generates cache keys.The
getMutateEndpoint
function properly handles different contexts (dataroom vs general documents) and folder paths, generating the appropriate SWR cache keys for revalidation.
33-40
: Validation and endpoint construction are robust.The team information validation provides early error feedback, and the endpoint construction correctly handles both dataroom and general document contexts.
42-59
: API call and error handling follow best practices.The implementation properly handles both success and error cases with appropriate user feedback, logging, and cache revalidation. The error re-throwing allows callers to implement additional error handling if needed.
components/view/dataroom/document-card.tsx (6)
5-5
: Imports and type extensions are appropriate.The new imports for
LockIcon
andBadge
are used appropriately in the component. TheDRDocument
type extension correctly reflects the backend data structure for approval status.Also applies to: 13-13, 32-35
65-65
: Interaction restriction properly enforces approval requirements.The approval status check and error handling correctly prevent access to unapproved documents while providing clear feedback to users about why the action is blocked.
Also applies to: 76-81
179-186
: Styling changes provide excellent visual feedback.The conditional styling clearly differentiates between approved and pending documents using opacity and backdrop blur effects. The element change to
<li>
suggests proper semantic structure for list items.
192-192
: Icon styling change is consistent with design system.The conditional opacity on the file icon maintains visual consistency with the overall approval state styling.
214-219
: Badge implementation provides clear status indication.The approval badge with lock icon and "Pending Approval" text effectively communicates the document's restricted status. The conditional rendering and styling are well-implemented.
228-228
: Download restriction logic is correctly implemented.The additional
!requireApproval
condition properly prevents download access for unapproved documents while maintaining all existing conditional checks.prisma/schema/schema.prisma (3)
158-162
: LGTM: Well-defined approval status enum.The
DocumentApprovalStatus
enum correctly defines the three states for document approval workflow with clear, self-explanatory values.
565-565
: Approve the unique constraint addition.Adding
@unique
todocumentId
properly enforces the one-to-one relationship betweenDocument
andDocumentUpload
, preventing duplicate upload records for the same document.
195-196
: No array usage foruploadedDocument
found – relation change is safe
A global search showed no instances of array-style access ([]
),.length
, or.map
onuploadedDocument
. All references treat it as a single optional relation, so no further code changes are needed.components/view/viewer/dataroom-viewer.tsx (7)
3-3
: Approve the import additions.The addition of
useCallback
anduseState
imports is appropriate for the new state management functionality.
9-13
: Approve the updated imports.Adding
Document
type import andFileText
icon for the uploaded documents UI is correct.
112-112
: Approve the narrowed accessControls type.Narrowing the
accessControls
prop type toViewerGroupAccessControls[]
improves type safety.
119-128
: Approve the state management setup.The state management for documents and uploaded documents count is properly initialized and follows React best practices.
474-486
: Approve the uploaded documents count UI.The conditional rendering of uploaded documents count with proper pluralization and clear visual styling is well-implemented.
504-504
: Approve the callback prop addition.Passing the
handleUploadSuccess
callback toDocumentUploadModal
enables proper state synchronization after successful uploads.
66-68
: No changes needed:uploadedDocument
type is consistentI’ve checked all relevant Next.js API routes—e.g.:
• pages/api/teams/[teamId]/folders/documents/[...name].ts
• pages/api/teams/[teamId]/documents/index.ts
• pages/api/teams/[teamId]/documents/[id]/approve.ts
• pages/api/teams/[teamId]/datarooms/[id]/documents/index.ts—they all return
uploadedDocument
with only{ requireApproval: boolean }
. Your optional{ requireApproval: boolean }
definition incomponents/view/viewer/dataroom-viewer.tsx
matches exactly.
…y uploaded
Summary by CodeRabbit
New Features
Bug Fixes
Chores