Files: b7ae6aab41bf1d2ae415e7621d196b09103f4371 / plugs / message / html / render / gathering.js
5300 bytesRaw
1 | var { h, computed, when, map, send } = require('mutant') |
2 | var nest = require('depnest') |
3 | var extend = require('xtend') |
4 | var moment = require('moment-timezone') |
5 | |
6 | var localTimezone = moment.tz.guess() |
7 | |
8 | exports.needs = nest({ |
9 | 'message.html.markdown': 'first', |
10 | 'message.html.layout': 'first', |
11 | 'message.html.decorate': 'reduce', |
12 | 'message.async.publish': 'first', |
13 | 'keys.sync.id': 'first', |
14 | 'about.html.image': 'first', |
15 | 'about.obs.latestValue': 'first', |
16 | 'about.obs.groupedValues': 'first', |
17 | 'about.obs.valueFrom': 'first', |
18 | 'about.obs.name': 'first', |
19 | 'contact.obs.following': 'first', |
20 | 'blob.sync.url': 'first', |
21 | 'gathering.sheet.edit': 'first' |
22 | }) |
23 | |
24 | exports.gives = nest('message.html', { |
25 | canRender: true, |
26 | render: true |
27 | }) |
28 | |
29 | exports.create = function (api) { |
30 | var following = null |
31 | |
32 | return nest('message.html', { |
33 | canRender: isRenderable, |
34 | render: function (msg, opts) { |
35 | if (!isRenderable(msg)) return |
36 | |
37 | var yourId = api.keys.sync.id() |
38 | |
39 | // allow override of resolved about messages for preview in modules/gathering/sheet/edit.js |
40 | var about = msg.key ? extend({ |
41 | hidden: api.about.obs.valueFrom(msg.key, 'hidden', yourId), |
42 | image: api.about.obs.latestValue(msg.key, 'image'), |
43 | title: api.about.obs.latestValue(msg.key, 'title'), |
44 | description: api.about.obs.latestValue(msg.key, 'description'), |
45 | location: api.about.obs.latestValue(msg.key, 'location'), |
46 | startDateTime: api.about.obs.latestValue(msg.key, 'startDateTime') |
47 | }, msg.previewAbout) : msg.previewAbout |
48 | |
49 | var attendees = msg.key ? computed([api.about.obs.groupedValues(msg.key, 'attendee')], getAttendees) : [] |
50 | var disableActions = !!msg.previewAbout |
51 | |
52 | if (!following) { |
53 | following = api.contact.obs.following(yourId) |
54 | } |
55 | |
56 | var imageUrl = computed(about.image, (id) => api.blob.sync.url(id)) |
57 | var imageId = computed(about.image, (link) => (link && link.link) || link) |
58 | var content = h('GatheringCard', [ |
59 | h('div.title', [ |
60 | h('a', { |
61 | href: msg.key |
62 | }, about.title), |
63 | h('button', { |
64 | disabled: disableActions, |
65 | 'ev-click': send(api.gathering.sheet.edit, msg.key) |
66 | }, 'Edit Details') |
67 | ]), |
68 | h('div.time', computed(about.startDateTime, formatTime)), |
69 | when(about.image, h('a.image', { |
70 | href: imageId, |
71 | style: { |
72 | 'background-image': computed(imageUrl, (url) => `url(${url})`) |
73 | } |
74 | })), |
75 | h('div.attending', [ |
76 | h('div.title', ['Attendees', ' (', computed([attendees], (x) => x.length), ')']), |
77 | h('div.attendees', [ |
78 | map(attendees, (attendee) => { |
79 | return h('a.attendee', { |
80 | href: attendee, |
81 | title: nameAndFollowWarning(attendee) |
82 | }, api.about.html.image(attendee)) |
83 | }) |
84 | ]), |
85 | h('div.actions', [ |
86 | h('button -attend', { |
87 | disabled: disableActions, |
88 | 'ev-click': send(publishAttending, msg.key) |
89 | }, `Attending`), |
90 | h('button -attend', { |
91 | disabled: disableActions, |
92 | 'ev-click': send(publishNotAttending, msg.key) |
93 | }, `Can't Attend`) |
94 | ]) |
95 | ]), |
96 | h('div.location', markdown(about.location)), |
97 | when(about.description, h('div.description', markdown(about.description))) |
98 | ]) |
99 | |
100 | var editPreview = msg.previewAbout && msg.key |
101 | |
102 | var element = api.message.html.layout(msg, extend({ |
103 | content, |
104 | miniContent: editPreview ? 'Edited a gathering' : 'Added a gathering', |
105 | actions: !msg.previewAbout, |
106 | layout: 'mini' |
107 | }, opts)) |
108 | |
109 | // hide if no title set or hidden |
110 | var visible = computed([about.title, about.hidden], (title, hidden) => { |
111 | return title && !hidden |
112 | }) |
113 | |
114 | return when(visible, api.message.html.decorate(element, { |
115 | msg |
116 | })) |
117 | } |
118 | }) |
119 | |
120 | function publishAttending (id) { |
121 | var yourId = api.keys.sync.id() |
122 | |
123 | // publish with confirm |
124 | api.message.async.publish({ |
125 | type: 'about', |
126 | about: id, |
127 | attendee: { |
128 | link: yourId |
129 | } |
130 | }) |
131 | } |
132 | |
133 | function publishNotAttending (id) { |
134 | var yourId = api.keys.sync.id() |
135 | |
136 | // publish with confirm |
137 | api.message.async.publish({ |
138 | type: 'about', |
139 | about: id, |
140 | attendee: { |
141 | link: yourId, |
142 | remove: true |
143 | } |
144 | }) |
145 | } |
146 | |
147 | function nameAndFollowWarning (id) { |
148 | var yourId = api.keys.sync.id() |
149 | return computed([api.about.obs.name(id), id, following], function nameAndFollowWarning (name, id, following) { |
150 | if (id === yourId) { |
151 | return `${name} (you)` |
152 | } else if (following.includes(id)) { |
153 | return `${name}` |
154 | } else { |
155 | return `${name} (not following)` |
156 | } |
157 | }) |
158 | } |
159 | |
160 | function markdown (obs) { |
161 | return computed(obs, (text) => { |
162 | if (typeof text === 'string') return api.message.html.markdown(text) |
163 | }) |
164 | } |
165 | } |
166 | |
167 | function formatTime (time) { |
168 | if (time && time.epoch) { |
169 | return moment(time.epoch).tz(localTimezone).format('LLLL zz') |
170 | } |
171 | } |
172 | |
173 | function getAttendees (lookup) { |
174 | return Object.keys(lookup) |
175 | } |
176 | |
177 | function isRenderable (msg) { |
178 | return (msg.value.content.type === 'gathering') ? true : undefined |
179 | } |
180 |
Built with git-ssb-web