Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ import edu.uci.ics.texera.web.resource.dashboard.user.dataset.DatasetResource.{
ERR_DATASET_NAME_ALREADY_EXISTS,
ERR_USER_HAS_NO_ACCESS_TO_DATASET_MESSAGE,
ListDatasetsResponse,
calculateLatestDatasetVersionSize,
calculateDatasetVersionSize,
calculateLatestDatasetVersionSize,
context,
createNewDatasetVersionFromFormData,
getDashboardDataset,
Expand Down Expand Up @@ -74,6 +74,7 @@ import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Paths}
import java.util.zip.{ZipEntry, ZipOutputStream}
import java.util
import java.util.Optional
import java.util.concurrent.locks.ReentrantLock
import javax.annotation.security.RolesAllowed
import javax.ws.rs.{
Expand Down Expand Up @@ -1108,25 +1109,29 @@ class DatasetResource {
/**
* Retrieves a ZIP file for a specific dataset version or the latest version.
*
* @param pathStr The dataset version path in the format: /ownerEmail/datasetName/versionName
* Example: /user@example.com/dataset/v1
* @param getLatest When true, retrieves the latest version regardless of the provided path.
* @param did The dataset ID (used when getLatest is true).
* @param did The dataset ID (used when getLatest is true).
* @param dvid The dataset version ID, if given, retrieve this version; if not given, retrieve the latest version
* @param user The session user.
* @return A Response containing the dataset version as a ZIP file.
*/
@GET
@Path("/version-zip")
def retrieveDatasetVersionZip(
@QueryParam("path") pathStr: String,
@QueryParam("getLatest") getLatest: Boolean,
@QueryParam("did") did: UInteger,
@QueryParam("dvid") dvid: Optional[Integer],
@Auth user: SessionUser
): Response = {
val (dataset, version) = if (getLatest) {
if (!userHasReadAccess(context, did, user.getUid)) {
throw new ForbiddenException(ERR_USER_HAS_NO_ACCESS_TO_DATASET_MESSAGE)
}
val (dataset, version) = if (dvid.isEmpty) {
// dvid is not given, retrieve latest
getLatestVersionInfo(did, user)
} else {
resolveAndValidatePath(pathStr, user)
// dvid is given, retrieve certain version
withTransaction(context)(ctx =>
(getDatasetByID(ctx, did), getDatasetVersionByID(ctx, UInteger.valueOf(dvid.get)))
)
}
val targetDatasetPath = PathUtils.getDatasetPath(dataset.getDid)
val fileNodes = GitVersionControlLocalFileStorage.retrieveRootFileNodesOfVersion(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,18 +193,11 @@ export class UserDatasetExplorerComponent implements OnInit {
this.downloadService.downloadSingleFile(this.currentDisplayedFileName).pipe(untilDestroyed(this)).subscribe();
};

extractVersionPath(currentDisplayedFileName: string): string {
const pathParts = currentDisplayedFileName.split("/");

return `/${pathParts[1]}/${pathParts[2]}/${pathParts[3]}`;
}

onClickDownloadVersionAsZip = (): void => {
if (!this.did || !this.selectedVersion?.dvid) return;

const versionPath = this.extractVersionPath(this.currentDisplayedFileName);
this.downloadService
.downloadDatasetVersion(versionPath, this.datasetName, this.selectedVersion.name)
.downloadDatasetVersion(this.did, this.selectedVersion.dvid, this.datasetName, this.selectedVersion.name)
.pipe(untilDestroyed(this))
.subscribe();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,11 @@ export class DatasetService {
* - did: A number representing the dataset ID
* @returns An Observable that emits a Blob containing the zip file
*/
public retrieveDatasetZip(options: { path?: string; did?: number }): Observable<Blob> {
public retrieveDatasetZip(options: { did: number; dvid?: number }): Observable<Blob> {
let params = new HttpParams();

if (options.path) {
params = params.set("path", encodeURIComponent(options.path));
}
if (options.did) {
params = params.set("did", options.did.toString());
params = params.set("getLatest", "true");
params = params.set("did", options.did.toString());
if (options.dvid) {
params = params.set("dvid", options.dvid.toString());
}

return this.http.get(`${AppSettings.getApiEndpoint()}/${DATASET_BASE_URL}/version-zip`, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,19 @@ describe("DownloadService", () => {
});

it("should download a dataset version successfully", done => {
const versionPath = "path/to/version";
const datasetId = 1;
const datasetVersionId = 1;
const datasetName = "TestDataset";
const versionName = "v1.0";
const mockBlob = new Blob(["version content"], { type: "application/zip" });

datasetServiceSpy.retrieveDatasetZip.and.returnValue(of(mockBlob));

downloadService.downloadDatasetVersion(versionPath, datasetName, versionName).subscribe({
downloadService.downloadDatasetVersion(datasetId, datasetVersionId, datasetName, versionName).subscribe({
next: blob => {
expect(blob).toBe(mockBlob);
expect(notificationServiceSpy.info).toHaveBeenCalledWith("Starting to download version v1.0 as ZIP");
expect(datasetServiceSpy.retrieveDatasetZip).toHaveBeenCalledWith({ path: versionPath });
expect(datasetServiceSpy.retrieveDatasetZip).toHaveBeenCalledWith({ did: datasetId, dvid: datasetVersionId });
expect(fileSaverServiceSpy.saveAs).toHaveBeenCalledWith(mockBlob, "TestDataset-v1.0.zip");
expect(notificationServiceSpy.success).toHaveBeenCalledWith("Version v1.0 has been downloaded as ZIP");
done();
Expand All @@ -157,21 +158,22 @@ describe("DownloadService", () => {
});

it("should handle dataset version download failure correctly", done => {
const versionPath = "path/to/version";
const datasetId = 1;
const datasetVersionId = 1;
const datasetName = "TestDataset";
const versionName = "v1.0";
const errorMessage = "Dataset version download failed";

datasetServiceSpy.retrieveDatasetZip.and.returnValue(throwError(() => new Error(errorMessage)));

downloadService.downloadDatasetVersion(versionPath, datasetName, versionName).subscribe({
downloadService.downloadDatasetVersion(datasetId, datasetVersionId, datasetName, versionName).subscribe({
next: () => {
fail("Should have thrown an error");
},
error: (error: unknown) => {
expect(error).toBeTruthy();
expect(notificationServiceSpy.info).toHaveBeenCalledWith("Starting to download version v1.0 as ZIP");
expect(datasetServiceSpy.retrieveDatasetZip).toHaveBeenCalledWith({ path: versionPath });
expect(datasetServiceSpy.retrieveDatasetZip).toHaveBeenCalledWith({ did: datasetId, dvid: datasetVersionId });
expect(fileSaverServiceSpy.saveAs).not.toHaveBeenCalled();
expect(notificationServiceSpy.error).toHaveBeenCalledWith("Error downloading version 'v1.0' as ZIP");
done();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,14 @@ export class DownloadService {
);
}

downloadDatasetVersion(versionPath: string, datasetName: string, versionName: string): Observable<Blob> {
downloadDatasetVersion(
datasetId: number,
datasetVersionId: number,
datasetName: string,
versionName: string
): Observable<Blob> {
return this.downloadWithNotification(
() => this.datasetService.retrieveDatasetZip({ path: versionPath }),
() => this.datasetService.retrieveDatasetZip({ did: datasetId, dvid: datasetVersionId }),
`${datasetName}-${versionName}.zip`,
`Starting to download version ${versionName} as ZIP`,
`Version ${versionName} has been downloaded as ZIP`,
Expand Down