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

@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: 23b70f8
Status: ✅  Deploy successful!
Preview URL: https://f3de1665.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 2 times, most recently 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.

@terrerox terrerox requested a review from xabg2 December 5, 2025 14:55
@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
  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.
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.
…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.
…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
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.
- Added a locked feature modal to inform users about version restoration capabilities in paid plans.
- Updated i18n translations for the new locked feature.
- Refactored file version service imports and related tests.
- Enhanced version history menu configuration to handle locked states.
- Implemented dropdown positioning hook for better UI interactions.
- Added tests for version item actions and dropdown positioning.
- Integrated version limits fetching in the PlansSection for better user experience.
  - Add downloadName option to DownloadItem type to support custom filenames
  - Update downloadWorkerHandler to accept and use custom download names
  - Format version download filenames as "(DD-MM-YYYY at HH:mm) filename.ext"
  - Use dateService and itemsUtils from @internxt/lib for proper formatting
  - Pass custom filename through downloadOptions instead of modifying item name
  Add intelligent exponential backoff polling that stops early when version limits are updated after
  subscription changes. Version limits are updated via webhook, so polling with change detection ensures the
  frontend receives updated state efficiently.

  - Add VERSION_LIMITS_POLL_MAX_ATTEMPTS (3) and VERSION_LIMITS_POLL_DELAYS (2s, 4s, 6s)
  - Add isSilent parameter to fetchVersionLimitsThunk to suppress loading skeleton during background polling
  - Implement pollVersionLimitsUntilChanged with limit comparison to detect when webhook has processed
  - Compare all versioning properties (enabled, maxFileSize, retentionDays, maxVersions) to detect changes
  - Stop polling early if limits change, continue until max attempts if unchanged
  - Apply polling to both payment success and subscription cancellation flows
  - Update tests to handle new payload structure { limits, isSilent }
@terrerox terrerox force-pushed the feature/file-version-history branch from f823908 to b6c7ee7 Compare February 11, 2026 15:41
@sonarqubecloud
Copy link

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.

4 participants