diff --git a/deploy/app.js b/deploy/app.js index 4ad2980db4fcebf6ae37d064653cb657805c9b92..ebbea597d3cc48f4257c59f12f87785fd14ee733 100644 --- a/deploy/app.js +++ b/deploy/app.js @@ -4,6 +4,7 @@ const app = express.Router() const session = require('express-session') const MemoryStore = require('memorystore')(session) const crypto = require('crypto') +const cookieParser = require('cookie-parser') if (process.env.NODE_ENV !== 'production') { app.use(require('cors')()) @@ -87,9 +88,15 @@ const indexTemplate = require('fs').readFileSync( path.join(PUBLIC_PATH, 'index.html'), 'utf-8' ) -app.get('/', (req, res) => { +app.get('/', cookieParser(), (req, res) => { + const iavError = req.cookies && req.cookies['iav-error'] + if (iavError) res.clearCookie('iav-error', { httpOnly: true, sameSite: 'strict' }) + res.setHeader('Content-Type', 'text/html') - res.status(200).send(`${indexTemplate.replace(/\$\$NONCE\$\$/g, res.locals.nonce)}`) + const returnTemplate = indexTemplate + .replace(/\$\$NONCE\$\$/g, res.locals.nonce) + .replace('<atlas-viewer>', `<atlas-viewer data-error="${iavError.replace(/"/g, '"')}">`) + res.status(200).send(returnTemplate) }) /** diff --git a/deploy/package.json b/deploy/package.json index 75b84d789ed5e2071f232e156a247c394d7e068f..2ea89d443536f93f88204c0fd727605313a9d21f 100644 --- a/deploy/package.json +++ b/deploy/package.json @@ -17,6 +17,7 @@ "dependencies": { "archiver": "^3.0.0", "body-parser": "^1.19.0", + "cookie-parser": "^1.4.5", "express": "^4.16.4", "express-rate-limit": "^5.1.1", "express-session": "^1.15.6", diff --git a/deploy/saneUrl/index.js b/deploy/saneUrl/index.js index c46d25a294ce5440039205d3fca02a72093abc05..2bd62b67fefc3e72518515ef344e55b350a26d7f 100644 --- a/deploy/saneUrl/index.js +++ b/deploy/saneUrl/index.js @@ -65,12 +65,29 @@ router.get('/:name', DISABLE_LIMITER ? passthrough : limiter, async (req, res) = const json = JSON.parse(value) const { queryString } = json - const REAL_HOSTNAME = `${HOSTNAME}${HOST_PATHNAME}/` + const REAL_HOSTNAME = `${HOSTNAME}${HOST_PATHNAME || ''}/` - if (redirectFlag) res.redirect(`${REAL_HOSTNAME}/?${queryString}`) + if (redirectFlag) res.redirect(`${REAL_HOSTNAME}?${queryString}`) else res.status(200).send(value) } catch (e) { + if (redirectFlag) { + + const REAL_HOSTNAME = `${HOSTNAME}${HOST_PATHNAME || ''}/` + + res.cookie( + 'iav-error', + e instanceof NotFoundError ? `${name} + + not found` : `error while fetching ${name}.`, + { + httpOnly: true, + sameSite: "strict", + maxAge: 1e3 * 30 + } + ) + return res.redirect(REAL_HOSTNAME) + } if (e instanceof NotFoundError) return res.status(404).end() else return res.status(500).send(e.toString()) } diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts index 94466205b5dd250b62717fc61b70e797fa7a478f..2ad1da35734e680e3522e37111a2d15b2a717910 100644 --- a/src/atlasViewer/atlasViewer.component.ts +++ b/src/atlasViewer/atlasViewer.component.ts @@ -7,6 +7,7 @@ import { Renderer2, TemplateRef, ViewChild, + ElementRef, } from "@angular/core"; import { ActionsSubject, select, Store } from "@ngrx/store"; import {combineLatest, interval, merge, Observable, of, Subscription} from "rxjs"; @@ -135,7 +136,8 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { private dispatcher$: ActionsSubject, private rd: Renderer2, public localFileService: LocalFileService, - private snackbar: MatSnackBar + private snackbar: MatSnackBar, + private el: ElementRef, ) { this.snackbarMessage$ = this.store.pipe( @@ -254,6 +256,13 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { this.subscriptions.push( this.pluginRegionSelectionEnabled$.subscribe(bool => this.pluginRegionSelectionEnabled = bool) ) + + const error = this.el.nativeElement.getAttribute('data-error') + + if (error) { + this.snackbar.open(error, 'Dismiss', { duration: 5000 }) + this.el.nativeElement.removeAttribute('data-error') + } } private selectedParcellation$: Observable<any>