Skip to content

Commit 8757712

Browse files
authored
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
1 parent b15e9d7 commit 8757712

File tree

11 files changed

+170
-101
lines changed

11 files changed

+170
-101
lines changed

src/app/footer/footer.component.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ <h5 class="text-uppercase">Footer Content</h5>
4949
<!-- Grid container -->
5050

5151
<!-- Copyright -->
52-
<div class="bottom-footer p-1 d-flex justify-content-center align-items-center text-white">
53-
<div class="content-container">
52+
<div class="bottom-footer p-1 d-flex flex-column flex-md-row justify-content-center align-items-center text-white">
53+
<div class="content-container align-self-center">
5454
<p class="m-0">
5555
<a class="text-white"
5656
href="http://www.dspace.org/" role="link" tabindex="0">{{ 'footer.link.dspace' | translate}}</a>
@@ -85,7 +85,7 @@ <h5 class="text-uppercase">Footer Content</h5>
8585
</ul>
8686
</div>
8787
@if (coarLdnEnabled$ | async) {
88-
<div class="notify-enabled text-white">
88+
<div class="notify-enabled text-white align-self-end">
8989
<a class="coar-notify-support-route" routerLink="info/coar-notify-support" role="link" tabindex="0">
9090
<img class="n-coar" src="assets/images/n-coar.svg" [attr.alt]="'menu.header.image.logo' | translate" />
9191
{{ 'footer.link.coar-notify-support' | translate }}
@@ -94,4 +94,4 @@ <h5 class="text-uppercase">Footer Content</h5>
9494
}
9595
</div>
9696
<!-- Copyright -->
97-
</footer>
97+
</footer>

src/app/footer/footer.component.scss

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@
2323

