diff --git a/back/webmin/graphql/resolvers/BigResolver.ts b/back/webmin/graphql/resolvers/BigResolver.ts index fee29143eaeadef0228f5546af7f1e021fd62279..3808fd70b9e9588d52a61fc9eec7b308bc1fc660 100644 --- a/back/webmin/graphql/resolvers/BigResolver.ts +++ b/back/webmin/graphql/resolvers/BigResolver.ts @@ -2,7 +2,7 @@ import {BlockType} from '../types/BlockType' import {WS2PHeadType} from '../types/WS2PHeadType' import {WS2PInfosType} from '../types/WS2PInfosType' import {Resolver} from 'type-graphql/dist/decorators/Resolver' -import {Query} from 'type-graphql' +import {Int, Query} from 'type-graphql' import {gqlNodeStart, gqlNodeState, gqlStopAndResetData} from '../../queries/gql-node-state' import {ApplicationContext} from '../di/application-context' import {gqlCurrent} from '../../queries/gql-current' @@ -11,6 +11,8 @@ import {gqlWs2pInfos} from '../../queries/gql-ws2p' import {gqlIsSyncStarted, gqlSynchronize} from '../../queries/gql-synchronize' import {gqlUid} from '../../queries/gql-uid' import {Arg} from 'type-graphql/dist/decorators/Arg' +import {getForks, getMainChain} from '../../queries/gql-forks' +import {ChainType} from '../types/ChainType' @Resolver() export class BigResolver { @@ -64,4 +66,14 @@ export class BigResolver { uid(@Arg("pub") pub: string): Promise<string|null> { return gqlUid(ApplicationContext.server)(null, { pub }) } + + @Query(type => ChainType) + getMainChain(@Arg("start", type => Int) start: number, @Arg("end", type => Int) end: number): Promise<ChainType> { + return getMainChain(ApplicationContext.server, start, end) + } + + @Query(type => ChainType) + getForks(@Arg("start", type => Int) start: number, @Arg("end", type => Int) end: number): Promise<ChainType> { + return getForks(ApplicationContext.server, start, end) + } } diff --git a/back/webmin/graphql/types/BlockType.ts b/back/webmin/graphql/types/BlockType.ts index a78b74b437c3eca53a53d944c33cb69a13161eef..8b0d939126a02ed137eb679077c5cf2f8bf10031 100644 --- a/back/webmin/graphql/types/BlockType.ts +++ b/back/webmin/graphql/types/BlockType.ts @@ -28,7 +28,7 @@ export class BlockType { @Field(type => [String]) certifications: string[] @Field(type => [BlockTransactionType]) transactions: BlockTransactionType[] @Field(type => Int) medianTime: number - @Field() nonce?: string + @Field() nonce?: number @Field({ nullable: true }) parameters?: string @Field(type => Int) monetaryMass: number @Field(type => Int, { nullable: true }) dividend?: number diff --git a/back/webmin/graphql/types/ChainType.ts b/back/webmin/graphql/types/ChainType.ts new file mode 100644 index 0000000000000000000000000000000000000000..7e132e524dc668bb42e9ed7b6e1424bbbc12627c --- /dev/null +++ b/back/webmin/graphql/types/ChainType.ts @@ -0,0 +1,8 @@ +import {Field, Int, ObjectType} from 'type-graphql' +import {BlockTransactionType} from './BlockTransactionType' +import {BlockType} from './BlockType' + +@ObjectType() +export class ChainType { + @Field(type => [BlockType]) blocks: BlockType[] +} diff --git a/back/webmin/graphql/types/transform/dbblock.transform.ts b/back/webmin/graphql/types/transform/dbblock.transform.ts new file mode 100644 index 0000000000000000000000000000000000000000..4ead7855d3017e195e1da8b0053c432a8f5205b8 --- /dev/null +++ b/back/webmin/graphql/types/transform/dbblock.transform.ts @@ -0,0 +1,40 @@ +import {DBBlock} from 'duniter/app/lib/db/DBBlock' +import {BlockType} from '../BlockType' + + +export function transformDBBlock(b: DBBlock): BlockType { + return { + version: b.version, + number: b.number, + currency: b.currency, + hash: b.hash, + inner_hash: b.inner_hash, + signature: b.signature, + previousHash: b.previousHash, + issuer: b.issuer, + previousIssuer: b.previousIssuer, + time: b.time, + powMin: b.powMin, + unitbase: b.unitbase, + membersCount: b.membersCount, + issuersCount: b.issuersCount, + issuersFrame: b.issuersFrame, + issuersFrameVar: b.issuersFrameVar, + identities: b.identities, + joiners: b.joiners, + actives: b.actives, + leavers: b.leavers, + revoked: b.revoked, + excluded: b.excluded, + certifications: b.certifications, + transactions: b.transactions, + medianTime: b.medianTime, + nonce: b.nonce, + parameters: b.parameters, + monetaryMass: b.monetaryMass, + dividend: b.dividend || undefined, + UDTime: b.UDTime, + writtenOn: b.writtenOn, + written_on: b.written_on, + } +} diff --git a/back/webmin/queries/gql-forks.ts b/back/webmin/queries/gql-forks.ts new file mode 100644 index 0000000000000000000000000000000000000000..762ea5a249d55507f822835b2b052d44befa5afd --- /dev/null +++ b/back/webmin/queries/gql-forks.ts @@ -0,0 +1,21 @@ +import {Server} from 'duniter/server' +import {transformDBBlock} from '../graphql/types/transform/dbblock.transform' +import {ChainType} from '../graphql/types/ChainType' + +export async function getMainChain(server: Server, start: number, end: number): Promise<ChainType> { + const current = await server.dal.getCurrentBlockOrNull() + if (!current) { + return { blocks: [] } + } + const main = await server.dal.getBlocksBetween(start, end) + return { blocks: main.map(transformDBBlock) } +} + +export async function getForks(server: Server, start: number, end: number): Promise<ChainType> { + const current = await server.dal.getCurrentBlockOrNull() + if (!current) { + return { blocks: [] } + } + const main = await server.dal.getPotentialForkBlocks(start, 0, end) + return { blocks: main.map(transformDBBlock) } +} diff --git a/src/components/ForkGraph.vue b/src/components/ForkGraph.vue new file mode 100644 index 0000000000000000000000000000000000000000..48162307be6d38a8e9cb0b12a356c9f1a8944103 --- /dev/null +++ b/src/components/ForkGraph.vue @@ -0,0 +1,249 @@ +<style scoped> + + + line { + stroke-width: 3px; + stroke: red; + } + +</style> + +<template> + <svg :width="width" :height="height"> + <g> + <svg-chain :chain="chain" :xOffset="xOffset" :yOffset="baseYoffset" + :pCircleR="circleR" + :pInterCircle="interCircle"></svg-chain> + <svg-chain v-for="(fork, i) in forkPoints" :chain="fork.blocks" :xOffset="fork.x" :yOffset="fork.y" + :pCircleR="circleR" + :pInterCircle="interCircle" + :key="i"></svg-chain> + <line + v-for="l in forkLines" + :x1="l.p1.x" + :y1="l.p1.y" + :x2="l.p2.x" + :y2="l.p2.y" + ></line> + </g> + </svg> +</template> + +<script lang="ts"> + import Component from 'vue-class-component'; + import Vue from 'vue'; + import {Prop, Watch} from 'vue-property-decorator'; + import SvgBlock from '@/components/svg/SvgBlock.vue'; + import SvgChain from '@/components/svg/SvgChain.vue'; + import {BlockType} from "../../back/webmin/graphql/types/BlockType"; + + const MAX_ROWS = 50 + const MAX_COLS = 17 + + function initMatrix() { + return Array.from({ length: MAX_ROWS }) + .map(i => Array.from({ length: MAX_COLS }) + .map(j => false)) + } + + @Component({ + components: {SvgChain, SvgBlock}, + }) + export default class extends Vue { + + @Prop(Array) chain: BlockType[] + @Prop(Array) forks: BlockType[][] + + maxCol = 0 + maxRow = 0 + + matrix: boolean[][] = initMatrix() + + forkPoints: ForkPoint[] = [] + forkLines: Line[] = [] + + mounted() { + this.forkChanged() + } + + @Watch('chain') + @Watch('forks') + forkChanged() { + if (this.chain.length) { + const mainFirst = this.chain[0].number + const mainLast = this.chain[this.chain.length - 1].number + const forkHighest = this.forks.reduce((max, f) => Math.max(max, f[f.length - 1].number), mainFirst) + this.maxCol = Math.max(mainLast, forkHighest) - mainFirst + 1 + this.maxRow = this.forks.length + 1 + this.matrix = initMatrix() + this.forkPoints = this.getNewForkPoints() + this.forkLines = this.getNewForkLines() + } + } + + get width() { + return this.xOffset + (this.maxCol) * (2 * this.circleR + this.interCircle) + 'px' + } + + get height() { + return (30 + (this.firstEmptyLine + 1) * this.lineHeight) + 'px' + } + + get firstEmptyLine() { + for (let i = 0; i < this.matrix.length; i++) { + const lineHasData = this.matrix[i].reduce((redux, cell) => redux || cell, false) + if (!lineHasData) { + return i + 1 + } + } + return this.matrix.length + } + + get xOffset() { + return 26 + } + + get circleR() { + return 25 + } + + get interCircle() { + return 10 + } + + get lineHeight() { + return 60 + } + + get baseYoffset() { + return 30 + } + + getNewForkLines(): Line[] { + return this.forks + .map((fork, i) => ({ + cell: this.getTargetCell(fork), + fork + })) + // Only forks with a target + .filter(data => data.cell.col !== -1 && data.cell.row !== -1) + .map(data => { + const cell = data.cell + const displayCell = this.forkPoints.filter(f => f.blocks[0].hash === data.fork[0].hash)[0] + const POS_ON_SOURCE = -45 * Math.PI / 180 + const POS_ON_TARGET = 135 * Math.PI / 180 + return { + p1: { + // Origin + x: (cell.col) * (this.circleR * 2 + this.interCircle) + this.circleR + this.circleR * Math.cos(POS_ON_SOURCE), + y: this.baseYoffset + this.circleR * Math.sin(-POS_ON_SOURCE), + }, + p2: { + // Fork place + x: (cell.col + 1) * (this.circleR * 2 + this.interCircle) + this.circleR + this.circleR * Math.cos(POS_ON_TARGET), + y: (displayCell.yFinal + 1) * this.lineHeight + this.baseYoffset + this.circleR * Math.sin(-POS_ON_TARGET), + }, + } + }) + } + + getNewForkPoints(): ForkPoint[] { + return this.forks.map(fork => { + const cell: Cell = this.getTargetCell(fork) + const y = this.getYoffset(cell, fork) + return { + x: this.getXoffset(cell, fork), + y: y.px, + yFinal: y.yFinal, + blocks: fork, + } + }) + } + + getTargetCell(fork: BlockType[]) { + const forkBlock = fork[0] + const allChains = [this.chain].concat(this.forks) + for (let i = 0; i < allChains.length; i++) { + let chain = allChains[i] + const diff = forkBlock.number - chain[0].number + if (diff > 0) { + const targetBlock = chain[diff - 1] + if (targetBlock && targetBlock.hash === forkBlock.previousHash) { + return { + row: i, + col: targetBlock.number - this.chain[0].number + } + } + else if (!targetBlock) { + return { + row: -1, + col: forkBlock.number - this.chain[0].number - 1, + } + } + } + } + // The origin block does not exist at all + return { + row: -1, + col: -1, + } + } + + getXoffset(cell: Cell, fork: BlockType[]){ + return this.xOffset + (cell.col + 1) * (this.circleR * 2 + this.interCircle) + } + + getYoffset(cell: Cell, fork: BlockType[]): { yFinal: number, px: number } { + if (!cell || !this.chain[0]) { + return { + yFinal: 0, + px: this.xOffset + } + } + let y = 0 + let oneCellConflicts = true + while (oneCellConflicts) { + const taken = fork.map((f, i) => this.matrix[y][cell.col + i]) + oneCellConflicts = taken.reduce((conflicts, cell) => conflicts || cell, false) + if (oneCellConflicts) { + y++ + } + } + // this.matrix[y].forEach((f, i) => this.matrix[y][i] = true) + fork.forEach((f, i) => this.matrix[y][cell.col + i] = true) + this.maxRow = Math.max(this.maxRow, y) + this.maxCol = Math.max(this.maxCol, cell.col + fork.length - 1) + return { + yFinal: y, + px: this.baseYoffset + (y + 1) * this.lineHeight + } + } + + get branches() { + return [this.chain].concat(this.forks) + } + } + + interface ForkPoint { + x: number + y: number + yFinal: number + blocks: BlockType[] + } + + interface Point { + x: number + y: number + } + + interface Line { + p1: Point + p2: Point + } + + interface Cell { + row: number + col: number + } + +</script> diff --git a/src/components/svg/SvgBlock.vue b/src/components/svg/SvgBlock.vue new file mode 100644 index 0000000000000000000000000000000000000000..6d741e314deb2d662d4014b8c956258e3da07295 --- /dev/null +++ b/src/components/svg/SvgBlock.vue @@ -0,0 +1,47 @@ +<style scoped> + circle { + fill: transparent; + stroke: black; + } + + text { + font-family: Consolas, "Courier New", Courier, monospace; + fill: black; + font-size: 10px; + } + + .prevHash { + font-weight: bold; + } +</style> + +<template> + <g :class="{ cssClass: true }"> + <circle :cx="x" :cy="y" :r="r"></circle> + <text :x="x - r + r/4 - 5" :y="y - 3">{{ blockNumber }}</text> + <text :x="x - r + r/4 - 2" :y="y + r/2 - 3">#{{ hash.slice(0, 6) }}</text> +<!-- <text :x="x - r + r/4 - 2" :y="y + r/2 + 5"--> +<!-- class="prevHash" v-if="previousHash">#{{ previousHash && previousHash.slice(0, 6) }}</text>--> + </g> +</template> + +<script lang="ts"> + import Component from 'vue-class-component'; + import Vue from 'vue'; + import {Prop} from 'vue-property-decorator'; + + @Component({}) + export default class extends Vue { + @Prop(Number) x + @Prop(Number) y + @Prop(Number) r + @Prop(Number) number + @Prop(String) hash + @Prop(String) previousHash + @Prop(String) cssClass + + get blockNumber() { + return String(this.number).padStart(7, ' ') + } + } +</script> diff --git a/src/components/svg/SvgChain.vue b/src/components/svg/SvgChain.vue new file mode 100644 index 0000000000000000000000000000000000000000..b63330d96536c79d5f3029673184fb15e96c68f0 --- /dev/null +++ b/src/components/svg/SvgChain.vue @@ -0,0 +1,82 @@ +<style scoped> + + line.chain { + stroke-width: 2px; + stroke: black; + } + +</style> + +<template> + <g> + <svg-block + v-for="c in circles" + :x="c.x" + :y="c.y" + :r="circleR" + :number="c.number" + :hash="c.hash" + :previousHash="c.previousHash" + :key="c.hash" + ></svg-block> + <line class="chain" v-for="(l, index) in lines" :x1="l.x1" :y1="l.y1" :x2="l.x2" :y2="l.y2" :key="index"></line> + </g> +</template> + +<script lang="ts"> + import Component from 'vue-class-component'; + import Vue from 'vue'; + import {Prop} from 'vue-property-decorator'; + import SvgBlock from '@/components/svg/SvgBlock.vue'; + + @Component({ + components: {SvgBlock} + }) + export default class extends Vue { + + @Prop(Array) chain: Block[] + @Prop(Number) xOffset: number + @Prop(Number) yOffset: number + @Prop(Number) pCircleR: number + @Prop(Number) pInterCircle: number + + get circleR() { + return this.pCircleR + } + + get interCircle() { + return this.pInterCircle + } + + get circles() { + const chain: Block[] = this.chain + return chain.map((b, i) => ({ + x: this.xOffset + i * (2 * this.circleR + this.interCircle), + y: this.yPos, + number: b.number, + hash: b.hash, + previousHash: b.previousHash + })) + } + + get lines() { + const offset = 0 + return this.$props.chain.slice(0, this.$props.chain.length - 1).map((b, i) => ({ + x1: this.xOffset + i * (2 * this.circleR + this.interCircle) + this.circleR, + y1: this.yPos, + x2: this.xOffset + i * (2 * this.circleR + this.interCircle) + this.circleR + this.interCircle, + y2: this.yPos, + })) + } + + get yPos() { + return this.yOffset + } + } + + interface Block { + number: number + hash: string + previousHash: string + } +</script> diff --git a/src/lib/services/webmin.service.ts b/src/lib/services/webmin.service.ts index 343d803855d17e177692f3539afbd091d987444f..44b717b00952c3cbdc58b805ee2d5bf372a01194 100644 --- a/src/lib/services/webmin.service.ts +++ b/src/lib/services/webmin.service.ts @@ -1,6 +1,7 @@ import gql from 'graphql-tag' import ApolloClient from 'apollo-client'; import {DBBlock, NodeState, WS2PConnectionInfos, WS2PHead} from '../../../common/types' +import {ChainType} from '../../../back/webmin/graphql/types/ChainType' export class WebminService { @@ -95,7 +96,6 @@ export class WebminService { `, }) .result() - console.log(res.data.nodeState) return res.data.nodeState } @@ -292,4 +292,49 @@ export class WebminService { .result() return res.data.uid } + + async getMainChain(start: number, end: number): Promise<ChainType> { + const res = await this.getApollo() + .watchQuery<{ getMainChain: ChainType }>({ + query: gql` + query ($start: Int!, $end: Int!){ + getMainChain(start: $start, end: $end) { + blocks { + number + hash + } + } + } + `, + variables: { + start, + end + } + }) + .result() + return res.data.getMainChain + } + + async getForks(start: number, end: number): Promise<ChainType> { + const res = await this.getApollo() + .watchQuery<{ getForks: ChainType }>({ + query: gql` + query ($start: Int!, $end: Int!){ + getForks(start: $start, end: $end) { + blocks { + number + hash + previousHash + } + } + } + `, + variables: { + start, + end + } + }) + .result() + return res.data.getForks + } } diff --git a/src/lib/utils/blockstamp.ts b/src/lib/utils/blockstamp.ts new file mode 100644 index 0000000000000000000000000000000000000000..fb822a7e087d259756107b3270bfeccc2716cbc4 --- /dev/null +++ b/src/lib/utils/blockstamp.ts @@ -0,0 +1,3 @@ +export function blockstamp(b: { number: number, hash: string }) { + return [b.number, b.hash].join('-') +} \ No newline at end of file diff --git a/src/views/Home.vue b/src/views/Home.vue index 3eecfded9d1090ee89f7ba1de37e9e5a964aaaaf..ab4746d8792cd1dca080b17b24e9d2f2bedadfe7 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -10,9 +10,9 @@ <b-navbar toggleable="lg" class="bg-light"> <b-navbar-brand id="brand"> - <a v-on:click="reload()"> + <router-link to="/home"> <img src="../assets/250×250.png" width="40" height="40" alt=""> - </a> + </router-link> </b-navbar-brand> <b-navbar-toggle target="nav-text-collapse"></b-navbar-toggle> @@ -21,27 +21,14 @@ <b-collapse id="nav-text-collapse" is-nav> <b-navbar-nav class="mr-auto"> - <b-nav-item><button class="btn"><font-awesome-icon icon="cube"/></button></b-nav-item> - <b-nav-item><button class="btn"><font-awesome-icon icon="cog"/></button></b-nav-item> - </b-navbar-nav> - - <b-navbar-nav> - <b-nav-item> - <b>State = {{ state }}</b> - </b-nav-item> - - <b-nav-item> - <b>Is started = {{ isStarted }}</b> - </b-nav-item> - - <b-nav-item> - <b>{{ hello2 }}</b> + <router-link to="home/forkview"> + <button class="btn"><font-awesome-icon icon="cube"/></button> + </router-link> </b-nav-item> + </b-navbar-nav> - <b-nav-item> - {{ hello }} - </b-nav-item> + <b-navbar-nav> <b-nav-item> @@ -79,13 +66,10 @@ hello = 'wait...' async reload() { - console.log('Reload!') this.hello = await this.$webmin.hello() - // TODO } async created() { - console.log('Created Home') await this.$store.dispatch('resetState') } @@ -106,12 +90,5 @@ return this.$store.state.lastState == 'STARTED' } - get hello2() { - return this.$webmin.hello() - } - - get state() { - return this.$store.state.lastState - } } </script> diff --git a/src/views/home/Forkview.vue b/src/views/home/Forkview.vue new file mode 100644 index 0000000000000000000000000000000000000000..cbda279b62972f27bfe0c3e4230f13fd5b8d08e1 --- /dev/null +++ b/src/views/home/Forkview.vue @@ -0,0 +1,116 @@ +<style lang="css" scoped> + + .col-12.graph { + overflow: auto !important; + } +</style> + +<template> + + <div class="container-fluid"> + <div class="row"> + <div class="col-12"> + <p> + <input type="number" v-model.number="start" @input="refreshForks" /> => + <input type="number" v-model.number="end" @input="refreshForks" /> + <input type="submit" @click="refreshForks" /> + </p> + <b-alert variant="warning" show v-if="end - start > MAX_BLOCKS_ALLOWED">{{ $t('fork.view.too.much', [MAX_BLOCKS_ALLOWED] )}}</b-alert> + </div> + <div class="col-12 graph"> + <ForkGraph :chain="chain" :forks="forks"></ForkGraph> + </div> + </div> + </div> + +</template> + +<script lang="ts"> + import {Component, Vue} from 'vue-property-decorator'; + import ForkGraph from '@/components/ForkGraph.vue'; + import {BlockType} from '../../../back/webmin/graphql/types/BlockType'; + import {blockstamp} from '@/lib/utils/blockstamp'; + + @Component({ + components: {ForkGraph}, + }) + export default class extends Vue { + + MAX_BLOCKS_ALLOWED = 1000 + + start: number = 0 + end: number = 0 + + chain: BlockType[] = [] + forks: BlockType[][] = [] + + async beforeMount() { + const current = await this.$webmin.current() + this.start = current.number - 20 + this.end = current.number + 10 + await this.refreshForks() + } + + async oneLess() { + this.start-- + await this.refreshForks() + } + + async refreshForks() { + if (this.end - this.start <= this.MAX_BLOCKS_ALLOWED) { + this.chain = (await this.$webmin.getMainChain(this.start, this.end)).blocks + this.forks = this.blocks2forks((await this.$webmin.getForks(this.start, this.end)).blocks) + } + } + + private blocks2forks(blocks: BlockType[]) { + const splitters: { [bs: string]: BlockType[] } = {} + blocks.forEach(b => { + const bs = [b.number - 1, b.previousHash].join('-') + if (!splitters[bs]) { + splitters[bs] = [] + } + splitters[bs].push(b) + }) + + const chains: BlockType[][] = [] + + function digChain(currentChain: BlockType[], bs: string) { + const forks = splitters[bs] + if (forks) { + currentChain.push(forks[0]) + digChain(currentChain, blockstamp(forks[0])) + + for (let i = 1; i < forks.length; i++) { + const newChain = [] + // chains.push(newChain) + // digChain(newChain, [forks[i].number, forks[i].hash].join('-')) + } + } + } + + const bss = blocks.map(blockstamp) + + Object.keys(splitters) + // Find the root blocks, not found in the fork blocks + .filter(bs => !bss.includes(bs)) + // Get the older first + .sort((b, a) => parseInt(b) - parseInt(a)) + .forEach(bs => { + const forks = splitters[bs] + for (let i = 0; i < forks.length; i++) { + chains.push([]) + digChain(chains[chains.length - 1], bs) + } + }) + + chains.sort((c1, c2) => { + if (c1.length !== c2.length) { + return c1.length - c2.length + } + return c1[c1.length - 1].number - c2[c2.length - 1].number + }) + return chains + } + } +</script> diff --git a/src/views/home/Overview.vue b/src/views/home/Overview.vue index 53e8fe892624b3417d049de745fc08ff54e382cf..a39b55703f2464eabb13969cd4aea09f04f7f579 100644 --- a/src/views/home/Overview.vue +++ b/src/views/home/Overview.vue @@ -152,8 +152,16 @@ softwares: string[] = [] - async mounted() { + private subscription: ZenObservable.Subscription + async beforeDestroy() { + this.subscription.unsubscribe() + console.log('beforeDestroy') + } + + async beforeMount() { + + console.log('beforeMount') this.current = await this.$webmin.current() this.currentBest = { bs: [this.current.number, this.current.hash].join('-'), count: 1 } this.updateHeads(await this.$webmin.heads()) @@ -166,7 +174,7 @@ } }) - this.$webmin.newDocuments().subscribe(async v => { + this.subscription = this.$webmin.newDocuments().subscribe(async v => { const ev = v.data.newDocuments ev.blocks.forEach(b => console.log(b)) this.blocks += ev.blocks.length diff --git a/src/vue-modules/register-router.ts b/src/vue-modules/register-router.ts index bd3272df25ae72f957318fd7ebf4f8489bc85688..57f1e3be42f30016bcb85ab0aac0eff0af60d122 100644 --- a/src/vue-modules/register-router.ts +++ b/src/vue-modules/register-router.ts @@ -1,10 +1,11 @@ import Vue from 'vue' import Router from 'vue-router' -import {Constants, RouteNames} from '@/lib/constants' +import {RouteNames} from '@/lib/constants' import Home from '@/views/Home.vue' import Loader from '@/views/Loader.vue' import Sync from '@/views/Sync.vue' import Overview from '@/views/home/Overview.vue' +import Forkview from '@/views/home/Forkview.vue' Vue.use(Router) @@ -30,6 +31,10 @@ export default new Router({ path: '', name: 'overview', component: Overview + },{ + path: 'forkview', + name: 'forkview', + component: Forkview }] }, { diff --git a/src/vue-modules/register-store.ts b/src/vue-modules/register-store.ts index 3668d770d3bc2ab4534a6dc27da521ee1e9ac799..50bddb689513b0776ccee072bf5ce247aa74bc31 100644 --- a/src/vue-modules/register-store.ts +++ b/src/vue-modules/register-store.ts @@ -21,7 +21,6 @@ export default function($webmin: WebminService): Store<DuniterNodeState> { }, actions: { async resetState({ commit }) { - console.log('Reset state ...') commit('setLastState', await $webmin.nodeState()) // switch (await this.lastState) { diff --git a/tsconfig.json b/tsconfig.json index a82b7cf410dbe4e98576a4c498ce00c4bd697d62..8a50e24354abfe2a9dfacd1772df658067a57f82 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,6 +29,7 @@ ] }, "include": [ + "src/*.ts", "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"