mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
support base path
This commit is contained in:
@@ -9,10 +9,11 @@
|
|||||||
"start:dev": "nodemon --exec \"cross-env NODE_ENV=development yarn run serve\"",
|
"start:dev": "nodemon --exec \"cross-env NODE_ENV=development yarn run serve\"",
|
||||||
"start:prod": "yarn run build:prod && cross-env NODE_ENV=production yarn run serve:ssr",
|
"start:prod": "yarn run build:prod && cross-env NODE_ENV=production yarn run serve:ssr",
|
||||||
"start:mirador:prod": "yarn run build:mirador && yarn run start:prod",
|
"start:mirador:prod": "yarn run build:mirador && yarn run start:prod",
|
||||||
"serve": "ng serve -c development",
|
"preserve": "yarn base-href",
|
||||||
|
"serve": "ng serve --configuration development",
|
||||||
"serve:ssr": "node dist/server/main",
|
"serve:ssr": "node dist/server/main",
|
||||||
"analyze": "webpack-bundle-analyzer dist/browser/stats.json",
|
"analyze": "webpack-bundle-analyzer dist/browser/stats.json",
|
||||||
"build": "ng build -c development",
|
"build": "ng build --configuration development",
|
||||||
"build:stats": "ng build --stats-json",
|
"build:stats": "ng build --stats-json",
|
||||||
"build:prod": "yarn run build:ssr",
|
"build:prod": "yarn run build:ssr",
|
||||||
"build:ssr": "ng build --configuration production && ng run dspace-angular:server:production",
|
"build:ssr": "ng build --configuration production && ng run dspace-angular:server:production",
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
"cypress:open": "cypress open",
|
"cypress:open": "cypress open",
|
||||||
"cypress:run": "cypress run",
|
"cypress:run": "cypress run",
|
||||||
"env:yaml": "ts-node --project ./tsconfig.ts-node.json scripts/env-to-yaml.ts",
|
"env:yaml": "ts-node --project ./tsconfig.ts-node.json scripts/env-to-yaml.ts",
|
||||||
|
"base-href": "ts-node --project ./tsconfig.ts-node.json scripts/base-href.ts",
|
||||||
"check-circ-deps": "npx madge --exclude '(bitstream|bundle|collection|config-submission-form|eperson|item|version)\\.model\\.ts$' --circular --extensions ts ./"
|
"check-circ-deps": "npx madge --exclude '(bitstream|bundle|collection|config-submission-form|eperson|item|version)\\.model\\.ts$' --circular --extensions ts ./"
|
||||||
},
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
|
36
scripts/base-href.ts
Normal file
36
scripts/base-href.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import * as fs from 'fs';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
import { AppConfig } from '../src/config/app-config.interface';
|
||||||
|
import { buildAppConfig } from '../src/config/config.server';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script to set baseHref as `ui.nameSpace` for development mode. Adds `baseHref` to angular.json build options.
|
||||||
|
*
|
||||||
|
* Usage (see package.json):
|
||||||
|
*
|
||||||
|
* yarn base-href
|
||||||
|
*/
|
||||||
|
|
||||||
|
const appConfig: AppConfig = buildAppConfig();
|
||||||
|
|
||||||
|
const angularJsonPath = join(process.cwd(), 'angular.json');
|
||||||
|
|
||||||
|
if (!fs.existsSync(angularJsonPath)) {
|
||||||
|
console.error(`Error:\n${angularJsonPath} does not exist\n`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const angularJson = require(angularJsonPath);
|
||||||
|
|
||||||
|
const baseHref = `${appConfig.ui.nameSpace}${appConfig.ui.nameSpace.endsWith('/') ? '' : '/'}`;
|
||||||
|
|
||||||
|
console.log(`Setting baseHref to ${baseHref} in angular.json`);
|
||||||
|
|
||||||
|
angularJson.projects['dspace-angular'].architect.build.options.baseHref = baseHref;
|
||||||
|
|
||||||
|
fs.writeFileSync(angularJsonPath, JSON.stringify(angularJson, null, 2) + '\n');
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
32
server.ts
32
server.ts
@@ -66,6 +66,8 @@ extendEnvironmentWithAppConfig(environment, appConfig);
|
|||||||
// The Express app is exported so that it can be used by serverless Functions.
|
// The Express app is exported so that it can be used by serverless Functions.
|
||||||
export function app() {
|
export function app() {
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new express application
|
* Create a new express application
|
||||||
*/
|
*/
|
||||||
@@ -133,7 +135,11 @@ export function app() {
|
|||||||
/**
|
/**
|
||||||
* Proxy the sitemaps
|
* Proxy the sitemaps
|
||||||
*/
|
*/
|
||||||
server.use('/sitemap**', createProxyMiddleware({ target: `${environment.rest.baseUrl}/sitemaps`, changeOrigin: true }));
|
router.use('/sitemap**', createProxyMiddleware({
|
||||||
|
target: `${environment.rest.baseUrl}/sitemaps`,
|
||||||
|
pathRewrite: path => path.replace(environment.ui.nameSpace, '/'),
|
||||||
|
changeOrigin: true
|
||||||
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the rateLimiter property is present
|
* Checks if the rateLimiter property is present
|
||||||
@@ -151,14 +157,16 @@ export function app() {
|
|||||||
/*
|
/*
|
||||||
* Serve static resources (images, i18n messages, …)
|
* Serve static resources (images, i18n messages, …)
|
||||||
*/
|
*/
|
||||||
server.get('*.*', cacheControl, express.static(DIST_FOLDER, { index: false }));
|
router.get('*.*', cacheControl, express.static(DIST_FOLDER, { index: false }));
|
||||||
/*
|
/*
|
||||||
* Fallthrough to the IIIF viewer (must be included in the build).
|
* Fallthrough to the IIIF viewer (must be included in the build).
|
||||||
*/
|
*/
|
||||||
server.use('/iiif', express.static(IIIF_VIEWER, {index:false}));
|
router.use('/iiif', express.static(IIIF_VIEWER, { index: false }));
|
||||||
|
|
||||||
// Register the ngApp callback function to handle incoming requests
|
// Register the ngApp callback function to handle incoming requests
|
||||||
server.get('*', ngApp);
|
router.get('*', ngApp);
|
||||||
|
|
||||||
|
server.use(environment.ui.nameSpace, router);
|
||||||
|
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
@@ -191,13 +199,25 @@ function ngApp(req, res) {
|
|||||||
if (hasValue(err)) {
|
if (hasValue(err)) {
|
||||||
console.warn('Error details : ', err);
|
console.warn('Error details : ', err);
|
||||||
}
|
}
|
||||||
res.sendFile(DIST_FOLDER + '/index.html');
|
res.render(indexHtml, {
|
||||||
|
req,
|
||||||
|
providers: [{
|
||||||
|
provide: APP_BASE_HREF,
|
||||||
|
useValue: req.baseUrl
|
||||||
|
}]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// If preboot is disabled, just serve the client
|
// If preboot is disabled, just serve the client
|
||||||
console.log('Universal off, serving for direct CSR');
|
console.log('Universal off, serving for direct CSR');
|
||||||
res.sendFile(DIST_FOLDER + '/index.html');
|
res.render(indexHtml, {
|
||||||
|
req,
|
||||||
|
providers: [{
|
||||||
|
provide: APP_BASE_HREF,
|
||||||
|
useValue: req.baseUrl
|
||||||
|
}]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -187,7 +187,7 @@ describe('App component', () => {
|
|||||||
link.setAttribute('rel', 'stylesheet');
|
link.setAttribute('rel', 'stylesheet');
|
||||||
link.setAttribute('type', 'text/css');
|
link.setAttribute('type', 'text/css');
|
||||||
link.setAttribute('class', 'theme-css');
|
link.setAttribute('class', 'theme-css');
|
||||||
link.setAttribute('href', '/custom-theme.css');
|
link.setAttribute('href', 'custom-theme.css');
|
||||||
|
|
||||||
expect(headSpy.appendChild).toHaveBeenCalledWith(link);
|
expect(headSpy.appendChild).toHaveBeenCalledWith(link);
|
||||||
});
|
});
|
||||||
|
@@ -268,7 +268,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||||||
link.setAttribute('rel', 'stylesheet');
|
link.setAttribute('rel', 'stylesheet');
|
||||||
link.setAttribute('type', 'text/css');
|
link.setAttribute('type', 'text/css');
|
||||||
link.setAttribute('class', 'theme-css');
|
link.setAttribute('class', 'theme-css');
|
||||||
link.setAttribute('href', `/${encodeURIComponent(themeName)}-theme.css`);
|
link.setAttribute('href', `${encodeURIComponent(themeName)}-theme.css`);
|
||||||
// wait for the new css to download before removing the old one to prevent a
|
// wait for the new css to download before removing the old one to prevent a
|
||||||
// flash of unstyled content
|
// flash of unstyled content
|
||||||
link.onload = () => {
|
link.onload = () => {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { APP_BASE_HREF, CommonModule } from '@angular/common';
|
import { APP_BASE_HREF, CommonModule, DOCUMENT } from '@angular/common';
|
||||||
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
|
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
|
||||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||||
import { AbstractControl } from '@angular/forms';
|
import { AbstractControl } from '@angular/forms';
|
||||||
@@ -66,9 +66,11 @@ export function getConfig() {
|
|||||||
return environment;
|
return environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBase(appConfig: AppConfig) {
|
const getBaseHref = (document: Document, appConfig: AppConfig): string => {
|
||||||
return appConfig.ui.nameSpace;
|
const baseTag = document.querySelector('head > base');
|
||||||
}
|
baseTag.setAttribute('href', `${appConfig.ui.nameSpace}${appConfig.ui.nameSpace.endsWith('/') ? '' : '/'}`);
|
||||||
|
return baseTag.getAttribute('href');
|
||||||
|
};
|
||||||
|
|
||||||
export function getMetaReducers(appConfig: AppConfig): MetaReducer<AppState>[] {
|
export function getMetaReducers(appConfig: AppConfig): MetaReducer<AppState>[] {
|
||||||
return appConfig.debug ? [...appMetaReducers, ...debugMetaReducers] : appMetaReducers;
|
return appConfig.debug ? [...appMetaReducers, ...debugMetaReducers] : appMetaReducers;
|
||||||
@@ -107,8 +109,8 @@ const PROVIDERS = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: APP_BASE_HREF,
|
provide: APP_BASE_HREF,
|
||||||
useFactory: getBase,
|
useFactory: getBaseHref,
|
||||||
deps: [APP_CONFIG]
|
deps: [DOCUMENT, APP_CONFIG]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: USER_PROVIDED_META_REDUCERS,
|
provide: USER_PROVIDED_META_REDUCERS,
|
||||||
|
@@ -368,25 +368,25 @@ describe('AuthService test', () => {
|
|||||||
it('should redirect to reload with redirect url', () => {
|
it('should redirect to reload with redirect url', () => {
|
||||||
authService.navigateToRedirectUrl('/collection/123');
|
authService.navigateToRedirectUrl('/collection/123');
|
||||||
// Reload with redirect URL set to /collection/123
|
// Reload with redirect URL set to /collection/123
|
||||||
expect(hardRedirectService.redirect).toHaveBeenCalledWith(jasmine.stringMatching(new RegExp('/reload/[0-9]*\\?redirect=' + encodeURIComponent('/collection/123'))));
|
expect(hardRedirectService.redirect).toHaveBeenCalledWith(jasmine.stringMatching(new RegExp('reload/[0-9]*\\?redirect=' + encodeURIComponent('/collection/123'))));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redirect to reload with /home', () => {
|
it('should redirect to reload with /home', () => {
|
||||||
authService.navigateToRedirectUrl('/home');
|
authService.navigateToRedirectUrl('/home');
|
||||||
// Reload with redirect URL set to /home
|
// Reload with redirect URL set to /home
|
||||||
expect(hardRedirectService.redirect).toHaveBeenCalledWith(jasmine.stringMatching(new RegExp('/reload/[0-9]*\\?redirect=' + encodeURIComponent('/home'))));
|
expect(hardRedirectService.redirect).toHaveBeenCalledWith(jasmine.stringMatching(new RegExp('reload/[0-9]*\\?redirect=' + encodeURIComponent('/home'))));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redirect to regular reload and not to /login', () => {
|
it('should redirect to regular reload and not to /login', () => {
|
||||||
authService.navigateToRedirectUrl('/login');
|
authService.navigateToRedirectUrl('/login');
|
||||||
// Reload without a redirect URL
|
// Reload without a redirect URL
|
||||||
expect(hardRedirectService.redirect).toHaveBeenCalledWith(jasmine.stringMatching(new RegExp('/reload/[0-9]*(?!\\?)$')));
|
expect(hardRedirectService.redirect).toHaveBeenCalledWith(jasmine.stringMatching(new RegExp('reload/[0-9]*(?!\\?)$')));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redirect to regular reload when no redirect url is found', () => {
|
it('should redirect to regular reload when no redirect url is found', () => {
|
||||||
authService.navigateToRedirectUrl(undefined);
|
authService.navigateToRedirectUrl(undefined);
|
||||||
// Reload without a redirect URL
|
// Reload without a redirect URL
|
||||||
expect(hardRedirectService.redirect).toHaveBeenCalledWith(jasmine.stringMatching(new RegExp('/reload/[0-9]*(?!\\?)$')));
|
expect(hardRedirectService.redirect).toHaveBeenCalledWith(jasmine.stringMatching(new RegExp('reload/[0-9]*(?!\\?)$')));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('impersonate', () => {
|
describe('impersonate', () => {
|
||||||
|
@@ -447,8 +447,8 @@ export class AuthService {
|
|||||||
*/
|
*/
|
||||||
public navigateToRedirectUrl(redirectUrl: string) {
|
public navigateToRedirectUrl(redirectUrl: string) {
|
||||||
// Don't do redirect if already on reload url
|
// Don't do redirect if already on reload url
|
||||||
if (!hasValue(redirectUrl) || !redirectUrl.includes('/reload/')) {
|
if (!hasValue(redirectUrl) || !redirectUrl.includes('reload/')) {
|
||||||
let url = `/reload/${new Date().getTime()}`;
|
let url = `reload/${new Date().getTime()}`;
|
||||||
if (isNotEmpty(redirectUrl) && !redirectUrl.startsWith(LOGIN_ROUTE)) {
|
if (isNotEmpty(redirectUrl) && !redirectUrl.startsWith(LOGIN_ROUTE)) {
|
||||||
url += `?redirect=${encodeURIComponent(redirectUrl)}`;
|
url += `?redirect=${encodeURIComponent(redirectUrl)}`;
|
||||||
}
|
}
|
||||||
|
@@ -192,7 +192,7 @@ export class LocaleService {
|
|||||||
this.routeService.getCurrentUrl().pipe(take(1)).subscribe((currentURL) => {
|
this.routeService.getCurrentUrl().pipe(take(1)).subscribe((currentURL) => {
|
||||||
// Hard redirect to the reload page with a unique number behind it
|
// Hard redirect to the reload page with a unique number behind it
|
||||||
// so that all state is definitely lost
|
// so that all state is definitely lost
|
||||||
this._window.nativeWindow.location.href = `/reload/${new Date().getTime()}?redirect=` + encodeURIComponent(currentURL);
|
this._window.nativeWindow.location.href = `reload/${new Date().getTime()}?redirect=` + encodeURIComponent(currentURL);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,17 @@
|
|||||||
import { ReloadGuard } from './reload.guard';
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
import { AppConfig } from '../../../config/app-config.interface';
|
||||||
|
import { DefaultAppConfig } from '../../../config/default-app-config';
|
||||||
|
import { ReloadGuard } from './reload.guard';
|
||||||
|
|
||||||
describe('ReloadGuard', () => {
|
describe('ReloadGuard', () => {
|
||||||
let guard: ReloadGuard;
|
let guard: ReloadGuard;
|
||||||
let router: Router;
|
let router: Router;
|
||||||
|
let appConfig: AppConfig;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
router = jasmine.createSpyObj('router', ['parseUrl', 'createUrlTree']);
|
router = jasmine.createSpyObj('router', ['parseUrl', 'createUrlTree']);
|
||||||
guard = new ReloadGuard(router);
|
appConfig = new DefaultAppConfig();
|
||||||
|
guard = new ReloadGuard(router, appConfig);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('canActivate', () => {
|
describe('canActivate', () => {
|
||||||
@@ -27,7 +31,7 @@ describe('ReloadGuard', () => {
|
|||||||
|
|
||||||
it('should create a UrlTree with the redirect URL', () => {
|
it('should create a UrlTree with the redirect URL', () => {
|
||||||
guard.canActivate(route, undefined);
|
guard.canActivate(route, undefined);
|
||||||
expect(router.parseUrl).toHaveBeenCalledWith(redirectUrl);
|
expect(router.parseUrl).toHaveBeenCalledWith(redirectUrl.substring(1));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
|
import { Inject, Injectable } from '@angular/core';
|
||||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
||||||
import { Injectable } from '@angular/core';
|
import { AppConfig, APP_CONFIG } from '../../../config/app-config.interface';
|
||||||
import { isNotEmpty } from '../../shared/empty.util';
|
import { isNotEmpty } from '../../shared/empty.util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8,7 +9,10 @@ import { isNotEmpty } from '../../shared/empty.util';
|
|||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ReloadGuard implements CanActivate {
|
export class ReloadGuard implements CanActivate {
|
||||||
constructor(private router: Router) {
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
@Inject(APP_CONFIG) private appConfig: AppConfig,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,7 +22,10 @@ export class ReloadGuard implements CanActivate {
|
|||||||
*/
|
*/
|
||||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): UrlTree {
|
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): UrlTree {
|
||||||
if (isNotEmpty(route.queryParams.redirect)) {
|
if (isNotEmpty(route.queryParams.redirect)) {
|
||||||
return this.router.parseUrl(route.queryParams.redirect);
|
const url = route.queryParams.redirect.startsWith(this.appConfig.ui.nameSpace)
|
||||||
|
? route.queryParams.redirect.substring(this.appConfig.ui.nameSpace.length)
|
||||||
|
: route.queryParams.redirect;
|
||||||
|
return this.router.parseUrl(url);
|
||||||
} else {
|
} else {
|
||||||
return this.router.createUrlTree(['home']);
|
return this.router.createUrlTree(['home']);
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,6 @@
|
|||||||
<p>{{"500.help" | translate}}</p>
|
<p>{{"500.help" | translate}}</p>
|
||||||
<br/>
|
<br/>
|
||||||
<p class="text-center">
|
<p class="text-center">
|
||||||
<a href="/home" class="btn btn-primary">{{"500.link.home-page" | translate}}</a>
|
<a href="home" class="btn btn-primary">{{"500.link.home-page" | translate}}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -4,7 +4,6 @@ import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { LinkMenuItemComponent } from './link-menu-item.component';
|
import { LinkMenuItemComponent } from './link-menu-item.component';
|
||||||
import { RouterLinkDirectiveStub } from '../../testing/router-link-directive.stub';
|
import { RouterLinkDirectiveStub } from '../../testing/router-link-directive.stub';
|
||||||
import { environment } from '../../../../environments/environment';
|
|
||||||
import { QueryParamsDirectiveStub } from '../../testing/query-params-directive.stub';
|
import { QueryParamsDirectiveStub } from '../../testing/query-params-directive.stub';
|
||||||
import { RouterStub } from '../../testing/router.stub';
|
import { RouterStub } from '../../testing/router.stub';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
@@ -58,7 +57,7 @@ describe('LinkMenuItemComponent', () => {
|
|||||||
const routerLinkQuery = linkDes.map((de) => de.injector.get(RouterLinkDirectiveStub));
|
const routerLinkQuery = linkDes.map((de) => de.injector.get(RouterLinkDirectiveStub));
|
||||||
|
|
||||||
expect(routerLinkQuery.length).toBe(1);
|
expect(routerLinkQuery.length).toBe(1);
|
||||||
expect(routerLinkQuery[0].routerLink).toBe(environment.ui.nameSpace + link);
|
expect(routerLinkQuery[0].routerLink).toBe(link);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have the right queryParams attribute', () => {
|
it('should have the right queryParams attribute', () => {
|
||||||
|
@@ -2,7 +2,6 @@ import { Component, Inject, Input, OnInit } from '@angular/core';
|
|||||||
import { LinkMenuItemModel } from './models/link.model';
|
import { LinkMenuItemModel } from './models/link.model';
|
||||||
import { rendersMenuItemForType } from '../menu-item.decorator';
|
import { rendersMenuItemForType } from '../menu-item.decorator';
|
||||||
import { isNotEmpty } from '../../empty.util';
|
import { isNotEmpty } from '../../empty.util';
|
||||||
import { environment } from '../../../../environments/environment';
|
|
||||||
import { MenuItemType } from '../menu-item-type.model';
|
import { MenuItemType } from '../menu-item-type.model';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ export class LinkMenuItemComponent implements OnInit {
|
|||||||
|
|
||||||
getRouterLink() {
|
getRouterLink() {
|
||||||
if (this.hasLink) {
|
if (this.hasLink) {
|
||||||
return environment.ui.nameSpace + this.item.link;
|
return this.item.link;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@@ -98,7 +98,7 @@ describe('NotificationComponent', () => {
|
|||||||
it('should have html content', () => {
|
it('should have html content', () => {
|
||||||
fixture = TestBed.createComponent(NotificationComponent);
|
fixture = TestBed.createComponent(NotificationComponent);
|
||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
const htmlContent = '<a class="btn btn-link p-0 m-0 pb-1" href="/test"><strong>test</strong></a>';
|
const htmlContent = '<a class="btn btn-link p-0 m-0 pb-1" href="test"><strong>test</strong></a>';
|
||||||
comp.notification = {
|
comp.notification = {
|
||||||
id: '1',
|
id: '1',
|
||||||
type: NotificationType.Info,
|
type: NotificationType.Info,
|
||||||
|
@@ -13,6 +13,6 @@
|
|||||||
</body>
|
</body>
|
||||||
|
|
||||||
<!-- this is needed for CSR fallback -->
|
<!-- this is needed for CSR fallback -->
|
||||||
<script async src="/client.js"></script>
|
<script async src="client.js"></script>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@@ -6,7 +6,9 @@ $sidebar-items-width: 250px !default;
|
|||||||
$total-sidebar-width: $collapsed-sidebar-width + $sidebar-items-width !default;
|
$total-sidebar-width: $collapsed-sidebar-width + $sidebar-items-width !default;
|
||||||
|
|
||||||
/* Fonts */
|
/* Fonts */
|
||||||
$fa-font-path: "/assets/fonts" !default;
|
// Starting this url with a caret (^) allows it to be a relative path based on UI's deployment path
|
||||||
|
// See https://github.com/angular/angular-cli/issues/12797#issuecomment-598534241
|
||||||
|
$fa-font-path: "^assets/fonts" !default;
|
||||||
/* Images */
|
/* Images */
|
||||||
$image-path: "../assets/images" !default;
|
$image-path: "../assets/images" !default;
|
||||||
|
|
||||||
|
@@ -6,7 +6,9 @@
|
|||||||
color: white;
|
color: white;
|
||||||
background-color: var(--bs-info);
|
background-color: var(--bs-info);
|
||||||
position: relative;
|
position: relative;
|
||||||
background-image: url('/assets/dspace/images/banner.jpg');
|
// Starting this url with a caret (^) allows it to be a relative path based on UI's deployment path
|
||||||
|
// See https://github.com/angular/angular-cli/issues/12797#issuecomment-598534241
|
||||||
|
background-image: url('^assets/dspace/images/banner.jpg');
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
|
Reference in New Issue
Block a user