2424
.bottom-footer {
2525
.notify-enabled {
26-
position: absolute;
27-
bottom: 4px;
28-
right: 0;
26+
position: relative;
27+
margin-top: 4px;
2928

3029
.coar-notify-support-route {
3130
padding: 0 calc(var(--bs-spacer) / 2);
@@ -37,7 +36,11 @@
3736
margin-bottom: 8.5px;
3837
}
3938

40-
margin-top: 20px;
39+
@media screen and (min-width: map-get($grid-breakpoints, md)) {
40+
position: absolute;
41+
bottom: 4px;
42+
right: 0;
43+
}
4144
}
4245
ul {
4346
li {
Lines changed: 96 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,108 @@
11
<ds-metadata-field-wrapper [label]="label | translate">
22
<div *ngVar="(originals$ | async)?.payload as originals">
33
@if (hasValuesInBundle(originals)) {
4-
<div>
5-
<h3 class="h5 simple-view-element-header">{{"item.page.filesection.original.bundle" | translate}}</h3>
6-
@if (originals?.page?.length > 0) {
7-
<ds-pagination
8-
[hideGear]="true"
9-
[hidePagerWhenSinglePage]="true"
10-
[paginationOptions]="originalOptions"
11-
[collectionSize]="originals?.totalElements"
12-
[retainScrollPosition]="true">
13-
@for (file of originals?.page; track file) {
14-
<div class="file-section row mb-3">
15-
<div class="col-3">
16-
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
17-
</div>
18-
<div class="col-7">
19-
<dl class="row">
20-
<dt class="col-md-4">{{"item.page.filesection.name" | translate}}</dt>
21-
<dd class="col-md-8">{{ dsoNameService.getName(file) }}</dd>
22-
<dt class="col-md-4">{{"item.page.filesection.size" | translate}}</dt>
23-
<dd class="col-md-8">{{(file.sizeBytes) | dsFileSize }}</dd>
24-
<dt class="col-md-4">{{"item.page.filesection.format" | translate}}</dt>
25-
<dd class="col-md-8">{{(file.format | async)?.payload?.description}}</dd>
26-
@if (file.hasMetadata('dc.description')) {
27-
<dt class="col-md-4">{{"item.page.filesection.description" | translate}}</dt>
28-
<dd class="col-md-8">{{file.firstMetadataValue("dc.description")}}</dd>
29-
}
30-
</dl>
31-
</div>
32-
<div class="col-2">
33-
<ds-file-download-link [bitstream]="file" [item]="item">
34-
{{"item.page.filesection.download" | translate}}
35-
</ds-file-download-link>
36-
</div>
37-
</div>
38-
}
39-
</ds-pagination>
4+
<div>
5+
<h3 class="h5 simple-view-element-header">
6+
{{ "item.page.filesection.original.bundle" | translate }}
7+
</h3>
8+
@if (originals?.page?.length > 0) {
9+
<ds-pagination [hideGear]="true" [hidePagerWhenSinglePage]="true" [paginationOptions]="originalOptions"
10+
[collectionSize]="originals?.totalElements" [retainScrollPosition]="true">
11+
@for (file of originals?.page; track file) {
12+
<div class="file-section row mb-3">
13+
<div class="col-3">
14+
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
15+
</div>
16+
<div class="col-7">
17+
<dl class="row">
18+
<dt class="col-md-4">
19+
{{ "item.page.filesection.name" | translate }}
20+
</dt>
21+
<dd class="col-md-8">{{ dsoNameService.getName(file) }}</dd>
22+
<dt class="col-md-4">
23+
{{ "item.page.filesection.size" | translate }}
24+
</dt>
25+
<dd class="col-md-8">{{ file.sizeBytes | dsFileSize }}</dd>
26+
<dt class="col-md-4">
27+
{{ "item.page.filesection.format" | translate }}
28+
</dt>
29+
<dd class="col-md-8">
30+
{{ (file.format | async)?.payload?.description }}
31+
</dd>
32+
@if (file.hasMetadata('dc.description')) {
33+
<dt class="col-md-4">
34+
{{ "item.page.filesection.description" | translate }}
35+
</dt>
36+
<dd class="col-md-8">
37+
{{ file.firstMetadataValue("dc.description") }}
38+
</dd>
39+
}
40+
</dl>
41+
</div>
42+
<div class="col-2">
43+
<ds-file-download-link [showIcon]="true" [bitstream]="file" [item]="item" cssClasses="btn btn-outline-primary btn-download">
44+
<span class="d-none d-md-inline">
45+
{{ "item.page.filesection.download" | translate }}
46+
</span>
47+
</ds-file-download-link>
48+
</div>
49+
</div>
4050
}
41-
</div>
51+
</ds-pagination>
52+
}
53+
</div>
4254
}
4355
</div>
4456
<div *ngVar="(licenses$ | async)?.payload as licenses">
4557
@if (hasValuesInBundle(licenses)) {
46-
<div>
47-
<h3 class="h5 simple-view-element-header">{{"item.page.filesection.license.bundle" | translate}}</h3>
48-
@if (licenses?.page?.length > 0) {
49-
<ds-pagination
50-
[hideGear]="true"
51-
[hidePagerWhenSinglePage]="true"
52-
[paginationOptions]="licenseOptions"
53-
[collectionSize]="licenses?.totalElements"
54-
[retainScrollPosition]="true">
55-
@for (file of licenses?.page; track file) {
56-
<div class="file-section row">
57-
<div class="col-3">
58-
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
59-
</div>
60-
<div class="col-7">
61-
<dl class="row">
62-
<dt class="col-md-4">{{"item.page.filesection.name" | translate}}</dt>
63-
<dd class="col-md-8">{{ dsoNameService.getName(file) }}</dd>
64-
<dt class="col-md-4">{{"item.page.filesection.size" | translate}}</dt>
65-
<dd class="col-md-8">{{(file.sizeBytes) | dsFileSize }}</dd>
66-
<dt class="col-md-4">{{"item.page.filesection.format" | translate}}</dt>
67-
<dd class="col-md-8">{{(file.format | async)?.payload?.description}}</dd>
68-
<dt class="col-md-4">{{"item.page.filesection.description" | translate}}</dt>
69-
<dd class="col-md-8">{{file.firstMetadataValue("dc.description")}}</dd>
70-
</dl>
71-
</div>
72-
<div class="col-2">
73-
<ds-file-download-link [bitstream]="file" [item]="item">
74-
{{"item.page.filesection.download" | translate}}
75-
</ds-file-download-link>
76-
</div>
77-
</div>
78-
}
79-
</ds-pagination>
58+
<div>
59+
<h3 class="h5 simple-view-element-header">
60+
{{ "item.page.filesection.license.bundle" | translate }}
61+
</h3>
62+
@if (licenses?.page?.length > 0) {
63+
<ds-pagination [hideGear]="true" [hidePagerWhenSinglePage]="true" [paginationOptions]="licenseOptions"
64+
[collectionSize]="licenses?.totalElements" [retainScrollPosition]="true">
65+
@for (file of licenses?.page; track file) {
66+
<div class="file-section row">
67+
<div class="col-3">
68+
<ds-thumbnail [thumbnail]="(file.thumbnail | async)?.payload"></ds-thumbnail>
69+
</div>
70+
<div class="col-7">
71+
<dl class="row">
72+
<dt class="col-md-4">
73+
{{ "item.page.filesection.name" | translate }}
74+
</dt>
75+
<dd class="col-md-8">{{ dsoNameService.getName(file) }}</dd>
76+
<dt class="col-md-4">
77+
{{ "item.page.filesection.size" | translate }}
78+
</dt>
79+
<dd class="col-md-8">{{ file.sizeBytes | dsFileSize }}</dd>
80+
<dt class="col-md-4">
81+
{{ "item.page.filesection.format" | translate }}
82+
</dt>
83+
<dd class="col-md-8">
84+
{{ (file.format | async)?.payload?.description }}
85+
</dd>
86+
<dt class="col-md-4">
87+
{{ "item.page.filesection.description" | translate }}
88+
</dt>
89+
<dd class="col-md-8">
90+
{{ file.firstMetadataValue("dc.description") }}
91+
</dd>
92+
</dl>
93+
</div>
94+
<div class="col-2">
95+
<ds-file-download-link [showIcon]="true" [bitstream]="file" [item]="item" cssClasses="btn btn-outline-primary btn-download">
96+
<span class="d-none d-md-inline">
97+
{{ "item.page.filesection.download" | translate }}
98+
</span>
99+
</ds-file-download-link>
100+
</div>
101+
</div>
80102
}
81-
</div>
103+
</ds-pagination>
104+
}
105+
</div>
82106
}
83107
</div>
84108
</ds-metadata-field-wrapper>

src/app/shared/file-download-link/file-download-link.component.html

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,29 @@
55
[queryParams]="(bitstreamPath$| async)?.queryParams"
66
[target]="isBlank ? '_blank': '_self'"
77
[ngClass]="cssClasses"
8-
[attr.aria-label]="('file-download-link.download' | translate) + dsoNameService.getName(bitstream)"
8+
[attr.aria-label]="getDownloadLinkTitle(canDownload$ | async, canDownloadWithToken$ | async, dsoNameService.getName(bitstream))"
9+
[title]="getDownloadLinkTitle(canDownload$ | async, canDownloadWithToken$ | async, dsoNameService.getName(bitstream))"
910
role="link"
1011
tabindex="0">
1112
@if ((canDownload$ | async) === false && (canDownloadWithToken$ | async) === false) {
1213
<!-- If the user cannot download the file by auth or token, show a lock icon -->
13-
<span role="img" [attr.aria-label]="'file-download-link.restricted' | translate" class="pr-1"><i class="fas fa-lock"></i></span>
14+
<span role="img"
15+
[attr.aria-label]="'file-download-link.restricted' | translate"
16+
[title]="'file-download-link.restricted' | translate"
17+
class="pr-1">
18+
<i class="fas fa-lock"></i>
19+
</span>
1420
} @else if ((canDownloadWithToken$ | async) && (canDownload$ | async) === false) {
1521
<!-- If the user can download the file by token, and NOT normally show a lock open icon -->
16-
<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>
22+
<span role="img"
23+
[attr.aria-label]="'file-download-link.secure-access' | translate"
24+
[title]="'file-download-link.secure-access' | translate"
25+
class="pr-1 request-a-copy-access-icon">
26+
<i class="fa-solid fa-lock-open"></i>
27+
</span>
28+
} @else if (showIcon) {
29+
<i class="fas fa-download d-inline"></i>
1730
}
18-
<!-- Otherwise, show no icon (normal download by authorized user), public access etc. -->
1931
<ng-container *ngTemplateOutlet="content"></ng-container>
2032
</a>
2133

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
.request-a-copy-access-icon {
22
color: var(--bs-success);
33
}
4+
5+
.btn-download{
6+
width: fit-content;
7+
}

src/app/shared/file-download-link/file-download-link.component.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import {
1212
ActivatedRoute,
1313
RouterLink,
1414
} from '@angular/router';
15-
import { TranslateModule } from '@ngx-translate/core';
15+
import {
16+
TranslateModule,
17+
TranslateService,
18+
} from '@ngx-translate/core';
1619
import {
1720
combineLatest as observableCombineLatest,
1821
Observable,
@@ -75,6 +78,11 @@ export class FileDownloadLinkComponent implements OnInit {
7578
*/
7679
@Input() showAccessStatusBadge = true;
7780

81+
/**
82+
* A boolean indicating whether the download icon should be displayed.
83+
*/
84+
@Input() showIcon = false;
85+
7886
itemRequest: ItemRequest;
7987

8088
bitstreamPath$: Observable<{
@@ -90,6 +98,7 @@ export class FileDownloadLinkComponent implements OnInit {
9098
private authorizationService: AuthorizationDataService,
9199
public dsoNameService: DSONameService,
92100
private route: ActivatedRoute,
101+
private translateService: TranslateService,
93102
) {
94103
}
95104

@@ -153,4 +162,9 @@ export class FileDownloadLinkComponent implements OnInit {
153162
queryParams: {},
154163
};
155164
}
165+
166+
getDownloadLinkTitle(canDownload: boolean,canDownloadWithToken: boolean, bitstreamName: string): string {
167+
return (canDownload || canDownloadWithToken ? this.translateService.instant('file-download-link.download') :
168+
this.translateService.instant('file-download-link.request-copy')) + bitstreamName;
169+
}
156170
}

src/app/shared/file-download-link/themed-file-download-link.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,16 @@ export class ThemedFileDownloadLinkComponent extends ThemedComponent<FileDownloa
2929

3030
@Input() showAccessStatusBadge: boolean;
3131

32+
@Input() showIcon = false;
33+
3234
protected inAndOutputNames: (keyof FileDownloadLinkComponent & keyof this)[] = [
3335
'bitstream',
3436
'item',
3537
'cssClasses',
3638
'isBlank',
3739
'enableRequestACopy',
3840
'showAccessStatusBadge',
41+
'showIcon',
3942
];
4043

4144
protected getComponentName(): string {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@if (showAccessStatus) {
22
@if ({ status: accessStatus$ | async, date: embargoDate$ | async }; as accessStatus) {
3-
<span [class]="'badge bg-secondary access-status-list-element-badge ' + accessStatusClass">{{ accessStatus.status | translate: {date: accessStatus.date} }}</span>
3+
<span [class]="'badge bg-secondary dont-break-out access-status-list-element-badge ' + accessStatusClass">{{ accessStatus.status | translate: {date: accessStatus.date} }}</span>
44
}
55
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
1+
span{
2+
white-space: normal;
3+
}
Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
<div class="thumbnail" [class.limit-width]="limitWidth">
22
@if (isLoading) {
3-
<div class="thumbnail-content outer">
4-
<div class="inner">
5-
<div class="centered">
6-
<ds-loading [spinner]="true"></ds-loading>
7-
</div>
3+
<div class="thumbnail-content outer">
4+
<div class="inner">
5+
<div class="centered">
6+
<ds-loading [spinner]="true"></ds-loading>
87
</div>
98
</div>
9+
</div>
1010
}
1111
<!-- don't use *ngIf="!isLoading" so the thumbnail can load in while the animation is playing -->
1212
@if (src !== null) {
13-
<img class="thumbnail-content img-fluid" [ngClass]="{'d-none': isLoading}"
14-
[src]="src | dsSafeUrl" [alt]="alt | translate" (error)="errorHandler()" (load)="successHandler()">
15-
}
16-
@if (src === null && !isLoading) {
17-
<div class="thumbnail-content outer">
18-
<div class="inner">
19-
<div class="thumbnail-placeholder centered lead">
20-
{{ placeholder | translate }}
21-
</div>
13+
<img
14+
class="thumbnail-content img-fluid"
15+
[ngClass]="{ 'd-none': isLoading }"
16+
[src]="src | dsSafeUrl"
17+
[alt]="alt | translate"
18+
(error)="errorHandler()"
19+
(load)="successHandler()"
20+
/>
21+
} @if (src === null && !isLoading) {
22+
<div class="thumbnail-content outer">
23+
<div class="inner">
24+
<div class="thumbnail-placeholder centered">
25+
{{ placeholder | translate }}
2226
</div>
2327
</div>
28+
</div>
2429
}
2530
</div>

0 commit comments

Comments
 (0)