mirror of
https://github.com/mempool/mempool.git
synced 2024-11-19 09:52:14 +01:00
Adding support for optional frontend config.
Dropdown network selector is hidden by default, and enabled using config. fixes #79
This commit is contained in:
parent
7e9ba6b983
commit
0a264a7078
@ -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:
|
||||
|
4
frontend/.gitignore
vendored
4
frontend/.gitignore
vendored
@ -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
|
||||
|
@ -30,7 +30,9 @@
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
"scripts": [
|
||||
"generated-config.js"
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
|
36
frontend/generate-config.js
Normal file
36
frontend/generate-config.js
Normal file
@ -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');
|
6
frontend/mempool-frontend-config.sample.json
Normal file
6
frontend/mempool-frontend-config.sample.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"TESTNET_ENABLED": false,
|
||||
"LIQUID_ENABLED": false,
|
||||
"ELCTRS_ITEMS_PER_PAGE": 25,
|
||||
"KEEP_BLOCKS_AMOUNT": 8
|
||||
}
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -6,14 +6,14 @@
|
||||
<div class="badge badge-warning connection-badge" style="left: 30px;" *ngIf="connectionState === 1">Reconnecting...</div>
|
||||
</a>
|
||||
|
||||
<div class="btn-group" style="margin-right: 16px;">
|
||||
<div class="btn-group" style="margin-right: 16px;" *ngIf="env.TESTNET_ENABLED || env.LIQUID_ENABLED">
|
||||
<button type="button" (click)="networkDropdownHidden = !networkDropdownHidden" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<div class="dropdown-menu" [class.d-block]="!networkDropdownHidden">
|
||||
<a class="dropdown-item mainnet" [class.active]="network === ''" routerLink="/"><img src="./resources/bitcoin-logo.png" style="width: 35.5px;"> Mainnet</a>
|
||||
<a class="dropdown-item liquid" [class.active]="network === 'liquid'" routerLink="/liquid"><img src="./resources/liquid-logo.png" style="width: 35.5px;"> Liquid</a>
|
||||
<a class="dropdown-item testnet" [class.active]="network === 'testnet'" routerLink="/testnet"><img src="./resources/testnet-logo.png" style="width: 35.5px;"> Testnet</a>
|
||||
<a *ngIf="env.LIQUID_ENABLED" class="dropdown-item liquid" [class.active]="network === 'liquid'" routerLink="/liquid"><img src="./resources/liquid-logo.png" style="width: 35.5px;"> Liquid</a>
|
||||
<a *ngIf="env.TESTNET_ENABLED" class="dropdown-item testnet" [class.active]="network === 'testnet'" routerLink="/testnet"><img src="./resources/testnet-logo.png" style="width: 35.5px;"> Testnet</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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<string>(1);
|
||||
blocks$ = new ReplaySubject<[Block, boolean, boolean]>(KEEP_BLOCKS_AMOUNT);
|
||||
blocks$ = new ReplaySubject<[Block, boolean, boolean]>(env.KEEP_BLOCKS_AMOUNT);
|
||||
conversions$ = new ReplaySubject<any>(1);
|
||||
mempoolStats$ = new ReplaySubject<MemPoolState>(1);
|
||||
mempoolBlocks$ = new ReplaySubject<MempoolBlock[]>(1);
|
||||
|
Loading…
Reference in New Issue
Block a user