mirror of https://github.com/ghostfolio/ghostfolio
8 changed files with 135 additions and 337 deletions
@ -1,234 +0,0 @@ |
|||||
// TODO: Remove
|
|
||||
|
|
||||
import * as fs from 'fs'; |
|
||||
import * as path from 'path'; |
|
||||
|
|
||||
import { environment } from '@ghostfolio/api/environments/environment'; |
|
||||
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; |
|
||||
import { DEFAULT_LANGUAGE_CODE } from '@ghostfolio/common/config'; |
|
||||
import { DATE_FORMAT, interpolate } from '@ghostfolio/common/helper'; |
|
||||
import { Injectable, NestMiddleware } from '@nestjs/common'; |
|
||||
import { format } from 'date-fns'; |
|
||||
import { NextFunction, Request, Response } from 'express'; |
|
||||
|
|
||||
@Injectable() |
|
||||
export class FrontendMiddleware implements NestMiddleware { |
|
||||
public indexHtmlDe = ''; |
|
||||
public indexHtmlEn = ''; |
|
||||
public indexHtmlEs = ''; |
|
||||
public indexHtmlFr = ''; |
|
||||
public indexHtmlIt = ''; |
|
||||
public indexHtmlNl = ''; |
|
||||
public indexHtmlPt = ''; |
|
||||
|
|
||||
private static readonly DEFAULT_DESCRIPTION = |
|
||||
'Ghostfolio is a personal finance dashboard to keep track of your assets like stocks, ETFs or cryptocurrencies across multiple platforms.'; |
|
||||
|
|
||||
public constructor( |
|
||||
private readonly configurationService: ConfigurationService |
|
||||
) { |
|
||||
try { |
|
||||
this.indexHtmlDe = fs.readFileSync( |
|
||||
this.getPathOfIndexHtmlFile('de'), |
|
||||
'utf8' |
|
||||
); |
|
||||
this.indexHtmlEn = fs.readFileSync( |
|
||||
this.getPathOfIndexHtmlFile(DEFAULT_LANGUAGE_CODE), |
|
||||
'utf8' |
|
||||
); |
|
||||
this.indexHtmlEs = fs.readFileSync( |
|
||||
this.getPathOfIndexHtmlFile('es'), |
|
||||
'utf8' |
|
||||
); |
|
||||
this.indexHtmlFr = fs.readFileSync( |
|
||||
this.getPathOfIndexHtmlFile('fr'), |
|
||||
'utf8' |
|
||||
); |
|
||||
this.indexHtmlIt = fs.readFileSync( |
|
||||
this.getPathOfIndexHtmlFile('it'), |
|
||||
'utf8' |
|
||||
); |
|
||||
this.indexHtmlNl = fs.readFileSync( |
|
||||
this.getPathOfIndexHtmlFile('nl'), |
|
||||
'utf8' |
|
||||
); |
|
||||
this.indexHtmlPt = fs.readFileSync( |
|
||||
this.getPathOfIndexHtmlFile('pt'), |
|
||||
'utf8' |
|
||||
); |
|
||||
} catch {} |
|
||||
} |
|
||||
|
|
||||
public use(request: Request, response: Response, next: NextFunction) { |
|
||||
const currentDate = format(new Date(), DATE_FORMAT); |
|
||||
let featureGraphicPath = 'assets/cover.png'; |
|
||||
let title = 'Ghostfolio – Open Source Wealth Management Software'; |
|
||||
|
|
||||
if (request.path.startsWith('/en/blog/2022/08/500-stars-on-github')) { |
|
||||
featureGraphicPath = 'assets/images/blog/500-stars-on-github.jpg'; |
|
||||
title = `500 Stars - ${title}`; |
|
||||
} else if (request.path.startsWith('/en/blog/2022/10/hacktoberfest-2022')) { |
|
||||
featureGraphicPath = 'assets/images/blog/hacktoberfest-2022.png'; |
|
||||
title = `Hacktoberfest 2022 - ${title}`; |
|
||||
} else if (request.path.startsWith('/en/blog/2022/11/black-friday-2022')) { |
|
||||
featureGraphicPath = 'assets/images/blog/black-friday-2022.jpg'; |
|
||||
title = `Black Friday 2022 - ${title}`; |
|
||||
} else if ( |
|
||||
request.path.startsWith( |
|
||||
'/en/blog/2022/12/the-importance-of-tracking-your-personal-finances' |
|
||||
) |
|
||||
) { |
|
||||
featureGraphicPath = 'assets/images/blog/20221226.jpg'; |
|
||||
title = `The importance of tracking your personal finances - ${title}`; |
|
||||
} else if ( |
|
||||
request.path.startsWith( |
|
||||
'/de/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt' |
|
||||
) |
|
||||
) { |
|
||||
featureGraphicPath = 'assets/images/blog/ghostfolio-x-sackgeld.png'; |
|
||||
title = `Ghostfolio auf Sackgeld.com vorgestellt - ${title}`; |
|
||||
} else if ( |
|
||||
request.path.startsWith('/en/blog/2023/02/ghostfolio-meets-umbrel') |
|
||||
) { |
|
||||
featureGraphicPath = 'assets/images/blog/ghostfolio-x-umbrel.png'; |
|
||||
title = `Ghostfolio meets Umbrel - ${title}`; |
|
||||
} else if ( |
|
||||
request.path.startsWith( |
|
||||
'/en/blog/2023/03/ghostfolio-reaches-1000-stars-on-github' |
|
||||
) |
|
||||
) { |
|
||||
featureGraphicPath = 'assets/images/blog/1000-stars-on-github.jpg'; |
|
||||
title = `Ghostfolio reaches 1’000 Stars on GitHub - ${title}`; |
|
||||
} else if ( |
|
||||
request.path.startsWith( |
|
||||
'/en/blog/2023/05/unlock-your-financial-potential-with-ghostfolio' |
|
||||
) |
|
||||
) { |
|
||||
featureGraphicPath = 'assets/images/blog/20230520.jpg'; |
|
||||
title = `Unlock your Financial Potential with Ghostfolio - ${title}`; |
|
||||
} else if ( |
|
||||
request.path.startsWith('/en/blog/2023/07/exploring-the-path-to-fire') |
|
||||
) { |
|
||||
featureGraphicPath = 'assets/images/blog/20230701.jpg'; |
|
||||
title = `Exploring the Path to FIRE - ${title}`; |
|
||||
} |
|
||||
|
|
||||
if ( |
|
||||
request.path.startsWith('/api/') || |
|
||||
this.isFileRequest(request.url) || |
|
||||
!environment.production |
|
||||
) { |
|
||||
// Skip
|
|
||||
next(); |
|
||||
} else if (request.path === '/de' || request.path.startsWith('/de/')) { |
|
||||
response.send( |
|
||||
interpolate(this.indexHtmlDe, { |
|
||||
currentDate, |
|
||||
featureGraphicPath, |
|
||||
title, |
|
||||
description: |
|
||||
'Mit dem Finanz-Dashboard Ghostfolio können Sie Ihr Vermögen in Form von Aktien, ETFs oder Kryptowährungen verteilt über mehrere Finanzinstitute überwachen.', |
|
||||
languageCode: 'de', |
|
||||
path: request.path, |
|
||||
rootUrl: this.configurationService.get('ROOT_URL') |
|
||||
}) |
|
||||
); |
|
||||
} else if (request.path === '/es' || request.path.startsWith('/es/')) { |
|
||||
response.send( |
|
||||
interpolate(this.indexHtmlEs, { |
|
||||
currentDate, |
|
||||
featureGraphicPath, |
|
||||
title, |
|
||||
description: |
|
||||
'Ghostfolio es un dashboard de finanzas personales para hacer un seguimiento de tus activos como acciones, ETFs o criptodivisas a través de múltiples plataformas.', |
|
||||
languageCode: 'es', |
|
||||
path: request.path, |
|
||||
rootUrl: this.configurationService.get('ROOT_URL') |
|
||||
}) |
|
||||
); |
|
||||
} else if (request.path === '/fr' || request.path.startsWith('/fr/')) { |
|
||||
response.send( |
|
||||
interpolate(this.indexHtmlFr, { |
|
||||
currentDate, |
|
||||
featureGraphicPath, |
|
||||
title, |
|
||||
description: |
|
||||
'Ghostfolio est un dashboard de finances personnelles qui permet de suivre vos actifs comme les actions, les ETF ou les crypto-monnaies sur plusieurs plateformes.', |
|
||||
languageCode: 'fr', |
|
||||
path: request.path, |
|
||||
rootUrl: this.configurationService.get('ROOT_URL') |
|
||||
}) |
|
||||
); |
|
||||
} else if (request.path === '/it' || request.path.startsWith('/it/')) { |
|
||||
response.send( |
|
||||
interpolate(this.indexHtmlIt, { |
|
||||
currentDate, |
|
||||
featureGraphicPath, |
|
||||
title, |
|
||||
description: |
|
||||
'Ghostfolio è un dashboard di finanza personale per tenere traccia delle vostre attività come azioni, ETF o criptovalute su più piattaforme.', |
|
||||
languageCode: 'it', |
|
||||
path: request.path, |
|
||||
rootUrl: this.configurationService.get('ROOT_URL') |
|
||||
}) |
|
||||
); |
|
||||
} else if (request.path === '/nl' || request.path.startsWith('/nl/')) { |
|
||||
response.send( |
|
||||
interpolate(this.indexHtmlNl, { |
|
||||
currentDate, |
|
||||
featureGraphicPath, |
|
||||
title, |
|
||||
description: |
|
||||
'Ghostfolio is een persoonlijk financieel dashboard om uw activa zoals aandelen, ETF’s of cryptocurrencies over meerdere platforms bij te houden.', |
|
||||
languageCode: 'nl', |
|
||||
path: request.path, |
|
||||
rootUrl: this.configurationService.get('ROOT_URL') |
|
||||
}) |
|
||||
); |
|
||||
} else if (request.path === '/pt' || request.path.startsWith('/pt/')) { |
|
||||
response.send( |
|
||||
interpolate(this.indexHtmlPt, { |
|
||||
currentDate, |
|
||||
featureGraphicPath, |
|
||||
title, |
|
||||
description: |
|
||||
'Ghostfolio é um dashboard de finanças pessoais para acompanhar os seus activos como acções, ETFs ou criptomoedas em múltiplas plataformas.', |
|
||||
languageCode: 'pt', |
|
||||
path: request.path, |
|
||||
rootUrl: this.configurationService.get('ROOT_URL') |
|
||||
}) |
|
||||
); |
|
||||
} else { |
|
||||
response.send( |
|
||||
interpolate(this.indexHtmlEn, { |
|
||||
currentDate, |
|
||||
featureGraphicPath, |
|
||||
title, |
|
||||
description: FrontendMiddleware.DEFAULT_DESCRIPTION, |
|
||||
languageCode: DEFAULT_LANGUAGE_CODE, |
|
||||
path: request.path, |
|
||||
rootUrl: this.configurationService.get('ROOT_URL') |
|
||||
}) |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private getPathOfIndexHtmlFile(aLocale: string) { |
|
||||
return path.join(__dirname, '..', 'client', aLocale, 'index.html'); |
|
||||
} |
|
||||
|
|
||||
private isFileRequest(filename: string) { |
|
||||
if (filename === '/assets/LICENSE') { |
|
||||
return true; |
|
||||
} else if ( |
|
||||
filename.includes('auth/ey') || |
|
||||
filename.includes( |
|
||||
'personal-finance-tools/open-source-alternative-to-markets.sh' |
|
||||
) |
|
||||
) { |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
return filename.split('.').pop() !== filename; |
|
||||
} |
|
||||
} |
|
@ -1,82 +0,0 @@ |
|||||
import * as fs from 'fs'; |
|
||||
|
|
||||
import { NextFunction, Request, Response } from 'express'; |
|
||||
import { join } from 'path'; |
|
||||
import { DATE_FORMAT, interpolate } from '@ghostfolio/common/helper'; |
|
||||
import { environment } from '@ghostfolio/api/environments/environment'; |
|
||||
import { SUPPORTED_LANGUAGE_CODES } from '@ghostfolio/common/config'; |
|
||||
import { format } from 'date-fns'; |
|
||||
|
|
||||
const title = 'Ghostfolio – Open Source Wealth Management Software'; |
|
||||
|
|
||||
// TODO
|
|
||||
const descriptions = { |
|
||||
en: 'Ghostfolio is a personal finance dashboard to keep track of your assets like stocks, ETFs or cryptocurrencies across multiple platforms.' |
|
||||
}; |
|
||||
|
|
||||
// TODO
|
|
||||
const locales = { |
|
||||
'/en/blog/2022/08/500-stars-on-github': { |
|
||||
featureGraphicPath: 'assets/images/blog/500-stars-on-github.jpg', |
|
||||
title: `500 Stars - ${title}` |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
const getPathOfIndexHtmlFile = (aLocale: string) => { |
|
||||
return join(__dirname, '..', 'client', aLocale, 'index.html'); |
|
||||
}; |
|
||||
|
|
||||
const isFileRequest = (filename: string) => { |
|
||||
if (filename === '/assets/LICENSE') { |
|
||||
return true; |
|
||||
} else if ( |
|
||||
filename.includes('auth/ey') || |
|
||||
filename.includes( |
|
||||
'personal-finance-tools/open-source-alternative-to-markets.sh' |
|
||||
) |
|
||||
) { |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
return filename.split('.').pop() !== filename; |
|
||||
}; |
|
||||
|
|
||||
export const StaticMiddleware = async ( |
|
||||
request: Request, |
|
||||
response: Response, |
|
||||
next: NextFunction |
|
||||
) => { |
|
||||
const path = request.originalUrl.replace(/\/$/, ''); |
|
||||
const languageCode = path.substr(1, 2); |
|
||||
|
|
||||
const currentDate = format(new Date(), DATE_FORMAT); |
|
||||
const rootUrl = 'https://ghostfol.io'; // TODO
|
|
||||
|
|
||||
if ( |
|
||||
path.startsWith('/api/') || |
|
||||
isFileRequest(path) /*|| |
|
||||
!environment.production*/ |
|
||||
) { |
|
||||
// Skip
|
|
||||
next(); |
|
||||
} else if (SUPPORTED_LANGUAGE_CODES.includes(languageCode)) { |
|
||||
// TODO: Only load once
|
|
||||
const indexHtml = interpolate( |
|
||||
fs.readFileSync(getPathOfIndexHtmlFile(languageCode), 'utf8'), |
|
||||
{ |
|
||||
currentDate, |
|
||||
languageCode, |
|
||||
path, |
|
||||
rootUrl, |
|
||||
description: descriptions[languageCode], |
|
||||
featureGraphicPath: |
|
||||
locales[path]?.featureGraphicPath ?? 'assets/cover.png', |
|
||||
title: locales[path]?.title ?? title |
|
||||
} |
|
||||
); |
|
||||
|
|
||||
return response.send(indexHtml); |
|
||||
} else { |
|
||||
// TODO
|
|
||||
} |
|
||||
}; |
|
@ -0,0 +1,128 @@ |
|||||
|
import * as fs from 'fs'; |
||||
|
import { join } from 'path'; |
||||
|
|
||||
|
import { environment } from '@ghostfolio/api/environments/environment'; |
||||
|
import { |
||||
|
DEFAULT_LANGUAGE_CODE, |
||||
|
DEFAULT_ROOT_URL, |
||||
|
SUPPORTED_LANGUAGE_CODES |
||||
|
} from '@ghostfolio/common/config'; |
||||
|
import { DATE_FORMAT, interpolate } from '@ghostfolio/common/helper'; |
||||
|
import { format } from 'date-fns'; |
||||
|
import { NextFunction, Request, Response } from 'express'; |
||||
|
|
||||
|
const descriptions = { |
||||
|
de: 'Mit dem Finanz-Dashboard Ghostfolio können Sie Ihr Vermögen in Form von Aktien, ETFs oder Kryptowährungen verteilt über mehrere Finanzinstitute überwachen.', |
||||
|
en: 'Ghostfolio is a personal finance dashboard to keep track of your assets like stocks, ETFs or cryptocurrencies across multiple platforms.', |
||||
|
es: 'Ghostfolio es un dashboard de finanzas personales para hacer un seguimiento de tus activos como acciones, ETFs o criptodivisas a través de múltiples plataformas.', |
||||
|
fr: 'Ghostfolio est un dashboard de finances personnelles qui permet de suivre vos actifs comme les actions, les ETF ou les crypto-monnaies sur plusieurs plateformes.', |
||||
|
it: 'Ghostfolio è un dashboard di finanza personale per tenere traccia delle vostre attività come azioni, ETF o criptovalute su più piattaforme.', |
||||
|
nl: 'Ghostfolio is een persoonlijk financieel dashboard om uw activa zoals aandelen, ETF’s of cryptocurrencies over meerdere platforms bij te houden.', |
||||
|
pt: 'Ghostfolio é um dashboard de finanças pessoais para acompanhar os seus activos como acções, ETFs ou criptomoedas em múltiplas plataformas.' |
||||
|
}; |
||||
|
|
||||
|
const title = 'Ghostfolio – Open Source Wealth Management Software'; |
||||
|
const titleShort = 'Ghostfolio'; |
||||
|
|
||||
|
let indexHtmlMap: { [languageCode: string]: string } = {}; |
||||
|
|
||||
|
try { |
||||
|
indexHtmlMap = SUPPORTED_LANGUAGE_CODES.reduce( |
||||
|
(map, languageCode) => ({ |
||||
|
...map, |
||||
|
[languageCode]: fs.readFileSync( |
||||
|
join(__dirname, '..', 'client', languageCode, 'index.html'), |
||||
|
'utf8' |
||||
|
) |
||||
|
}), |
||||
|
{} |
||||
|
); |
||||
|
} catch {} |
||||
|
|
||||
|
const locales = { |
||||
|
'/de/blog/2023/01/ghostfolio-auf-sackgeld-vorgestellt': { |
||||
|
featureGraphicPath: 'assets/images/blog/ghostfolio-x-sackgeld.png', |
||||
|
title: `Ghostfolio auf Sackgeld.com vorgestellt - ${titleShort}` |
||||
|
}, |
||||
|
'/en/blog/2022/08/500-stars-on-github': { |
||||
|
featureGraphicPath: 'assets/images/blog/500-stars-on-github.jpg', |
||||
|
title: `500 Stars - ${titleShort}` |
||||
|
}, |
||||
|
'/en/blog/2022/10/hacktoberfest-2022': { |
||||
|
featureGraphicPath: 'assets/images/blog/hacktoberfest-2022.png', |
||||
|
title: `Hacktoberfest 2022 - ${titleShort}` |
||||
|
}, |
||||
|
'/en/blog/2022/12/the-importance-of-tracking-your-personal-finances': { |
||||
|
featureGraphicPath: 'assets/images/blog/20221226.jpg', |
||||
|
title: `The importance of tracking your personal finances - ${titleShort}` |
||||
|
}, |
||||
|
'/en/blog/2023/02/ghostfolio-meets-umbrel': { |
||||
|
featureGraphicPath: 'assets/images/blog/ghostfolio-x-umbrel.png', |
||||
|
title: `Ghostfolio meets Umbrel - ${titleShort}` |
||||
|
}, |
||||
|
'/en/blog/2023/03/ghostfolio-reaches-1000-stars-on-github': { |
||||
|
featureGraphicPath: 'assets/images/blog/1000-stars-on-github.jpg', |
||||
|
title: `Ghostfolio reaches 1’000 Stars on GitHub - ${titleShort}` |
||||
|
}, |
||||
|
'/en/blog/2023/05/unlock-your-financial-potential-with-ghostfolio': { |
||||
|
featureGraphicPath: 'assets/images/blog/20230520.jpg', |
||||
|
title: `Unlock your Financial Potential with Ghostfolio - ${titleShort}` |
||||
|
}, |
||||
|
'/en/blog/2023/07/exploring-the-path-to-fire': { |
||||
|
featureGraphicPath: 'assets/images/blog/20230701.jpg', |
||||
|
title: `Exploring the Path to FIRE - ${titleShort}` |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const isFileRequest = (filename: string) => { |
||||
|
if (filename === '/assets/LICENSE') { |
||||
|
return true; |
||||
|
} else if ( |
||||
|
filename.includes('auth/ey') || |
||||
|
filename.includes( |
||||
|
'personal-finance-tools/open-source-alternative-to-markets.sh' |
||||
|
) |
||||
|
) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return filename.split('.').pop() !== filename; |
||||
|
}; |
||||
|
|
||||
|
export const StaticMiddleware = async ( |
||||
|
request: Request, |
||||
|
response: Response, |
||||
|
next: NextFunction |
||||
|
) => { |
||||
|
const path = request.originalUrl.replace(/\/$/, ''); |
||||
|
let languageCode = path.substr(1, 2); |
||||
|
|
||||
|
if (!SUPPORTED_LANGUAGE_CODES.includes(languageCode)) { |
||||
|
languageCode = DEFAULT_LANGUAGE_CODE; |
||||
|
} |
||||
|
|
||||
|
const currentDate = format(new Date(), DATE_FORMAT); |
||||
|
const rootUrl = process.env.ROOT_URL || DEFAULT_ROOT_URL; |
||||
|
|
||||
|
if ( |
||||
|
path.startsWith('/api/') || |
||||
|
isFileRequest(path) /*|| |
||||
|
!environment.production*/ |
||||
|
) { |
||||
|
// Skip
|
||||
|
next(); |
||||
|
} else { |
||||
|
const indexHtml = interpolate(indexHtmlMap[languageCode], { |
||||
|
currentDate, |
||||
|
languageCode, |
||||
|
path, |
||||
|
rootUrl, |
||||
|
description: descriptions[languageCode], |
||||
|
featureGraphicPath: |
||||
|
locales[path]?.featureGraphicPath ?? 'assets/cover.png', |
||||
|
title: locales[path]?.title ?? title |
||||
|
}); |
||||
|
|
||||
|
return response.send(indexHtml); |
||||
|
} |
||||
|
}; |
Loading…
Reference in new issue