Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,10 @@ mediaViewer:
image: false
video: false

# Whether to enable the PDF viewer for Bitstreams (i.e. Bitstreams whose MIME type starts with 'application/pdf').
pdfViewer:
enabled: true

# Whether the end user agreement is required before users use the repository.
# If enabled, the user will be required to accept the agreement before they can use the repository.
# And whether the privacy statement/COAR notify support page should exist or not.
Expand Down
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
"morgan": "^1.10.1",
"ng2-file-upload": "9.0.0",
"ng2-nouislider": "^2.0.0",
"ngx-extended-pdf-viewer": "^25.6.4",
"ngx-infinite-scroll": "^20.0.0",
"ngx-matomo-client": "^8.0.0",
"ngx-pagination": "6.0.3",
Expand Down
7 changes: 7 additions & 0 deletions src/app/app-routes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {

Check failure on line 1 in src/app/app-routes.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Run autofix to sort these imports!

Check failure on line 1 in src/app/app-routes.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Run autofix to sort these imports!
InMemoryScrollingOptions,
Route,
RouterConfigOptions,
Expand Down Expand Up @@ -36,6 +36,7 @@
WORKFLOW_ITEM_MODULE_PATH,
} from './app-routing-paths';
import { notAuthenticatedGuard } from './core/auth/not-authenticated.guard';
import { PDF_VIEWER_MODULE_PATH } from './pdf-viewer/pdf-viewer-routing-paths';
import { ThemedForbiddenComponent } from './forbidden/themed-forbidden.component';
import { homePageResolver } from './home-page/home-page.resolver';
import { provideSuggestionNotificationsState } from './notifications/provide-suggestion-notifications-state';
Expand Down Expand Up @@ -144,6 +145,12 @@
.then((m) => m.ROUTES),
canActivate: [endUserAgreementCurrentUserGuard],
},
{
path: PDF_VIEWER_MODULE_PATH,
loadChildren: () => import('./pdf-viewer/pdf-viewer.routes')
.then((m) => m.ROUTES),
canActivate: [endUserAgreementCurrentUserGuard],
},
{
path: 'mydspace',
loadChildren: () => import('./my-dspace-page/my-dspace-page-routes')
Expand Down
6 changes: 6 additions & 0 deletions src/app/app.reducer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { hasValue } from '@dspace/shared/utils/empty.util';

Check failure on line 1 in src/app/app.reducer.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Run autofix to sort these imports!

Check failure on line 1 in src/app/app.reducer.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Run autofix to sort these imports!
import {
routerReducer,
RouterReducerState,
Expand Down Expand Up @@ -43,6 +43,10 @@
} from './shared/form/form.reducer';
import { menusReducer } from './shared/menu/menu.reducer';
import { MenusState } from './shared/menu/menus-state.model';
import {
pdfViewerFullscreenReducer,
PdfViewerFullscreenState,
} from './shared/pdf-viewer-fullscreen/pdf-viewer-fullscreen.reducer';
import {
selectableListReducer,
SelectableListsState,
Expand Down Expand Up @@ -95,6 +99,7 @@
groupRegistry: GroupRegistryState;
contextHelp: ContextHelpState;
bitstreamFormats: BitstreamFormatRegistryState;
pdfViewerFullscreen: PdfViewerFullscreenState;
}

export const appReducers: ActionReducerMap<AppState> = {
Expand All @@ -116,6 +121,7 @@
groupRegistry: groupRegistryReducer,
contextHelp: contextHelpReducer,
bitstreamFormats: bitstreamFormatReducer,
pdfViewerFullscreen: pdfViewerFullscreenReducer,
};

export const routerStateSelector = (state: AppState) => state.router;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ <h1 class="h2 dont-break-out">{{dsoNameService.getName(bitstreamRD?.payload)}} <
<div additional class="container py-3">
<a [routerLink]="['/bitstreams', bitstreamRD?.payload?.id, 'authorizations']">{{'bitstream.edit.authorizations.link' | translate}}</a>
</div>
<div additional class="container mt-2">
<ds-pdf-viewer-enable [dso]="bitstreamRD?.payload"
(onChange)="updateViewerEnabled($event)"></ds-pdf-viewer-enable>
</div>
</ds-form>
}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncPipe } from '@angular/common';

Check failure on line 1 in src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Run autofix to sort these imports!

