Files: bd040e587da9831443f9a4542c1a318f354a7487 / book / html / layout / detail.js
3987 bytesRaw
1 | const nest = require('depnest') |
2 | const { h, when, computed } = require('mutant') |
3 | var htmlEscape = require('html-escape') |
4 | |
5 | exports.needs = nest({ |
6 | 'book.obs.book': 'first', |
7 | 'about.html.image': 'first', |
8 | 'about.obs.name': 'first', |
9 | 'emoji.sync.url': 'first', |
10 | 'message.html': { |
11 | 'markdown': 'first' |
12 | }, |
13 | 'book.html': { |
14 | 'title': 'first', |
15 | 'authors': 'first', |
16 | 'description': 'first', |
17 | 'images': 'first' |
18 | } |
19 | }) |
20 | |
21 | exports.gives = nest('book.html.layout') |
22 | |
23 | exports.create = (api) => { |
24 | return nest('book.html.layout', bookLayout) |
25 | |
26 | function renderEmoji (emoji, url) { |
27 | if (!url) return ':' + emoji + ':' |
28 | return ` |
29 | <img |
30 | src="${htmlEscape(url)}" |
31 | alt=":${htmlEscape(emoji)}:" |
32 | title=":${htmlEscape(emoji)}:" |
33 | class="emoji" |
34 | > |
35 | ` |
36 | } |
37 | |
38 | function simpleMarkdown(text) { |
39 | if (text.startsWith(':')) |
40 | return renderEmoji(text, api.emoji.sync.url(text.match(/:([^:]*)/)[1])) |
41 | else |
42 | return text |
43 | } |
44 | |
45 | function valueEdit(isEditing, value) { |
46 | return when(isEditing, |
47 | h('input', {'ev-input': e => value.set(e.target.value), value: value }), |
48 | h('span', { innerHTML: computed(value, simpleMarkdown) })) |
49 | |
50 | } |
51 | |
52 | function simpleEdit(isEditing, name, value) { |
53 | return h('div', { classList: when(computed([value, isEditing], (v, e) => { return v || e }), |
54 | '-expanded', '-contracted') }, |
55 | [h('span', name + ':'), |
56 | when(isEditing, |
57 | h('input', {'ev-input': e => value.set(e.target.value), value: value }), |
58 | h('span', value))]) |
59 | |
60 | } |
61 | |
62 | function textEdit(isEditing, name, value) { |
63 | const markdown = api.message.html.markdown |
64 | const input = h('textarea', {'ev-input': e => value.set(e.target.value), value: value() }) |
65 | |
66 | return h('div', { classList: when(computed([value, isEditing], (v, e) => { return v || e }), |
67 | '-expanded', '-contracted') }, |
68 | [h('div', name + ':'), |
69 | when(isEditing, input, computed(value, markdown))]) |
70 | } |
71 | |
72 | function bookLayout (msg, opts) { |
73 | if (!(opts.layout === undefined || opts.layout === 'detail')) return |
74 | |
75 | const { obs, isEditing, isCard } = opts |
76 | |
77 | const { title, authors, description, images } = api.book.html |
78 | |
79 | let reviews = [] |
80 | |
81 | return h('Message -book-detail', [ |
82 | title({ title: obs.title, msg, isEditing, onUpdate: obs.title.set }), |
83 | authors({authors: obs.authors, isEditing, onUpdate: obs.authors.set}), |
84 | h('section.content', [ |
85 | images({images: obs.images, isEditing, onUpdate: obs.images.add }), |
86 | h('section.description', |
87 | description({description: obs.description, isEditing, onUpdate: obs.description.set})), |
88 | ]), |
89 | h('section.subjective', [ |
90 | computed(obs.subjective, subjectives => { |
91 | let i = 0; |
92 | Object.keys(subjectives).forEach(user => { |
93 | if (i++ < reviews.length) return |
94 | let subjective = obs.subjective.get(user) |
95 | reviews.push([ |
96 | h('section', [api.about.html.image(user), |
97 | h('span', [api.about.obs.name(msg.value.author), ' rated ']), |
98 | valueEdit(isEditing, subjective.rating), |
99 | valueEdit(isEditing, subjective.ratingType)]), |
100 | simpleEdit(isEditing, 'Shelve', subjective.shelve), |
101 | simpleEdit(isEditing, 'Genre', subjective.genre), |
102 | textEdit(isEditing, 'Review', subjective.review) |
103 | ]) |
104 | }) |
105 | |
106 | return reviews |
107 | }) |
108 | ]), |
109 | h('section.actions', [ |
110 | h('button.edit', { 'ev-click': () => isEditing.set(!isEditing()) }, |
111 | when(isEditing, 'Cancel', 'Edit')), |
112 | when(isEditing, h('button', {'ev-click': () => save(obs)}, 'Update')) |
113 | ]) |
114 | ]) |
115 | |
116 | function save (obs) { |
117 | // FIXME: check if anything changed |
118 | obs.amend() |
119 | |
120 | isEditing.set(false) |
121 | } |
122 | } |
123 | } |
124 |
Built with git-ssb-web