Skip to content

Commit

Permalink
Merge pull request IQSS#171 from IQSS/feature/167-integration-dataset…
Browse files Browse the repository at this point in the history
…-page-filters

167 - Files table UI [1/2] - Integration filters and search
  • Loading branch information
kcondon authored Sep 22, 2023
2 parents 372fb10 + e5d74cb commit f9ae2db
Show file tree
Hide file tree
Showing 42 changed files with 818 additions and 272 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"dependencies": {
"@faker-js/faker": "7.6.0",
"@iqss/dataverse-client-javascript": "2.0.0-pr80.3e0c21e",
"@iqss/dataverse-client-javascript": "2.0.0-pr88.9d7ced6",
"@iqss/dataverse-design-system": "*",
"@istanbuljs/nyc-config-typescript": "1.0.2",
"@tanstack/react-table": "8.9.2",
Expand Down
32 changes: 28 additions & 4 deletions src/files/domain/models/FileCriteria.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,47 @@ export class FileCriteria {
) {}

withSortBy(sortBy: FileSortByOption): FileCriteria {
return new FileCriteria(sortBy, this.filterByType, this.filterByAccess, this.filterByTag)
return new FileCriteria(
sortBy,
this.filterByType,
this.filterByAccess,
this.filterByTag,
this.searchText
)
}

withFilterByType(filterByType: string | undefined): FileCriteria {
const newFilterByType = filterByType === undefined ? undefined : new FileType(filterByType)

return new FileCriteria(this.sortBy, newFilterByType, this.filterByAccess, this.filterByTag)
return new FileCriteria(
this.sortBy,
newFilterByType,
this.filterByAccess,
this.filterByTag,
this.searchText
)
}

withFilterByAccess(filterByAccess: FileAccessOption | undefined): FileCriteria {
return new FileCriteria(this.sortBy, this.filterByType, filterByAccess, this.filterByTag)
return new FileCriteria(
this.sortBy,
this.filterByType,
filterByAccess,
this.filterByTag,
this.searchText
)
}

withFilterByTag(filterByTag: string | undefined): FileCriteria {
const newFilterByTag = filterByTag === undefined ? undefined : new FileTag(filterByTag)

return new FileCriteria(this.sortBy, this.filterByType, this.filterByAccess, newFilterByTag)
return new FileCriteria(
this.sortBy,
this.filterByType,
this.filterByAccess,
newFilterByTag,
this.searchText
)
}

withSearchText(searchText: string | undefined): FileCriteria {
Expand Down
4 changes: 2 additions & 2 deletions src/files/domain/repositories/FileRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export interface FileRepository {
paginationInfo?: FilePaginationInfo,
criteria?: FileCriteria
) => Promise<File[]>
getCountInfoByDatasetPersistentId: (
getFilesCountInfoByDatasetPersistentId: (
datasetPersistentId: string,
datasetVersion: DatasetVersion
) => Promise<FilesCountInfo>
getFileUserPermissionsById: (id: number) => Promise<FileUserPermissions>
getUserPermissionsById: (id: number) => Promise<FileUserPermissions>
}
4 changes: 2 additions & 2 deletions src/files/domain/useCases/checkFileDownloadPermission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export async function checkFileDownloadPermission(
file: File
): Promise<boolean> {
if (file.version.publishingStatus === FilePublishingStatus.DEACCESSIONED) {
return fileRepository.getFileUserPermissionsById(file.id).then((permissions) => {
return fileRepository.getUserPermissionsById(file.id).then((permissions) => {
return permissions.canEditDataset
})
}
Expand All @@ -16,7 +16,7 @@ export async function checkFileDownloadPermission(
return true
}

return fileRepository.getFileUserPermissionsById(file.id).then((permissions) => {
return fileRepository.getUserPermissionsById(file.id).then((permissions) => {
return permissions.canDownloadFile
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export async function checkFileEditDatasetPermission(
fileRepository: FileRepository,
file: File
): Promise<boolean> {
return fileRepository.getFileUserPermissionsById(file.id).then((permissions) => {
return fileRepository.getUserPermissionsById(file.id).then((permissions) => {
return permissions.canEditDataset
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export async function getFilesCountInfoByDatasetPersistentId(
datasetVersion: DatasetVersion
): Promise<FilesCountInfo> {
return fileRepository
.getCountInfoByDatasetPersistentId(datasetPersistentId, datasetVersion)
.getFilesCountInfoByDatasetPersistentId(datasetPersistentId, datasetVersion)
.catch((error: Error) => {
throw new Error(error.message)
})
Expand Down
57 changes: 29 additions & 28 deletions src/files/infrastructure/FileJSDataverseRepository.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { FileRepository } from '../domain/repositories/FileRepository'
import { File, FilePublishingStatus } from '../domain/models/File'
import { FilesCountInfo } from '../domain/models/FilesCountInfo'
import { FilesCountInfoMother } from '../../../tests/component/files/domain/models/FilesCountInfoMother'
import { FilePaginationInfo } from '../domain/models/FilePaginationInfo'
import { FileUserPermissions } from '../domain/models/FileUserPermissions'
import {
getDatasetFileCounts,
getDatasetFiles,
getFileDownloadCount,
getFileUserPermissions,
Expand All @@ -20,39 +20,39 @@ export class FileJSDataverseRepository implements FileRepository {
datasetPersistentId: string,
datasetVersion: DatasetVersion,
paginationInfo: FilePaginationInfo = new FilePaginationInfo(),
criteria?: FileCriteria
criteria: FileCriteria = new FileCriteria()
): Promise<File[]> {
const jsPagination = DomainFileMapper.toJSPagination(paginationInfo)
const jsFileOrderCriteria = DomainFileMapper.toJSFileOrderCriteria(criteria)

return getDatasetFiles
.execute(
datasetPersistentId,
datasetVersion.toString(),
jsPagination.limit,
jsPagination.offset,
jsFileOrderCriteria
DomainFileMapper.toJSFileCriteria(criteria)
)
.then((jsFiles) => jsFiles.map((jsFile) => JSFileMapper.toFile(jsFile, datasetVersion)))
.then((files) =>
Promise.all(
files.map((file) =>
FileJSDataverseRepository.getFileDownloadCount(
file.id,
file.version.publishingStatus
).then((downloadCount) => {
file.downloadCount = downloadCount
return file
})
)
)
)
.then((files) => FileJSDataverseRepository.getAllWithDownloadCount(files))
.catch((error: WriteError) => {
throw new Error(error.message)
})
}

private static getFileDownloadCount(
private static getAllWithDownloadCount(files: File[]): Promise<File[]> {
return Promise.all(
files.map((file) =>
FileJSDataverseRepository.getDownloadCountById(file.id, file.version.publishingStatus).then(
(downloadCount) => {
file.downloadCount = downloadCount
return file
}
)
)
)
}

private static getDownloadCountById(
id: number,
publishingStatus: FilePublishingStatus
): Promise<number> {
Expand All @@ -62,21 +62,22 @@ export class FileJSDataverseRepository implements FileRepository {
return Promise.resolve(0)
}

getCountInfoByDatasetPersistentId(
// eslint-disable-next-line unused-imports/no-unused-vars
getFilesCountInfoByDatasetPersistentId(
datasetPersistentId: string,
// eslint-disable-next-line unused-imports/no-unused-vars
datasetVersion: DatasetVersion
): Promise<FilesCountInfo> {
// TODO - implement using js-dataverse
return new Promise((resolve) => {
setTimeout(() => {
resolve(FilesCountInfoMother.create())
}, 1000)
})
// TODO - Take into account the FileCriteria https://github.com/IQSS/dataverse-frontend/issues/172
return getDatasetFileCounts
.execute(datasetPersistentId, datasetVersion.toString())
.then((jsFilesCountInfo) => {
return JSFileMapper.toFilesCountInfo(jsFilesCountInfo)
})
.catch((error: WriteError) => {
throw new Error(error.message)
})
}

getFileUserPermissionsById(id: number): Promise<FileUserPermissions> {
getUserPermissionsById(id: number): Promise<FileUserPermissions> {
return getFileUserPermissions
.execute(id)
.then((jsFileUserPermissions) =>
Expand Down
69 changes: 57 additions & 12 deletions src/files/infrastructure/mappers/DomainFileMapper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { FilePaginationInfo } from '../../domain/models/FilePaginationInfo'
import { FileCriteria, FileSortByOption } from '../../domain/models/FileCriteria'
import { FileOrderCriteria } from '@iqss/dataverse-client-javascript'
import {
FileAccessOption,
FileCriteria,
FileSortByOption,
FileTag
} from '../../domain/models/FileCriteria'
import {
FileAccessStatus as JSFileAccessStatus,
FileCriteria as JSFileCriteria,
FileOrderCriteria as JSFileOrderCriteria
} from '@iqss/dataverse-client-javascript'
import { FileType } from '../../domain/models/File'

export class DomainFileMapper {
static toJSPagination(paginationInfo: FilePaginationInfo): { limit?: number; offset?: number } {
Expand All @@ -10,22 +20,57 @@ export class DomainFileMapper {
}
}

static toJSFileOrderCriteria(criteria?: FileCriteria): FileOrderCriteria {
switch (criteria?.sortBy) {
static toJSFileCriteria(criteria: FileCriteria): JSFileCriteria {
return new JSFileCriteria(
this.toJSOrderCriteria(criteria.sortBy),
this.toJSContentType(criteria.filterByType),
this.toJSAccessStatus(criteria.filterByAccess),
this.toJSCategoryName(criteria.filterByTag),
this.toJSSearchText(criteria.searchText)
)
}

static toJSOrderCriteria(sortBy: FileSortByOption): JSFileOrderCriteria {
switch (sortBy) {
case FileSortByOption.NAME_AZ:
return FileOrderCriteria.NAME_AZ
return JSFileOrderCriteria.NAME_AZ
case FileSortByOption.NAME_ZA:
return FileOrderCriteria.NAME_ZA
return JSFileOrderCriteria.NAME_ZA
case FileSortByOption.NEWEST:
return FileOrderCriteria.NEWEST
return JSFileOrderCriteria.NEWEST
case FileSortByOption.OLDEST:
return FileOrderCriteria.OLDEST
return JSFileOrderCriteria.OLDEST
case FileSortByOption.SIZE:
return FileOrderCriteria.SIZE
return JSFileOrderCriteria.SIZE
case FileSortByOption.TYPE:
return FileOrderCriteria.TYPE
default:
return FileOrderCriteria.NAME_AZ
return JSFileOrderCriteria.TYPE
}
}

static toJSContentType(type: FileType | undefined): string | undefined {
return type === undefined ? undefined : type.value
}

static toJSAccessStatus(
accessStatus: FileAccessOption | undefined
): JSFileAccessStatus | undefined {
switch (accessStatus) {
case FileAccessOption.PUBLIC:
return JSFileAccessStatus.PUBLIC
case FileAccessOption.RESTRICTED:
return JSFileAccessStatus.RESTRICTED
case FileAccessOption.EMBARGOED:
return JSFileAccessStatus.EMBARGOED
case FileAccessOption.EMBARGOED_RESTRICTED:
return JSFileAccessStatus.EMBARGOED_RESTRICTED
}
}

static toJSCategoryName(filterByTag: FileTag | undefined): string | undefined {
return filterByTag === undefined ? undefined : filterByTag.value
}

static toJSSearchText(searchText: string | undefined): string | undefined {
return searchText
}
}
63 changes: 62 additions & 1 deletion src/files/infrastructure/mappers/JSFileMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,22 @@ import {
import {
File as JSFile,
FileEmbargo as JSFileEmbargo,
FileChecksum as JSFileChecksum
FileChecksum as JSFileChecksum,
FileCounts as JSFilesCountInfo,
FileContentTypeCount as JSFileContentTypeCount,
FileCategoryNameCount as JSFileCategoryNameCount,
FileAccessStatusCount as JSFileAccessStatusCount,
FileAccessStatus as JSFileAccessStatus
} from '@iqss/dataverse-client-javascript'
import { DatasetPublishingStatus, DatasetVersion } from '../../../dataset/domain/models/Dataset'
import { FileUserPermissions } from '../../domain/models/FileUserPermissions'
import {
FileAccessCount,
FilesCountInfo,
FileTagCount,
FileTypeCount
} from '../../domain/models/FilesCountInfo'
import { FileAccessOption, FileTag } from '../../domain/models/FileCriteria'

export class JSFileMapper {
static toFile(jsFile: JSFile, datasetVersion: DatasetVersion): File {
Expand Down Expand Up @@ -169,4 +181,53 @@ export class JSFileMapper {
static toFileDescription(jsFileDescription?: string): string | undefined {
return jsFileDescription
}

static toFilesCountInfo(jsFilesCountInfo: JSFilesCountInfo): FilesCountInfo {
return {
total: jsFilesCountInfo.total,
perFileType: jsFilesCountInfo.perContentType.map((jsFileContentTypeCount) =>
JSFileMapper.toFileTypeCount(jsFileContentTypeCount)
),
perFileTag: jsFilesCountInfo.perCategoryName.map((jsFileCategoryNameCount) =>
JSFileMapper.toFileTagCount(jsFileCategoryNameCount)
),
perAccess: jsFilesCountInfo.perAccessStatus.map((jsFileAccessStatusCount) =>
JSFileMapper.toFileAccessCount(jsFileAccessStatusCount)
)
}
}

static toFileTypeCount(jsFileContentTypeCount: JSFileContentTypeCount): FileTypeCount {
return {
type: new FileType(jsFileContentTypeCount.contentType),
count: jsFileContentTypeCount.count
}
}

static toFileTagCount(jsFileCategoryNameCount: JSFileCategoryNameCount): FileTagCount {
return {
tag: new FileTag(jsFileCategoryNameCount.categoryName),
count: jsFileCategoryNameCount.count
}
}

static toFileAccessCount(jsFileAccessStatusCount: JSFileAccessStatusCount): FileAccessCount {
return {
access: JSFileMapper.toFileAccessOption(jsFileAccessStatusCount.accessStatus),
count: jsFileAccessStatusCount.count
}
}

static toFileAccessOption(jsFileAccessStatus: JSFileAccessStatus): FileAccessOption {
switch (jsFileAccessStatus) {
case JSFileAccessStatus.RESTRICTED:
return FileAccessOption.RESTRICTED
case JSFileAccessStatus.PUBLIC:
return FileAccessOption.PUBLIC
case JSFileAccessStatus.EMBARGOED:
return FileAccessOption.EMBARGOED
case JSFileAccessStatus.EMBARGOED_RESTRICTED:
return FileAccessOption.EMBARGOED_RESTRICTED
}
}
}
Loading

0 comments on commit f9ae2db

Please sign in to comment.