Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add use case to get all datasets previews with pagination #107

Merged
merged 15 commits into from
Dec 22, 2023
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
10 changes: 10 additions & 0 deletions src/datasets/domain/models/DatasetPreview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { DatasetVersionInfo } from './Dataset';

export interface DatasetPreview {
persistentId: string;
title: string;
versionId: number;
versionInfo: DatasetVersionInfo;
citation: string;
description: string;
}
6 changes: 6 additions & 0 deletions src/datasets/domain/models/DatasetPreviewSubset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { DatasetPreview } from './DatasetPreview';

export interface DatasetPreviewSubset {
datasetPreviews: DatasetPreview[];
totalDatasetCount: number;
}
Comment on lines +1 to +6
Copy link
Contributor

@MellyGray MellyGray Dec 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that for the sake of consistency within the module, getDatasetFiles should also return FilesSubset, including files and the count information

This would ensure that the module's responses are predictable. Users of the module would then know that if they use some getAllItems use case, the response will be paginated and will include both the items and their count

I think that the module use cases shouldn't be coupled to the type of API used and how they are implemented, (Native API or Search API) and the module should be consistent even if each API works differently

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but I wouldn't make this change now as I would first extend the files API to return the total files count along with the files to avoid making two API calls per use case call. We can create two new issues for this: Files API extension + files use case extension.

Copy link
Contributor Author

@GPortas GPortas Dec 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 changes: 2 additions & 0 deletions src/datasets/domain/repositories/IDatasetsRepository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dataset } from '../models/Dataset';
import { DatasetUserPermissions } from '../models/DatasetUserPermissions';
import { DatasetLock } from '../models/DatasetLock';
import { DatasetPreviewSubset } from '../models/DatasetPreviewSubset';

export interface IDatasetsRepository {
getDatasetSummaryFieldNames(): Promise<string[]>;
Expand All @@ -10,4 +11,5 @@ export interface IDatasetsRepository {
getPrivateUrlDatasetCitation(token: string): Promise<string>;
getDatasetUserPermissions(datasetId: number | string): Promise<DatasetUserPermissions>;
getDatasetLocks(datasetId: number | string): Promise<DatasetLock[]>;
getAllDatasetPreviews(limit?: number, offset?: number): Promise<DatasetPreviewSubset>;
}
15 changes: 15 additions & 0 deletions src/datasets/domain/useCases/GetAllDatasetPreviews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { UseCase } from '../../../core/domain/useCases/UseCase';
import { IDatasetsRepository } from '../repositories/IDatasetsRepository';
import { DatasetPreviewSubset } from '../models/DatasetPreviewSubset';

export class GetAllDatasetPreviews implements UseCase<DatasetPreviewSubset> {
private datasetsRepository: IDatasetsRepository;

constructor(datasetsRepository: IDatasetsRepository) {
this.datasetsRepository = datasetsRepository;
}

async execute(limit?: number, offset?: number): Promise<DatasetPreviewSubset> {
return await this.datasetsRepository.getAllDatasetPreviews(limit, offset);
}
}
2 changes: 1 addition & 1 deletion src/datasets/domain/useCases/GetDatasetCitation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ export class GetDatasetCitation implements UseCase<string> {
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST,
includeDeaccessioned: boolean = false,
): Promise<string> {
return await this.datasetsRepository.getDatasetCitation(datasetId, datasetVersionId, includeDeaccessioned)
return await this.datasetsRepository.getDatasetCitation(datasetId, datasetVersionId, includeDeaccessioned);
}
}
5 changes: 5 additions & 0 deletions src/datasets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { GetDatasetCitation } from './domain/useCases/GetDatasetCitation';
import { GetPrivateUrlDatasetCitation } from './domain/useCases/GetPrivateUrlDatasetCitation';
import { GetDatasetUserPermissions } from './domain/useCases/GetDatasetUserPermissions';
import { GetDatasetLocks } from './domain/useCases/GetDatasetLocks';
import { GetAllDatasetPreviews } from './domain/useCases/GetAllDatasetPreviews';

const datasetsRepository = new DatasetsRepository();

Expand All @@ -16,6 +17,7 @@ const getDatasetCitation = new GetDatasetCitation(datasetsRepository);
const getPrivateUrlDatasetCitation = new GetPrivateUrlDatasetCitation(datasetsRepository);
const getDatasetUserPermissions = new GetDatasetUserPermissions(datasetsRepository);
const getDatasetLocks = new GetDatasetLocks(datasetsRepository);
const getAllDatasetPreviews = new GetAllDatasetPreviews(datasetsRepository);

