Skip to content

Commit

Permalink
Merge pull request #285 from IQSS/refactor/263-extract-file-metadata
Browse files Browse the repository at this point in the history
Refactor extract File Metadata to its own model
  • Loading branch information
GPortas authored Feb 8, 2024
2 parents debb816 + 16fad5f commit 4e949d3
Show file tree
Hide file tree
Showing 130 changed files with 2,731 additions and 1,993 deletions.
3 changes: 3 additions & 0 deletions public/locales/en/file.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,8 @@
"directory": "File Path",
"description": "Description"
}
},
"actionButtons": {
"title": "File Action Buttons"
}
}
2 changes: 1 addition & 1 deletion src/dataset/domain/models/Dataset.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Alert, AlertMessageKey } from '../../../alert/domain/models/Alert'
import { FileDownloadSize } from '../../../files/domain/models/FilePreview'
import { FileDownloadSize } from '../../../files/domain/models/FileMetadata'

export enum DatasetLabelSemanticMeaning {
DATASET = 'dataset',
Expand Down
2 changes: 1 addition & 1 deletion src/dataset/infrastructure/mappers/JSDatasetMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
FileDownloadMode,
FileDownloadSize,
FileSizeUnit
} from '../../../files/domain/models/FilePreview'
} from '../../../files/domain/models/FileMetadata'
import { JSDatasetVersionMapper } from './JSDatasetVersionMapper'

export class JSDatasetMapper {
Expand Down
41 changes: 11 additions & 30 deletions src/files/domain/models/File.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,18 @@
import { DatasetVersion } from '../../../dataset/domain/models/Dataset'
import {
FileChecksum,
FileDownloadUrls,
FileEmbargo,
FileLabel,
FileSize,
FileTabularData,
FileType,
FileVersion
} from './FilePreview'

export interface FilePermissions {
canDownloadFile: boolean
}
import { FileMetadata } from './FileMetadata'
import { FileVersion } from './FileVersion'
import { FileAccess } from './FileAccess'
import { FileUserPermissions } from './FileUserPermissions'
import { FileIngest } from './FileIngest'

export interface File {
name: string
id: number
version: FileVersion
name: string
access: FileAccess
datasetVersion: DatasetVersion
type: FileType
size: FileSize
citation: string
restricted: boolean
permissions: FilePermissions
labels: FileLabel[]
downloadUrls: FileDownloadUrls
depositDate: Date
publicationDate?: Date
persistentId?: string
thumbnail?: string
directory?: string
tabularData?: FileTabularData
description?: string
checksum?: FileChecksum
embargo?: FileEmbargo
permissions: FileUserPermissions
metadata: FileMetadata
ingest: FileIngest
}
6 changes: 6 additions & 0 deletions src/files/domain/models/FileAccess.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface FileAccess {
restricted: boolean
latestVersionRestricted: boolean
canBeRequested: boolean
requested: boolean
}
2 changes: 1 addition & 1 deletion src/files/domain/models/FileCriteria.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FileType } from './FilePreview'
import { FileType } from './FileMetadata'

