Moving Docs and Faq to separate lazy loaded module
This commit is contained in:
4587
frontend/src/app/docs/api-docs/api-docs-data.ts
Normal file
4587
frontend/src/app/docs/api-docs/api-docs-data.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
<div *ngFor="let item of tabData">
|
||||
<p *ngIf="( item.type === 'category' ) && ( item.showConditions.indexOf(network.val) > -1 )">{{ item.title }}</p>
|
||||
<a *ngIf="( item.type !== 'category' ) && ( item.showConditions.indexOf(network.val) > -1 )" [routerLink]="['./']" fragment="{{ item.fragment }}" (click)="navLinkClick($event)">{{ item.title }}</a>
|
||||
</div>
|
||||
13
frontend/src/app/docs/api-docs/api-docs-nav.component.scss
Normal file
13
frontend/src/app/docs/api-docs/api-docs-nav.component.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
p {
|
||||
color: #4a68b9;
|
||||
font-weight: 700;
|
||||
margin: 10px 0;
|
||||
margin: 15px 0 10px 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
margin: 5px 0;
|
||||
}
|
||||
31
frontend/src/app/docs/api-docs/api-docs-nav.component.ts
Normal file
31
frontend/src/app/docs/api-docs/api-docs-nav.component.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { restApiDocsData } from './api-docs-data';
|
||||
import { faqData } from './api-docs-data';
|
||||
|
||||
@Component({
|
||||
selector: 'app-api-docs-nav',
|
||||
templateUrl: './api-docs-nav.component.html',
|
||||
styleUrls: ['./api-docs-nav.component.scss']
|
||||
})
|
||||
export class ApiDocsNavComponent implements OnInit {
|
||||
|
||||
@Input() network: any;
|
||||
@Input() whichTab: string;
|
||||
@Output() navLinkClickEvent: EventEmitter<any> = new EventEmitter();
|
||||
tabData: any[];
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
if( this.whichTab === 'rest' ) {
|
||||
this.tabData = restApiDocsData;
|
||||
} else if( this.whichTab = 'faq' ) {
|
||||
this.tabData = faqData;
|
||||
}
|
||||
}
|
||||
|
||||
navLinkClick( event ) {
|
||||
this.navLinkClickEvent.emit( event );
|
||||
}
|
||||
|
||||
}
|
||||
111
frontend/src/app/docs/api-docs/api-docs.component.html
Normal file
111
frontend/src/app/docs/api-docs/api-docs.component.html
Normal file
@@ -0,0 +1,111 @@
|
||||
<ng-container *ngIf="{ val: network$ | async } as network">
|
||||
<div class="container-xl text-left">
|
||||
|
||||
<div id="faq" *ngIf="whichTab === 'faq'">
|
||||
|
||||
<div id="doc-nav-desktop" class="hide-on-mobile" [ngClass]="desktopDocsNavPosition">
|
||||
<app-api-docs-nav (navLinkClickEvent)="anchorLinkClick( $event )" [network]="{ val: network$ | async }" [whichTab]="whichTab"></app-api-docs-nav>
|
||||
</div>
|
||||
|
||||
<div class="doc-content">
|
||||
|
||||
<div class="doc-item-container" *ngFor="let item of faq">
|
||||
<h3 *ngIf="item.type === 'category'">{{ item.title }}</h3>
|
||||
<div *ngIf="item.type !== 'category'" class="endpoint-container" id="{{ item.fragment }}">
|
||||
<a id="{{ item.fragment + '-tab-header' }}" class="section-header" (click)="anchorLinkClick( $event )" [routerLink]="['./']" fragment="{{ item.fragment }}"><table><tr><td>{{ item.title }}</td><td><span>{{ item.category }}</span></td></tr></table></a>
|
||||
<div class="endpoint-content">
|
||||
<div class="endpoint" [innerHTML]="item.answer | noSanitize"></div>
|
||||
<div class="blockchain-wrapper" *ngIf="item.fragment === 'what-is-a-mempool-explorer'">
|
||||
<app-blockchain></app-blockchain>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="restAPI" *ngIf="whichTab === 'rest'">
|
||||
|
||||
<div id="doc-nav-desktop" class="hide-on-mobile" [ngClass]="desktopDocsNavPosition">
|
||||
<app-api-docs-nav (navLinkClickEvent)="anchorLinkClick( $event )" [network]="{ val: network$ | async }" [whichTab]="whichTab"></app-api-docs-nav>
|
||||
</div>
|
||||
|
||||
<div class="doc-content">
|
||||
|
||||
<p class="hide-on-mobile no-bottom-space">Reference for the {{ network.val === '' ? 'Bitcoin' : network.val.charAt(0).toUpperCase() + network.val.slice(1) }} <ng-container i18n="api-docs.title">API service</ng-container>.</p>
|
||||
|
||||
<div class="doc-item-container" *ngFor="let item of restDocs">
|
||||
<h3 *ngIf="( item.type === 'category' ) && ( item.showConditions.indexOf(network.val) > -1 )">{{ item.title }}</h3>
|
||||
<div *ngIf="( item.type !== 'category' ) && ( item.showConditions.indexOf(network.val) > -1 )" class="endpoint-container" id="{{ item.fragment }}">
|
||||
<a id="{{ item.fragment + '-tab-header' }}" class="section-header" (click)="anchorLinkClick( $event )" [routerLink]="['./']" fragment="{{ item.fragment }}">{{ item.title }} <span>{{ item.category }}</span></a>
|
||||
<div class="endpoint-content">
|
||||
<div class="endpoint">
|
||||
<div class="subtitle" i18n="Api docs endpoint">Endpoint</div>
|
||||
<ng-container *ngIf="item.httpRequestMethod === 'GET' && network.val === 'bisq' && item.codeExample.hasOwnProperty('bisq');else liquid_link_example" #bisq_link_example>
|
||||
<a [href]="wrapUrl(network.val, item.codeExample.bisq)" target="_blank">{{ item.httpRequestMethod }} {{ baseNetworkUrl }}/api{{ item.urlString }}</a>
|
||||
</ng-container>
|
||||
<ng-template #liquid_link_example>
|
||||
<ng-container *ngIf="item.httpRequestMethod === 'GET' && network.val === 'liquid' && item.codeExample.hasOwnProperty('liquid');else default_link_example">
|
||||
<a [href]="wrapUrl(network.val, item.codeExample.liquid)" target="_blank">{{ item.httpRequestMethod }} {{ baseNetworkUrl }}/api{{ item.urlString }}</a>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
<ng-template #default_link_example>
|
||||
<ng-container *ngIf="item.httpRequestMethod === 'GET'">
|
||||
<a [href]="wrapUrl(network.val, item.codeExample.default)" target="_blank">{{ item.httpRequestMethod }} {{ baseNetworkUrl }}/api{{ item.urlString }}</a>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
<div *ngIf="item.httpRequestMethod === 'POST'">{{ item.httpRequestMethod }} {{ item.urlString }}</div>
|
||||
</div>
|
||||
<div class="description">
|
||||
<div class="subtitle" i18n>Description</div>
|
||||
<ng-container *ngIf="network.val === 'bisq' && item.description.hasOwnProperty('bisq');else liquid_description" #bisq_description>
|
||||
<div [innerHTML]="item.description.bisq" i18n></div>
|
||||
</ng-container>
|
||||
<ng-template #liquid_description>
|
||||
<ng-container *ngIf="network.val === 'liquid' && item.description.hasOwnProperty('liquid');else default_description">
|
||||
<div [innerHTML]="item.description.liquid" i18n></div>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
<ng-template #default_description>
|
||||
<div [innerHTML]="item.description.default" i18n></div>
|
||||
</ng-template>
|
||||
</div>
|
||||
<ng-container *ngIf="network.val === 'bisq' && item.codeExample.hasOwnProperty('bisq');else liquid_code_example" #bisq_code_example>
|
||||
<app-code-template [hostname]="hostname" [baseNetworkUrl]="baseNetworkUrl" [method]="item.httpRequestMethod" [code]="item.codeExample.bisq" [network]="network.val" ></app-code-template>
|
||||
</ng-container>
|
||||
<ng-template #liquid_code_example>
|
||||
<ng-container *ngIf="network.val === 'liquid' && item.codeExample.hasOwnProperty('liquid');else default_code_example">
|
||||
<app-code-template [hostname]="hostname" [baseNetworkUrl]="baseNetworkUrl" [method]="item.httpRequestMethod" [code]="item.codeExample.liquid" [network]="network.val" ></app-code-template>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
<ng-template #default_code_example>
|
||||
<app-code-template [hostname]="hostname" [baseNetworkUrl]="baseNetworkUrl" [method]="item.httpRequestMethod" [code]="item.codeExample.default" [network]="network.val" ></app-code-template>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="websocketAPI" *ngIf="( whichTab === 'websocket' ) && ( network.val !== 'bisq' )">
|
||||
<div class="api-category">
|
||||
<div class="websocket">
|
||||
<div class="endpoint">
|
||||
<div class="subtitle" i18n="Api docs endpoint">Endpoint</div>
|
||||
{{ wrapUrl(network.val, wsDocs, true) }}
|
||||
</div>
|
||||
<div class="description">
|
||||
<div class="subtitle" i18n>Description</div>
|
||||
<div i18n="api-docs.websocket.websocket">Default push: <code>{{ '{' }} action: 'want', data: ['blocks', ...] {{ '}' }}</code> to express what you want pushed. Available: <code>blocks</code>, <code>mempool-blocks</code>, <code>live-2h-chart</code>, and <code>stats</code>.<br><br>Push transactions related to address: <code>{{ '{' }} 'track-address': '3PbJ...bF9B' {{ '}' }}</code> to receive all new transactions containing that address as input or output. Returns an array of transactions. <code>address-transactions</code> for new mempool transactions, and <code>block-transactions</code> for new block confirmed transactions.</div>
|
||||
</div>
|
||||
<app-code-template [method]="'websocket'" [hostname]="hostname" [code]="wsDocs" [network]="network.val" ></app-code-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
256
frontend/src/app/docs/api-docs/api-docs.component.scss
Normal file
256
frontend/src/app/docs/api-docs/api-docs.component.scss
Normal file
@@ -0,0 +1,256 @@
|
||||
.text-small {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #1d1f31;
|
||||
font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;
|
||||
}
|
||||
|
||||
tr {
|
||||
white-space: inherit;
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
li.nav-item {
|
||||
width: 100%;
|
||||
@media (min-width: 676px){
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.no-bottom-space {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link.active {
|
||||
border-bottom: 1px solid #fff;
|
||||
@media (min-width: 676px){
|
||||
border-bottom: 1px solid #11131f;
|
||||
}
|
||||
}
|
||||
|
||||
.code-tab {
|
||||
width: auto;
|
||||
margin: 20px auto 10px;
|
||||
li.nav-item {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.code {
|
||||
.tab-content {
|
||||
padding: 0px;
|
||||
}
|
||||
.nav-tabs .nav-link.active {
|
||||
border-bottom: 1px solid #11131f;
|
||||
}
|
||||
.subtitle {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
.description {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.title {
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
.subtitle {
|
||||
font-weight: bold;
|
||||
}
|
||||
.divider {
|
||||
width: 100%;
|
||||
margin: 30px auto;
|
||||
height: 1px;
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.difficulty {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
#doc-nav-desktop {
|
||||
width: 300px;
|
||||
margin-top: -15px;
|
||||
}
|
||||
|
||||
#doc-nav-desktop.relative {
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#doc-nav-desktop.fixed {
|
||||
float: unset;
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
overflow-y: auto;
|
||||
height: calc(100vh - 50px);
|
||||
scrollbar-color: #2d3348 #11131f;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: #11131f;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #2d3348;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.doc-content {
|
||||
width: calc(100% - 330px);
|
||||
float: right;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 2rem 0 0 0;
|
||||
}
|
||||
|
||||
.endpoint-container:before {
|
||||
display: block;
|
||||
content: " ";
|
||||
height: 1px;
|
||||
margin-top: -1px;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.endpoint-container .section-header {
|
||||
display: block;
|
||||
background-color: #2d3348;
|
||||
color: #1bd8f4;
|
||||
padding: 1rem 1.3rem 1rem 1.3rem;
|
||||
font-weight: bold;
|
||||
border-radius: 0.25rem;
|
||||
margin: 20px 0 20px 0;
|
||||
font-size: 24px;
|
||||
position: relative;
|
||||
}
|
||||
.endpoint-container .section-header:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.endpoint-container .section-header span {
|
||||
color: #fff;
|
||||
background-color: #653b9c;
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
padding: 8px 10px;
|
||||
letter-spacing: 1px;
|
||||
border-radius: 0.25rem;
|
||||
font-family: monospace;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.endpoint-container .section-header table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.endpoint-container .section-header table td:first-child {
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
#doc-nav-mobile {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
width: calc(100% - 60px);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
#doc-nav-mobile .card-body {
|
||||
padding: 0 1.25rem 1.25rem 1.25rem;
|
||||
}
|
||||
|
||||
#doc-nav-mobile > div {
|
||||
background-color: #2d3348;
|
||||
z-index: 100;
|
||||
border-radius: 0 0 0.5rem 0.5rem;
|
||||
height: 55vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#doc-nav-mobile button {
|
||||
width: 100%;
|
||||
background-color: #105fb0;
|
||||
color: #fff;
|
||||
border-color: #105fb0;
|
||||
border-radius: 0.5rem 0.5rem 0 0;
|
||||
}
|
||||
|
||||
.blockchain-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.blockchain-wrapper::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
|
||||
.hide-on-mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.doc-content {
|
||||
width: 100%;
|
||||
margin-top: -20px;
|
||||
float: unset;
|
||||
}
|
||||
|
||||
.endpoint-container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
transition: 0.5s height ease;
|
||||
}
|
||||
|
||||
.endpoint-container .section-header {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.endpoint-container .section-header span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.endpoint-container:before {
|
||||
height: 5px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.endpoint-container .endpoint-content {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
opacity: 0;
|
||||
transition: 0.5s opacity ease;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
|
||||
.hide-on-desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.doc-item-container:last-of-type .endpoint-container {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
}
|
||||
164
frontend/src/app/docs/api-docs/api-docs.component.ts
Normal file
164
frontend/src/app/docs/api-docs/api-docs.component.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { Component, OnInit, Input, ViewChild, ElementRef } from '@angular/core';
|
||||
import { Env, StateService } from '../../services/state.service';
|
||||
import { Observable, merge, of } from 'rxjs';
|
||||
import { SeoService } from '../../services/seo.service';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { faqData, restApiDocsData, wsApiDocsData } from './api-docs-data';
|
||||
|
||||
@Component({
|
||||
selector: 'app-api-docs',
|
||||
templateUrl: './api-docs.component.html',
|
||||
styleUrls: ['./api-docs.component.scss']
|
||||
})
|
||||
export class ApiDocsComponent implements OnInit {
|
||||
hostname = document.location.hostname;
|
||||
network$: Observable<string>;
|
||||
active = 0;
|
||||
env: Env;
|
||||
code: any;
|
||||
baseNetworkUrl = '';
|
||||
@Input() whichTab: string;
|
||||
desktopDocsNavPosition = "relative";
|
||||
faq: any[];
|
||||
restDocs: any[];
|
||||
wsDocs: any;
|
||||
screenWidth: number;
|
||||
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
private seoService: SeoService,
|
||||
private route: ActivatedRoute,
|
||||
) { }
|
||||
|
||||
ngAfterViewInit() {
|
||||
const that = this;
|
||||
setTimeout( () => {
|
||||
if( this.route.snapshot.fragment ) {
|
||||
this.openEndpointContainer( this.route.snapshot.fragment );
|
||||
}
|
||||
window.addEventListener('scroll', function() {
|
||||
that.desktopDocsNavPosition = ( window.pageYOffset > 182 ) ? "fixed" : "relative";
|
||||
});
|
||||
}, 1 );
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.env = this.stateService.env;
|
||||
this.seoService.setTitle($localize`:@@e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4:API`);
|
||||
this.network$ = merge(of(''), this.stateService.networkChanged$).pipe(
|
||||
tap((network: string) => {
|
||||
if (this.env.BASE_MODULE === 'mempool' && network !== '') {
|
||||
this.baseNetworkUrl = `/${network}`;
|
||||
} else if (this.env.BASE_MODULE === 'liquid') {
|
||||
if (!['', 'liquid'].includes(network)) {
|
||||
this.baseNetworkUrl = `/${network}`;
|
||||
}
|
||||
}
|
||||
return network;
|
||||
})
|
||||
);
|
||||
|
||||
if (document.location.port !== '') {
|
||||
this.hostname = `${this.hostname}:${document.location.port}`;
|
||||
}
|
||||
|
||||
this.hostname = `${document.location.protocol}//${this.hostname}`;
|
||||
|
||||
this.faq = faqData;
|
||||
this.restDocs = restApiDocsData;
|
||||
this.wsDocs = wsApiDocsData;
|
||||
|
||||
this.network$.subscribe((network) => {
|
||||
this.active = (network === 'liquid' || network === 'liquidtestnet') ? 2 : 0;
|
||||
});
|
||||
}
|
||||
|
||||
anchorLinkClick( event: any ) {
|
||||
let targetId = "";
|
||||
if( event.target.nodeName === "A" ) {
|
||||
targetId = event.target.hash.substring(1);
|
||||
} else {
|
||||
let element = event.target;
|
||||
while( element.nodeName !== "A" ) {
|
||||
element = element.parentElement;
|
||||
}
|
||||
targetId = element.hash.substring(1);
|
||||
}
|
||||
if( this.route.snapshot.fragment === targetId ) {
|
||||
document.getElementById( targetId ).scrollIntoView();
|
||||
}
|
||||
this.openEndpointContainer( targetId );
|
||||
}
|
||||
|
||||
openEndpointContainer( targetId ) {
|
||||
const tabHeaderHeight = document.getElementById( targetId + "-tab-header" ).scrollHeight;
|
||||
if( ( window.innerWidth <= 992 ) && ( ( this.whichTab === 'rest' ) || ( this.whichTab === 'faq' ) ) && targetId ) {
|
||||
const endpointContainerEl = document.querySelector<HTMLElement>( "#" + targetId );
|
||||
const endpointContentEl = document.querySelector<HTMLElement>( "#" + targetId + " .endpoint-content" );
|
||||
const endPointContentElHeight = endpointContentEl.clientHeight;
|
||||
|
||||
if( endpointContentEl.classList.contains( "open" ) ) {
|
||||
endpointContainerEl.style.height = "auto";
|
||||
endpointContentEl.style.top = "-10000px";
|
||||
endpointContentEl.style.opacity = "0";
|
||||
endpointContentEl.classList.remove( "open" );
|
||||
} else {
|
||||
endpointContainerEl.style.height = endPointContentElHeight + tabHeaderHeight + 28 + "px";
|
||||
endpointContentEl.style.top = tabHeaderHeight + 28 + "px";
|
||||
endpointContentEl.style.opacity = "1";
|
||||
endpointContentEl.classList.add( "open" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrapUrl(network: string, code: any, websocket: boolean = false) {
|
||||
|
||||
let curlResponse = [];
|
||||
if (['', 'mainnet'].includes(network)){
|
||||
curlResponse = code.codeSampleMainnet.curl;
|
||||
}
|
||||
if (network === 'testnet') {
|
||||
curlResponse = code.codeSampleTestnet.curl;
|
||||
}
|
||||
if (network === 'signet') {
|
||||
curlResponse = code.codeSampleSignet.curl;
|
||||
}
|
||||
if (network === 'liquid') {
|
||||
curlResponse = code.codeSampleLiquid.curl;
|
||||
}
|
||||
if (network === 'liquidtestnet') {
|
||||
curlResponse = code.codeSampleLiquidTestnet.curl;
|
||||
}
|
||||
if (network === 'bisq') {
|
||||
curlResponse = code.codeSampleBisq.curl;
|
||||
}
|
||||
|
||||
let curlNetwork = '';
|
||||
if (this.env.BASE_MODULE === 'mempool') {
|
||||
if (!['', 'mainnet'].includes(network)) {
|
||||
curlNetwork = `/${network}`;
|
||||
}
|
||||
} else if (this.env.BASE_MODULE === 'liquid') {
|
||||
if (!['', 'liquid'].includes(network)) {
|
||||
curlNetwork = `/${network}`;
|
||||
}
|
||||
}
|
||||
|
||||
let text = code.codeTemplate.curl;
|
||||
for (let index = 0; index < curlResponse.length; index++) {
|
||||
const curlText = curlResponse[index];
|
||||
const indexNumber = index + 1;
|
||||
text = text.replace('%{' + indexNumber + '}', curlText);
|
||||
}
|
||||
|
||||
if (websocket) {
|
||||
const wsHostname = this.hostname.replace('https://', 'wss://');
|
||||
wsHostname.replace('http://', 'ws://');
|
||||
return `${wsHostname}${curlNetwork}${text}`;
|
||||
}
|
||||
return `${this.hostname}${curlNetwork}${text}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<div class="code">
|
||||
<ul ngbNav #navCodeTemplate="ngbNav" class="nav-tabs code-tab">
|
||||
<li ngbNavItem *ngIf="code.codeTemplate.curl && method !== 'websocket'">
|
||||
<a ngbNavLink (click)="adjustContainerHeight( $event )">cURL</a>
|
||||
<ng-template ngbNavContent>
|
||||
<div class="subtitle"><ng-container i18n="API Docs code example">Code Example</ng-container> <app-clipboard [text]="wrapCurlTemplate(code)"></app-clipboard></div>
|
||||
<pre><code [innerText]="wrapCurlTemplate(code)"></code></pre>
|
||||
</ng-template>
|
||||
</li>
|
||||
<li ngbNavItem *ngIf="network !== 'liquidtestnet'">
|
||||
<a ngbNavLink (click)="adjustContainerHeight( $event )" >CommonJS</a>
|
||||
<ng-template ngbNavContent>
|
||||
<div class="subtitle"><ng-container i18n="API Docs code example">Code Example</ng-container> <app-clipboard [text]="wrapCommonJS(code)"></app-clipboard></div>
|
||||
<div class="links">
|
||||
<a [href]="npmGithubLink()" target="_blank">GitHub Repo</a>
|
||||
</div>
|
||||
<pre><code [innerText]="wrapCommonJS(code)"></code></pre>
|
||||
</ng-template>
|
||||
</li>
|
||||
<li ngbNavItem>
|
||||
<a ngbNavLink (click)="adjustContainerHeight( $event )" *ngIf="network !== 'liquidtestnet'">ES Module</a>
|
||||
<ng-template ngbNavContent>
|
||||
<div class="subtitle"><ng-container i18n="API Docs install lib">Install Package</ng-container> <app-clipboard [text]="wrapImportTemplate()"></app-clipboard></div>
|
||||
<div class="links">
|
||||
<a [href]="npmGithubLink()" target="_blank">GitHub Repo</a>
|
||||
<a [href]="npmModuleLink()" target="_blank">NPM Package</a>
|
||||
</div>
|
||||
<pre><code [innerText]="wrapImportTemplate()"></code></pre>
|
||||
<div class="subtitle"><ng-container i18n="API Docs code example">Code Example</ng-container> <app-clipboard [text]="wrapEsModule(code)"></app-clipboard></div>
|
||||
<pre><code [innerText]="wrapEsModule(code)"></code></pre>
|
||||
</ng-template>
|
||||
</li>
|
||||
</ul>
|
||||
<div [ngbNavOutlet]="navCodeTemplate"></div>
|
||||
<div *ngIf="code.codeTemplate && wrapResponse(code) !== ''" class="response">
|
||||
<div class="subtitle"><ng-container i18n="API Docs API response">Response</ng-container> <app-clipboard [text]="wrapResponse(code)"></app-clipboard></div>
|
||||
<pre><code [innerText]="wrapResponse(code)"></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,97 @@
|
||||
.text-small {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #1d1f31;
|
||||
font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;
|
||||
}
|
||||
|
||||
tr {
|
||||
white-space: inherit;
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
li.nav-item {
|
||||
width: 100%;
|
||||
@media (min-width: 676px){
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link.active {
|
||||
border-bottom: 1px solid #fff;
|
||||
@media (min-width: 676px){
|
||||
border-bottom: 1px solid #11131f;
|
||||
}
|
||||
}
|
||||
|
||||
.code-tab {
|
||||
width: auto;
|
||||
margin: 20px auto 10px;
|
||||
li.nav-item {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.code {
|
||||
.tab-content {
|
||||
padding: 0px;
|
||||
}
|
||||
.nav-tabs .nav-link.active {
|
||||
border-bottom: 1px solid #11131f;
|
||||
}
|
||||
.subtitle {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
.description {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.title {
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
.subtitle {
|
||||
font-weight: bold;
|
||||
}
|
||||
.divider {
|
||||
width: 100%;
|
||||
margin: 30px auto;
|
||||
height: 1px;
|
||||
background: #333;
|
||||
}
|
||||
.websocket {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.difficulty {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.links {
|
||||
margin-bottom: 5px;
|
||||
a {
|
||||
font-size: 14px;
|
||||
margin: 0px 10px 0px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
font-size: 87.5%;
|
||||
color: #f18920;
|
||||
background-color: #1d1f31;
|
||||
padding: 30px;
|
||||
code{
|
||||
background-color: transparent;
|
||||
white-space: break-spaces;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
333
frontend/src/app/docs/code-template/code-template.component.ts
Normal file
333
frontend/src/app/docs/code-template/code-template.component.ts
Normal file
@@ -0,0 +1,333 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Env, StateService } from '../../services/state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-code-template',
|
||||
templateUrl: './code-template.component.html',
|
||||
styleUrls: ['./code-template.component.scss']
|
||||
})
|
||||
export class CodeTemplateComponent implements OnInit {
|
||||
@Input() network: string;
|
||||
@Input() code: any;
|
||||
@Input() hostname: string;
|
||||
@Input() baseNetworkUrl: string;
|
||||
@Input() method: 'GET' | 'POST' | 'websocket' = 'GET';
|
||||
env: Env;
|
||||
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.env = this.stateService.env;
|
||||
}
|
||||
|
||||
adjustContainerHeight( event ) {
|
||||
if( ( window.innerWidth <= 992 ) && ( this.method !== "websocket" ) ) {
|
||||
const urlObj = new URL( window.location + "" );
|
||||
const endpointContainerEl = document.querySelector<HTMLElement>( urlObj.hash );
|
||||
const endpointContentEl = document.querySelector<HTMLElement>( urlObj.hash + " .endpoint-content" );
|
||||
window.setTimeout( function() {
|
||||
endpointContainerEl.style.height = endpointContentEl.clientHeight + 90 + "px";
|
||||
}, 550);
|
||||
}
|
||||
}
|
||||
|
||||
npmGithubLink(){
|
||||
let npmLink = `https://github.com/mempool/mempool.js`;
|
||||
if (this.network === 'bisq') {
|
||||
npmLink = `https://github.com/mempool/mempool.js/tree/main/npm-bisq-js`;
|
||||
}
|
||||
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
|
||||
npmLink = `https://github.com/mempool/mempool.js/tree/main/npm-liquid-js`;
|
||||
}
|
||||
return npmLink;
|
||||
}
|
||||
|
||||
npmModuleLink() {
|
||||
let npmLink = `https://www.npmjs.org/package/@mempool/mempool.js`;
|
||||
if (this.network === 'bisq') {
|
||||
npmLink = `https://www.npmjs.org/package/@mempool/bisq.js`;
|
||||
}
|
||||
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
|
||||
npmLink = `https://www.npmjs.org/package/@mempool/liquid.js`;
|
||||
}
|
||||
return npmLink;
|
||||
}
|
||||
|
||||
normalizeHostsESModule(codeText: string) {
|
||||
if (this.env.BASE_MODULE === 'mempool') {
|
||||
if (['liquid', 'bisq'].includes(this.network)) {
|
||||
codeText = codeText.replace('%{0}', this.network);
|
||||
} else {
|
||||
codeText = codeText.replace('%{0}', 'bitcoin');
|
||||
}
|
||||
if(['', 'main', 'liquid', 'bisq', 'liquidtestnet'].includes(this.network)) {
|
||||
codeText = codeText.replace('mempoolJS();', `mempoolJS({
|
||||
hostname: '${document.location.hostname}'
|
||||
});`);
|
||||
} else {
|
||||
codeText = codeText.replace('mempoolJS();', `mempoolJS({
|
||||
hostname: '${document.location.hostname}',
|
||||
network: '${this.network}'
|
||||
});`);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.env.BASE_MODULE === 'bisq') {
|
||||
codeText = codeText.replace('} = mempoolJS();', ` = bisqJS();`);
|
||||
codeText = codeText.replace('{ %{0}: ', '');
|
||||
}
|
||||
|
||||
if (this.env.BASE_MODULE === 'liquid') {
|
||||
codeText = codeText.replace('} = mempoolJS();', ` = liquidJS();`);
|
||||
codeText = codeText.replace('{ %{0}: ', '');
|
||||
}
|
||||
return codeText;
|
||||
}
|
||||
|
||||
normalizeHostsCommonJS(codeText: string) {
|
||||
if (this.env.BASE_MODULE === 'mempool') {
|
||||
if (['liquid', 'bisq'].includes(this.network)) {
|
||||
codeText = codeText.replace('%{0}', this.network);
|
||||
} else {
|
||||
codeText = codeText.replace('%{0}', 'bitcoin');
|
||||
}
|
||||
if(['', 'main', 'liquid', 'bisq'].includes(this.network)) {
|
||||
codeText = codeText.replace('mempoolJS();', `mempoolJS({
|
||||
hostname: '${document.location.hostname}'
|
||||
});`);
|
||||
} else {
|
||||
codeText = codeText.replace('mempoolJS();', `mempoolJS({
|
||||
hostname: '${document.location.hostname}',
|
||||
network: '${this.network}'
|
||||
});`);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.env.BASE_MODULE === 'bisq') {
|
||||
codeText = codeText.replace('} = mempoolJS();', ` = bisqJS();`);
|
||||
codeText = codeText.replace('{ %{0}: ', '');
|
||||
}
|
||||
|
||||
if (this.env.BASE_MODULE === 'liquid') {
|
||||
codeText = codeText.replace('} = mempoolJS();', ` = liquidJS();`);
|
||||
codeText = codeText.replace('{ %{0}: ', '');
|
||||
}
|
||||
return codeText;
|
||||
}
|
||||
|
||||
wrapEsModule(code: any) {
|
||||
let codeText: string;
|
||||
if (code.codeTemplate) {
|
||||
codeText = this.normalizeHostsESModule(code.codeTemplate.esModule);
|
||||
|
||||
if(this.network === '' || this.network === 'main') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleMainnet.esModule);
|
||||
}
|
||||
if (this.network === 'testnet') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleTestnet.esModule);
|
||||
}
|
||||
if (this.network === 'signet') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleSignet.esModule);
|
||||
}
|
||||
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleLiquid.esModule);
|
||||
}
|
||||
if (this.network === 'bisq') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleBisq.esModule);
|
||||
}
|
||||
|
||||
let importText = `import mempoolJS from "@mempool/mempool.js";`;
|
||||
if (this.env.BASE_MODULE === 'bisq') {
|
||||
importText = `import bisqJS from "@mempool/bisq.js";`;
|
||||
}
|
||||
if (this.env.BASE_MODULE === 'liquid') {
|
||||
importText = `import liquidJS from "@mempool/liquid.js";`;
|
||||
}
|
||||
|
||||
return `${importText}
|
||||
|
||||
const init = async () => {
|
||||
${codeText}
|
||||
};
|
||||
init();`;
|
||||
}
|
||||
}
|
||||
|
||||
wrapCommonJS(code: any) {
|
||||
let codeText: string;
|
||||
if (code.codeTemplate) {
|
||||
codeText = this.normalizeHostsCommonJS(code.codeTemplate.commonJS);
|
||||
|
||||
if(this.network === '' || this.network === 'main') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleMainnet.esModule);
|
||||
}
|
||||
if (this.network === 'testnet') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleTestnet.esModule);
|
||||
}
|
||||
if (this.network === 'signet') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleSignet.esModule);
|
||||
}
|
||||
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleLiquid.esModule);
|
||||
}
|
||||
if (this.network === 'bisq') {
|
||||
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleBisq.esModule);
|
||||
}
|
||||
|
||||
if (code.noWrap) {
|
||||
return codeText;
|
||||
}
|
||||
|
||||
let importText = `<script src="https://mempool.space/mempool.js"></script>`;
|
||||
if (this.env.BASE_MODULE === 'bisq') {
|
||||
importText = `<script src="https://bisq.markets/bisq.js"></script>`;
|
||||
}
|
||||
if (this.env.BASE_MODULE === 'liquid') {
|
||||
importText = `<script src="https://liquid.network/liquid.js"></script>`;
|
||||
}
|
||||
|
||||
let resultHtml = '<pre id="result"></pre>';
|
||||
if (this.method === 'websocket') {
|
||||
resultHtml = `<h2>Blocks</h2><pre id="result-blocks">Waiting for data</pre><br>
|
||||
<h2>Mempool Info</h2><pre id="result-mempool-info">Waiting for data</pre><br>
|
||||
<h2>Transactions</h2><pre id="result-transactions">Waiting for data</pre><br>
|
||||
<h2>Mempool Blocks</h2><pre id="result-mempool-blocks">Waiting for data</pre><br>`;
|
||||
}
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
${importText}
|
||||
<script>
|
||||
const init = async () => {
|
||||
${codeText}
|
||||
};
|
||||
init();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
${resultHtml}
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
}
|
||||
|
||||
wrapImportTemplate() {
|
||||
|
||||
let importTemplate = `# npm
|
||||
npm install @mempool/mempool.js --save
|
||||
|
||||
# yarn
|
||||
yarn add @mempool/mempool.js`;
|
||||
|
||||
if (this.env.BASE_MODULE === 'bisq') {
|
||||
importTemplate = `# npm
|
||||
npm install @mempool/bisq.js --save
|
||||
|
||||
# yarn
|
||||
yarn add @mempool/bisq.js`;
|
||||
}
|
||||
|
||||
if (this.env.BASE_MODULE === 'liquid') {
|
||||
importTemplate = `# npm
|
||||
npm install @mempool/liquid.js --save
|
||||
|
||||
# yarn
|
||||
yarn add @mempool/liquid.js`;
|
||||
}
|
||||
|
||||
return importTemplate;
|
||||
}
|
||||
|
||||
wrapCurlTemplate(code: any) {
|
||||
if (code.codeTemplate) {
|
||||
if (this.network === 'testnet') {
|
||||
return this.replaceCurlPlaceholder(code.codeTemplate.curl, code.codeSampleTestnet);
|
||||
}
|
||||
if (this.network === 'signet') {
|
||||
return this.replaceCurlPlaceholder(code.codeTemplate.curl, code.codeSampleSignet);
|
||||
}
|
||||
if (this.network === 'liquid') {
|
||||
return this.replaceCurlPlaceholder(code.codeTemplate.curl, code.codeSampleLiquid);
|
||||
}
|
||||
if (this.network === 'liquidtestnet') {
|
||||
return this.replaceCurlPlaceholder(code.codeTemplate.curl, code.codeSampleLiquidTestnet);
|
||||
}
|
||||
if (this.network === 'bisq') {
|
||||
return this.replaceCurlPlaceholder(code.codeTemplate.curl, code.codeSampleBisq);
|
||||
}
|
||||
if (this.network === '' || this.network === 'main') {
|
||||
return this.replaceCurlPlaceholder(code.codeTemplate.curl, code.codeSampleMainnet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrapResponse(code: any) {
|
||||
if (this.method === 'websocket') {
|
||||
return '';
|
||||
}
|
||||
if (this.network === 'testnet') {
|
||||
return code.codeSampleTestnet.response;
|
||||
}
|
||||
if (this.network === 'signet') {
|
||||
return code.codeSampleSignet.response;
|
||||
}
|
||||
if (this.network === 'liquid') {
|
||||
return code.codeSampleLiquid.response;
|
||||
}
|
||||
if (this.network === 'liquidtestnet') {
|
||||
return code.codeSampleLiquidTestnet.response;
|
||||
}
|
||||
if (this.network === 'bisq') {
|
||||
return code.codeSampleBisq.response;
|
||||
}
|
||||
return code.codeSampleMainnet.response;
|
||||
}
|
||||
|
||||
replaceJSPlaceholder(text: string, code: any) {
|
||||
for (let index = 0; index < code.length; index++) {
|
||||
const textReplace = code[index];
|
||||
const indexNumber = index + 1;
|
||||
text = text.replace('%{' + indexNumber + '}', textReplace);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
replaceCurlPlaceholder(curlText: any, code: any) {
|
||||
let text = curlText;
|
||||
text = text.replace( "[[hostname]]", this.hostname );
|
||||
text = text.replace( "[[baseNetworkUrl]]", this.baseNetworkUrl );
|
||||
for (let index = 0; index < code.curl.length; index++) {
|
||||
const textReplace = code.curl[index];
|
||||
const indexNumber = index + 1;
|
||||
text = text.replace('%{' + indexNumber + '}', textReplace);
|
||||
}
|
||||
|
||||
if (this.env.BASE_MODULE === 'mempool') {
|
||||
if (this.network === 'main' || this.network === '') {
|
||||
if (this.method === 'POST') {
|
||||
return `curl -X POST -sSLd "${text}"`;
|
||||
}
|
||||
return `curl -sSL "${this.hostname}${text}"`;
|
||||
}
|
||||
if (this.method === 'POST') {
|
||||
return `curl -X POST -sSLd "${text}"`;
|
||||
}
|
||||
return `curl -sSL "${this.hostname}/${this.network}${text}"`;
|
||||
} else if (this.env.BASE_MODULE === 'liquid') {
|
||||
if (this.method === 'POST') {
|
||||
if (this.network !== 'liquid') {
|
||||
text = text.replace('/api', `/${this.network}/api`);
|
||||
}
|
||||
return `curl -X POST -sSLd "${text}"`;
|
||||
}
|
||||
return ( this.network === 'liquid' ? `curl -sSL "${this.hostname}${text}"` : `curl -sSL "${this.hostname}/${this.network}${text}"` );
|
||||
} else {
|
||||
return `curl -sSL "${this.hostname}${text}"`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
22
frontend/src/app/docs/docs.module.ts
Normal file
22
frontend/src/app/docs/docs.module.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { ApiDocsComponent } from './/api-docs/api-docs.component';
|
||||
import { DocsComponent } from './docs/docs.component';
|
||||
import { ApiDocsNavComponent } from './api-docs/api-docs-nav.component';
|
||||
import { CodeTemplateComponent } from './code-template/code-template.component';
|
||||
import { DocsRoutingModule } from './docs.routing.module';
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ApiDocsComponent,
|
||||
CodeTemplateComponent,
|
||||
ApiDocsNavComponent,
|
||||
DocsComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
DocsRoutingModule,
|
||||
]
|
||||
})
|
||||
export class DocsModule { }
|
||||
58
frontend/src/app/docs/docs.routing.module.ts
Normal file
58
frontend/src/app/docs/docs.routing.module.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { DocsComponent } from './docs/docs.component';
|
||||
|
||||
const browserWindow = window || {};
|
||||
// @ts-ignore
|
||||
const browserWindowEnv = browserWindow.__env || {};
|
||||
|
||||
let routes: Routes = [];
|
||||
|
||||
if (browserWindowEnv.BASE_MODULE && (browserWindowEnv.BASE_MODULE === 'bisq' || browserWindowEnv.BASE_MODULE === 'liquid')) {
|
||||
routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'api/rest'
|
||||
},
|
||||
{
|
||||
path: 'api/:type',
|
||||
component: DocsComponent
|
||||
},
|
||||
{
|
||||
path: 'api',
|
||||
redirectTo: 'api/rest'
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: 'api/rest'
|
||||
}
|
||||
];
|
||||
} else {
|
||||
routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'faq'
|
||||
},
|
||||
{
|
||||
path: 'api/:type',
|
||||
component: DocsComponent
|
||||
},
|
||||
{
|
||||
path: 'faq',
|
||||
component: DocsComponent
|
||||
},
|
||||
{
|
||||
path: 'api',
|
||||
redirectTo: 'api/rest'
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: 'api/faq'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
})
|
||||
export class DocsRoutingModule { }
|
||||
48
frontend/src/app/docs/docs/docs.component.html
Normal file
48
frontend/src/app/docs/docs/docs.component.html
Normal file
@@ -0,0 +1,48 @@
|
||||
<div class="container-xl">
|
||||
<div class="text-center">
|
||||
|
||||
<h2 i18n="documentation.title">Documentation</h2>
|
||||
|
||||
<ul ngbNav #nav="ngbNav" [(activeId)]="activeTab" class="nav-tabs">
|
||||
|
||||
<li [ngbNavItem]="0" *ngIf="showFaqTab">
|
||||
<a ngbNavLink [routerLink]="['/docs/faq' | relativeUrl]">FAQ</a>
|
||||
<ng-template ngbNavContent>
|
||||
|
||||
<app-api-docs [whichTab]="'faq'"></app-api-docs>
|
||||
|
||||
</ng-template>
|
||||
</li>
|
||||
|
||||
<li [ngbNavItem]="1">
|
||||
<a ngbNavLink [routerLink]="['/docs/api/rest' | relativeUrl]">API - REST</a>
|
||||
<ng-template ngbNavContent>
|
||||
|
||||
<app-api-docs [whichTab]="'rest'"></app-api-docs>
|
||||
|
||||
</ng-template>
|
||||
</li>
|
||||
|
||||
<li [ngbNavItem]="2" *ngIf="showWebSocketTab">
|
||||
<a ngbNavLink [routerLink]="['/docs/api/websocket' | relativeUrl]">API - WebSocket</a>
|
||||
<ng-template ngbNavContent>
|
||||
|
||||
<app-api-docs [whichTab]="'websocket'"></app-api-docs>
|
||||
|
||||
</ng-template>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<div id="main-tab-content" [ngbNavOutlet]="nav" class="mt-2"></div>
|
||||
|
||||
<br>
|
||||
|
||||
<div id="footer" class="text-center">
|
||||
<a [routerLink]="['/terms-of-service']" i18n="shared.terms-of-service|Terms of Service">Terms of Service</a>
|
||||
|
|
||||
<a [routerLink]="['/privacy-policy']" i18n="shared.privacy-policy|Privacy Policy">Privacy Policy</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
9
frontend/src/app/docs/docs/docs.component.scss
Normal file
9
frontend/src/app/docs/docs/docs.component.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
#main-tab-content {
|
||||
text-align: left;
|
||||
padding-top: 10px;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
#footer {
|
||||
clear: both;
|
||||
}
|
||||
47
frontend/src/app/docs/docs/docs.component.ts
Normal file
47
frontend/src/app/docs/docs/docs.component.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Env, StateService } from '../../services/state.service';
|
||||
import { WebsocketService } from '../../services/websocket.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-docs',
|
||||
templateUrl: './docs.component.html',
|
||||
styleUrls: ['./docs.component.scss']
|
||||
})
|
||||
export class DocsComponent implements OnInit {
|
||||
|
||||
activeTab = 0;
|
||||
env: Env;
|
||||
showWebSocketTab = true;
|
||||
showFaqTab = true;
|
||||
|
||||
@HostBinding('attr.dir') dir = 'ltr';
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private stateService: StateService,
|
||||
private websocket: WebsocketService,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.websocket.want(['blocks']);
|
||||
const url = this.route.snapshot.url;
|
||||
if (url[0].path === "faq" ) {
|
||||
this.activeTab = 0;
|
||||
} else if( url[1].path === "rest" ) {
|
||||
this.activeTab = 1;
|
||||
} else {
|
||||
this.activeTab = 2;
|
||||
}
|
||||
|
||||
this.env = this.stateService.env;
|
||||
this.showWebSocketTab = ( ! ( ( this.stateService.network === "bisq" ) || ( this.stateService.network === "liquidtestnet" ) ) );
|
||||
this.showFaqTab = ( this.env.BASE_MODULE === 'mempool' ) ? true : false;
|
||||
|
||||
document.querySelector<HTMLElement>( "html" ).style.scrollBehavior = "smooth";
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
document.querySelector<HTMLElement>( "html" ).style.scrollBehavior = "auto";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user