Merge pull request #3878 from mempool/mononaut/full-mempool-graph
Add 'all time' option for mempool graph
This commit is contained in:
		
						commit
						2e285c8d86
					
				@ -211,7 +211,7 @@ class StatisticsApi {
 | 
			
		||||
      CAST(avg(vsize_1800) as DOUBLE) as vsize_1800,
 | 
			
		||||
      CAST(avg(vsize_2000) as DOUBLE) as vsize_2000 \
 | 
			
		||||
      FROM statistics \
 | 
			
		||||
      WHERE added BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW() \
 | 
			
		||||
      ${interval === 'all' ? '' : `WHERE added BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`} \
 | 
			
		||||
      GROUP BY UNIX_TIMESTAMP(added) DIV ${div} \
 | 
			
		||||
      ORDER BY statistics.added DESC;`;
 | 
			
		||||
  }
 | 
			
		||||
@ -259,7 +259,7 @@ class StatisticsApi {
 | 
			
		||||
      vsize_1800,
 | 
			
		||||
      vsize_2000 \
 | 
			
		||||
      FROM statistics \
 | 
			
		||||
      WHERE added BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW() \
 | 
			
		||||
      ${interval === 'all' ? '' : `WHERE added BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`} \
 | 
			
		||||
      GROUP BY UNIX_TIMESTAMP(added) DIV ${div} \
 | 
			
		||||
      ORDER BY statistics.added DESC;`;
 | 
			
		||||
  }
 | 
			
		||||
