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