git ssb

0+

mixmix / patchbay-scry



Tree: 462c60502f8c45618c08ea0232132580d5801964

Files: 462c60502f8c45618c08ea0232132580d5801964 / views / show.js

5161 bytesRaw
1const { h, Struct, computed, resolve } = require('mutant')
2const pull = require('pull-stream')
3const printTime = require('../lib/print-time')
4
5const YES = '✔'
6const EDIT_YES = '☑'
7const EDIT_NO = '☐'
8
9module.exports = function ScryShow (opts) {
10 const {
11 poll,
12 myFeedId,
13 scuttle,
14 name = k => k.slice(0, 9)
15 // avatar = ''
16 } = opts
17
18 const state = Struct(initialState())
19 fetchState()
20 watchForUpdates(fetchState)
21
22 return h('ScryShow', [
23 h('h1', state.now.title),
24 h('div.closes-at', [
25 'Closes at ',
26 computed(state.now.closesAt, t => t ? t.toString() : '')
27 ]),
28 ScryShowTable(),
29 computed([state.now, state.next], (current, next) => {
30 if (!next.isEditing) return
31 if (next.isPublishing) return h('button', h('i.fa.fa-spin.fa-pulse'))
32
33 const newPosition = current.position.join() !== next.position.join()
34 return h('button',
35 {
36 className: newPosition ? '-primary' : '',
37 disabled: !newPosition,
38 'ev-click': () => {
39 state.next.isPublishing.set(true)
40 const choices = next.position.reduce((acc, el, i) => {
41 if (el) acc.push(i)
42 return acc
43 }, [])
44
45 scuttle.position.async.publishMeetingTime({ poll, choices }, (err, data) => {
46 console.log(err, data)
47 })
48 }
49 }, 'Publish'
50 )
51 })
52 ])
53
54 function ScryShowTable () {
55 return computed(state.now, ({ title, closesAt, times, rows }) => {
56 const style = {
57 display: 'grid',
58 'grid-template-columns': `minmax(8rem, auto) repeat(${times.length}, 4rem)`
59 }
60
61 return [
62 h('div.results', { style }, [
63 times.map(ScryShowTime),
64 rows.map(ScryShowRow)
65 ])
66 ]
67 })
68 }
69
70 function ScryShowRow ({ author, position }) {
71 if (author !== myFeedId) {
72 return [
73 h('div.name', name(author)),
74 position.map(pos => pos
75 ? h('div.position.-yes', YES)
76 : h('div.position.-no')
77 )
78 ]
79 }
80
81 return [
82 h('div.name', name(author)),
83 computed(state.next, ({ isEditing, position }) => {
84 if (isEditing) {
85 return position.map((pos, i) => {
86 return h('div.position.-edit',
87 {
88 'ev-click': () => {
89 const nextPosition = resolve(state.next.position)
90 nextPosition[i] = !pos
91 state.next.position.set(nextPosition)
92 }
93 },
94 pos ? EDIT_YES : EDIT_NO
95 )
96 })
97 }
98
99 return position.map(pos => pos
100 ? h('div.position.-yes', '✔')
101 : h('div.position.-no')
102 )
103 })
104 ]
105 }
106
107 function fetchState () {
108 scuttle.poll.async.get(poll.key, (err, doc) => {
109 if (err) return console.error(err)
110
111 const { title, closesAt, positions } = doc
112 const times = doc.results.map(result => result.choice)
113 const results = times.map(t => doc.results.find(result => result.choice === t))
114 // this ensures results Array is in same order as a times Array
115
116 const rows = positions
117 .reduce((acc, pos) => {
118 if (!acc.includes(pos.value.author)) acc.push(pos.value.author)
119 return acc
120 }, [])
121 .map(author => {
122 const position = times.map((time, i) => {
123 return results[i].voters.hasOwnProperty(author)
124 })
125 return { author, position }
126 })
127
128 const myRow = rows.find(r => r.author === myFeedId)
129 const myPosition = myRow ? myRow.position : Array(times.length).fill(false)
130
131 var isEditing = false
132 if (!myRow) {
133 rows.push({ author: myFeedId, position: myPosition })
134 isEditing = true
135 }
136
137 state.now.set({
138 title,
139 closesAt,
140 times,
141 rows,
142 position: myPosition
143 })
144 state.next.set({
145 position: Array.from(myPosition),
146 isEditing,
147 isPublishing: false
148 })
149 })
150 }
151
152 function watchForUpdates (cb) {
153 // TODO check if isEditing before calling cb
154 // start a loop to trigger cb after finished editing
155 pull(
156 scuttle.poll.pull.updates(poll.key),
157 pull.filter(m => !m.sync),
158 pull.drain(cb)
159 )
160 }
161}
162
163function initialState () {
164 return {
165 now: Struct({
166 title: '',
167 times: [],
168 closesAt: undefined,
169 rows: [],
170 position: []
171 }),
172 next: Struct({
173 position: [],
174 isEditing: false,
175 isPublishing: false
176 })
177 }
178}
179
180// component: show-time
181
182function ScryShowTime (time, i) {
183 const style = { 'grid-column': i + 2 }
184
185 return h('ScryShowTime', { style }, [
186 h('div.month', month(time)),
187 h('div.date', time.getDate()),
188 h('div.day', day(time)),
189 h('div.time', printTime(time))
190 ])
191}
192
193function month (date) {
194 const months = ['Jan', 'Feb', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sept', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
195
196 return months[date.getMonth()]
197}
198
199function day (date) {
200 const days = ['Sun', 'Mon', 'Tues', 'Wed', 'Thu', 'Fri', 'Sat']
201
202 return days[date.getDay()]
203}
204

Built with git-ssb-web