git ssb

16+

Dominic / patchbay



Tree: bc574122903c7ef4a0abf0fb4918a12a4e96a977

Files: bc574122903c7ef4a0abf0fb4918a12a4e96a977 / app / page / network.js

4756 bytesRaw
1const nest = require('depnest')
2const { h, Value, Dict, onceTrue, computed, watchAll, throttle } = require('mutant')
3const Chart = require('chart.js')
4const pull = require('pull-stream')
5
6const MINUTE = 60 * 1000
7const DAY = 24 * 60 * MINUTE
8
9const GRAPH_Y_STEP = 50
10const GRAPH_Y_MIN = 100
11
12exports.gives = nest({
13 'app.html.menuItem': true,
14 'app.page.network': true
15})
16
17exports.needs = nest({
18 'sbot.obs.connection': 'first'
19})
20
21exports.create = function (api) {
22 return nest({
23 'app.html.menuItem': menuItem,
24 'app.page.network': networkPage
25 })
26
27 function menuItem () {
28 return h('a', {
29 'ev-click': () => api.app.sync.goTo({ page: 'network' })
30 }, '/network')
31 }
32
33 function networkPage (location) {
34 const minsPerStep = 5
35
36 const data = Dict()
37 onceTrue(api.sbot.obs.connection, server => {
38 getData({ data, server, minsPerStep })
39 })
40
41 const latest = Value(toTimeBlock(Date.now(), minsPerStep))
42 // start of the most recent bar
43 setInterval(() => {
44 console.log('boop')
45 latest.set(toTimeBlock(Date.now(), minsPerStep))
46 }, 2 * MINUTE)
47
48 const range = computed([latest], (latest) => {
49 return {
50 upper: latest + minsPerStep * MINUTE,
51 lower: latest + minsPerStep * MINUTE - DAY
52 }
53 })
54
55 //
56
57 const canvas = h('canvas', { height: 300, width: 1200, style: { height: '300px', width: '1200px' } })
58 const page = h('NetworkPage', { title: '/network' }, [
59 h('div.container', [
60 h('h1', 'Network'),
61 canvas
62 ])
63 ])
64
65 initialiseChart({ canvas, data, range })
66
67 return page
68 }
69}
70
71function getData ({ data, server, minsPerStep }) {
72 const query = [
73 {
74 $filter: {
75 timestamp: { $gte: toTimeBlock(Date.now(), minsPerStep) + minsPerStep * MINUTE - DAY }
76 }
77 }, {
78 $map: {
79 ts: ['timestamp']
80 }
81 }
82 ]
83
84 pull(
85 server.query.read({ query, live: true }),
86 pull.filter(m => !m.sync),
87 pull.map(m => toTimeBlock(m.ts, minsPerStep)),
88 pull.drain(ts => {
89 if (data.has(ts)) data.put(ts, data.get(ts) + 1)
90 else data.put(ts, 1)
91 })
92 )
93}
94
95function initialiseChart ({ canvas, data, range }) {
96 var chart = new Chart(canvas.getContext('2d'), chartConfig(range))
97
98 const chartData = computed([throttle(data, 300), range], (data, range) => {
99 return Object.keys(data)
100 .filter(ts => ts >= range.lower && ts < range.upper)
101 .map(ts => {
102 return {
103 t: Number(ts), // NOTE - might need to offset by a half-step ?
104 y: data[ts]
105 }
106 })
107 })
108 chartData(data => {
109 chart.data.datasets[0].data = data
110 chart.update()
111 })
112
113 // Scales the height of the graph (to the visible data)!
114 watchAll([chartData, range], (chartData, range) => {
115 const { lower, upper } = range
116 const slice = chartData
117 .filter(d => d.t >= lower && d.t < upper) // unnecessary ??
118 .map(d => d.y)
119 .sort((a, b) => a > b ? -1 : +1)
120
121 var h = slice[0]
122 if (!h || h < GRAPH_Y_MIN) h = GRAPH_Y_MIN // min-height
123 else h = h + (GRAPH_Y_STEP - h % GRAPH_Y_STEP) // round height to multiples of GRAPH_Y_STEP
124
125 chart.options.scales.yAxes[0].ticks.max = h
126
127 chart.update()
128 })
129
130 // Update the x-axes bounds of the graph!
131 range(range => {
132 const { lower, upper } = range
133
134 chart.options.scales.xAxes[0].time.min = lower
135 chart.options.scales.xAxes[0].time.max = upper
136
137 chart.update()
138 })
139}
140
141// ///// HELPERS /////
142
143function toTimeBlock (ts, minsPerStep) {
144 return Math.floor(ts / (minsPerStep * MINUTE)) * (minsPerStep * MINUTE)
145}
146
147function chartConfig ({ lower, upper }) {
148 const barColor = 'hsla(215, 57%, 60%, 1)'
149
150 return {
151 type: 'bar',
152 data: {
153 datasets: [{
154 backgroundColor: barColor,
155 borderColor: barColor,
156 data: []
157 }]
158 },
159 options: {
160 legend: {
161 display: false
162 },
163 scales: {
164 xAxes: [{
165 type: 'time',
166 distribution: 'linear',
167 time: {
168 // unit: 'day',
169 // min: lower,
170 // max: upper,
171 // tooltipFormat: 'MMMM D',
172 // stepSize: 7
173 unit: 'minute',
174 min: lower,
175 max: upper,
176 tooltipFormat: 'HH:mm',
177 stepSize: 240
178 },
179 bounds: 'ticks',
180 ticks: {
181 // maxTicksLimit: 4 // already disabled
182 },
183 gridLines: {
184 display: false
185 },
186 // maxBarThickness: 2
187 }],
188
189 yAxes: [{
190 ticks: {
191 min: 0,
192 stepSize: GRAPH_Y_STEP,
193 suggestedMax: GRAPH_Y_MIN
194 }
195 }]
196 },
197 animation: {
198 // duration: 300
199 }
200 }
201 }
202}
203

Built with git-ssb-web