Skip to content

Conversation

@terrerox
Copy link
Contributor

@terrerox terrerox commented Dec 4, 2025

Description

Add version history sidebar with UI for viewing, restoring, and deleting file versions. Includes state management in UI slice, integration with drive explorer context menus, and mock data structure for version display.

Related Issues

Related Pull Requests

Checklist

  • Changes have been tested locally.
  • Unit tests have been written or updated as necessary.
  • The code adheres to the repository's coding standards.
  • Relevant documentation has been added or updated.
  • No new warnings or errors have been introduced.
  • SonarCloud issues have been reviewed and addressed.
  • QA Passed

Testing Process

Additional Notes

  Add "Version history" option to drive item context menu for files across all drive views (personal, shared, workspace). Menu item is disabled for folders and includes placeholder implementation in useDriveItemActions hook.
  Add version history sidebar with UI for viewing, restoring, and deleting file versions. Includes state management in UI slice,
  integration with drive explorer context menus, and mock data structure for version display.
@terrerox terrerox marked this pull request as draft December 4, 2025 04:13
@terrerox terrerox self-assigned this Dec 4, 2025
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 4, 2025

Deploying drive-web with  Cloudflare Pages  Cloudflare Pages

Latest commit: 039ce89
Status: ✅  Deploy successful!
Preview URL: https://07cc7299.drive-web.pages.dev
Branch Preview URL: https://feature-file-version-history.drive-web.pages.dev

View logs

@terrerox terrerox force-pushed the feature/file-version-history branch from e0a0878 to cc7a1ac Compare December 5, 2025 05:18
Refactors the version history sidebar by extracting components into separate files for better maintainability and code organization. Replaces magic strings with constants for dropdown positioning.
@terrerox terrerox force-pushed the feature/file-version-history branch from cc7a1ac to fc14a30 Compare December 5, 2025 05:21
@terrerox
Copy link
Contributor Author

terrerox commented Dec 5, 2025

Quality Gate Failed Quality Gate failed

Failed conditions 0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

NOTE: Tests will be added in another PR.

@terrerox terrerox marked this pull request as ready for review December 5, 2025 05:39
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You must add the translations for the other 7 languages.

className="h-4 w-4"
/>
<span className="text-base text-gray-80">
{totalAutosaveCount}/{totalAutosaveCount} autosave versions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the text to the JSON and add its translations.

Also, these values are the same {totalAutosaveCount}/{totalAutosaveCount}. How should it look like?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The {totalAutosaveCount}/{totalAutosaveCount} was intentional. I plan to address that in a separate PR

<div className="flex min-w-0 flex-1 flex-col space-y-1">
<div className="flex items-center justify-between">
<span className="text-base font-semibold text-gray-100">
{dateService.format(version.date, 'MMM D, h:mm A')}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract that to a variable, something like const versionDate = dateService.format...

{dateService.format(version.date, 'MMM D, h:mm A')}
</span>
<span className="rounded bg-primary/10 px-[4px] py-[2px] text-xs font-semibold text-primary dark:bg-[#082D66] dark:text-[#72AAFF]">
Current
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract the text to the JSON and add its translations.

<div className="flex min-w-0 flex-1 flex-col space-y-1">
<div className="flex items-center justify-between">
<span className="text-base font-semibold text-gray-100">
{dateService.format(version.date, 'MMM D, h:mm A')}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you use the date with the same format. What about format the date when you fetch it so you can use directly version.date instead of formatting it every time?

