mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge remote-tracking branch 'remotes/origin/main' into authorities_and_controlled_vocabularies
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
# This workflow runs whenever a new pull request is created
|
# This workflow runs whenever a new pull request is created
|
||||||
|
# TEMPORARILY DISABLED. Unfortunately this doesn't work for PRs created from forked repositories (which is how we tend to create PRs).
|
||||||
|
# There is no known workaround yet. See https://github.community/t/how-to-use-github-token-for-prs-from-forks/16818
|
||||||
name: Pull Request opened
|
name: Pull Request opened
|
||||||
|
|
||||||
# Only run for newly opened PRs against the "main" branch
|
# Only run for newly opened PRs against the "main" branch
|
@@ -1,24 +1,26 @@
|
|||||||
import {Component, Input, OnInit} from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import {filter, first, map, switchMap, take} from 'rxjs/operators';
|
import { defaultIfEmpty, filter, first, map, switchMap, take } from 'rxjs/operators';
|
||||||
import {AbstractSimpleItemActionComponent} from '../simple-item-action/abstract-simple-item-action.component';
|
import { AbstractSimpleItemActionComponent } from '../simple-item-action/abstract-simple-item-action.component';
|
||||||
import {getItemEditPath} from '../../item-page-routing.module';
|
import { getItemEditPath } from '../../item-page-routing.module';
|
||||||
import {NgbModal, NgbModalRef} from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import {combineLatest as observableCombineLatest, combineLatest, Observable} from 'rxjs';
|
import { combineLatest as observableCombineLatest, combineLatest, Observable, of as observableOf } from 'rxjs';
|
||||||
import {RelationshipType} from '../../../core/shared/item-relationships/relationship-type.model';
|
import { RelationshipType } from '../../../core/shared/item-relationships/relationship-type.model';
|
||||||
import {VirtualMetadata} from '../virtual-metadata/virtual-metadata.component';
|
import { VirtualMetadata } from '../virtual-metadata/virtual-metadata.component';
|
||||||
import {Relationship} from '../../../core/shared/item-relationships/relationship.model';
|
import { Relationship } from '../../../core/shared/item-relationships/relationship.model';
|
||||||
import {getRemoteDataPayload, getSucceededRemoteData} from '../../../core/shared/operators';
|
import { getRemoteDataPayload, getSucceededRemoteData } from '../../../core/shared/operators';
|
||||||
import {hasValue, isNotEmpty} from '../../../shared/empty.util';
|
import { hasValue, isNotEmpty } from '../../../shared/empty.util';
|
||||||
import {Item} from '../../../core/shared/item.model';
|
import { Item } from '../../../core/shared/item.model';
|
||||||
import {MetadataValue} from '../../../core/shared/metadata.models';
|
import { MetadataValue } from '../../../core/shared/metadata.models';
|
||||||
import {ViewMode} from '../../../core/shared/view-mode.model';
|
import { ViewMode } from '../../../core/shared/view-mode.model';
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import {NotificationsService} from '../../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||||
import {ItemDataService} from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
import {TranslateService} from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import {ObjectUpdatesService} from '../../../core/data/object-updates/object-updates.service';
|
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
||||||
import {RelationshipService} from '../../../core/data/relationship.service';
|
import { RelationshipService } from '../../../core/data/relationship.service';
|
||||||
import {EntityTypeService} from '../../../core/data/entity-type.service';
|
import { EntityTypeService } from '../../../core/data/entity-type.service';
|
||||||
|
import { LinkService } from '../../../core/cache/builders/link.service';
|
||||||
|
import { followLink } from '../../../shared/utils/follow-link-config.model';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-item-delete',
|
selector: 'ds-item-delete',
|
||||||
@@ -80,6 +82,7 @@ export class ItemDeleteComponent
|
|||||||
protected objectUpdatesService: ObjectUpdatesService,
|
protected objectUpdatesService: ObjectUpdatesService,
|
||||||
protected relationshipService: RelationshipService,
|
protected relationshipService: RelationshipService,
|
||||||
protected entityTypeService: EntityTypeService,
|
protected entityTypeService: EntityTypeService,
|
||||||
|
protected linkService: LinkService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
route,
|
route,
|
||||||
@@ -98,30 +101,33 @@ export class ItemDeleteComponent
|
|||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
this.url = this.router.url;
|
this.url = this.router.url;
|
||||||
|
|
||||||
this.types$ = this.entityTypeService.getEntityTypeByLabel(
|
const label = this.item.firstMetadataValue('relationship.type');
|
||||||
this.item.firstMetadataValue('relationship.type')
|
if (label !== undefined) {
|
||||||
).pipe(
|
this.types$ = this.entityTypeService.getEntityTypeByLabel(label).pipe(
|
||||||
getSucceededRemoteData(),
|
getSucceededRemoteData(),
|
||||||
getRemoteDataPayload(),
|
getRemoteDataPayload(),
|
||||||
switchMap((entityType) => this.entityTypeService.getEntityTypeRelationships(entityType.id)),
|
switchMap((entityType) => this.entityTypeService.getEntityTypeRelationships(entityType.id)),
|
||||||
getSucceededRemoteData(),
|
getSucceededRemoteData(),
|
||||||
getRemoteDataPayload(),
|
getRemoteDataPayload(),
|
||||||
map((relationshipTypes) => relationshipTypes.page),
|
map((relationshipTypes) => relationshipTypes.page),
|
||||||
switchMap((types) =>
|
switchMap((types) =>
|
||||||
combineLatest(types.map((type) => this.getRelationships(type))).pipe(
|
combineLatest(types.map((type) => this.getRelationships(type))).pipe(
|
||||||
map((relationships) =>
|
map((relationships) =>
|
||||||
types.reduce<RelationshipType[]>((includedTypes, type, index) => {
|
types.reduce<RelationshipType[]>((includedTypes, type, index) => {
|
||||||
if (!includedTypes.some((includedType) => includedType.id === type.id)
|
if (!includedTypes.some((includedType) => includedType.id === type.id)
|
||||||
&& !(relationships[index].length === 0)) {
|
&& !(relationships[index].length === 0)) {
|
||||||
return [...includedTypes, type];
|
return [...includedTypes, type];
|
||||||
} else {
|
} else {
|
||||||
return includedTypes;
|
return includedTypes;
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
this.types$ = observableOf([]);
|
||||||
|
}
|
||||||
|
|
||||||
this.types$.pipe(
|
this.types$.pipe(
|
||||||
take(1),
|
take(1),
|
||||||
@@ -187,6 +193,7 @@ export class ItemDeleteComponent
|
|||||||
observableCombineLatest(
|
observableCombineLatest(
|
||||||
relationships.map((relationship) => this.getRelationshipType(relationship))
|
relationships.map((relationship) => this.getRelationshipType(relationship))
|
||||||
).pipe(
|
).pipe(
|
||||||
|
defaultIfEmpty([]),
|
||||||
map((types) => relationships.filter(
|
map((types) => relationships.filter(
|
||||||
(relationship, index) => relationshipType.id === types[index].id
|
(relationship, index) => relationshipType.id === types[index].id
|
||||||
)),
|
)),
|
||||||
@@ -205,6 +212,12 @@ export class ItemDeleteComponent
|
|||||||
*/
|
*/
|
||||||
private getRelationshipType(relationship: Relationship): Observable<RelationshipType> {
|
private getRelationshipType(relationship: Relationship): Observable<RelationshipType> {
|
||||||
|
|
||||||
|
this.linkService.resolveLinks(
|
||||||
|
relationship,
|
||||||
|
followLink('relationshipType'),
|
||||||
|
followLink('leftItem'),
|
||||||
|
followLink('rightItem'),
|
||||||
|
);
|
||||||
return relationship.relationshipType.pipe(
|
return relationship.relationshipType.pipe(
|
||||||
getSucceededRemoteData(),
|
getSucceededRemoteData(),
|
||||||
getRemoteDataPayload(),
|
getRemoteDataPayload(),
|
||||||
@@ -305,6 +318,7 @@ export class ItemDeleteComponent
|
|||||||
combineLatest(
|
combineLatest(
|
||||||
types.map((type) => this.isSelected(type))
|
types.map((type) => this.isSelected(type))
|
||||||
).pipe(
|
).pipe(
|
||||||
|
defaultIfEmpty([]),
|
||||||
map((selection) => types.filter(
|
map((selection) => types.filter(
|
||||||
(type, index) => selection[index]
|
(type, index) => selection[index]
|
||||||
)),
|
)),
|
||||||
|
@@ -1,48 +1,56 @@
|
|||||||
<div class="item-relationships">
|
<div class="item-relationships">
|
||||||
<div class="button-row top d-flex">
|
<ng-container *ngVar="entityType$ | async as entityType">
|
||||||
<button class="btn btn-danger ml-auto" *ngIf="!(isReinstatable() | async)"
|
<ng-container *ngIf="entityType">
|
||||||
[disabled]="!(hasChanges() | async)"
|
<div class="button-row top d-flex">
|
||||||
(click)="discard()"><i
|
<button class="btn btn-danger ml-auto" *ngIf="!(isReinstatable() | async)"
|
||||||
class="fas fa-times"></i>
|
[disabled]="!(hasChanges() | async)"
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
(click)="discard()"><i
|
||||||
</button>
|
class="fas fa-times"></i>
|
||||||
<button class="btn btn-warning ml-auto" *ngIf="isReinstatable() | async"
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
||||||
(click)="reinstate()"><i
|
</button>
|
||||||
class="fas fa-undo-alt"></i>
|
<button class="btn btn-warning ml-auto" *ngIf="isReinstatable() | async"
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
(click)="reinstate()"><i
|
||||||
</button>
|
class="fas fa-undo-alt"></i>
|
||||||
<button class="btn btn-primary" [disabled]="!(hasChanges() | async)"
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
||||||
(click)="submit()"><i
|
</button>
|
||||||
class="fas fa-save"></i>
|
<button class="btn btn-primary" [disabled]="!(hasChanges() | async)"
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
(click)="submit()"><i
|
||||||
</button>
|
class="fas fa-save"></i>
|
||||||
</div>
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
||||||
<div *ngFor="let relationshipType of relationshipTypes$ | async" class="mb-4">
|
</button>
|
||||||
<ds-edit-relationship-list
|
</div>
|
||||||
[url]="url"
|
<div *ngFor="let relationshipType of relationshipTypes$ | async" class="mb-4">
|
||||||
[item]="item"
|
<ds-edit-relationship-list
|
||||||
[itemType]="entityType$ | async"
|
[url]="url"
|
||||||
[relationshipType]="relationshipType"
|
[item]="item"
|
||||||
></ds-edit-relationship-list>
|
[itemType]="entityType"
|
||||||
</div>
|
[relationshipType]="relationshipType"
|
||||||
<div class="button-row bottom">
|
></ds-edit-relationship-list>
|
||||||
<div class="float-right">
|
</div>
|
||||||
<button class="btn btn-danger" *ngIf="!(isReinstatable() | async)"
|
<div class="button-row bottom">
|
||||||
[disabled]="!(hasChanges() | async)"
|
<div class="float-right">
|
||||||
(click)="discard()"><i
|
<button class="btn btn-danger" *ngIf="!(isReinstatable() | async)"
|
||||||
class="fas fa-times"></i>
|
[disabled]="!(hasChanges() | async)"
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
(click)="discard()"><i
|
||||||
</button>
|
class="fas fa-times"></i>
|
||||||
<button class="btn btn-warning" *ngIf="isReinstatable() | async"
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
||||||
(click)="reinstate()"><i
|
</button>
|
||||||
class="fas fa-undo-alt"></i>
|
<button class="btn btn-warning" *ngIf="isReinstatable() | async"
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
(click)="reinstate()"><i
|
||||||
</button>
|
class="fas fa-undo-alt"></i>
|
||||||
<button class="btn btn-primary" [disabled]="!(hasChanges() | async)"
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
||||||
(click)="submit()"><i
|
</button>
|
||||||
class="fas fa-save"></i>
|
<button class="btn btn-primary" [disabled]="!(hasChanges() | async)"
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
(click)="submit()"><i
|
||||||
</button>
|
class="fas fa-save"></i>
|
||||||
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
<div *ngIf="!entityType"
|
||||||
|
class="alert alert-info mt-2" role="alert">
|
||||||
|
{{ 'item.edit.relationships.no-entity-type' | translate }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -3,7 +3,7 @@ import { Item } from '../../../core/shared/item.model';
|
|||||||
import { DeleteRelationship, FieldUpdate, FieldUpdates } from '../../../core/data/object-updates/object-updates.reducer';
|
import { DeleteRelationship, FieldUpdate, FieldUpdates } from '../../../core/data/object-updates/object-updates.reducer';
|
||||||
import { Observable } from 'rxjs/internal/Observable';
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
import { filter, map, switchMap, take } from 'rxjs/operators';
|
import { filter, map, switchMap, take } from 'rxjs/operators';
|
||||||
import { zip as observableZip } from 'rxjs';
|
import { of as observableOf, zip as observableZip} from 'rxjs';
|
||||||
import { followLink } from '../../../shared/utils/follow-link-config.model';
|
import { followLink } from '../../../shared/utils/follow-link-config.model';
|
||||||
import { AbstractItemUpdateComponent } from '../abstract-item-update/abstract-item-update.component';
|
import { AbstractItemUpdateComponent } from '../abstract-item-update/abstract-item-update.component';
|
||||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
@@ -87,26 +87,30 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent impl
|
|||||||
*/
|
*/
|
||||||
public initializeUpdates(): void {
|
public initializeUpdates(): void {
|
||||||
|
|
||||||
this.entityType$ = this.entityTypeService.getEntityTypeByLabel(
|
const label = this.item.firstMetadataValue('relationship.type');
|
||||||
this.item.firstMetadataValue('relationship.type')
|
if (label !== undefined) {
|
||||||
).pipe(
|
|
||||||
getSucceededRemoteData(),
|
|
||||||
getRemoteDataPayload(),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.relationshipTypes$ = this.entityType$.pipe(
|
this.entityType$ = this.entityTypeService.getEntityTypeByLabel(label).pipe(
|
||||||
switchMap((entityType) =>
|
getSucceededRemoteData(),
|
||||||
this.entityTypeService.getEntityTypeRelationships(
|
getRemoteDataPayload(),
|
||||||
entityType.id,
|
);
|
||||||
followLink('leftType'),
|
|
||||||
followLink('rightType'))
|
this.relationshipTypes$ = this.entityType$.pipe(
|
||||||
.pipe(
|
switchMap((entityType) =>
|
||||||
getSucceededRemoteData(),
|
this.entityTypeService.getEntityTypeRelationships(
|
||||||
getRemoteDataPayload(),
|
entityType.id,
|
||||||
map((relationshipTypes) => relationshipTypes.page),
|
followLink('leftType'),
|
||||||
)
|
followLink('rightType'))
|
||||||
),
|
.pipe(
|
||||||
);
|
getSucceededRemoteData(),
|
||||||
|
getRemoteDataPayload(),
|
||||||
|
map((relationshipTypes) => relationshipTypes.page),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.entityType$ = observableOf(undefined);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -27,9 +27,6 @@ export class ServerAuthService extends AuthService {
|
|||||||
|
|
||||||
headers = headers.append('Accept', 'application/json');
|
headers = headers.append('Accept', 'application/json');
|
||||||
headers = headers.append('Authorization', `Bearer ${token.accessToken}`);
|
headers = headers.append('Authorization', `Bearer ${token.accessToken}`);
|
||||||
// NB this is used to pass server client IP check.
|
|
||||||
const clientIp = this.req.get('x-forwarded-for') || this.req.connection.remoteAddress;
|
|
||||||
headers = headers.append('X-Forwarded-For', clientIp);
|
|
||||||
|
|
||||||
options.headers = headers;
|
options.headers = headers;
|
||||||
return this.authRequestService.getRequest('status', options).pipe(
|
return this.authRequestService.getRequest('status', options).pipe(
|
||||||
|
@@ -0,0 +1,44 @@
|
|||||||
|
import { ForwardClientIpInterceptor } from './forward-client-ip.interceptor';
|
||||||
|
import { DSpaceRESTv2Service } from '../dspace-rest-v2/dspace-rest-v2.service';
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
|
||||||
|
import { HTTP_INTERCEPTORS, HttpRequest } from '@angular/common/http';
|
||||||
|
import { REQUEST } from '@nguniversal/express-engine/tokens';
|
||||||
|
|
||||||
|
describe('ForwardClientIpInterceptor', () => {
|
||||||
|
let service: DSpaceRESTv2Service;
|
||||||
|
let httpMock: HttpTestingController;
|
||||||
|
|
||||||
|
let requestUrl;
|
||||||
|
let clientIp;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
requestUrl = 'test-url';
|
||||||
|
clientIp = '1.2.3.4';
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [HttpClientTestingModule],
|
||||||
|
providers: [
|
||||||
|
DSpaceRESTv2Service,
|
||||||
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: ForwardClientIpInterceptor,
|
||||||
|
multi: true,
|
||||||
|
},
|
||||||
|
{ provide: REQUEST, useValue: { get: () => undefined, connection: { remoteAddress: clientIp } }}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
service = TestBed.get(DSpaceRESTv2Service);
|
||||||
|
httpMock = TestBed.get(HttpTestingController);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add an X-Forwarded-For header matching the client\'s IP', () => {
|
||||||
|
service.get(requestUrl).subscribe((response) => {
|
||||||
|
expect(response).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
const httpRequest = httpMock.expectOne(requestUrl);
|
||||||
|
expect(httpRequest.request.headers.get('X-Forwarded-For')).toEqual(clientIp);
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,23 @@
|
|||||||
|
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
||||||
|
import { Inject, Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
|
import { REQUEST } from '@nguniversal/express-engine/tokens';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
/**
|
||||||
|
* Http Interceptor intercepting Http Requests, adding the client's IP to their X-Forwarded-For header
|
||||||
|
*/
|
||||||
|
export class ForwardClientIpInterceptor implements HttpInterceptor {
|
||||||
|
constructor(@Inject(REQUEST) protected req: any) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercept http requests and add the client's IP to the X-Forwarded-For header
|
||||||
|
* @param httpRequest
|
||||||
|
* @param next
|
||||||
|
*/
|
||||||
|
intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
const clientIp = this.req.get('x-forwarded-for') || this.req.connection.remoteAddress;
|
||||||
|
return next.handle(httpRequest.clone({ setHeaders: { 'X-Forwarded-For': clientIp } }));
|
||||||
|
}
|
||||||
|
}
|
@@ -19,6 +19,7 @@ describe('ProcessFormComponent', () => {
|
|||||||
let component: ProcessFormComponent;
|
let component: ProcessFormComponent;
|
||||||
let fixture: ComponentFixture<ProcessFormComponent>;
|
let fixture: ComponentFixture<ProcessFormComponent>;
|
||||||
let scriptService;
|
let scriptService;
|
||||||
|
let router;
|
||||||
let parameterValues;
|
let parameterValues;
|
||||||
let script;
|
let script;
|
||||||
|
|
||||||
@@ -41,7 +42,10 @@ describe('ProcessFormComponent', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
|
router = {
|
||||||
|
navigateByUrl: () => undefined,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
|
@@ -1378,6 +1378,8 @@
|
|||||||
|
|
||||||
"item.edit.relationships.save-button": "Save",
|
"item.edit.relationships.save-button": "Save",
|
||||||
|
|
||||||
|
"item.edit.relationships.no-entity-type": "Add 'relationship.type' metadata to enable relationships for this item",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"item.edit.tabs.bitstreams.head": "Bitstreams",
|
"item.edit.tabs.bitstreams.head": "Bitstreams",
|
||||||
|
@@ -27,6 +27,8 @@ import { Angulartics2RouterlessModule } from 'angulartics2/routerlessmodule';
|
|||||||
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
|
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
|
||||||
import { ServerLocaleService } from 'src/app/core/locale/server-locale.service';
|
import { ServerLocaleService } from 'src/app/core/locale/server-locale.service';
|
||||||
import { LocaleService } from 'src/app/core/locale/locale.service';
|
import { LocaleService } from 'src/app/core/locale/locale.service';
|
||||||
|
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
|
import { ForwardClientIpInterceptor } from '../../app/core/forward-client-ip/forward-client-ip.interceptor';
|
||||||
|
|
||||||
export function createTranslateLoader() {
|
export function createTranslateLoader() {
|
||||||
return new TranslateJson5UniversalLoader('dist/server/assets/i18n/', '.json5');
|
return new TranslateJson5UniversalLoader('dist/server/assets/i18n/', '.json5');
|
||||||
@@ -79,7 +81,13 @@ export function createTranslateLoader() {
|
|||||||
{
|
{
|
||||||
provide: LocaleService,
|
provide: LocaleService,
|
||||||
useClass: ServerLocaleService
|
useClass: ServerLocaleService
|
||||||
}
|
},
|
||||||
|
// register ForwardClientIpInterceptor as HttpInterceptor
|
||||||
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: ForwardClientIpInterceptor,
|
||||||
|
multi: true
|
||||||
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class ServerAppModule {
|
export class ServerAppModule {
|
||||||
|
Reference in New Issue
Block a user