Check failure on line 1 in src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Run autofix to sort these imports!
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Expand Down Expand Up @@ -76,14 +76,16 @@
import { FileSizePipe } from '../../shared/utils/file-size-pipe';
import { VarDirective } from '../../shared/utils/var.directive';
import { ThemedThumbnailComponent } from '../../thumbnail/themed-thumbnail.component';
import { PdfViewerEnableComponent } from '../../pdf-viewer/pdf-viewer-enable/pdf-viewer-enable.component';

@Component({
selector: 'ds-base-edit-bitstream-page',
styleUrls: ['./edit-bitstream-page.component.scss'],
templateUrl: './edit-bitstream-page.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [

Check failure on line 86 in src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Standalone imports should be sorted alphabetically

Check failure on line 86 in src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Standalone imports should be sorted alphabetically
AsyncPipe,
PdfViewerEnableComponent,
ErrorComponent,
FileSizePipe,
FormComponent,
Expand All @@ -93,6 +95,7 @@
TranslateModule,
VarDirective,
],
standalone: true,

Check failure on line 98 in src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Unnecessary explicit standalone declaration of the @component decorator should be removed

Check failure on line 98 in src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Unnecessary explicit standalone declaration of the @component decorator should be removed
})
/**
* Page component for editing a bitstream
Expand All @@ -115,6 +118,11 @@
*/
bitstream: Bitstream;

/**
* Whether the PDF viewer is enabled for this bitstream
*/
viewerEnabled: string;

/**
* The originally selected format
*/
Expand Down Expand Up @@ -445,16 +453,16 @@
*/
private selectedFormat: BitstreamFormat;

constructor(private route: ActivatedRoute,
private router: Router,
private changeDetectorRef: ChangeDetectorRef,
private formService: DynamicFormService,
private translate: TranslateService,
private bitstreamService: BitstreamDataService,
public dsoNameService: DSONameService,
private notificationsService: NotificationsService,
private bitstreamFormatService: BitstreamFormatDataService,
private primaryBitstreamService: PrimaryBitstreamService,
constructor(protected route: ActivatedRoute,
protected router: Router,
protected changeDetectorRef: ChangeDetectorRef,
protected formService: DynamicFormService,
protected translate: TranslateService,
protected bitstreamService: BitstreamDataService,
protected dsoNameService: DSONameService,
protected notificationsService: NotificationsService,
protected bitstreamFormatService: BitstreamFormatDataService,
protected primaryBitstreamService: PrimaryBitstreamService,
) {
}

Expand Down Expand Up @@ -733,6 +741,9 @@
} else {
Metadata.setFirstValue(newMetadata, 'dc.description', rawForm.descriptionContainer.description);
}
if (hasValue(this.viewerEnabled)) {
Metadata.setFirstValue(newMetadata, 'dspace.pdfviewer.enabled', this.viewerEnabled);
}
if (this.isIIIF) {
// It's helpful to remove these metadata elements entirely when the form value is empty.
// This avoids potential issues on the REST side and makes it possible to do things like
Expand Down Expand Up @@ -777,6 +788,10 @@
* When the item ID is present, navigate back to the item's edit bitstreams page,
* otherwise retrieve the item ID based on the owning bundle's link
*/
updateViewerEnabled(viewerEnabled: string) {
this.viewerEnabled = viewerEnabled;
}

navigateToItemEditBitstreams() {
this.router.navigate([getEntityEditRoute(this.entityType, this.itemId), 'bitstreams']);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Route } from '@angular/router';

Check failure on line 1 in src/app/collection-page/edit-collection-page/edit-collection-page-routes.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Run autofix to sort these imports!

Check failure on line 1 in src/app/collection-page/edit-collection-page/edit-collection-page-routes.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Run autofix to sort these imports!
import { i18nBreadcrumbResolver } from '@dspace/core/breadcrumbs/i18n-breadcrumb.resolver';
import { collectionAdministratorGuard } from '@dspace/core/data/feature-authorization/feature-authorization-guard/collection-administrator.guard';

import { PdfViewerEnableDsoComponent } from '../../pdf-viewer/pdf-viewer-enable-dso/pdf-viewer-enable-dso.component';
import { ResourcePolicyCreateComponent } from '../../shared/resource-policies/create/resource-policy-create.component';
import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit/resource-policy-edit.component';
import { resourcePolicyResolver } from '../../shared/resource-policies/resolvers/resource-policy.resolver';
Expand Down Expand Up @@ -95,6 +95,16 @@
component: CollectionItemMapperComponent,
data: { title: 'collection.edit.tabs.item-mapper.title', hideReturnButton: true, showBreadcrumbs: true },
},
{
path: 'pdf-viewer',
component: PdfViewerEnableDsoComponent,
data: {
title: 'collection.edit.tabs.pdf-viewer.title',
showBreadcrumbs: true,
hideReturnButton: true,
buttonStyle: 'comcol',
},
},
],
},
];
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Route } from '@angular/router';

