views/show.jsView |
---|
1 | | -const { h, Struct, Array: MutantArray, map, computed, resolve } = require('mutant') |
| 1 … | +const { h, Struct, computed, resolve } = require('mutant') |
| 2 … | +const pull = require('pull-stream') |
2 | 3 … | const printTime = require('../lib/print-time') |
3 | 4 … | |
| 5 … | +const YES = '✔' |
| 6 … | +const EDIT_YES = '☑' |
| 7 … | +const EDIT_NO = '☐' |
| 8 … | + |
4 | 9 … | module.exports = function ScryShow (opts) { |
5 | 10 … | const { |
6 | | - key, |
| 11 … | + poll, |
| 12 … | + myFeedId, |
7 | 13 … | scuttle, |
8 | 14 … | name = k => k.slice(0, 9) |
9 | 15 … | |
10 | 16 … | } = opts |
11 | 17 … | |
12 | 18 … | const state = Struct(initialState()) |
13 | 19 … | fetchState() |
| 20 … | + watchForUpdates(fetchState) |
14 | 21 … | |
15 | | - const body = computed(state, state => { |
16 | | - const { title, closesAt, times, rows } = state |
| 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')) |
17 | 32 … | |
18 | | - const style = { |
19 | | - display: 'grid', |
20 | | - 'grid-template-columns': `minmax(8rem, auto) repeat(${times.length}, 4rem)` |
| 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 … | + ] |
21 | 79 … | } |
22 | 80 … | |
23 | 81 … | return [ |
24 | | - h('h1', title), |
25 | | - h('div.closes-at', [ |
26 | | - 'Closes at ', |
27 | | - closesAt ? closesAt.toString() : '' |
28 | | - ]), |
29 | | - h('div.results', { style }, [ |
30 | | - times.map(ScryShowTime), |
31 | | - rows.map(({ author, position }, i) => { |
32 | | - return [ |
33 | | - h('div.name', name(author)), |
34 | | - position.map(pos => pos |
35 | | - ? h('div.position.-yes', '✔') |
36 | | - : h('div.position.-no') |
| 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 |
37 | 95 … | ) |
38 | | - ] |
39 | | - |
40 | | - }) |
| 96 … | + }) |
| 97 … | + } |
41 | 98 … | |
42 | | - ]) |
| 99 … | + return position.map(pos => pos |
| 100 … | + ? h('div.position.-yes', '✔') |
| 101 … | + : h('div.position.-no') |
| 102 … | + ) |
| 103 … | + }) |
43 | 104 … | ] |
44 | | - }) |
45 | | - |
46 | | - return h('ScryShow', body) |
47 | | - |
48 | | - function initialState () { |
49 | | - return { |
50 | | - title: '', |
51 | | - times: [], |
52 | | - closesAt: undefined, |
53 | | - rows: [] |
54 | | - } |
55 | 105 … | } |
56 | 106 … | |
57 | 107 … | function fetchState () { |
58 | | - scuttle.poll.async.get(key, (err, doc) => { |
| 108 … | + scuttle.poll.async.get(poll.key, (err, doc) => { |
59 | 109 … | if (err) return console.error(err) |
60 | 110 … | |
61 | 111 … | const { title, closesAt, positions } = doc |
62 | 112 … | const times = doc.results.map(result => result.choice) |
74 | 124 … | }) |
75 | 125 … | return { author, position } |
76 | 126 … | }) |
77 | 127 … | |
78 | | - state.set({ |
| 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({ |
79 | 138 … | title, |
80 | 139 … | closesAt, |
81 | 140 … | times, |
82 | | - rows |
| 141 … | + rows, |
| 142 … | + position: myPosition |
83 | 143 … | }) |
| 144 … | + state.next.set({ |
| 145 … | + position: Array.from(myPosition), |
| 146 … | + isEditing, |
| 147 … | + isPublishing: false |
| 148 … | + }) |
84 | 149 … | }) |
85 | 150 … | } |
| 151 … | + |
| 152 … | + function watchForUpdates (cb) { |
| 153 … | + |
| 154 … | + |
| 155 … | + pull( |
| 156 … | + scuttle.poll.pull.updates(poll.key), |
| 157 … | + pull.filter(m => !m.sync), |
| 158 … | + pull.drain(cb) |
| 159 … | + ) |
| 160 … | + } |
86 | 161 … | } |
87 | 162 … | |
| 163 … | +function 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 … | + |
| 181 … | + |
88 | 182 … | function ScryShowTime (time, i) { |
89 | 183 … | const style = { 'grid-column': i + 2 } |
90 | 184 … | |
91 | 185 … | return h('ScryShowTime', { style }, [ |