git ssb

0+

mixmix / patchbay-scry



Tree: d6ef2d8d03691e2b92bfa1599d8c4ad87ade87ae

Files: d6ef2d8d03691e2b92bfa1599d8c4ad87ade87ae / views / show.js

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

Built with git-ssb-web