@ -386,6 +386,17 @@ class StatisticsApi {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $listAll(): Promise<OptimizedStatistic[]> {
 | 
			
		||||
    try {
 | 
			
		||||
      const query = this.getQueryForDays(43200, 'all'); // 12h interval
 | 
			
		||||
      const [rows] = await DB.query({ sql: query, timeout: this.queryTimeout });
 | 
			
		||||
      return this.mapStatisticToOptimizedStatistic(rows as Statistic[]);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('$listAll() error' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      return [];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private mapStatisticToOptimizedStatistic(statistic: Statistic[]): OptimizedStatistic[] {
 | 
			
		||||
    return statistic.map((s) => {
 | 
			
		||||
      return {
 | 
			
		||||
 | 
			
		||||
@ -15,10 +15,11 @@ class StatisticsRoutes {
 | 
			
		||||
      .get(config.MEMPOOL.API_URL_PREFIX + 'statistics/2y', this.$getStatisticsByTime.bind(this, '2y'))
 | 
			
		||||
      .get(config.MEMPOOL.API_URL_PREFIX + 'statistics/3y', this.$getStatisticsByTime.bind(this, '3y'))
 | 
			
		||||
      .get(config.MEMPOOL.API_URL_PREFIX + 'statistics/4y', this.$getStatisticsByTime.bind(this, '4y'))
 | 
			
		||||
      .get(config.MEMPOOL.API_URL_PREFIX + 'statistics/all', this.$getStatisticsByTime.bind(this, 'all'))
 | 
			
		||||
    ;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async $getStatisticsByTime(time: '2h' | '24h' | '1w' | '1m' | '3m' | '6m' | '1y' | '2y' | '3y' | '4y', req: Request, res: Response) {
 | 
			
		||||
  private async $getStatisticsByTime(time: '2h' | '24h' | '1w' | '1m' | '3m' | '6m' | '1y' | '2y' | '3y' | '4y' | 'all', req: Request, res: Response) {
 | 
			
		||||
    res.header('Pragma', 'public');
 | 
			
		||||
    res.header('Cache-control', 'public');
 | 
			
		||||
    res.setHeader('Expires', new Date(Date.now() + 1000 * 300).toUTCString());
 | 
			
		||||
@ -26,10 +27,6 @@ class StatisticsRoutes {
 | 
			
		||||
    try {
 | 
			
		||||
      let result;
 | 
			
		||||
      switch (time as string) {
 | 
			
		||||
        case '2h':
 | 
			
		||||
          result = await statisticsApi.$list2H();
 | 
			
		||||
          res.setHeader('Expires', new Date(Date.now() + 1000 * 30).toUTCString());
 | 
			
		||||
          break;
 | 
			
		||||
        case '24h':
 | 
			
		||||
          result = await statisticsApi.$list24H();
 | 
			
		||||
          res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString());
 | 
			
		||||
@ -58,8 +55,13 @@ class StatisticsRoutes {
 | 
			
		||||
        case '4y':
 | 
			
		||||
          result = await statisticsApi.$list4Y();
 | 
			
		||||
          break;
 | 
			
		||||
        case 'all':
 | 
			
		||||
          result = await statisticsApi.$listAll();
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          result = await statisticsApi.$list2H();
 | 
			
		||||
          res.setHeader('Expires', new Date(Date.now() + 1000 * 30).toUTCString());
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
      res.json(result);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
 | 
			
		||||
@ -20,39 +20,46 @@
 | 
			
		||||
                <fa-icon [icon]="['fas', 'tv']" [fixedWidth]="true" i18n-title="master-page.tvview" title="TV view"></fa-icon>
 | 
			
		||||
              </a>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="btn-group btn-group-toggle" name="radioBasic">
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '2h'">
 | 
			
		||||
                <input type="radio" [value]="'2h'" [routerLink]="['/graphs' | relativeUrl]" fragment="2h" formControlName="dateSpan"> 2H
 | 
			
		||||
                (LIVE)
 | 
			
		||||
              </label>
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
 | 
			
		||||
                <input type="radio" [value]="'24h'" [routerLink]="['/graphs' | relativeUrl]" fragment="24h" formControlName="dateSpan">
 | 
			
		||||
                24H
 | 
			
		||||
              </label>
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
 | 
			
		||||
                <input type="radio" [value]="'1w'" [routerLink]="['/graphs' | relativeUrl]" fragment="1w" formControlName="dateSpan"> 1W
 | 
			
		||||
              </label>
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
 | 
			
		||||
                <input type="radio" [value]="'1m'" [routerLink]="['/graphs' | relativeUrl]" fragment="1m" formControlName="dateSpan"> 1M
 | 
			
		||||
              </label>
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
 | 
			
		||||
                <input type="radio" [value]="'3m'" [routerLink]="['/graphs' | relativeUrl]" fragment="3m" formControlName="dateSpan"> 3M
 | 
			
		||||
              </label>
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
 | 
			
		||||
                <input type="radio" [value]="'6m'" [routerLink]="['/graphs' | relativeUrl]" fragment="6m" formControlName="dateSpan"> 6M
 | 
			
		||||
              </label>
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
 | 
			
		||||
                <input type="radio" [value]="'1y'" [routerLink]="['/graphs' | relativeUrl]" fragment="1y" formControlName="dateSpan"> 1Y
 | 
			
		||||
              </label>
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
 | 
			
		||||
                <input type="radio" [value]="'2y'" [routerLink]="['/graphs' | relativeUrl]" fragment="2y" formControlName="dateSpan"> 2Y
 | 
			
		||||
              </label>
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
 | 
			
		||||
                <input type="radio" [value]="'3y'" [routerLink]="['/graphs' | relativeUrl]" fragment="3y" formControlName="dateSpan"> 3Y
 | 
			
		||||
              </label>
 | 
			
		||||
              <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '4y'">
 | 
			
		||||
                <input type="radio" [value]="'4y'" [routerLink]="['/graphs' | relativeUrl]" fragment="4y" formControlName="dateSpan"> 4Y
 | 
			
		||||
              </label>
 | 
			
		||||
            <div class="btn-toggle-rows" name="radioBasic">
 | 
			
		||||
              <div class="btn-group btn-group-toggle">
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '2h'">
 | 
			
		||||
                  <input type="radio" [value]="'2h'" [routerLink]="['/graphs' | relativeUrl]" fragment="2h" formControlName="dateSpan"> 2H
 | 
			
		||||
                  (LIVE)
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
 | 
			
		||||
                  <input type="radio" [value]="'24h'" [routerLink]="['/graphs' | relativeUrl]" fragment="24h" formControlName="dateSpan">
 | 
			
		||||
                  24H
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
 | 
			
		||||
                  <input type="radio" [value]="'1w'" [routerLink]="['/graphs' | relativeUrl]" fragment="1w" formControlName="dateSpan"> 1W
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
 | 
			
		||||
                  <input type="radio" [value]="'1m'" [routerLink]="['/graphs' | relativeUrl]" fragment="1m" formControlName="dateSpan"> 1M
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
 | 
			
		||||
                  <input type="radio" [value]="'3m'" [routerLink]="['/graphs' | relativeUrl]" fragment="3m" formControlName="dateSpan"> 3M
 | 
			
		||||
                </label>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="btn-group btn-group-toggle">
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
 | 
			
		||||
                  <input type="radio" [value]="'6m'" [routerLink]="['/graphs' | relativeUrl]" fragment="6m" formControlName="dateSpan"> 6M
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
 | 
			
		||||
                  <input type="radio" [value]="'1y'" [routerLink]="['/graphs' | relativeUrl]" fragment="1y" formControlName="dateSpan"> 1Y
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
 | 
			
		||||
                  <input type="radio" [value]="'2y'" [routerLink]="['/graphs' | relativeUrl]" fragment="2y" formControlName="dateSpan"> 2Y
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
 | 
			
		||||
                  <input type="radio" [value]="'3y'" [routerLink]="['/graphs' | relativeUrl]" fragment="3y" formControlName="dateSpan"> 3Y
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '4y'">
 | 
			
		||||
                  <input type="radio" [value]="'4y'" [routerLink]="['/graphs' | relativeUrl]" fragment="4y" formControlName="dateSpan"> 4Y
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === 'all'">
 | 
			
		||||
                  <input type="radio" [value]="'all'" [routerLink]="['/graphs' | relativeUrl]" fragment="all" formControlName="dateSpan"><span i18n="all">All</span>
 | 
			
		||||
                </label>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="small-buttons">
 | 
			
		||||
              <div ngbDropdown #myDrop="ngbDropdown">
 | 
			
		||||
 | 
			
		||||
@ -53,17 +53,17 @@
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.formRadioGroup.mining {
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
  @media (min-width: 1035px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 1035px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.formRadioGroup.no-menu {
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
  @media (min-width: 1035px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -33px;
 | 
			
		||||
  }
 | 
			
		||||
@ -183,3 +183,43 @@
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-toggle-rows {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
  align-items: stretch;
 | 
			
		||||
  justify-content: stretch;
 | 
			
		||||
 | 
			
		||||
  .btn-group {
 | 
			
		||||
    flex-grow: 1;
 | 
			
		||||
    flex-shrink: 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (min-width: 500px) {
 | 
			
		||||
    .btn-group:first-child > .btn:last-child {
 | 
			
		||||
      border-top-right-radius: 0;
 | 
			
		||||
      border-bottom-right-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
    .btn-group:last-child > .btn:first-child {
 | 
			
		||||
      border-top-left-radius: 0;
 | 
			
		||||
      border-bottom-left-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 499px) {
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
 | 
			
		||||
    .btn-group:first-child > .btn:first-child {
 | 
			
		||||
      border-bottom-left-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
    .btn-group:first-child > .btn:last-child {
 | 
			
		||||
      border-bottom-right-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
    .btn-group:last-child > .btn:first-child {
 | 
			
		||||
      border-top-left-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
    .btn-group:last-child > .btn:last-child {
 | 
			
		||||
      border-top-right-radius: 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -72,8 +72,10 @@ export class StatisticsComponent implements OnInit {
 | 
			
		||||
    this.route
 | 
			
		||||
      .fragment
 | 
			
		||||
      .subscribe((fragment) => {
 | 
			
		||||
        if (['2h', '24h', '1w', '1m', '3m', '6m', '1y', '2y', '3y', '4y'].indexOf(fragment) > -1) {
 | 
			
		||||
        if (['2h', '24h', '1w', '1m', '3m', '6m', '1y', '2y', '3y', '4y', 'all'].indexOf(fragment) > -1) {
 | 
			
		||||
          this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
 | 
			
		||||
        } else {
 | 
			
		||||
          this.radioGroupForm.controls.dateSpan.setValue('2h', { emitEvent: false });
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
@ -114,7 +116,12 @@ export class StatisticsComponent implements OnInit {
 | 
			
		||||
        if (this.radioGroupForm.controls.dateSpan.value === '3y') {
 | 
			
		||||
          return this.apiService.list3YStatistics$();
 | 
			
		||||
        }
 | 
			
		||||
        return this.apiService.list4YStatistics$();
 | 
			
		||||
        if (this.radioGroupForm.controls.dateSpan.value === '4y') {
 | 
			
		||||
          return this.apiService.list4YStatistics$();
 | 
			
		||||
        }
 | 
			
		||||
        if (this.radioGroupForm.controls.dateSpan.value === 'all') {
 | 
			
		||||
          return this.apiService.listAllTimeStatistics$();
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
    .subscribe((mempoolStats: any) => {
 | 
			
		||||
 | 
			
		||||
@ -72,6 +72,10 @@ export class ApiService {
 | 
			
		||||
    return this.httpClient.get<OptimizedMempoolStats[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/statistics/4y');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  listAllTimeStatistics$(): Observable<OptimizedMempoolStats[]> {
 | 
			
		||||
    return this.httpClient.get<OptimizedMempoolStats[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/statistics/all');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getTransactionTimes$(txIds: string[]): Observable<number[]> {
 | 
			
		||||
    let params = new HttpParams();
 | 
			
		||||
    txIds.forEach((txId: string) => {
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@ do for url in / \
 | 
			
		||||
	'/api/v1/statistics/2y' \
 | 
			
		||||
	'/api/v1/statistics/3y' \
 | 
			
		||||
	'/api/v1/statistics/4y' \
 | 
			
		||||
	'/api/v1/statistics/all' \
 | 
			
		||||
	'/api/v1/mining/pools/24h' \
 | 
			
		||||
	'/api/v1/mining/pools/3d' \
 | 
			
		||||
	'/api/v1/mining/pools/1w' \
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user