Check failure on line 1 in src/app/community-page/edit-community-page/edit-community-page-routes.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Run autofix to sort these imports!

Check failure on line 1 in src/app/community-page/edit-community-page/edit-community-page-routes.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Run autofix to sort these imports!
import { i18nBreadcrumbResolver } from '@dspace/core/breadcrumbs/i18n-breadcrumb.resolver';
import { communityAdministratorGuard } from '@dspace/core/data/feature-authorization/feature-authorization-guard/community-administrator.guard';

import { PdfViewerEnableDsoComponent } from '../../pdf-viewer/pdf-viewer-enable-dso/pdf-viewer-enable-dso.component';
import { ResourcePolicyCreateComponent } from '../../shared/resource-policies/create/resource-policy-create.component';
import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit/resource-policy-edit.component';
import { resourcePolicyResolver } from '../../shared/resource-policies/resolvers/resource-policy.resolver';
Expand Down Expand Up @@ -83,6 +83,16 @@
},
],
},
{
path: 'pdf-viewer',
component: PdfViewerEnableDsoComponent,
data: {
title: 'community.edit.tabs.pdf-viewer.title',
showBreadcrumbs: true,
hideReturnButton: true,
buttonStyle: 'comcol',
},
},
],
},
];
2 changes: 1 addition & 1 deletion src/app/core/shared/bitstream.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,6 @@ export class Bitstream extends DSpaceObject implements ChildHALResource {
accessStatus?: Observable<RemoteData<AccessStatusObject>>;

getParentLinkKey(): keyof this['_links'] {
return 'format';
return 'bundle';
}
}
7 changes: 6 additions & 1 deletion src/app/core/shared/bundle.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {

Check failure on line 1 in src/app/core/shared/bundle.model.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Run autofix to sort these imports!

Check failure on line 1 in src/app/core/shared/bundle.model.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Run autofix to sort these imports!
deserialize,
inheritSerialization,
} from 'cerialize';
Expand All @@ -17,10 +17,11 @@
import { HALLink } from './hal-link.model';
import { Item } from './item.model';
import { ITEM } from './item.resource-type';
import { ChildHALResource } from './child-hal-resource.model';

@typedObject
@inheritSerialization(DSpaceObject)
export class Bundle extends DSpaceObject {
export class Bundle extends DSpaceObject implements ChildHALResource {
static type = BUNDLE;

/**
Expand Down Expand Up @@ -54,4 +55,8 @@
*/
@link(ITEM)
item?: Observable<RemoteData<Item>>;

getParentLinkKey(): keyof this['_links'] {
return 'item';
}
}
12 changes: 11 additions & 1 deletion src/app/item-page/edit-item-page/edit-item-page-routes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Route } from '@angular/router';

Check failure on line 1 in src/app/item-page/edit-item-page/edit-item-page-routes.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Run autofix to sort these imports!

Check failure on line 1 in src/app/item-page/edit-item-page/edit-item-page-routes.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Run autofix to sort these imports!
import { i18nBreadcrumbResolver } from '@dspace/core/breadcrumbs/i18n-breadcrumb.resolver';

