mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge pull request #2075 from atmire/w2p-98855_themeable-file-download-link_contribute-main
Pass `ng-content` to themed child components
This commit is contained in:
@@ -33,9 +33,9 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<ds-file-download-link [bitstream]="file" [item]="item">
|
<ds-themed-file-download-link [bitstream]="file" [item]="item">
|
||||||
{{"item.page.filesection.download" | translate}}
|
{{"item.page.filesection.download" | translate}}
|
||||||
</ds-file-download-link>
|
</ds-themed-file-download-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ds-pagination>
|
</ds-pagination>
|
||||||
@@ -74,9 +74,9 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<ds-file-download-link [bitstream]="file" [item]="item">
|
<ds-themed-file-download-link [bitstream]="file" [item]="item">
|
||||||
{{"item.page.filesection.download" | translate}}
|
{{"item.page.filesection.download" | translate}}
|
||||||
</ds-file-download-link>
|
</ds-themed-file-download-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ds-pagination>
|
</ds-pagination>
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
<ng-container *ngVar="(bitstreams$ | async) as bitstreams">
|
<ng-container *ngVar="(bitstreams$ | async) as bitstreams">
|
||||||
<ds-metadata-field-wrapper *ngIf="bitstreams?.length > 0" [label]="label | translate">
|
<ds-metadata-field-wrapper *ngIf="bitstreams?.length > 0" [label]="label | translate">
|
||||||
<div class="file-section">
|
<div class="file-section">
|
||||||
<ds-file-download-link *ngFor="let file of bitstreams; let last=last;" [bitstream]="file" [item]="item">
|
<ds-themed-file-download-link *ngFor="let file of bitstreams; let last=last;" [bitstream]="file" [item]="item">
|
||||||
<span>{{file?.name}}</span>
|
<span>{{file?.name}}</span>
|
||||||
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
|
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
|
||||||
<span *ngIf="!last" innerHTML="{{separator}}"></span>
|
<span *ngIf="!last" innerHTML="{{separator}}"></span>
|
||||||
</ds-file-download-link>
|
</ds-themed-file-download-link>
|
||||||
<ds-themed-loading *ngIf="isLoading" message="{{'loading.default' | translate}}" [showMessage]="false"></ds-themed-loading>
|
<ds-themed-loading *ngIf="isLoading" message="{{'loading.default' | translate}}" [showMessage]="false"></ds-themed-loading>
|
||||||
<div *ngIf="!isLastPage" class="mt-1" id="view-more">
|
<div *ngIf="!isLastPage" class="mt-1" id="view-more">
|
||||||
<a class="bitstream-view-more btn btn-outline-secondary btn-sm" [routerLink]="[]" (click)="getNextPage()">{{'item.page.bitstreams.view-more' | translate}}</a>
|
<a class="bitstream-view-more btn btn-outline-secondary btn-sm" [routerLink]="[]" (click)="getNextPage()">{{'item.page.bitstreams.view-more' | translate}}</a>
|
||||||
|
@@ -112,7 +112,7 @@ describe('FileSectionComponent', () => {
|
|||||||
it('one bitstream should be on the page', () => {
|
it('one bitstream should be on the page', () => {
|
||||||
const viewMore = fixture.debugElement.query(By.css('.bitstream-view-more'));
|
const viewMore = fixture.debugElement.query(By.css('.bitstream-view-more'));
|
||||||
viewMore.triggerEventHandler('click', null);
|
viewMore.triggerEventHandler('click', null);
|
||||||
const fileDownloadLink = fixture.debugElement.queryAll(By.css('ds-file-download-link'));
|
const fileDownloadLink = fixture.debugElement.queryAll(By.css('ds-themed-file-download-link'));
|
||||||
expect(fileDownloadLink.length).toEqual(1);
|
expect(fileDownloadLink.length).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ describe('FileSectionComponent', () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
it('should contain another bitstream', () => {
|
it('should contain another bitstream', () => {
|
||||||
const fileDownloadLink = fixture.debugElement.queryAll(By.css('ds-file-download-link'));
|
const fileDownloadLink = fixture.debugElement.queryAll(By.css('ds-themed-file-download-link'));
|
||||||
expect(fileDownloadLink.length).toEqual(2);
|
expect(fileDownloadLink.length).toEqual(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -17,10 +17,10 @@
|
|||||||
<div *ngVar="(filesRD$ | async)?.payload?.page as files">
|
<div *ngVar="(filesRD$ | async)?.payload?.page as files">
|
||||||
<ds-process-detail-field *ngIf="files && files?.length > 0" id="process-files"
|
<ds-process-detail-field *ngIf="files && files?.length > 0" id="process-files"
|
||||||
[title]="'process.detail.output-files'">
|
[title]="'process.detail.output-files'">
|
||||||
<ds-file-download-link *ngFor="let file of files; let last=last;" [bitstream]="file">
|
<ds-themed-file-download-link *ngFor="let file of files; let last=last;" [bitstream]="file">
|
||||||
<span>{{getFileName(file)}}</span>
|
<span>{{getFileName(file)}}</span>
|
||||||
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
|
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
|
||||||
</ds-file-download-link>
|
</ds-themed-file-download-link>
|
||||||
</ds-process-detail-field>
|
</ds-process-detail-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -0,0 +1,38 @@
|
|||||||
|
import { ThemedComponent } from '../theme-support/themed.component';
|
||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { FileDownloadLinkComponent } from './file-download-link.component';
|
||||||
|
import { Bitstream } from '../../core/shared/bitstream.model';
|
||||||
|
import { Item } from '../../core/shared/item.model';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-themed-file-download-link',
|
||||||
|
styleUrls: [],
|
||||||
|
templateUrl: '../theme-support/themed.component.html',
|
||||||
|
})
|
||||||
|
export class ThemedFileDownloadLinkComponent extends ThemedComponent<FileDownloadLinkComponent> {
|
||||||
|
|
||||||
|
@Input() bitstream: Bitstream;
|
||||||
|
|
||||||
|
@Input() item: Item;
|
||||||
|
|
||||||
|
@Input() cssClasses: string;
|
||||||
|
|
||||||
|
@Input() isBlank: boolean;
|
||||||
|
|
||||||
|
@Input() enableRequestACopy: boolean;
|
||||||
|
|
||||||
|
protected inAndOutputNames: (keyof FileDownloadLinkComponent & keyof this)[] = ['bitstream', 'item', 'cssClasses', 'isBlank', 'enableRequestACopy'];
|
||||||
|
|
||||||
|
protected getComponentName(): string {
|
||||||
|
return 'FileDownloadLinkComponent';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importThemedComponent(themeName: string): Promise<any> {
|
||||||
|
return import(`../../../themes/${themeName}/app/shared/file-download-link/file-download-link.component`);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importUnthemedComponent(): Promise<any> {
|
||||||
|
return import('./file-download-link.component');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -200,6 +200,7 @@ import { ClaimedTaskActionsDirective } from './mydspace-actions/claimed-task/swi
|
|||||||
import { ImpersonateNavbarComponent } from './impersonate-navbar/impersonate-navbar.component';
|
import { ImpersonateNavbarComponent } from './impersonate-navbar/impersonate-navbar.component';
|
||||||
import { NgForTrackByIdDirective } from './ng-for-track-by-id.directive';
|
import { NgForTrackByIdDirective } from './ng-for-track-by-id.directive';
|
||||||
import { FileDownloadLinkComponent } from './file-download-link/file-download-link.component';
|
import { FileDownloadLinkComponent } from './file-download-link/file-download-link.component';
|
||||||
|
import { ThemedFileDownloadLinkComponent } from './file-download-link/themed-file-download-link.component';
|
||||||
import { CollectionDropdownComponent } from './collection-dropdown/collection-dropdown.component';
|
import { CollectionDropdownComponent } from './collection-dropdown/collection-dropdown.component';
|
||||||
import { EntityDropdownComponent } from './entity-dropdown/entity-dropdown.component';
|
import { EntityDropdownComponent } from './entity-dropdown/entity-dropdown.component';
|
||||||
import { CurationFormComponent } from '../curation-form/curation-form.component';
|
import { CurationFormComponent } from '../curation-form/curation-form.component';
|
||||||
@@ -413,6 +414,7 @@ const ENTRY_COMPONENTS = [
|
|||||||
CollectionDropdownComponent,
|
CollectionDropdownComponent,
|
||||||
ThemedCollectionDropdownComponent,
|
ThemedCollectionDropdownComponent,
|
||||||
FileDownloadLinkComponent,
|
FileDownloadLinkComponent,
|
||||||
|
ThemedFileDownloadLinkComponent,
|
||||||
CurationFormComponent,
|
CurationFormComponent,
|
||||||
ExportMetadataSelectorComponent,
|
ExportMetadataSelectorComponent,
|
||||||
ImportBatchSelectorComponent,
|
ImportBatchSelectorComponent,
|
||||||
|
@@ -1 +1,5 @@
|
|||||||
<ng-template #vcr></ng-template>
|
<ng-template #vcr>
|
||||||
|
</ng-template>
|
||||||
|
<div #content>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
@@ -9,7 +9,8 @@ import {
|
|||||||
ComponentFactoryResolver,
|
ComponentFactoryResolver,
|
||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
OnChanges,
|
OnChanges,
|
||||||
HostBinding
|
HostBinding,
|
||||||
|
ElementRef,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { hasValue, isNotEmpty } from '../empty.util';
|
import { hasValue, isNotEmpty } from '../empty.util';
|
||||||
import { from as fromPromise, Observable, of as observableOf, Subscription, BehaviorSubject } from 'rxjs';
|
import { from as fromPromise, Observable, of as observableOf, Subscription, BehaviorSubject } from 'rxjs';
|
||||||
@@ -25,6 +26,7 @@ import { BASE_THEME_NAME } from './theme.constants';
|
|||||||
})
|
})
|
||||||
export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges {
|
export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges {
|
||||||
@ViewChild('vcr', { read: ViewContainerRef }) vcr: ViewContainerRef;
|
@ViewChild('vcr', { read: ViewContainerRef }) vcr: ViewContainerRef;
|
||||||
|
@ViewChild('content') themedElementContent: ElementRef;
|
||||||
protected compRef: ComponentRef<T>;
|
protected compRef: ComponentRef<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,7 +48,7 @@ export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges
|
|||||||
constructor(
|
constructor(
|
||||||
protected resolver: ComponentFactoryResolver,
|
protected resolver: ComponentFactoryResolver,
|
||||||
protected cdr: ChangeDetectorRef,
|
protected cdr: ChangeDetectorRef,
|
||||||
protected themeService: ThemeService
|
protected themeService: ThemeService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,10 +104,11 @@ export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges
|
|||||||
}),
|
}),
|
||||||
).subscribe((constructor: GenericConstructor<T>) => {
|
).subscribe((constructor: GenericConstructor<T>) => {
|
||||||
const factory = this.resolver.resolveComponentFactory(constructor);
|
const factory = this.resolver.resolveComponentFactory(constructor);
|
||||||
this.compRef = this.vcr.createComponent(factory);
|
this.compRef = this.vcr.createComponent(factory, undefined, undefined, [this.themedElementContent.nativeElement.childNodes]);
|
||||||
this.connectInputsAndOutputs();
|
this.connectInputsAndOutputs();
|
||||||
this.compRef$.next(this.compRef);
|
this.compRef$.next(this.compRef);
|
||||||
this.cdr.markForCheck();
|
this.cdr.markForCheck();
|
||||||
|
this.themedElementContent.nativeElement.remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +124,7 @@ export abstract class ThemedComponent<T> implements OnInit, OnDestroy, OnChanges
|
|||||||
|
|
||||||
protected connectInputsAndOutputs(): void {
|
protected connectInputsAndOutputs(): void {
|
||||||
if (isNotEmpty(this.inAndOutputNames) && hasValue(this.compRef) && hasValue(this.compRef.instance)) {
|
if (isNotEmpty(this.inAndOutputNames) && hasValue(this.compRef) && hasValue(this.compRef.instance)) {
|
||||||
this.inAndOutputNames.forEach((name: any) => {
|
this.inAndOutputNames.filter((name: any) => this[name] !== undefined).forEach((name: any) => {
|
||||||
this.compRef.instance[name] = this[name];
|
this.compRef.instance[name] = this[name];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -10,9 +10,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="float-right w-15">
|
<div class="float-right w-15">
|
||||||
<ng-container>
|
<ng-container>
|
||||||
<ds-file-download-link [cssClasses]="'btn btn-link-focus'" [isBlank]="true" [bitstream]="getBitstream()" [enableRequestACopy]="false">
|
<ds-themed-file-download-link [cssClasses]="'btn btn-link-focus'" [isBlank]="true" [bitstream]="getBitstream()" [enableRequestACopy]="false">
|
||||||
<i class="fa fa-download fa-2x text-normal" aria-hidden="true"></i>
|
<i class="fa fa-download fa-2x text-normal" aria-hidden="true"></i>
|
||||||
</ds-file-download-link>
|
</ds-themed-file-download-link>
|
||||||
<button class="btn btn-link-focus"
|
<button class="btn btn-link-focus"
|
||||||
[attr.aria-label]="'submission.sections.upload.edit.title' | translate"
|
[attr.aria-label]="'submission.sections.upload.edit.title' | translate"
|
||||||
title="{{ 'submission.sections.upload.edit.title' | translate }}"
|
title="{{ 'submission.sections.upload.edit.title' | translate }}"
|
||||||
|
@@ -0,0 +1,14 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import {
|
||||||
|
FileDownloadLinkComponent as BaseComponent
|
||||||
|
} from '../../../../../app/shared/file-download-link/file-download-link.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-file-download-link',
|
||||||
|
// templateUrl: './file-download-link.component.html',
|
||||||
|
templateUrl: '../../../../../app/shared/file-download-link/file-download-link.component.html',
|
||||||
|
// styleUrls: ['./file-download-link.component.scss'],
|
||||||
|
styleUrls: ['../../../../../app/shared/file-download-link/file-download-link.component.scss'],
|
||||||
|
})
|
||||||
|
export class FileDownloadLinkComponent extends BaseComponent {
|
||||||
|
}
|
@@ -45,6 +45,7 @@ import { CollectionDropdownComponent } from './app/shared/collection-dropdown/co
|
|||||||
import { SharedBrowseByModule } from '../../app/shared/browse-by/shared-browse-by.module';
|
import { SharedBrowseByModule } from '../../app/shared/browse-by/shared-browse-by.module';
|
||||||
import { ResultsBackButtonModule } from '../../app/shared/results-back-button/results-back-button.module';
|
import { ResultsBackButtonModule } from '../../app/shared/results-back-button/results-back-button.module';
|
||||||
import { DsoPageModule } from '../../app/shared/dso-page/dso-page.module';
|
import { DsoPageModule } from '../../app/shared/dso-page/dso-page.module';
|
||||||
|
import { FileDownloadLinkComponent } from './app/shared/file-download-link/file-download-link.component';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,6 +62,7 @@ const ENTRY_COMPONENTS = [
|
|||||||
CommunityListElementComponent,
|
CommunityListElementComponent,
|
||||||
CollectionListElementComponent,
|
CollectionListElementComponent,
|
||||||
CollectionDropdownComponent,
|
CollectionDropdownComponent,
|
||||||
|
FileDownloadLinkComponent,
|
||||||
];
|
];
|
||||||
|
|
||||||
const DECLARATIONS = [
|
const DECLARATIONS = [
|
||||||
@@ -80,21 +82,21 @@ const DECLARATIONS = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
RootModule,
|
RootModule,
|
||||||
NavbarModule,
|
NavbarModule,
|
||||||
SharedBrowseByModule,
|
SharedBrowseByModule,
|
||||||
ResultsBackButtonModule,
|
ResultsBackButtonModule,
|
||||||
ItemPageModule,
|
ItemPageModule,
|
||||||
ItemSharedModule,
|
ItemSharedModule,
|
||||||
DsoPageModule,
|
DsoPageModule,
|
||||||
],
|
],
|
||||||
declarations: DECLARATIONS,
|
declarations: DECLARATIONS,
|
||||||
providers: [
|
providers: [
|
||||||
...ENTRY_COMPONENTS.map((component) => ({provide: component}))
|
...ENTRY_COMPONENTS.map((component) => ({provide: component}))
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* This module is included in the main bundle that gets downloaded at first page load. So it should
|
* This module is included in the main bundle that gets downloaded at first page load. So it should
|
||||||
|
Reference in New Issue
Block a user