diff --git a/catalog/app/components/FileEditor/loader.ts b/catalog/app/components/FileEditor/loader.ts index 5affd13e28e..5392fdde2c7 100644 --- a/catalog/app/components/FileEditor/loader.ts +++ b/catalog/app/components/FileEditor/loader.ts @@ -77,18 +77,24 @@ export const isSupportedFileType: (path: string) => boolean = R.pipe( export function useWriteData({ bucket, key, + version, }: S3HandleBase): (value: string) => Promise { const s3 = AWS.S3.use() return React.useCallback( async (value) => { - const { VersionId: version } = await s3 + const { VersionId: latestVersion } = await s3 + .headObject({ Bucket: bucket, Key: key }) + .promise() + if (latestVersion !== version) throw new Error('Revision is outdated') + + const { VersionId } = await s3 .putObject({ Bucket: bucket, Key: key, Body: value }) .promise() const { ContentLength: size } = await s3 - .headObject({ Bucket: bucket, Key: key, VersionId: version }) + .headObject({ Bucket: bucket, Key: key, VersionId }) .promise() - return { bucket, key, size, version } + return { bucket, key, size, version: VersionId } }, - [bucket, key, s3], + [bucket, key, s3, version], ) } diff --git a/catalog/app/containers/Bucket/File.js b/catalog/app/containers/Bucket/File.js index cc5feb0f24b..7ca6352e799 100644 --- a/catalog/app/containers/Bucket/File.js +++ b/catalog/app/containers/Bucket/File.js @@ -382,15 +382,20 @@ export default function File({ }), }) - const downloadable = - !noDownload && - versionExistsData.case({ - _: () => false, - Ok: requests.ObjectExistence.case({ - _: () => false, - Exists: ({ deleted, archived }) => !deleted && !archived, + const { downloadable, fileVersionId } = versionExistsData.case({ + _: () => ({ + downloadable: false, + }), + Ok: requests.ObjectExistence.case({ + _: () => ({ + downloadable: false, }), - }) + Exists: ({ deleted, archived, version: versionId }) => ({ + downloadable: !noDownload && !deleted && !archived, + fileVersionId: versionId, + }), + }), + }) const viewModes = useViewModes(path, mode) @@ -402,8 +407,8 @@ export default function File({ ) const handle = React.useMemo( - () => ({ bucket, key: path, version }), - [bucket, path, version], + () => ({ bucket, key: path, version: fileVersionId }), + [bucket, path, fileVersionId], ) const editorState = FileEditor.useState(handle) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 76cf79e2e23..4d6752cf27a 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -48,6 +48,7 @@ * [Changed] Fixed config and docs mistyping: `ui.athena.defaultWorkflow` should be `ui.athena.defaultWorkgroup` ([#3067](https://github.com/quiltdata/quilt/pull/3067)) * [Changed] Use dedicated columns field instead of first row, fix duplicated first row in table results ([#3101](https://github.com/quiltdata/quilt/pull/3101)) * [Changed] Allow pushing empty packages, suggest creating a stub `README.md` file when trying to push an empty package ([#3114](https://github.com/quiltdata/quilt/pull/3114)) +* [Changed] Allow to save only latest revisions of files ([#3124](https://github.com/quiltdata/quilt/pull/3124)) ## Docs * [Added] Add Amazon Athena documentation, examples and references ([#3116](https://github.com/quiltdata/quilt/pull/3116))