The _deprecated_numchild and _deprecated_numchild_folder fields were
kept temporarily to preserve the underlying columns during the tree
model transition. The columns are no longer read or written, so the
fields and their columns can now be removed.
When we try to get the VersionId from the s3 response
but this one is not send by the s3 storage (garage for example),
we get a 500 error.
To fix this issue we use the ETag sent by the object storage to track
the version id. This ETag is present also when versionning is not
implemented.
Co-authored-by: RolletQuentin <rolletquen@gmail.com>
Detailed FilePreview behavior is now covered by Playwright CT inside
the ui-kit repo, so the drive e2e suite only keeps integration smoke
checks: upload -> open -> render for PDF, image, video, audio, plus
prev/next navigation across files.
The ui-kit ships a complete FilePreview (PDF, image, video, audio,
WOPI, error/unsupported, navigation, controls), so we drop the in-app
implementation under features/ui/preview/ and keep only a thin
CustomFilesPreview wrapper that maps Item to FilePreviewType, plugs
in the share modal, info sidebar and posthog event.
The WOPI editor is moved to its own features/wopi/ folder and
openWopiInNewTab now takes a FilePreviewType to match the ui-kit
onOpenInEditor callback. The file_preview translation block moves to
the ui-kit too.
The ui-kit now ships FileIcon along with mime-category and icon-set
utilities, so we drop the local catalog (MIME_MAP, KNOWN_EXTENSIONS,
getMimeCategory, getIconByMimeType, FolderIcon, WorkspaceIcon) and
keep only the drive-specific extensions: folders and suspicious
uploads, exposed through getItemExtendedIcon. ItemIcon falls back to
ui-kit FileIcon for everything else.
Duplication is currently invisible to product analytics because the
event is fired from the API rather than the UI. Emit it from the
viewset right after the duplicate row is created so the duplicated
item context (workspace, mimetype, ...) is attached to the event.
Track when users customize their column layout so product can see
which columns get adopted vs ignored. The event carries the slot
plus old and new column types to support funnel analysis.
Asserting only on the event name is not enough when the same event is
emitted from multiple call sites with different payloads. Expose
expectEventSentWithProps so specs can pin down the expected slot or
context, and keep the captured properties available alongside the
existing names array.
In the get_file_content action we want to log the received max expected
file size when this one is lower than the file size the user wants to
edit. This will help us to correctly configure the WOPI host.
On the duplicate action we are using the decorator @transaction.atomic
to be sure that the duplicated item and its accesses are correctly
created. The problem with that is that the celery task doing the file
duplication on the object storage can be executed before the transaction
is commited leading to an error saying that the duplicated_item does not
exists.
Scalingo's Ubuntu runtime ships a newer libmagic that returns
application/CDFV2 for legacy .doc/.xls/.ppt files, where Alpine's
older libmagic (used in our Docker image) returns the older label
application/x-ole-storage. Both describe the same OLE2 / Composite
Document File V2 container.
detect_mimetype() already treats application/x-ole-storage as a
generic content-detection result and falls back to extension-based
detection (yielding application/msword, application/vnd.ms-excel,
etc.). Without the same handling for CDFV2, legacy .doc uploads on
Scalingo are rejected by the mimetype allow-list with
"mimetype not allowed application/CDFV2 for filename ...".
Cover the per-page-dimensions path with a 17-page fixture
spanning portrait, landscape, square, wide-banner and tall-strip
ratios. Asserts that rendered pages and thumbnails match each
page's real aspect ratio, that page-input jumps land precisely
across mixed ratios, and that the virtual-list total height
matches the sum of per-page heights.
Pages were laid out with a hardcoded A4 portrait ratio, so
landscape, square and extreme-ratio pages rendered with wrong
row heights and page-input jumps could land on a neighbour.
A new usePdfPageDimensions hook lazily fetches each page's
viewport from pdfjs and dedupes concurrent requests. The main
viewer and thumbnail sidebar now size rows from the cache and
fall back to A4 only until real dimensions arrive. Page-input
jumps await the prefix's dimensions before computing the scroll
offset so the viewport center lands inside the requested page.
Record the metrics filter, entitlement payload additions, and the
frontend disclaimer feature shipped on this branch, alongside the
already-landed organization metrics entry.
Cover visibility rules (enabled / disabled / flagged reasons), the
seen-flag lifecycle, the showPotentialOperators branch with and
without signupUrl, and the OK-click close interaction.
Show a one-shot modal when the user's can_upload is blocked for a
recoverable reason (not_activated / no_organization), with an optional
list of potential operators where they can self-register. Tracks
"seen" per disclaimer in localStorage so users are not nagged on
every load, but re-shows the disclaimer if the underlying entitlement
changes and then regresses.
Type the new backend fields (\`can_upload.reason\`, \`context\`) and
the new \`FRONTEND_ENTITLEMENTS_DISCLAIMERS\` config key so downstream
components can consume them with no casts.
Add a dict-shaped config exposed to the frontend so operators can
enable or disable entitlement disclaimers per reason without code
changes. Also pin the Test settings to the local entitlements backend
so test runs do not depend on external state.
Add account_type=organization support to the usage metrics
endpoint. When requested, the API filters users by a shared
OIDC claim (account_id_key/account_id_value) and returns
aggregated storage across all matching users.
Add handling of account_id_key/account_id_value pair, allowing
filtering on allowed parameters in a more generic way. At the
moment `account_email` filter is still needed.
Also include the context of the entitlement in the /entitlements
response.
Change compute_storage_used signature from a single user
to a queryset of users. This enables aggregating storage
usage across multiple users, which is needed for
organization-level metrics.
Restructure the entitlements module from flat files into a
backends/ package with a factory pattern. This enables
constructor kwargs injection for backend configuration.
Rename ANCT backend to DeployCenter to match the actual
service name, and rename Dummy backend to Static for clarity.
The factory now passes ENTITLEMENTS_BACKEND_PARAMETERS to
the backend constructor, making configuration more explicit
and testable.
Some request parameters get updated because of changes on
deploy center side that need to be reflected in services.
Added
- ✨(backend) make invitation validity duration configurable via env var
- ✨(frontend) enhance upload toast with progress, errors and cancel support
- ✨(frontend) add ErrorIcon component and support numeric icon sizes
- ✨(frontend) make file upload abortable in driver layer
- ✨(frontend) files preview v2
- 🔧(project) add DJANGO_EMAIL_URL_APP environment variable
Fixed
- 🐛(frontend) add actions menu on mobile My Files page
- 🐛(frontend) show actual selection count in hard delete modal
- 🐛(frontend) Responsive broken with long filters in search #659
- 🐛(front) set size and variant on trash navigate modal #666
- 🐛(frontend) fix uploads continuing after parent folder deletion
- 🐛(frontend) fix SDK picker link reach promotion
- 🐛(backend) route share invitation link to file view for files
- 🐛(frontend) fix "+ New" menu in read-only folders and virtual tabs
- 🐛(frontend) range selection freezes when there are many items in the list
- 🐛(backend) fix openapi schema for item access endpoints
- 🐛(backend) load jwks url when OIDC_RS_PRIVATE_KEY_STR is set
Share invitation emails embedded `Site.domain` directly, producing
schemeless links that mail clients failed to resolve. Introduce a
`DJANGO_EMAIL_URL_APP` environment variable holding the app's
absolute URL used when building invitation links, with a fallback
on the current Site domain when unset. Wire it in dev env, helm
dev values, the helm example and the env reference.
Clicking the invitation link for a shared file opened the folder
explorer page with an empty children listing, because
`Item.send_email` hardcoded `/explorer/items/<uuid>/` regardless of
the item type.
Branch on `item.type` to use the dedicated file route
`/explorer/items/files/<uuid>/` already served by nginx and used by
the in-app share-link copy button.
Cover the two main picker outcomes: cancelling leaves the item
private, and confirming exposes a publicly reachable URL. The
reach check opens the returned URL in a fresh anonymous context
and waits for the download event, since the backend serves
attachments with Content-Disposition and navigation aborts.
To run the test in CI, build the drive SDK package and start the
sdk-consumer dev server before the playwright job.
Switch to useMutationUpdateLinkConfiguration and preserve the
item's existing link_role. Also add the missing sdk.explorer.cancel
translations for en and nl so the Cancel button label renders
correctly. This should have been done when migration to this new
API route. The existing update did not have any effect.
When the resource server is enabled and the backend used is
JWTResourceServerBackend, then the API should expose a JWKS endpoint
to share the RSA public key to the OIDC provider. Everything is made
in the Django LaSuite library, but the URL is not included in the
Drive URLs. This commit adds it when the setting OIDC_RS_PRIVATE_KEY_STR
is set.
The invitation validity duration was hardcoded to 7 days. Expose it as
an INVITATION_VALIDITY_DURATION env var so operators can tune it per
deployment without patching settings. Default remains 7 days.
`ItemAccessViewSet.get_serializer_class` depends on `self.item`, which
reads `self.kwargs["resource_id"]`. This is unavailable during
drf-spectacular introspection, so spectacular fails to resolve the
serializer and drops the requestBody for POST/PUT/PATCH operations.
Declare the schema statically via `@extend_schema` and
`@extend_schema_view` so the generated OpenAPI exposes the proper
request and response payloads for item access endpoints.
Drop selectedItems / selectedItemsMap from GlobalExplorerContext and
move every call-site to the selection store introduced in the previous
commit. Rows of the embedded explorer grid are extracted into a memoed
EmbeddedExplorerGridRow that subscribes to its own id via
useIsItemSelected, and the name/actions/mobile cells are memoed and
read their selection status the same way.
High-level consumers that only need a boolean or a count use
useHasSelection / useSelectionCount so they no longer re-render on
every marquee tick:
- AppExplorerInner uses useHasSelection to toggle the selection bar
- ExplorerDndProvider splits the count consumers into dedicated child
components (drag overlay and move confirmation modal)
- useTableKeyboardNavigation subscribes imperatively through
selectionStore.subscribe so the focus effect runs without
invalidating the host component
EmbeddedExplorer creates its own local store so the move modal and the
SDK picker keep their selection scoped and do not leak into the main
explorer selection.
Fixes#124
Introduce a lightweight external store compatible with
useSyncExternalStore. It exposes:
- a global subscription for consumers that need the full list or count
- per-id subscriptions so a row can bail out automatically when its own
isSelected boolean has not changed
- setSelectedItems that diffs the previous and next id maps and
notifies only the listeners whose status actually flipped
No React state, no context fan-out: a marquee tick that flips N rows
notifies exactly N listeners instead of invalidating the whole tree.
Add an architecture doc covering the rationale behind the selection
store refactor: why React Context did not scale to 200+ rows during a
marquee drag, why useSyncExternalStore with per-id listeners enables
automatic bailout, and how global vs embedded scopes are wired.
Lives under docs/architecture/ for long-term reference.
Cover the four scenarios of the new "+ New" behavior:
- folder creation from a read-only shared folder redirects into the
newly created folder under My Files
- document creation from a read-only shared folder redirects to the
My Files view with the new file listed
- folder creation from the Recent / Shared with me / Starred virtual
tabs creates in My Files
- folder creation in a writable folder still happens in place, with
no fallback redirect
The "+ New" dropdown used to hide all its entries when the user lacked
children_create on the current folder, leaving an empty popover. On
virtual tabs (Recent, My Files, Shared with me, Starred) there is no
real current folder either, so the same empty state could be reached.
Always populate the menu and, when the user cannot create in place,
fall back to creating the item in "My Files" (no parent). After a
fallback creation we redirect:
- into the new folder for folder creation
- to the My Files view for file creation, since a file is not a
navigable route
The new item is pre-selected in both cases.