git ssb

3+

arj / patchbook



Tree: fd2459df8b46e1e0fe589fc20f3d16020399d671

Files: fd2459df8b46e1e0fe589fc20f3d16020399d671 / book / html / layout / detail.js

6598 bytesRaw
1const nest = require('depnest')
2const { h, when, computed, Value, map } = require('mutant')
3const addSuggest = require('suggest-box')
4
5exports.needs = nest({
6 'book.obs.book': 'first',
7 'about.html.image': 'first',
8 'about.obs.name': 'first',
9 'keys.sync.id': 'first',
10 'emoji.async.suggest': 'first',
11 'message.html': {
12 markdown: 'first'
13 },
14 'book.html': {
15 title: 'first',
16 authors: 'first',
17 series: 'first',
18 description: 'first',
19 images: 'first',
20 simpleEmoji: 'first'
21 }
22})
23
24exports.gives = nest('book.html.layout')
25
26exports.create = (api) => {
27 return nest('book.html.layout', bookLayout)
28
29 function ratingEdit(isEditing, value) {
30 return when(isEditing,
31 h('input', {
32 'ev-input': e => value.set(e.target.value),
33 value,
34 placeholder: 'your rating'
35 }),
36 h('span.text', { innerHTML: computed(value, api.book.html.simpleEmoji) })
37 )
38 }
39
40 function ratingTypeEdit(isEditing, value) {
41 let getEmojiSuggestions = api.emoji.async.suggest()
42
43 let ratingTypeInput = h('input', {'ev-input': e => value.set(e.target.value),
44 value: value, placeholder: 'rating type' })
45
46 let suggestWrapper = h('span.ratingType', ratingTypeInput)
47
48 addSuggest(ratingTypeInput, (inputText, cb) => {
49 if (inputText[0] === ':') {
50 cb(null, getEmojiSuggestions(inputText.slice(1)))
51 }
52 }, {cls: 'PatchSuggest'})
53
54 ratingTypeInput.addEventListener('suggestselect', ev => {
55 value.set(ev.detail.value)
56 })
57
58 return when(isEditing, suggestWrapper,
59 h('span.text', { innerHTML: computed(value, api.book.html.simpleEmoji) }))
60 }
61
62 function simpleEdit(isEditing, name, value) {
63 const classList = computed([value, isEditing], (v, e) => {
64 return v || e
65 ? '-expanded'
66 : '-contracted'
67 })
68
69 return h('div', { classList }, [
70 h('span', name + ':'),
71 when(isEditing,
72 h('input', {'ev-input': e => value.set(e.target.value), value }),
73 h('span', value)
74 )
75 ])
76 }
77
78 function textEdit(isEditing, name, value) {
79 const classList = computed([value, isEditing], (v, e) => {
80 return v || e
81 ? '-expanded'
82 : '-contracted'
83 })
84
85 return h('div', { classList }, [
86 h('div', name + ':'),
87 when(isEditing,
88 h('textarea', {'ev-input': e => value.set(e.target.value), value }),
89 computed(value, api.message.html.markdown)
90 )
91 ])
92 }
93
94 function saveSubjective(obs, isEditingSubjective) {
95 obs.updateSubjective()
96 isEditingSubjective.set(false)
97 }
98
99 function handleSubjective(user, i, obs) {
100 let originalSubjective = {}
101 let isEditingSubjective = Value(false)
102 let subjective = obs.subjective.get(user)
103 let isMe = Value(api.keys.sync.id() == user)
104 let isOwnEditingSubj = computed([isEditingSubjective, isMe],
105 (e, me) => { return e && me })
106 let showRating = computed([subjective.rating, isEditingSubjective, isMe],
107 (v, e, me) => { return v || (e && me) })
108
109 function editRatingClick() {
110 if (isEditingSubjective()) { // cancel
111 if (obs.subjective.has(api.keys.sync.id())) {
112 let subj = obs.subjective.get(api.keys.sync.id())
113 Object.keys(originalSubjective).forEach((v) => {
114 subj[v].set(originalSubjective[v])
115 })
116 }
117 } else {
118 if (obs.subjective.has(api.keys.sync.id()))
119 originalSubjective = JSON.parse(JSON.stringify(obs.subjective.get(api.keys.sync.id())()))
120 }
121
122 isEditingSubjective.set(!isEditingSubjective())
123 }
124
125 return [
126 h('section',
127 [api.about.html.image(user),
128 h('span.text', [api.about.obs.name(user), when(showRating, ' rated ')]),
129 ratingEdit(isOwnEditingSubj, subjective.rating),
130 ratingTypeEdit(isOwnEditingSubj, subjective.ratingType)]),
131 simpleEdit(isOwnEditingSubj, 'Shelve', subjective.shelve),
132 simpleEdit(isOwnEditingSubj, 'Genre', subjective.genre),
133 textEdit(isOwnEditingSubj, 'Review', subjective.review),
134 h('section.comments', map(subjective.comments, com => {
135 return h('div',
136 [api.about.html.image(com.author),
137 // FIXME: time, in general like cards
138 h('span.text', computed(com.content.text, api.message.html.markdown))])
139 })),
140 h('section.actions',
141 when(isMe, [
142 h('button.subjective', { 'ev-click': editRatingClick },
143 when(isEditingSubjective, 'Cancel', 'Edit my rating')),
144 when(isEditingSubjective,
145 h('button', { 'ev-click': () => saveSubjective(obs, isEditingSubjective) },
146 'Update rating'))
147 ]))
148 ]
149 }
150
151 function bookLayout(msg, opts) {
152 const { layout, obs, isEditing, isCard } = opts
153
154 if (layout !== undefined && layout !== 'detail') return
155
156 const { title, authors, description,
157 series, seriesNo, images } = api.book.html
158
159 let originalBook = {}
160 let reviews = []
161
162 function editClick() {
163 if (isEditing()) { // cancel
164 Object.keys(originalBook).forEach((v) => {
165 obs[v].set(originalBook[v])
166 })
167 } else
168 originalBook = JSON.parse(JSON.stringify(obs()))
169
170 isEditing.set(!isEditing())
171 }
172
173 return [h('Message -book-detail', [
174 title({ title: obs.title, msg, isEditing, onUpdate: obs.title.set }),
175 series({ series: obs.series, seriesNo: obs.seriesNo, msg, isEditing,
176 onUpdate: obs.series.set, onUpdateNo: obs.seriesNo.set }),
177 authors({authors: obs.authors, isEditing, onUpdate: obs.authors.set}),
178 h('section.content', [
179 images({images: obs.images, isEditing, onUpdate: obs.images.add }),
180 h('section.description',
181 description({description: obs.description, isEditing, onUpdate: obs.description.set})),
182 ]),
183 h('section.actions', [
184 h('button.edit', { 'ev-click': editClick },
185 when(isEditing, 'Cancel', 'Edit book')),
186 when(isEditing, h('button', {'ev-click': () => saveBook(obs)}, 'Update book'))
187 ]),
188 h('section.subjective', [
189 computed(obs.subjective, subjectives => {
190 let i = 0;
191 Object.keys(subjectives).forEach(user => {
192 if (i++ < reviews.length) return
193 reviews.push(handleSubjective(user, i, obs))
194 })
195
196 return reviews
197 })
198 ])
199 ])]
200
201 function saveBook(obs) {
202 obs.amend()
203
204 isEditing.set(false)
205 }
206 }
207}
208

Built with git-ssb-web