diff --git a/src/app/item-page/clarin-files-section/clarin-files-section.component.html b/src/app/item-page/clarin-files-section/clarin-files-section.component.html new file mode 100644 index 00000000000..6b0703f8fb3 --- /dev/null +++ b/src/app/item-page/clarin-files-section/clarin-files-section.component.html @@ -0,0 +1,25 @@ + + +
 {{'item.page.files.head' | translate}}
+
+ + +   + {{'item.page.download.button.command.line' | translate}} + + +
+ +
{{ command }}
+
+ + +   + {{'item.page.download.button.all.files.zip' | translate}} ({{ totalFileSizes }}) + + +
+ +
diff --git a/src/app/item-page/clarin-files-section/clarin-files-section.component.scss b/src/app/item-page/clarin-files-section/clarin-files-section.component.scss new file mode 100644 index 00000000000..5c2e6aacdef --- /dev/null +++ b/src/app/item-page/clarin-files-section/clarin-files-section.component.scss @@ -0,0 +1,16 @@ +/** +The styling file for the `clarin-files-section.component` + */ + +.btn-download{ + color: #fff !important; + background-color: #428bca; + border-color: #357ebd; + cursor: pointer; +} + +.btn-download:hover { + color: #fff; + background-color: #3276b1; + border-color: #285e8e; +} diff --git a/src/app/item-page/clarin-files-section/clarin-files-section.component.spec.ts b/src/app/item-page/clarin-files-section/clarin-files-section.component.spec.ts new file mode 100644 index 00000000000..d7f0f08d869 --- /dev/null +++ b/src/app/item-page/clarin-files-section/clarin-files-section.component.spec.ts @@ -0,0 +1,69 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ClarinFilesSectionComponent } from './clarin-files-section.component'; +import { RegistryService } from '../../core/registry/registry.service'; +import { Router } from '@angular/router'; +import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; +import { RouterMock } from '../../shared/mocks/router.mock'; +import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service.stub'; +import { TranslateModule } from '@ngx-translate/core'; +import { MetadataBitstream } from '../../core/metadata/metadata-bitstream.model'; +import { ResourceType } from '../../core/shared/resource-type'; +import { HALLink } from '../../core/shared/hal-link.model'; +import { BehaviorSubject , of} from 'rxjs'; + +describe('ClarinFilesSectionComponent', () => { + let component: ClarinFilesSectionComponent; + let fixture: ComponentFixture; + + let mockRegistryService: any; + let halService: HALEndpointService; + // Set up the mock service's getMetadataBitstream method to return a simple stream + const metadatabitstream = new MetadataBitstream(); + metadatabitstream.id = 123; + metadatabitstream.name = 'test'; + metadatabitstream.description = 'test'; + metadatabitstream.fileSize = '1MB'; + metadatabitstream.checksum = 'abc'; + metadatabitstream.type = new ResourceType('item'); + metadatabitstream.fileInfo = []; + metadatabitstream.format = 'text'; + metadatabitstream.canPreview = false; + metadatabitstream._links = { + self: new HALLink(), + schema: new HALLink(), + }; + + metadatabitstream._links.self.href = ''; + metadatabitstream._links.schema.href = ''; + const metadataBitstreams: MetadataBitstream[] = [metadatabitstream]; + const bitstreamStream = new BehaviorSubject(metadataBitstreams); + + beforeEach(async () => { + mockRegistryService = jasmine.createSpyObj('RegistryService', { + 'getMetadataBitstream': of(bitstreamStream) + } + ); + halService = Object.assign(new HALEndpointServiceStub('some url')); + + await TestBed.configureTestingModule({ + declarations: [ ClarinFilesSectionComponent ], + imports: [ + TranslateModule.forRoot() + ], + providers: [ + { provide: RegistryService, useValue: mockRegistryService }, + { provide: Router, useValue: new RouterMock() }, + { provide: HALEndpointService, useValue: halService } + ], + }) + .compileComponents(); + + fixture = TestBed.createComponent(ClarinFilesSectionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/item-page/clarin-files-section/clarin-files-section.component.ts b/src/app/item-page/clarin-files-section/clarin-files-section.component.ts new file mode 100644 index 00000000000..5879769370c --- /dev/null +++ b/src/app/item-page/clarin-files-section/clarin-files-section.component.ts @@ -0,0 +1,125 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Item } from '../../core/shared/item.model'; +import { getAllSucceededRemoteListPayload } from '../../core/shared/operators'; +import { getItemPageRoute } from '../item-page-routing-paths'; +import { MetadataBitstream } from '../../core/metadata/metadata-bitstream.model'; +import { RegistryService } from '../../core/registry/registry.service'; +import { Router } from '@angular/router'; +import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; + +@Component({ + selector: 'ds-clarin-files-section', + templateUrl: './clarin-files-section.component.html', + styleUrls: ['./clarin-files-section.component.scss'] +}) +export class ClarinFilesSectionComponent implements OnInit { + + /** + * The item to display files for + */ + @Input() item: Item; + + /** + * handle of the current item + */ + @Input() itemHandle: string; + + canShowCurlDownload = false; + + /** + * If download by command button is click, the command line will be shown + */ + isCommandLineVisible = false; + + /** + * command for the download command feature + */ + command: string; + + /** + * determine to show download all zip button or not + */ + canDownloadAllFiles = false; + + /** + * total size of list of files uploaded by users to this item + */ + totalFileSizes: string; + + /** + * list of files uploaded by users to this item + */ + listOfFiles: MetadataBitstream[]; + + + constructor(protected registryService: RegistryService, + protected router: Router, + protected halService: HALEndpointService) { + } + + ngOnInit(): void { + this.registryService + .getMetadataBitstream(this.itemHandle, 'ORIGINAL,TEXT,THUMBNAIL') + .pipe(getAllSucceededRemoteListPayload()) + .subscribe((data: MetadataBitstream[]) => { + this.listOfFiles = data; + this.generateCurlCommand(); + this.sumFileSizes(); + }); + } + + setCommandline() { + this.isCommandLineVisible = !this.isCommandLineVisible; + } + + downloadFiles() { + void this.router.navigate([getItemPageRoute(this.item), 'download']); + } + + generateCurlCommand() { + const fileNames = this.listOfFiles.map((file: MetadataBitstream) => { + // Show `Download All Files` only if there are more files. + if (this.listOfFiles.length > 1) { + this.canDownloadAllFiles = true; + } + + if (file.canPreview) { + this.canShowCurlDownload = true; + } + + return file.name; + }); + + this.command = `curl --remote-name-all ` + this.halService.getRootHref() + `/core/bitstreams/handle/${ + this.itemHandle + }/{${fileNames.join(',')}}`; + } + + sumFileSizes() { + const sizeUnits = { + B: 1, + KB: 1000, + MB: 1000 * 1000, + GB: 1000 * 1000 * 1000, + TB: 1000 * 1000 * 1000 * 1000, + }; + + let totalBytes = this.listOfFiles.reduce((total, file) => { + const [valueStr, unit] = file.fileSize.split(' '); + const value = parseFloat(valueStr); + const bytes = value * sizeUnits[unit.toUpperCase()]; + return total + bytes; + }, 0); + + let finalUnit = 'B'; + for (const unit of ['KB', 'MB', 'GB', 'TB']) { + if (totalBytes < 1000) { + break; + } + totalBytes /= 1000; + finalUnit = unit; + } + + this.totalFileSizes = totalBytes.toFixed(2) + ' ' + finalUnit; + } +} diff --git a/src/app/item-page/clarin-license-info/clarin-license-info.component.html b/src/app/item-page/clarin-license-info/clarin-license-info.component.html index d2f0f90dbb8..e58afeccdd3 100644 --- a/src/app/item-page/clarin-license-info/clarin-license-info.component.html +++ b/src/app/item-page/clarin-license-info/clarin-license-info.component.html @@ -1,14 +1,14 @@
-
+
{{'item.page.license.message.0' | translate}} - - {{licenseType}} - + {{licenseType}} +
+
{{'item.page.license.message.1' | translate}}
-
- {{license}} +
diff --git a/src/app/item-page/clarin-license-info/clarin-license-info.component.spec.ts b/src/app/item-page/clarin-license-info/clarin-license-info.component.spec.ts index e72b3e9da0d..3ccb05ad6e3 100644 --- a/src/app/item-page/clarin-license-info/clarin-license-info.component.spec.ts +++ b/src/app/item-page/clarin-license-info/clarin-license-info.component.spec.ts @@ -10,6 +10,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import { ClarinLicenseDataService } from '../../core/data/clarin/clarin-license-data.service'; import { ItemMock } from '../../shared/mocks/item.mock'; import { MetadataValue } from '../../core/shared/metadata.models'; +import { LocaleService } from '../../core/locale/locale.service'; const item = ItemMock; const license = 'Test License Name'; @@ -22,6 +23,7 @@ describe('ClarinLicenseInfoComponent', () => { let clarinLicenseDataService: ClarinLicenseDataService; let sanitizerStub: DomSanitizer; + let localeService: LocaleService; // initialize license metadata item.metadata['dc.rights.label'] = [Object.assign(new MetadataValue(), { @@ -46,6 +48,9 @@ describe('ClarinLicenseInfoComponent', () => { sanitizerStub = jasmine.createSpyObj('sanitizer', { bypassSecurityTrustUrl: null }); + localeService = jasmine.createSpyObj('LocaleService', { + getCurrentLanguageCode: jasmine.createSpy('getCurrentLanguageCode'), + }); await TestBed.configureTestingModule({ imports: [ @@ -59,6 +64,7 @@ describe('ClarinLicenseInfoComponent', () => { providers: [ { provide: ClarinLicenseDataService, useValue: clarinLicenseDataService }, { provide: DomSanitizer, useValue: sanitizerStub }, + { provide: LocaleService, useValue: localeService } ], }) .compileComponents(); diff --git a/src/app/item-page/clarin-license-info/clarin-license-info.component.ts b/src/app/item-page/clarin-license-info/clarin-license-info.component.ts index 5762533bbdf..a962bc221c4 100644 --- a/src/app/item-page/clarin-license-info/clarin-license-info.component.ts +++ b/src/app/item-page/clarin-license-info/clarin-license-info.component.ts @@ -9,6 +9,7 @@ import { ClarinLicense } from '../../core/shared/clarin/clarin-license.model'; import { DomSanitizer } from '@angular/platform-browser'; import { secureImageData } from '../../shared/clarin-shared-util'; import { BehaviorSubject } from 'rxjs'; +import { LocaleService } from '../../core/locale/locale.service'; /** * This component show clarin license info in the item page and item full page. @@ -21,7 +22,8 @@ import { BehaviorSubject } from 'rxjs'; export class ClarinLicenseInfoComponent implements OnInit { constructor(private sanitizer: DomSanitizer, - private clarinLicenseService: ClarinLicenseDataService) { } + private clarinLicenseService: ClarinLicenseDataService, + private localeService: LocaleService) { } /** * The item to display a version history for @@ -95,6 +97,13 @@ export class ClarinLicenseInfoComponent implements OnInit { secureImageData(imageByteArray) { return secureImageData(this.sanitizer, imageByteArray); } + + /** + * Check if current english is Czech + */ + isCsLocale() { + return this.localeService.getCurrentLanguageCode() === 'cs'; + } } export enum LicenseType { diff --git a/src/app/item-page/clarin-ref-box/clarin-ref-box.component.html b/src/app/item-page/clarin-ref-box/clarin-ref-box.component.html index ed66dd735e5..ac4de580791 100644 --- a/src/app/item-page/clarin-ref-box/clarin-ref-box.component.html +++ b/src/app/item-page/clarin-ref-box/clarin-ref-box.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/src/app/item-page/clarin-ref-citation-modal/clarin-ref-citation-modal.component.html b/src/app/item-page/clarin-ref-citation-modal/clarin-ref-citation-modal.component.html index 201ad3de387..2a2eaf8c1fa 100644 --- a/src/app/item-page/clarin-ref-citation-modal/clarin-ref-citation-modal.component.html +++ b/src/app/item-page/clarin-ref-citation-modal/clarin-ref-citation-modal.component.html @@ -5,7 +5,7 @@
-