export class FileCriteria {
constructor(
Expand Down
14 changes: 14 additions & 0 deletions src/files/domain/models/FileIngest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export enum FileIngestStatus {
NONE = 'none',
IN_PROGRESS = 'inProgress',
SCHEDULED = 'scheduled',
ERROR = 'error'
}

export class FileIngest {
constructor(readonly status: FileIngestStatus, readonly message?: string) {}

get isInProgress(): boolean {
return this.status === FileIngestStatus.IN_PROGRESS
}
}
174 changes: 174 additions & 0 deletions src/files/domain/models/FileMetadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import FileTypeToFriendlyTypeMap from './FileTypeToFriendlyTypeMap'

export enum FileSizeUnit {
BYTES = 'B',
KILOBYTES = 'KB',
MEGABYTES = 'MB',
GIGABYTES = 'GB',
TERABYTES = 'TB',
PETABYTES = 'PB'
}

export class FileSize {
static readonly multiplier = {
[FileSizeUnit.BYTES]: 1,
[FileSizeUnit.KILOBYTES]: 1024,
[FileSizeUnit.MEGABYTES]: 1024 ** 2,
[FileSizeUnit.GIGABYTES]: 1024 ** 3,
[FileSizeUnit.TERABYTES]: 1024 ** 4,
[FileSizeUnit.PETABYTES]: 1024 ** 5
}

constructor(readonly value: number, readonly unit: FileSizeUnit) {
;[this.value, this.unit] = FileSize.convertToLargestUnit(value, unit)
}

toString(): string {
const formattedValue =
this.value % 1 === 0 ? this.value.toFixed(0) : (Math.round(this.value * 10) / 10).toString()
return `${formattedValue} ${this.unit}`
}

toBytes(): number {
return this.value * FileSize.multiplier[this.unit]
}

static convertToLargestUnit(value: number, unit: FileSizeUnit): [number, FileSizeUnit] {
let convertedValue = value
let convertedUnit = unit

while (convertedValue >= 1024 && convertedUnit !== FileSizeUnit.PETABYTES) {
convertedValue /= 1024
convertedUnit = this.getNextUnit(convertedUnit)
}

return [convertedValue, convertedUnit]
}

static getNextUnit(unit: FileSizeUnit): FileSizeUnit {
switch (unit) {
case FileSizeUnit.BYTES:
return FileSizeUnit.KILOBYTES
case FileSizeUnit.KILOBYTES:
return FileSizeUnit.MEGABYTES
case FileSizeUnit.MEGABYTES:
return FileSizeUnit.GIGABYTES
case FileSizeUnit.GIGABYTES:
return FileSizeUnit.TERABYTES
case FileSizeUnit.TERABYTES:
return FileSizeUnit.PETABYTES
default:
return unit
}
}
}

export enum FileDownloadMode {
ORIGINAL = 'original',
ARCHIVAL = 'archival'
}

export class FileDownloadSize extends FileSize {
constructor(
readonly value: number,
readonly unit: FileSizeUnit,
readonly mode: FileDownloadMode
) {
super(value, unit)
;[this.value, this.unit] = FileDownloadSize.convertToLargestUnit(value, unit)
}
}

export enum FileDateType {
METADATA_RELEASED = 'metadataReleased',
PUBLISHED = 'published',
DEPOSITED = 'deposited'
}

export interface FileDate {
type: FileDateType
date: Date
}

export class FileEmbargo {
constructor(readonly dateAvailable: Date, readonly reason?: string) {}

get isActive(): boolean {
return this.dateAvailable > new Date()
}
}

export interface FileTabularData {
variablesCount: number
observationsCount: number
unf?: string
}

export enum FileLabelType {
CATEGORY = 'category',
TAG = 'tag'
}

export interface FileLabel {
type: FileLabelType
value: string
}

export class FileType {
constructor(readonly value: string, readonly original?: string) {}

toDisplayFormat(): string {
return FileTypeToFriendlyTypeMap[this.value] || FileTypeToFriendlyTypeMap.unknown
}

get displayFormatIsUnknown(): boolean {
return this.toDisplayFormat() === FileTypeToFriendlyTypeMap.unknown
}

get originalFormatIsUnknown(): boolean {
return this.original === undefined || this.original === FileTypeToFriendlyTypeMap.unknown
}
}

export interface FileChecksum {
algorithm: string
value: string
}

export interface FileDownloadUrls {
original: string
tabular?: string
rData?: string
}

export class FileMetadata {
constructor(
readonly type: FileType,
readonly size: FileSize,
readonly date: FileDate,
readonly downloadCount: number,
readonly labels: FileLabel[],
public readonly isDeleted: boolean,
public readonly downloadUrls: FileDownloadUrls,
readonly depositDate: Date,
readonly publicationDate?: Date,
public thumbnail?: string,
readonly directory?: string,
readonly embargo?: FileEmbargo,
readonly tabularData?: FileTabularData,
readonly description?: string,
readonly checksum?: FileChecksum,
readonly persistentId?: string
) {}

get isActivelyEmbargoed(): boolean {
if (this.embargo) {
return this.embargo.isActive
}
return false
}

get isTabular(): boolean {
return this.tabularData !== undefined
}
}
Loading

0 comments on commit 4e949d3

Please sign in to comment.