diff --git a/DEVELOPING.md b/DEVELOPING.md index 07e093151f..9fd058e535 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -4,7 +4,7 @@ Our development setup assumes a LINUX/BSD environment. ## Project Setup -1. Install Node v22 `nvm install lts/jod && nvm use lts/jod`. +1. Install Node v22 `nvm install && nvm use`. 2. Install Yarn package manager `https://yarnpkg.com/en/docs/install` v1.10 or higher. 3. Fork the upstream repo `https://github.com/box/box-ui-elements` via github. 4. Clone your fork locally `git clone git@github.com:[YOUR GITHUB USERNAME]/box-ui-elements.git`. diff --git a/src/api/uploads/BaseUpload.js b/src/api/uploads/BaseUpload.js index 3fc8dcbb6f..81921dee6b 100644 --- a/src/api/uploads/BaseUpload.js +++ b/src/api/uploads/BaseUpload.js @@ -30,6 +30,8 @@ class BaseUpload extends Base { folderId: string; + fields: ?Array; + overwrite: boolean | 'error'; conflictCallback: ?(fileName: string) => string; diff --git a/src/api/uploads/MultiputUpload.js b/src/api/uploads/MultiputUpload.js index fdf42a23f3..2e8b70b84c 100644 --- a/src/api/uploads/MultiputUpload.js +++ b/src/api/uploads/MultiputUpload.js @@ -12,6 +12,7 @@ import { digest } from '../../utils/webcrypto'; import hexToBase64 from '../../utils/base64'; import createWorker from '../../utils/uploadsSHA1Worker'; import Browser from '../../utils/Browser'; +import { updateQueryParameters } from '../../utils/url'; import { DEFAULT_RETRY_DELAY_MS, ERROR_CODE_UPLOAD_STORAGE_LIMIT_EXCEEDED, @@ -161,6 +162,7 @@ class MultiputUpload extends BaseMultiput { * @param {File} options.file * @param {string} options.folderId - Untyped folder id (e.g. no "folder_" prefix) * @param {string} [options.fileId] - Untyped file id (e.g. no "file_" prefix) + * @param {Array} options.fields * @param {string} options.sessionId * @param {Function} [options.errorCallback] * @param {Function} [options.progressCallback] @@ -177,6 +179,7 @@ class MultiputUpload extends BaseMultiput { overwrite = true, conflictCallback, fileId, + fields, }: { conflictCallback?: Function, errorCallback?: Function, @@ -186,6 +189,7 @@ class MultiputUpload extends BaseMultiput { overwrite?: boolean | 'error', progressCallback?: Function, successCallback?: Function, + fields: ?Array, }): void { this.file = file; this.fileName = this.file.name; @@ -196,6 +200,7 @@ class MultiputUpload extends BaseMultiput { this.overwrite = overwrite; this.conflictCallback = conflictCallback; this.fileId = fileId; + this.fields = fields; } /** @@ -206,6 +211,7 @@ class MultiputUpload extends BaseMultiput { * @param {File} options.file * @param {string} options.folderId - Untyped folder id (e.g. no "folder_" prefix) * @param {string} [options.fileId] - Untyped file id (e.g. no "file_" prefix) + * @param {Array} options.fields * @param {Function} [options.errorCallback] * @param {Function} [options.progressCallback] * @param {Function} [options.successCallback] @@ -222,6 +228,7 @@ class MultiputUpload extends BaseMultiput { overwrite = true, conflictCallback, fileId, + fields, }: { conflictCallback?: Function, errorCallback?: Function, @@ -232,6 +239,7 @@ class MultiputUpload extends BaseMultiput { overwrite?: boolean | 'error', progressCallback?: Function, successCallback?: Function, + fields: ?Array, }): void { this.file = file; this.fileName = this.file.name; @@ -251,6 +259,7 @@ class MultiputUpload extends BaseMultiput { this.overwrite = overwrite; this.fileId = fileId; this.fileDescription = fileDescription; + this.fields = fields; this.makePreflightRequest(); } @@ -429,6 +438,7 @@ class MultiputUpload extends BaseMultiput { * @param {File} options.file * @param {string} options.folderId - Untyped folder id (e.g. no "folder_" prefix) * @param {string} [options.fileId] - Untyped file id (e.g. no "file_" prefix) + * @param {Array} options.fields * @param {string} options.sessionId * @param {Function} [options.errorCallback] * @param {Function} [options.progressCallback] @@ -447,6 +457,7 @@ class MultiputUpload extends BaseMultiput { overwrite = true, conflictCallback, fileId, + fields, }: { conflictCallback?: Function, errorCallback?: Function, @@ -457,6 +468,7 @@ class MultiputUpload extends BaseMultiput { progressCallback?: Function, sessionId: string, successCallback?: Function, + fields: ?Array, }): void { this.setFileInfo({ file, @@ -467,6 +479,7 @@ class MultiputUpload extends BaseMultiput { conflictCallback, overwrite, fileId, + fields, }); this.sessionId = sessionId; @@ -571,6 +584,7 @@ class MultiputUpload extends BaseMultiput { successCallback: this.successCallback, overwrite: this.overwrite, fileId: this.fileId, + fields: this.fields, }; this.upload(uploadOptions); } else { @@ -925,6 +939,12 @@ class MultiputUpload extends BaseMultiput { return; } + let url = this.sessionEndpoints.commit; + + if (this.fields) { + url = updateQueryParameters(url, { fields: this.fields.toString() }); + } + const stats = { totalPartReadTime: 0, totalPartDigestTime: 0, @@ -968,7 +988,7 @@ class MultiputUpload extends BaseMultiput { }; this.xhr - .post({ url: this.sessionEndpoints.commit, data, headers }) + .post({ url, data, headers }) .then(this.commitSessionSuccessHandler) .catch(this.commitSessionErrorHandler); }; diff --git a/src/api/uploads/PlainUpload.js b/src/api/uploads/PlainUpload.js index 9ecb0a829a..3acb849a0a 100644 --- a/src/api/uploads/PlainUpload.js +++ b/src/api/uploads/PlainUpload.js @@ -7,6 +7,7 @@ import noop from 'lodash/noop'; import { digest } from '../../utils/webcrypto'; import { getFileLastModifiedAsISONoMSIfPossible } from '../../utils/uploads'; +import { updateQueryParameters } from '../../utils/url'; import BaseUpload from './BaseUpload'; import type { BoxItem } from '../../common/types/core'; @@ -72,6 +73,10 @@ class PlainUpload extends BaseUpload { if (this.fileId) { uploadUrl = uploadUrl.replace('content', `${this.fileId}/content`); } + + if (this.fields) { + uploadUrl = updateQueryParameters(uploadUrl, { fields: this.fields.toString() }); + } } const attributes = JSON.stringify({ @@ -112,6 +117,7 @@ class PlainUpload extends BaseUpload { * @param {string} options.folderId - untyped folder id * @param {string} [options.fileId] - Untyped file id (e.g. no "file_" prefix) * @param {File} options.file - File blob object + * @param {Array} options.fields * @param {Function} [options.successCallback] - Function to call with response * @param {Function} [options.errorCallback] - Function to call with errors * @param {Function} [options.progressCallback] - Function to call with progress @@ -130,6 +136,7 @@ class PlainUpload extends BaseUpload { conflictCallback, // $FlowFixMe overwrite = true, + fields, }: { conflictCallback?: Function, errorCallback: Function, @@ -140,6 +147,7 @@ class PlainUpload extends BaseUpload { overwrite: boolean | 'error', progressCallback: Function, successCallback: Function, + fields: ?Array, }): void { if (this.isDestroyed()) { return; @@ -156,6 +164,7 @@ class PlainUpload extends BaseUpload { this.progressCallback = progressCallback; this.overwrite = overwrite; this.conflictCallback = conflictCallback; + this.fields = fields; this.makePreflightRequest(); } diff --git a/src/constants.js b/src/constants.js index da51241d2d..218f306964 100644 --- a/src/constants.js +++ b/src/constants.js @@ -106,6 +106,7 @@ export const FIELD_SIZE: 'size' = 'size'; export const FIELD_PARENT = 'parent'; export const FIELD_EXTENSION = 'extension'; export const FIELD_ITEM_EXPIRATION = 'expires_at'; +export const FIELD_ITEM_STATUS = 'item_status'; export const FIELD_PERMISSIONS = 'permissions'; export const FIELD_PERMISSIONS_CAN_SHARE = `${FIELD_PERMISSIONS}.can_share`; export const FIELD_PERMISSIONS_CAN_UPLOAD = `${FIELD_PERMISSIONS}.can_upload`; @@ -137,6 +138,7 @@ export const FIELD_MODIFIED_BY = 'modified_by'; export const FIELD_OWNED_BY = 'owned_by'; export const FIELD_PROMOTED_BY = 'promoted_by'; export const FIELD_RESTORED_BY = 'restored_by'; +export const FIELD_PURGED_AT = 'purged_at'; export const FIELD_TRASHED_BY = 'trashed_by'; export const FIELD_DESCRIPTION = 'description'; export const FIELD_REPRESENTATIONS = 'representations'; diff --git a/src/elements/content-uploader/ContentUploader.tsx b/src/elements/content-uploader/ContentUploader.tsx index 9923bf3ced..2c90272f0b 100644 --- a/src/elements/content-uploader/ContentUploader.tsx +++ b/src/elements/content-uploader/ContentUploader.tsx @@ -20,6 +20,7 @@ import { withBlueprintModernization } from '../common/withBlueprintModernization import ThemingStyles, { Theme } from '../common/theming'; import FolderUpload from '../../api/uploads/FolderUpload'; import { getTypedFileId, getTypedFolderId } from '../../utils/file'; +import { UPLOADER_FIELDS_TO_FETCH } from '../../utils/fields'; import { getDataTransferItemId, getFile, @@ -815,7 +816,7 @@ class ContentUploader extends Component { * @return {void} */ uploadFile(item: UploadItem) { - const { overwrite, rootFolderId } = this.props; + const { enableModernizedUploads, overwrite, rootFolderId } = this.props; const { api, file, options } = item; const numItemsUploading = this.itemsRef.current.filter(item_t => item_t.status === STATUS_IN_PROGRESS).length; @@ -832,6 +833,7 @@ class ContentUploader extends Component { successCallback: entries => this.handleUploadSuccess(item, entries), overwrite, fileId: options && options.fileId ? options.fileId : null, + fields: enableModernizedUploads ? UPLOADER_FIELDS_TO_FETCH : null, }; item.status = STATUS_IN_PROGRESS; @@ -850,7 +852,7 @@ class ContentUploader extends Component { * @return {void} */ resumeFile(item: UploadItem) { - const { onResume, overwrite, rootFolderId } = this.props; + const { enableModernizedUploads, onResume, overwrite, rootFolderId } = this.props; const { api, file, options } = item; const numItemsUploading = this.itemsRef.current.filter(item_t => item_t.status === STATUS_IN_PROGRESS).length; @@ -868,6 +870,7 @@ class ContentUploader extends Component { overwrite, sessionId: api && api.sessionId ? api.sessionId : null, fileId: options && options.fileId ? options.fileId : null, + fields: enableModernizedUploads ? UPLOADER_FIELDS_TO_FETCH : null, }; item.status = STATUS_IN_PROGRESS; @@ -1326,9 +1329,9 @@ class ContentUploader extends Component { view={view} /> - ) + ); } - + return (
@@ -1353,14 +1356,12 @@ class ContentUploader extends Component { isDone={isDone} />
- ) - } + ); + }; return ( - - {renderUploader()} - + {renderUploader()} ); } diff --git a/src/utils/fields.js b/src/utils/fields.js index 8290d34844..45002d57f5 100644 --- a/src/utils/fields.js +++ b/src/utils/fields.js @@ -16,6 +16,7 @@ import { FIELD_PERMISSIONS, FIELD_ITEM_COLLECTION, FIELD_ITEM_EXPIRATION, + FIELD_ITEM_STATUS, FIELD_PATH_COLLECTION, FIELD_CONTENT_CREATED_AT, FIELD_CONTENT_MODIFIED_AT, @@ -30,6 +31,7 @@ import { FIELD_OWNED_BY, FIELD_PROMOTED_BY, FIELD_RESTORED_BY, + FIELD_PURGED_AT, FIELD_TRASHED_BY, FIELD_DESCRIPTION, FIELD_REPRESENTATIONS, @@ -222,6 +224,26 @@ const APP_ACTIVITY_FIELDS_TO_FETCH = [ FIELD_RENDERED_TEXT, ]; +// Fields needed for uploader +const UPLOADER_FIELDS_TO_FETCH = [ + FIELD_CONTENT_CREATED_AT, + FIELD_CONTENT_MODIFIED_AT, + FIELD_CREATED_AT, + FIELD_CREATED_BY, + FIELD_DESCRIPTION, + FIELD_ITEM_STATUS, + FIELD_MODIFIED_AT, + FIELD_MODIFIED_BY, + FIELD_OWNED_BY, + FIELD_PARENT, + FIELD_PATH_COLLECTION, + FIELD_PURGED_AT, + FIELD_SHARED_LINK, + FIELD_SIZE, + FIELD_TRASHED_AT, + FIELD_VERSION_NUMBER, +]; + /** * Finds properties missing in an object * @@ -297,4 +319,5 @@ export { TASK_ASSIGNMENTS_FIELDS_TO_FETCH, TASKS_FIELDS_TO_FETCH, USER_FIELDS, + UPLOADER_FIELDS_TO_FETCH, };