import { PdfViewerEnableDsoComponent } from '../../pdf-viewer/pdf-viewer-enable-dso/pdf-viewer-enable-dso.component';
import { ThemedDsoEditMetadataComponent } from '../../dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component';
import { ResourcePolicyCreateComponent } from '../../shared/resource-policies/create/resource-policy-create.component';
import { ResourcePolicyEditComponent } from '../../shared/resource-policies/edit/resource-policy-edit.component';
Expand Down Expand Up @@ -129,6 +129,16 @@
data: { title: 'item.edit.tabs.item-mapper.title', showBreadcrumbs: true },
canActivate: [itemPageCollectionMapperGuard],
},
{
path: 'pdf-viewer',
component: PdfViewerEnableDsoComponent,
data: {
title: 'item.edit.tabs.pdf-viewer.title',
showBreadcrumbs: true,
hideReturnButton: true,
buttonStyle: 'item',
},
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { inject } from '@angular/core';

Check failure on line 1 in src/app/pdf-viewer/breadcrumbs/pdf-viewer-page-breadcrumb.resolver.ts

View workflow job for this annotation

GitHub Actions / tests (22.x)

Run autofix to sort these imports!

Check failure on line 1 in src/app/pdf-viewer/breadcrumbs/pdf-viewer-page-breadcrumb.resolver.ts

View workflow job for this annotation

GitHub Actions / tests (20.x)

Run autofix to sort these imports!
import {
ActivatedRouteSnapshot,
ResolveFn,
RouterStateSnapshot,
} from '@angular/router';
import { Observable } from 'rxjs';

import { BreadcrumbConfig } from '../../core/breadcrumbs/models/breadcrumb-config.model';
import { DSOBreadcrumbResolver } from '../../core/breadcrumbs/dso-breadcrumb.resolver';
import { BitstreamDataService } from '../../core/data/bitstream-data.service';
import { Bitstream } from '../../core/shared/bitstream.model';
import { DSpaceObject } from '../../core/shared/dspace-object.model';
import {
followLink,
FollowLinkConfig,
} from '../../core/shared/follow-link-config.model';
import { PdfViewerPageBreadcrumbsService } from './pdf-viewer-page-breadcrumbs.service';

export const BITSTREAM_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig<Bitstream>[] =
[
followLink('bundle', {},
followLink('item', {},
followLink('owningCollection', {},
followLink('parentCommunity', {},
followLink('parentCommunity'))))),
followLink('format'),
];

export const pdfViewerPageBreadcrumbResolver: ResolveFn<BreadcrumbConfig<Bitstream>> = (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
breadcrumbService = inject(PdfViewerPageBreadcrumbsService),
dataService = inject(BitstreamDataService),
): Observable<BreadcrumbConfig<Bitstream>> => {
const linksToFollow: FollowLinkConfig<DSpaceObject>[] = BITSTREAM_PAGE_LINKS_TO_FOLLOW as FollowLinkConfig<DSpaceObject>[];
return DSOBreadcrumbResolver(route, state, breadcrumbService, dataService, ...linksToFollow) as Observable<BreadcrumbConfig<Bitstream>>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Injectable } from '@angular/core';
import {
Observable,
of,
} from 'rxjs';
import {
find,
map,
switchMap,
} from 'rxjs/operators';

import { getDSORoute } from '../../core/router/utils/dso-route.utils';
import { Breadcrumb } from '../../core/breadcrumbs/models/breadcrumb.model';
import { DSOBreadcrumbsService } from '../../core/breadcrumbs/dso-breadcrumbs.service';
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
import { LinkService } from '../../core/cache/builders/link.service';
import { RemoteData } from '../../core/data/remote-data';
import { BITSTREAM } from '../../core/shared/bitstream.resource-type';
import { BUNDLE } from '../../core/shared/bundle.resource-type';
import { ChildHALResource } from '../../core/shared/child-hal-resource.model';
import { DSpaceObject } from '../../core/shared/dspace-object.model';
import { hasValue } from '@dspace/shared/utils/empty.util';
import { followLink } from '../../core/shared/follow-link-config.model';

@Injectable({
providedIn: 'root',
})
export class PdfViewerPageBreadcrumbsService extends DSOBreadcrumbsService {
pdfViewerBreadcrumb = new Breadcrumb('pdf-viewer.breadcrumb.pdf-viewer');
constructor(
protected linkService: LinkService,
protected dsoNameService: DSONameService,
) {
super(linkService, dsoNameService);
}

getBreadcrumbs(key: ChildHALResource & DSpaceObject, url: string): Observable<Breadcrumb[]> {
let breadcrumb;
if (key.type.toString() === BITSTREAM.value) {
breadcrumb = this.pdfViewerBreadcrumb;
} else if (key.type.toString() !== BUNDLE.value) {
return super.getBreadcrumbs(key, url);
}
const propertyName = key.getParentLinkKey();
return this.linkService.resolveLink(key, followLink(propertyName))[propertyName].pipe(
find((parentRD: RemoteData<ChildHALResource & DSpaceObject>) => parentRD.hasSucceeded || parentRD.statusCode === 204),
switchMap((parentRD: RemoteData<ChildHALResource & DSpaceObject>) => {
if (hasValue(parentRD.payload)) {
return this.getBreadcrumbs(parentRD.payload, getDSORoute(parentRD.payload));
}
return of([]);
}),
map((breadcrumbs: Breadcrumb[]) => hasValue(breadcrumb) ? [...breadcrumbs, breadcrumb] : breadcrumbs),
);
}
}
Loading
Loading