export {
getDatasetSummaryFieldNames,
Expand All @@ -25,6 +27,7 @@ export {
getPrivateUrlDatasetCitation,
getDatasetUserPermissions,
getDatasetLocks,
getAllDatasetPreviews,
};
export { DatasetNotNumberedVersion } from './domain/models/DatasetNotNumberedVersion';
export { DatasetUserPermissions } from './domain/models/DatasetUserPermissions';
Expand All @@ -40,3 +43,5 @@ export {
DatasetMetadataFieldValue,
DatasetMetadataSubField,
} from './domain/models/Dataset';
export { DatasetPreview } from './domain/models/DatasetPreview';
export { DatasetPreviewSubset } from './domain/models/DatasetPreviewSubset';
36 changes: 29 additions & 7 deletions src/datasets/infra/repositories/DatasetsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import { DatasetUserPermissions } from '../../domain/models/DatasetUserPermissio
import { transformDatasetUserPermissionsResponseToDatasetUserPermissions } from './transformers/datasetUserPermissionsTransformers';
import { DatasetLock } from '../../domain/models/DatasetLock';
import { transformDatasetLocksResponseToDatasetLocks } from './transformers/datasetLocksTransformers';
import { transformDatasetPreviewsResponseToDatasetPreviewSubset } from './transformers/datasetPreviewsTransformers';
import { DatasetPreviewSubset } from '../../domain/models/DatasetPreviewSubset';

export interface GetAllDatasetPreviewsQueryParams {
per_page?: number;
start?: number;
}

export class DatasetsRepository extends ApiRepository implements IDatasetsRepository {
private readonly datasetsResourceName: string = 'datasets';
Expand Down Expand Up @@ -37,7 +43,7 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
true,
{
includeDeaccessioned: includeDeaccessioned,
includeFiles: false
includeFiles: false,
},
)
.then((response) => transformVersionResponseToDataset(response))
Expand All @@ -46,14 +52,15 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
});
}



public async getDatasetCitation(datasetId: number, datasetVersionId: string,
includeDeaccessioned: boolean): Promise<string> {

public async getDatasetCitation(
datasetId: number,
datasetVersionId: string,
includeDeaccessioned: boolean,
): Promise<string> {
return this.doGet(
this.buildApiEndpoint(this.datasetsResourceName, `versions/${datasetVersionId}/citation`, datasetId),
true, { includeDeaccessioned: includeDeaccessioned}
true,
{ includeDeaccessioned: includeDeaccessioned },
)
.then((response) => response.data.data.message)
.catch((error) => {
Expand Down Expand Up @@ -84,4 +91,19 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
throw error;
});
}

public async getAllDatasetPreviews(limit?: number, offset?: number): Promise<DatasetPreviewSubset> {
const queryParams: GetAllDatasetPreviewsQueryParams = {};
if (limit !== undefined) {
queryParams.per_page = limit;
}
if (offset !== undefined) {
queryParams.start = offset;
}
return this.doGet('/search?q=*&type=dataset&sort=date&order=desc', true, queryParams)
.then((response) => transformDatasetPreviewsResponseToDatasetPreviewSubset(response))
.catch((error) => {
throw error;
});
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { AxiosResponse } from 'axios';
import { DatasetLock, DatasetLockType } from '../../../domain/models/DatasetLock';

export interface DatasetLockPayload {
lockType: string;
date?: string;
user: string;
dataset: string;
message?: string;
}

export const transformDatasetLocksResponseToDatasetLocks = (response: AxiosResponse): DatasetLock[] => {
const datasetLocks: DatasetLock[] = [];
const datasetLocksPayload = response.data.data;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
datasetLocksPayload.forEach(function (datasetLockPayload: any) {
datasetLocksPayload.forEach(function (datasetLockPayload: DatasetLockPayload) {
datasetLocks.push(transformDatasetLockPayloadToDatasetLock(datasetLockPayload));
});
return datasetLocks;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const transformDatasetLockPayloadToDatasetLock = (datasetLockPayload: any): DatasetLock => {
const transformDatasetLockPayloadToDatasetLock = (datasetLockPayload: DatasetLockPayload): DatasetLock => {
return {
lockType: datasetLockPayload.lockType as DatasetLockType,
...(datasetLockPayload.date && { date: datasetLockPayload.date }),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { AxiosResponse } from 'axios';
import { DatasetPreview } from '../../../domain/models/DatasetPreview';
import { DatasetVersionState } from '../../../domain/models/Dataset';
import { DatasetPreviewSubset } from '../../../domain/models/DatasetPreviewSubset';

export interface DatasetPreviewPayload {
global_id: string;
name: string;
versionId: number;
majorVersion: number;
minorVersion: number;
versionState: string;
createdAt: string;
updatedAt: string;
published_at?: string;
citation: string;
description: string;
}

export const transformDatasetPreviewsResponseToDatasetPreviewSubset = (
response: AxiosResponse,
): DatasetPreviewSubset => {
const responseDataPayload = response.data.data;
const datasetPreviewsPayload = responseDataPayload.items;
const datasetPreviews: DatasetPreview[] = [];
datasetPreviewsPayload.forEach(function (datasetPreviewPayload: DatasetPreviewPayload) {
datasetPreviews.push(transformDatasetPreviewPayloadToDatasetPreview(datasetPreviewPayload));
});
return {
datasetPreviews: datasetPreviews,
totalDatasetCount: responseDataPayload.total_count,
};
};

const transformDatasetPreviewPayloadToDatasetPreview = (
datasetPreviewPayload: DatasetPreviewPayload,
): DatasetPreview => {
return {
persistentId: datasetPreviewPayload.global_id,
title: datasetPreviewPayload.name,
versionId: datasetPreviewPayload.versionId,
versionInfo: {
majorNumber: datasetPreviewPayload.majorVersion,
minorNumber: datasetPreviewPayload.minorVersion,
state: datasetPreviewPayload.versionState as DatasetVersionState,
createTime: new Date(datasetPreviewPayload.createdAt),
lastUpdateTime: new Date(datasetPreviewPayload.updatedAt),
...(datasetPreviewPayload.published_at && { releaseTime: new Date(datasetPreviewPayload.published_at) }),
},
citation: datasetPreviewPayload.citation,
description: datasetPreviewPayload.description,
};
};
Loading