mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Fix: Improve footer responsiveness and download button on the full item page (#4218)
* fix: footer and download button responsiveness * Revert styling changes to the download button on the simple item page * fix: for restrict bitstrream show only lock icon * ix: display download icon consistently across all item pages * fix embargo label responsiveness * Recommit without json5 changes * Recommit without json5 changes * Recommit without json5 changes
This commit is contained in:
@@ -49,8 +49,8 @@
|
|||||||
<!-- Grid container -->
|
<!-- Grid container -->
|
||||||
|
|
||||||
<!-- Copyright -->
|
<!-- Copyright -->
|
||||||
<div class="bottom-footer p-1 d-flex justify-content-center align-items-center text-white">
|
<div class="bottom-footer p-1 d-flex flex-column flex-md-row justify-content-center align-items-center text-white">
|
||||||
<div class="content-container">
|
<div class="content-container align-self-center">
|
||||||
<p class="m-0">
|
<p class="m-0">
|
||||||
<a class="text-white"
|
<a class="text-white"
|
||||||
href="http://www.dspace.org/" role="link" tabindex="0">{{ 'footer.link.dspace' | translate}}</a>
|
href="http://www.dspace.org/" role="link" tabindex="0">{{ 'footer.link.dspace' | translate}}</a>
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@if (coarLdnEnabled$ | async) {
|
@if (coarLdnEnabled$ | async) {
|
||||||
<div class="notify-enabled text-white">
|
<div class="notify-enabled text-white align-self-end">
|
||||||
<a class="coar-notify-support-route" routerLink="info/coar-notify-support" role="link" tabindex="0">
|
<a class="coar-notify-support-route" routerLink="info/coar-notify-support" role="link" tabindex="0">
|
||||||
<img class="n-coar" src="assets/images/n-coar.svg" [attr.alt]="'menu.header.image.logo' | translate" />
|
<img class="n-coar" src="assets/images/n-coar.svg" [attr.alt]="'menu.header.image.logo' | translate" />
|
||||||
{{ 'footer.link.coar-notify-support' | translate }}
|
{{ 'footer.link.coar-notify-support' | translate }}
|
||||||
|
@@ -23,9 +23,8 @@
|
|||||||
|
|
||||||
.bottom-footer {
|
.bottom-footer {
|
||||||
.notify-enabled {
|
.notify-enabled {
|
||||||
position: absolute;
|
position: relative;
|
||||||
bottom: 4px;
|
margin-top: 4px;
|
||||||
right: 0;
|
|
||||||
|
|
||||||
.coar-notify-support-route {
|
.coar-notify-support-route {
|
||||||
padding: 0 calc(var(--bs-spacer) / 2);
|
padding: 0 calc(var(--bs-spacer) / 2);
|
||||||
@@ -37,7 +36,11 @@
|
|||||||
margin-bottom: 8.5px;
|
margin-bottom: 8.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
margin-top: 20px;
|
@media screen and (min-width: map-get($grid-breakpoints, md)) {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 4px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ul {
|
ul {
|
||||||
li {
|
li {
|
||||||
|
@@ -1,84 +1,108 @@
|
|||||||
<ds-metadata-field-wrapper [label]="label | translate">
|
<ds-metadata-field-wrapper [label]="label | translate">
|
||||||
<div *ngVar="(originals$ | async)?.payload as originals">
|
<div *ngVar="(originals$ | async)?.payload as originals">
|
||||||
@if (hasValuesInBundle(originals)) {
|
@if (hasValuesInBundle(originals)) {
|
||||||
<div>
|
<div>
|
||||||
<h3 class="h5 simple-view-element-header">{{"item.page.filesection.original.bundle" | translate}}</h3>
|
<h3 class="h5 simple-view-element-header">
|
||||||
@if (originals?.page?.length > 0) {
|
{{ "item.page.filesection.original.bundle" | translate }}
|
||||||
<ds-pagination
|
</h3>
|
||||||
[hideGear]="true"
|
@if (originals?.page?.length > 0) {
|
||||||
[hidePagerWhenSinglePage]="true"
|
<ds-pagination [hideGear]="true" [hidePagerWhenSinglePage]="true" [paginationOptions]="originalOptions"
|
||||||
[paginationOptions]="originalOptions"
|
[collectionSize]="originals?.totalElements" [retainScrollPosition]="true">
|
||||||
[collectionSize]="originals?.totalElements"
|
@for (file of originals?.page; track file) {
|
||||||
[retainScrollPosition]="true">
|
<div class="file-section row mb-3">
|
||||||
@for (file of originals?.page; track file) {
|
<div class="col-3">
|
||||||
<div class="file-section row mb-3">
|
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
|
||||||
<div class="col-3">
|
</div>
|
||||||
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
|
<div class="col-7">
|
||||||
</div>
|
<dl class="row">
|
||||||
<div class="col-7">
|
<dt class="col-md-4">
|
||||||
<dl class="row">
|
{{ "item.page.filesection.name" | translate }}
|
||||||
<dt class="col-md-4">{{"item.page.filesection.name" | translate}}</dt>
|
</dt>
|
||||||
<dd class="col-md-8">{{ dsoNameService.getName(file) }}</dd>
|
<dd class="col-md-8">{{ dsoNameService.getName(file) }}</dd>
|
||||||
<dt class="col-md-4">{{"item.page.filesection.size" | translate}}</dt>
|
<dt class="col-md-4">
|
||||||
<dd class="col-md-8">{{(file.sizeBytes) | dsFileSize }}</dd>
|
{{ "item.page.filesection.size" | translate }}
|
||||||
<dt class="col-md-4">{{"item.page.filesection.format" | translate}}</dt>
|
</dt>
|
||||||
<dd class="col-md-8">{{(file.format | async)?.payload?.description}}</dd>
|
<dd class="col-md-8">{{ file.sizeBytes | dsFileSize }}</dd>
|
||||||
@if (file.hasMetadata('dc.description')) {
|
<dt class="col-md-4">
|
||||||
<dt class="col-md-4">{{"item.page.filesection.description" | translate}}</dt>
|
{{ "item.page.filesection.format" | translate }}
|
||||||
<dd class="col-md-8">{{file.firstMetadataValue("dc.description")}}</dd>
|
</dt>
|
||||||
}
|
<dd class="col-md-8">
|
||||||
</dl>
|
{{ (file.format | async)?.payload?.description }}
|
||||||
</div>
|
</dd>
|
||||||
<div class="col-2">
|
@if (file.hasMetadata('dc.description')) {
|
||||||
<ds-file-download-link [bitstream]="file" [item]="item">
|
<dt class="col-md-4">
|
||||||
{{"item.page.filesection.download" | translate}}
|
{{ "item.page.filesection.description" | translate }}
|
||||||
</ds-file-download-link>
|
</dt>
|
||||||
</div>
|
<dd class="col-md-8">
|
||||||
</div>
|
{{ file.firstMetadataValue("dc.description") }}
|
||||||
}
|
</dd>
|
||||||
</ds-pagination>
|
}
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
<ds-file-download-link [showIcon]="true" [bitstream]="file" [item]="item" cssClasses="btn btn-outline-primary btn-download">
|
||||||
|
<span class="d-none d-md-inline">
|
||||||
|
{{ "item.page.filesection.download" | translate }}
|
||||||
|
</span>
|
||||||
|
</ds-file-download-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</ds-pagination>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div *ngVar="(licenses$ | async)?.payload as licenses">
|
<div *ngVar="(licenses$ | async)?.payload as licenses">
|
||||||
@if (hasValuesInBundle(licenses)) {
|
@if (hasValuesInBundle(licenses)) {
|
||||||
<div>
|
<div>
|
||||||
<h3 class="h5 simple-view-element-header">{{"item.page.filesection.license.bundle" | translate}}</h3>
|
<h3 class="h5 simple-view-element-header">
|
||||||
@if (licenses?.page?.length > 0) {
|
{{ "item.page.filesection.license.bundle" | translate }}
|
||||||
<ds-pagination
|
</h3>
|
||||||
[hideGear]="true"
|
@if (licenses?.page?.length > 0) {
|
||||||
[hidePagerWhenSinglePage]="true"
|
<ds-pagination [hideGear]="true" [hidePagerWhenSinglePage]="true" [paginationOptions]="licenseOptions"
|
||||||
[paginationOptions]="licenseOptions"
|
[collectionSize]="licenses?.totalElements" [retainScrollPosition]="true">
|
||||||
[collectionSize]="licenses?.totalElements"
|
@for (file of licenses?.page; track file) {
|
||||||
[retainScrollPosition]="true">
|
<div class="file-section row">
|
||||||
@for (file of licenses?.page; track file) {
|
<div class="col-3">
|
||||||
<div class="file-section row">
|
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
|
||||||
<div class="col-3">
|
</div>
|
||||||
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
|
<div class="col-7">
|
||||||
</div>
|
<dl class="row">
|
||||||
<div class="col-7">
|
<dt class="col-md-4">
|
||||||
<dl class="row">
|
{{ "item.page.filesection.name" | translate }}
|
||||||
<dt class="col-md-4">{{"item.page.filesection.name" | translate}}</dt>
|
</dt>
|
||||||
<dd class="col-md-8">{{ dsoNameService.getName(file) }}</dd>
|
<dd class="col-md-8">{{ dsoNameService.getName(file) }}</dd>
|
||||||
<dt class="col-md-4">{{"item.page.filesection.size" | translate}}</dt>
|
<dt class="col-md-4">
|
||||||
<dd class="col-md-8">{{(file.sizeBytes) | dsFileSize }}</dd>
|
{{ "item.page.filesection.size" | translate }}
|
||||||
<dt class="col-md-4">{{"item.page.filesection.format" | translate}}</dt>
|
</dt>
|
||||||
<dd class="col-md-8">{{(file.format | async)?.payload?.description}}</dd>
|
<dd class="col-md-8">{{ file.sizeBytes | dsFileSize }}</dd>
|
||||||
<dt class="col-md-4">{{"item.page.filesection.description" | translate}}</dt>
|
<dt class="col-md-4">
|
||||||
<dd class="col-md-8">{{file.firstMetadataValue("dc.description")}}</dd>
|
{{ "item.page.filesection.format" | translate }}
|
||||||
</dl>
|
</dt>
|
||||||
</div>
|
<dd class="col-md-8">
|
||||||
<div class="col-2">
|
{{ (file.format | async)?.payload?.description }}
|
||||||
<ds-file-download-link [bitstream]="file" [item]="item">
|
</dd>
|
||||||
{{"item.page.filesection.download" | translate}}
|
<dt class="col-md-4">
|
||||||
</ds-file-download-link>
|
{{ "item.page.filesection.description" | translate }}
|
||||||
</div>
|
</dt>
|
||||||
</div>
|
<dd class="col-md-8">
|
||||||
}
|
{{ file.firstMetadataValue("dc.description") }}
|
||||||
</ds-pagination>
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
<ds-file-download-link [showIcon]="true" [bitstream]="file" [item]="item" cssClasses="btn btn-outline-primary btn-download">
|
||||||
|
<span class="d-none d-md-inline">
|
||||||
|
{{ "item.page.filesection.download" | translate }}
|
||||||
|
</span>
|
||||||
|
</ds-file-download-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</ds-pagination>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</ds-metadata-field-wrapper>
|
</ds-metadata-field-wrapper>
|
||||||
|
@@ -5,17 +5,29 @@
|
|||||||
[queryParams]="(bitstreamPath$| async)?.queryParams"
|
[queryParams]="(bitstreamPath$| async)?.queryParams"
|
||||||
[target]="isBlank ? '_blank': '_self'"
|
[target]="isBlank ? '_blank': '_self'"
|
||||||
[ngClass]="cssClasses"
|
[ngClass]="cssClasses"
|
||||||
[attr.aria-label]="('file-download-link.download' | translate) + dsoNameService.getName(bitstream)"
|
[attr.aria-label]="getDownloadLinkTitle(canDownload$ | async, canDownloadWithToken$ | async, dsoNameService.getName(bitstream))"
|
||||||
|
[title]="getDownloadLinkTitle(canDownload$ | async, canDownloadWithToken$ | async, dsoNameService.getName(bitstream))"
|
||||||
role="link"
|
role="link"
|
||||||
tabindex="0">
|
tabindex="0">
|
||||||
@if ((canDownload$ | async) === false && (canDownloadWithToken$ | async) === false) {
|
@if ((canDownload$ | async) === false && (canDownloadWithToken$ | async) === false) {
|
||||||
<!-- If the user cannot download the file by auth or token, show a lock icon -->
|
<!-- If the user cannot download the file by auth or token, show a lock icon -->
|
||||||
<span role="img" [attr.aria-label]="'file-download-link.restricted' | translate" class="pr-1"><i class="fas fa-lock"></i></span>
|
<span role="img"
|
||||||
|
[attr.aria-label]="'file-download-link.restricted' | translate"
|
||||||
|
[title]="'file-download-link.restricted' | translate"
|
||||||
|
class="pr-1">
|
||||||
|
<i class="fas fa-lock"></i>
|
||||||
|
</span>
|
||||||
} @else if ((canDownloadWithToken$ | async) && (canDownload$ | async) === false) {
|
} @else if ((canDownloadWithToken$ | async) && (canDownload$ | async) === false) {
|
||||||
<!-- If the user can download the file by token, and NOT normally show a lock open icon -->
|
<!-- If the user can download the file by token, and NOT normally show a lock open icon -->
|
||||||
<span role="img" [attr.aria-label]="'file-download-link.secure-access' | translate" class="pr-1 request-a-copy-access-icon"><i class="fa-solid fa-lock-open" style=""></i></span>
|
<span role="img"
|
||||||
|
[attr.aria-label]="'file-download-link.secure-access' | translate"
|
||||||
|
[title]="'file-download-link.secure-access' | translate"
|
||||||
|
class="pr-1 request-a-copy-access-icon">
|
||||||
|
<i class="fa-solid fa-lock-open"></i>
|
||||||
|
</span>
|
||||||
|
} @else if (showIcon) {
|
||||||
|
<i class="fas fa-download d-inline"></i>
|
||||||
}
|
}
|
||||||
<!-- Otherwise, show no icon (normal download by authorized user), public access etc. -->
|
|
||||||
<ng-container *ngTemplateOutlet="content"></ng-container>
|
<ng-container *ngTemplateOutlet="content"></ng-container>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@@ -1,3 +1,7 @@
|
|||||||
.request-a-copy-access-icon {
|
.request-a-copy-access-icon {
|
||||||
color: var(--bs-success);
|
color: var(--bs-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-download{
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
@@ -12,7 +12,10 @@ import {
|
|||||||
ActivatedRoute,
|
ActivatedRoute,
|
||||||
RouterLink,
|
RouterLink,
|
||||||
} from '@angular/router';
|
} from '@angular/router';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import {
|
||||||
|
TranslateModule,
|
||||||
|
TranslateService,
|
||||||
|
} from '@ngx-translate/core';
|
||||||
import {
|
import {
|
||||||
combineLatest as observableCombineLatest,
|
combineLatest as observableCombineLatest,
|
||||||
Observable,
|
Observable,
|
||||||
@@ -75,6 +78,11 @@ export class FileDownloadLinkComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
@Input() showAccessStatusBadge = true;
|
@Input() showAccessStatusBadge = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A boolean indicating whether the download icon should be displayed.
|
||||||
|
*/
|
||||||
|
@Input() showIcon = false;
|
||||||
|
|
||||||
itemRequest: ItemRequest;
|
itemRequest: ItemRequest;
|
||||||
|
|
||||||
bitstreamPath$: Observable<{
|
bitstreamPath$: Observable<{
|
||||||
@@ -90,6 +98,7 @@ export class FileDownloadLinkComponent implements OnInit {
|
|||||||
private authorizationService: AuthorizationDataService,
|
private authorizationService: AuthorizationDataService,
|
||||||
public dsoNameService: DSONameService,
|
public dsoNameService: DSONameService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
|
private translateService: TranslateService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,4 +162,9 @@ export class FileDownloadLinkComponent implements OnInit {
|
|||||||
queryParams: {},
|
queryParams: {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDownloadLinkTitle(canDownload: boolean,canDownloadWithToken: boolean, bitstreamName: string): string {
|
||||||
|
return (canDownload || canDownloadWithToken ? this.translateService.instant('file-download-link.download') :
|
||||||
|
this.translateService.instant('file-download-link.request-copy')) + bitstreamName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,8 @@ export class ThemedFileDownloadLinkComponent extends ThemedComponent<FileDownloa
|
|||||||
|
|
||||||
@Input() showAccessStatusBadge: boolean;
|
@Input() showAccessStatusBadge: boolean;
|
||||||
|
|
||||||
|
@Input() showIcon = false;
|
||||||
|
|
||||||
protected inAndOutputNames: (keyof FileDownloadLinkComponent & keyof this)[] = [
|
protected inAndOutputNames: (keyof FileDownloadLinkComponent & keyof this)[] = [
|
||||||
'bitstream',
|
'bitstream',
|
||||||
'item',
|
'item',
|
||||||
@@ -36,6 +38,7 @@ export class ThemedFileDownloadLinkComponent extends ThemedComponent<FileDownloa
|
|||||||
'isBlank',
|
'isBlank',
|
||||||
'enableRequestACopy',
|
'enableRequestACopy',
|
||||||
'showAccessStatusBadge',
|
'showAccessStatusBadge',
|
||||||
|
'showIcon',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected getComponentName(): string {
|
protected getComponentName(): string {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
@if (showAccessStatus) {
|
@if (showAccessStatus) {
|
||||||
@if ({ status: accessStatus$ | async, date: embargoDate$ | async }; as accessStatus) {
|
@if ({ status: accessStatus$ | async, date: embargoDate$ | async }; as accessStatus) {
|
||||||
<span [class]="'badge bg-secondary access-status-list-element-badge ' + accessStatusClass">{{ accessStatus.status | translate: {date: accessStatus.date} }}</span>
|
<span [class]="'badge bg-secondary dont-break-out access-status-list-element-badge ' + accessStatusClass">{{ accessStatus.status | translate: {date: accessStatus.date} }}</span>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1 +1,3 @@
|
|||||||
|
span{
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
@@ -1,25 +1,30 @@
|
|||||||
<div class="thumbnail" [class.limit-width]="limitWidth">
|
<div class="thumbnail" [class.limit-width]="limitWidth">
|
||||||
@if (isLoading) {
|
@if (isLoading) {
|
||||||
<div class="thumbnail-content outer">
|
<div class="thumbnail-content outer">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<div class="centered">
|
<div class="centered">
|
||||||
<ds-loading [spinner]="true"></ds-loading>
|
<ds-loading [spinner]="true"></ds-loading>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
<!-- don't use *ngIf="!isLoading" so the thumbnail can load in while the animation is playing -->
|
<!-- don't use *ngIf="!isLoading" so the thumbnail can load in while the animation is playing -->
|
||||||
@if (src !== null) {
|
@if (src !== null) {
|
||||||
<img class="thumbnail-content img-fluid" [ngClass]="{'d-none': isLoading}"
|
<img
|
||||||
[src]="src | dsSafeUrl" [alt]="alt | translate" (error)="errorHandler()" (load)="successHandler()">
|
class="thumbnail-content img-fluid"
|
||||||
}
|
[ngClass]="{ 'd-none': isLoading }"
|
||||||
@if (src === null && !isLoading) {
|
[src]="src | dsSafeUrl"
|
||||||
<div class="thumbnail-content outer">
|
[alt]="alt | translate"
|
||||||
<div class="inner">
|
(error)="errorHandler()"
|
||||||
<div class="thumbnail-placeholder centered lead">
|
(load)="successHandler()"
|
||||||
{{ placeholder | translate }}
|
/>
|
||||||
</div>
|
} @if (src === null && !isLoading) {
|
||||||
|
<div class="thumbnail-content outer">
|
||||||
|
<div class="inner">
|
||||||
|
<div class="thumbnail-placeholder centered">
|
||||||
|
{{ placeholder | translate }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -7061,4 +7061,6 @@
|
|||||||
"embargo.listelement.badge": "Embargo until {{ date }}",
|
"embargo.listelement.badge": "Embargo until {{ date }}",
|
||||||
|
|
||||||
"metadata-export-search.submit.error.limit-exceeded": "Only the first {{limit}} items will be exported",
|
"metadata-export-search.submit.error.limit-exceeded": "Only the first {{limit}} items will be exported",
|
||||||
|
|
||||||
|
"file-download-link.request-copy": "Request a copy of ",
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user