git ssb

16+

Dominic / patchbay



Tree: 6a3d48ccffcc728c78becadf218b6b15fe9f7fc8

Files: 6a3d48ccffcc728c78becadf218b6b15fe9f7fc8 / app / page / network.js

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

Built with git-ssb-web