{version.expiresInDays !== undefined && (
<div className="flex items-center space-x-1 text-[12px] text-red-dark">
<Info size={16} weight="regular" />
<span>Expires in {version.expiresInDays} days</span>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the text to the JSONs and ad its translations.

Comment on lines 26 to 43
{
name: 'Restore version',
icon: ClockCounterClockwise,
action: handleRestore,
},
{
name: 'Download version',
icon: DownloadSimple,
action: handleDownload,
},
{
separator: true,
},
{
name: 'Delete version',
icon: Trash,
action: handleDelete,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the text to the JSONs and add its translations.

@terrerox terrerox requested a review from xabg2 December 5, 2025 14:55
terrerox and others added 9 commits December 5, 2025 12:18
…wnload functionality

  Adds complete file version management system with API integration for viewing, restoring, deleting, and downloading file
  versions. Updates name collision dialog to use replaceFile endpoint instead of delete-and-reupload for file replacements.
…etter UX

  - Replace direct download with DownloadManager for efficient multipart downloads
  - Add workspace credentials support for version downloads
  - Position TaskLogger at bottom-right
  - Refactor: rename service files to camelCase convention (file-version.service.ts → fileVersion.service.ts,
  replace-file.service.ts → replaceFile.service.ts)
  - Pass file item and workspace context to downloadVersion for proper credential handling
Remove try-catch block and error handling from useVersionItemActions since DownloadManager already handles error reporting,
notifications, and task status updates internally. This prevents duplicate error notifications from being shown to the user.
[PB-5465]: enhance internationalization for version management
…ration

  - Update @internxt/sdk to 1.11.21 for improved version history support
  - Add batch delete functionality for multiple version selections
  - Implement version limits display showing used/total allowed versions
  - Fix file replace operation to properly upload new file content
  - Migrate from local FileVersion type to SDK types for better consistency
  - Add indeterminate checkbox state for partial selections
  - Improve version restoration to update current version state
  - Enhance skeleton loading to show more realistic version count
  - Add getLimits API call to fetch version constraints
  - Refactor CurrentVersionItem to use version info instead of full item data
terrerox and others added 26 commits December 12, 2025 11:47
…tory menu with lock state

  Add VersioningLimitsProvider to DriveView and implement version history menu configuration with locked
  state support. The version history menu now shows a lock icon and handles locked state when versioning
  is not available or extension is not allowed.
… context API

  Replace VersioningLimitsContext with Redux store for consistent state management and improved
  performance. Add fileVersions slice to cache API responses and prevent redundant fetches.

  - Create fileVersions Redux slice with caching for versions and limits
  - Add thunks for fetching file versions and versioning limits
  - Implement cache invalidation on version create, delete, and restore
  - Optimize Sidebar to use cached data and avoid infinite loops
  - Memoize VersionItem component to prevent unnecessary re-renders
  - Remove VersioningLimitsContext and consolidate all state in Redux
  - Update all components to use Redux selectors instead of context
  - Create fileVersions selectors for centralized state access
  - Rename state properties for clarity:
    - loadingStates → isLoadingByFileId
    - errors → errorsByFileId
    - limitsLoading → isLimitsLoading
  - Update type imports to use FileLimitsResponse (SDK v1.11.24)
  - Use NonNullable for Record keys to prevent null index types
  - Refactor version history menu config:
    - Rename properties: locked → isLocked, allowedExtension → isExtensionAllowed, onLockedClick → onUpgradeClick
    - Simplify getVersionHistoryMenuItem with early return pattern
  - Replace direct state access with selectors across components
  - Export getDaysUntilExpiration utility function
  - Add type assertion for restored version fileId
Add unit tests for date service, version history hooks, and file version service to ensure
reliability of the file versioning functionality. Tests cover dropdown positioning logic, version
history menu configuration, file version operations, and date utility functions including expiration
calculations.
…ctions hook

Add comprehensive test coverage for fileVersions Redux slice and useVersionItemActions hook. Tests include thunk
operations (fetch versions, fetch limits), reducer state management (loading, errors, cache invalidation), and
menu action handlers (restore, download, delete). Uses icon-based menu item selection for robust, maintainable
tests.
[PB-5542]: add unit tests for Redux file versions slice and version item actions hook
[PB-5542]: add versioning limits context and premium feature gating
  [PB-5466]: enhance version history with batch operations and SDK integration
  [PB-5465] Implement file version history actions
@sonarqubecloud
Copy link

});
const file = itemToUpload as File;
const canReplaceVersion = isVersioningEnabled && isVersioningExtensionAllowed(itemToReplace);
canReplaceVersion ? await replaceFileVersion(file, itemToReplace) : await trashAndUpload(file, itemToReplace);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is necessary to mantain the old trashAndUpload logic or we can replace it with new replace file logic for all users?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to maintain the old logic for users who don’t have versioning enabled. You might ask: why not move this to the backend? That won’t be possible because the replace file endpoint is used by the CLI. If a user with versioning enabled creates another version and exceeds the limit, we need to permanently delete the older version of the file. That endpoint already handles this logic for the CLI, and now it’s being used for the web as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps that is the new desired behaviour. Please confirm with Product dept if the replacement behaviour is the new desired one :)
If not, we can leave it as it is

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The replace file endpoint is open for everyone (including free users). Desktop, mobile, etc.

I think the same as Ramon, for me it makes more sense to actually replace the file always, as it is the expected behaviour (instead of trashing and uploading it again)

Copy link
Contributor Author

@terrerox terrerox Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That approach falls under criteria #2 and #3 of this story

@terrerox terrerox requested a review from CandelR January 13, 2026 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants