From 0a264a707803cff03b06c96b419ed8a3cea44563 Mon Sep 17 00:00:00 2001 From: softsimon Date: Mon, 22 Jun 2020 22:10:49 +0700 Subject: [PATCH] Adding support for optional frontend config. Dropdown network selector is hidden by default, and enabled using config. fixes #79 --- README.md | 7 ++++ frontend/.gitignore | 4 +++ frontend/angular.json | 4 ++- frontend/generate-config.js | 36 +++++++++++++++++++ frontend/mempool-frontend-config.sample.json | 6 ++++ frontend/package.json | 5 +-- frontend/src/app/app.constants.ts | 20 +++++++++-- .../app/components/block/block.component.ts | 4 +-- .../master-page/master-page.component.html | 6 ++-- .../master-page/master-page.component.ts | 2 ++ frontend/src/app/services/state.service.ts | 4 +-- 11 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 frontend/generate-config.js create mode 100644 frontend/mempool-frontend-config.sample.json diff --git a/README.md b/README.md index 66ef48845..5af4a8d56 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,13 @@ Build the frontend static HTML/CSS/JS, rsync the output into nginx folder: sudo rsync -av --delete dist/mempool/ /var/www/html/ ``` +### Optional frontend configuration +In the `frontend` folder, make a copy of the sample config and modify it to fit your settings. + +```bash + cp mempool-frontend-config.sample.json mempool-frontend-config.json +``` + ## Try It Out If everything went okay you should see the beautiful mempool :grin: diff --git a/frontend/.gitignore b/frontend/.gitignore index 1b086fca2..aa63d58c5 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -48,3 +48,7 @@ Thumbs.db src/resources/assets.json src/resources/assets.minimal.json src/resources/pools.json + +# environment config +mempool-frontend-config.json +generated-config.js diff --git a/frontend/angular.json b/frontend/angular.json index 4db637818..b6fce6d00 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -30,7 +30,9 @@ "styles": [ "src/styles.scss" ], - "scripts": [] + "scripts": [ + "generated-config.js" + ] }, "configurations": { "production": { diff --git a/frontend/generate-config.js b/frontend/generate-config.js new file mode 100644 index 000000000..614e61e5f --- /dev/null +++ b/frontend/generate-config.js @@ -0,0 +1,36 @@ +var fs = require('fs'); + +const CONFIG_FILE_NAME = 'mempool-frontend-config.json'; +const GENERATED_CONFIG_FILE_NAME = 'generated-config.js'; + +let settings = []; +let configContent = {}; + +try { + const rawConfig = fs.readFileSync(CONFIG_FILE_NAME); + configContent = JSON.parse(rawConfig); +} catch (e) { + if (e.code !== 'ENOENT') { + throw new Error(e); + } +} + +for (setting in configContent) { + settings.push({ + key: setting, + value: configContent[setting] + }); +} + +const code = `(function (window) { + window.__env = window.__env || {};${settings.reduce((str, obj) => `${str} + window.__env.${obj.key} = ${ typeof obj.value === 'string' ? `'${obj.value}'` : obj.value };`, '')} + }(this));`; + +try { + fs.writeFileSync(GENERATED_CONFIG_FILE_NAME, code, 'utf8'); +} catch (e) { + throw new Error(e); +} + +console.log('Config file generated'); \ No newline at end of file diff --git a/frontend/mempool-frontend-config.sample.json b/frontend/mempool-frontend-config.sample.json new file mode 100644 index 000000000..13ba1cd5d --- /dev/null +++ b/frontend/mempool-frontend-config.sample.json @@ -0,0 +1,6 @@ +{ + "TESTNET_ENABLED": false, + "LIQUID_ENABLED": false, + "ELCTRS_ITEMS_PER_PAGE": 25, + "KEEP_BLOCKS_AMOUNT": 8 +} \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 924f6176d..a7a4dc76c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -21,10 +21,11 @@ "main": "index.ts", "scripts": { "ng": "ng", - "start": "npm run sync-assets-dev && ng serve --proxy-config proxy.conf.json", - "build": "ng build --prod && npm run sync-assets", + "start": "npm run generate-config && npm run sync-assets-dev && ng serve --proxy-config proxy.conf.json", + "build": "npm run generate-config && ng build --prod && npm run sync-assets", "sync-assets": "node sync-assets.js", "sync-assets-dev": "node sync-assets.js dev", + "generate-config": "node generate-config.js", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" diff --git a/frontend/src/app/app.constants.ts b/frontend/src/app/app.constants.ts index de257f833..76808bcb9 100644 --- a/frontend/src/app/app.constants.ts +++ b/frontend/src/app/app.constants.ts @@ -34,5 +34,21 @@ export const mempoolFeeColors = [ export const feeLevels = [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 125, 150, 175, 200, 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000]; -export const ELCTRS_ITEMS_PER_PAGE = 25; -export const KEEP_BLOCKS_AMOUNT = 8; +interface Env { + TESTNET_ENABLED: boolean; + LIQUID_ENABLED: boolean; + ELCTRS_ITEMS_PER_PAGE: number; + KEEP_BLOCKS_AMOUNT: number; +}; + +const defaultEnv: Env = { + 'TESTNET_ENABLED': false, + 'LIQUID_ENABLED': false, + 'ELCTRS_ITEMS_PER_PAGE': 25, + 'KEEP_BLOCKS_AMOUNT': 8 +}; + +const browserWindow = window || {}; +// @ts-ignore +const browserWindowEnv = browserWindow.__env || {}; +export const env: Env = Object.assign(defaultEnv, browserWindowEnv); diff --git a/frontend/src/app/components/block/block.component.ts b/frontend/src/app/components/block/block.component.ts index 356e650af..9199a2e5b 100644 --- a/frontend/src/app/components/block/block.component.ts +++ b/frontend/src/app/components/block/block.component.ts @@ -7,7 +7,7 @@ import { Block, Transaction, Vout } from '../../interfaces/electrs.interface'; import { of } from 'rxjs'; import { StateService } from '../../services/state.service'; import { SeoService } from 'src/app/services/seo.service'; -import { ELCTRS_ITEMS_PER_PAGE } from 'src/app/app.constants'; +import { env } from 'src/app/app.constants'; @Component({ selector: 'app-block', @@ -28,7 +28,7 @@ export class BlockComponent implements OnInit, OnDestroy { fees: number; paginationMaxSize: number; page = 1; - itemsPerPage = ELCTRS_ITEMS_PER_PAGE; + itemsPerPage = env.ELCTRS_ITEMS_PER_PAGE; constructor( private route: ActivatedRoute, diff --git a/frontend/src/app/components/master-page/master-page.component.html b/frontend/src/app/components/master-page/master-page.component.html index 022acd7ae..5f971aba2 100644 --- a/frontend/src/app/components/master-page/master-page.component.html +++ b/frontend/src/app/components/master-page/master-page.component.html @@ -6,14 +6,14 @@
Reconnecting...
-
+ diff --git a/frontend/src/app/components/master-page/master-page.component.ts b/frontend/src/app/components/master-page/master-page.component.ts index c7cc33b80..a1987193b 100644 --- a/frontend/src/app/components/master-page/master-page.component.ts +++ b/frontend/src/app/components/master-page/master-page.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit, HostListener } from '@angular/core'; import { StateService } from '../../services/state.service'; +import { env } from 'src/app/app.constants'; @Component({ selector: 'app-master-page', @@ -9,6 +10,7 @@ import { StateService } from '../../services/state.service'; export class MasterPageComponent implements OnInit { network = ''; tvViewRoute = '/tv'; + env = env; navCollapsed = false; connectionState = 2; diff --git a/frontend/src/app/services/state.service.ts b/frontend/src/app/services/state.service.ts index ffb6c9231..438683f6e 100644 --- a/frontend/src/app/services/state.service.ts +++ b/frontend/src/app/services/state.service.ts @@ -4,7 +4,7 @@ import { Block, Transaction } from '../interfaces/electrs.interface'; import { MempoolBlock, MemPoolState } from '../interfaces/websocket.interface'; import { OptimizedMempoolStats } from '../interfaces/node-api.interface'; import { Router, NavigationStart } from '@angular/router'; -import { KEEP_BLOCKS_AMOUNT } from '../app.constants'; +import { env } from '../app.constants'; import { shareReplay, map } from 'rxjs/operators'; interface MarkBlockState { @@ -21,7 +21,7 @@ export class StateService { latestBlockHeight = 0; networkChanged$ = new ReplaySubject(1); - blocks$ = new ReplaySubject<[Block, boolean, boolean]>(KEEP_BLOCKS_AMOUNT); + blocks$ = new ReplaySubject<[Block, boolean, boolean]>(env.KEEP_BLOCKS_AMOUNT); conversions$ = new ReplaySubject(1); mempoolStats$ = new ReplaySubject(1); mempoolBlocks$ = new ReplaySubject(1);