git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Tree: cf39615322e5ca1a830f9a79d8bf0c1ed80e1c8b

Files: cf39615322e5ca1a830f9a79d8bf0c1ed80e1c8b / modules / gathering / sheet / edit.js

5545 bytesRaw
1var nest = require('depnest')
2var extend = require('xtend')
3var Pickr = require('flatpickr')
4var spacetime = require('spacetime')
5
6var {Value, h, computed, when} = require('mutant')
7
8exports.gives = nest('gathering.sheet.edit')
9
10exports.needs = nest({
11 'sheet.display': 'first',
12 'keys.sync.id': 'first',
13 'sbot.async.publish': 'first',
14 'about.obs.latestValue': 'first',
15 'blob.html.input': 'first',
16 'blob.sync.url': 'first'
17})
18
19exports.create = function (api) {
20 return nest('gathering.sheet.edit', function (id) {
21 api.sheet.display(close => {
22 var current = id ? {
23 title: api.about.obs.latestValue(id, 'title'),
24 startDateTime: api.about.obs.latestValue(id, 'startDateTime'),
25 image: api.about.obs.latestValue(id, 'image'),
26 description: api.about.obs.latestValue(id, 'description')
27 } : {
28 title: Value(),
29 startDateTime: Value(),
30 image: Value(),
31 description: Value()
32 }
33
34 var publishing = Value(false)
35
36 var chosen = {
37 title: Value(current.title()),
38 startDateTime: Value(current.startDateTime()),
39 image: Value(current.image()),
40 description: Value(current.description())
41 }
42
43 var imageUrl = computed(chosen.image, (id) => id && api.blob.sync.url(id))
44
45 return {
46 content: h('div', {
47 style: {
48 padding: '20px',
49 'text-align': 'center'
50 }
51 }, [
52 h('h2', {
53 style: {
54 'font-weight': 'normal'
55 }
56 }, [id ? 'Edit' : 'Create', ' Gathering']),
57 h('GatheringEditor', [
58 h('input.title', {
59 placeholder: 'Choose a title',
60 hooks: [ValueHook(chosen.title), FocusHook()]
61 }),
62 h('input.date', {
63 placeholder: 'Choose date and time',
64 hooks: [
65 PickrHook(chosen.startDateTime)
66 ]
67 }),
68 h('ImageInput .banner', {
69 style: { 'background-image': computed(imageUrl, x => `url(${x})`) }
70 }, [
71 h('span', ['🖼 Choose Banner Image...']),
72 api.blob.html.input(file => {
73 chosen.image.set(file)
74 }, {
75 accept: 'image/*'
76 })
77 ]),
78 h('textarea.description', {
79 placeholder: 'Describe the gathering (if you want)',
80 hooks: [ValueHook(chosen.description)]
81 })
82 ])
83 ]),
84 footer: [
85 h('button -save', {
86 'ev-click': save,
87 'disabled': publishing
88 }, when(publishing, 'Publishing...', 'Publish')),
89 h('button -cancel', {
90 'ev-click': close
91 }, 'Cancel')
92 ]
93 }
94
95 function ensureExists (cb) {
96 if (!id) {
97 api.sbot.async.publish({
98 type: 'gathering'
99 }, (err, msg) => {
100 if (err) return cb(err)
101 cb(null, msg.key)
102 })
103 } else {
104 cb(null, id)
105 }
106 }
107
108 function save () {
109 // no confirm
110 var update = {}
111
112 if (!compareImage(chosen.image(), current.image())) update.image = chosen.image()
113 if (!compareTime(chosen.startDateTime(), current.startDateTime())) update.startDateTime = chosen.startDateTime()
114 if (chosen.title() !== current.title()) update.title = chosen.title() || 'Untitled Gathering'
115 if (chosen.description() !== current.description()) update.description = chosen.description()
116
117 if (Object.keys(update).length) {
118 publishing.set(true)
119 ensureExists((err, id) => {
120 if (err) throw err
121 api.sbot.async.publish(extend({
122 type: 'about',
123 about: id
124 }, update), (err) => {
125 if (err) {
126 publishing.set(false)
127 showDialog({
128 type: 'error',
129 title: 'Error',
130 buttons: ['OK'],
131 message: 'An error occurred while attempting to publish gathering.',
132 detail: err.message
133 })
134 } else {
135 close()
136 }
137 })
138 })
139 } else {
140 close()
141 }
142 }
143 })
144 })
145}
146
147function compareTime (a, b) {
148 if (!a && !b) {
149 return true
150 } else if (!a || !b) {
151 return false
152 } else {
153 return a.epoch === b.epoch
154 }
155}
156
157function compareImage (a, b) {
158 a = isObject(a) ? a.link : a
159 b = isObject(b) ? b.link : b
160 return a === b
161}
162
163function isObject (value) {
164 return value && typeof value === 'object'
165}
166
167function FocusHook () {
168 return function (element) {
169 setTimeout(() => {
170 element.focus()
171 element.select()
172 }, 5)
173 }
174}
175
176function ValueHook (obs) {
177 return function (element) {
178 element.value = obs()
179 element.oninput = function () {
180 obs.set(element.value.trim())
181 }
182 }
183}
184
185function showDialog (opts) {
186 var electron = require('electron')
187 electron.remote.dialog.showMessageBox(electron.remote.getCurrentWindow(), opts)
188}
189
190function PickrHook (obs) {
191 return function (element) {
192 var picker = new Pickr(element, {
193 enableTime: true,
194 altInput: true,
195 dateFormat: 'U',
196 onChange: function (dates) {
197 obs.set(spacetime(parseInt(element.value, 10) * 1000))
198 }
199 })
200
201 var value = obs()
202 if (value) {
203 picker.setDate(value.epoch)
204 }
205 return () => picker.destroy()
206 }
207}
208

Built with git-ssb-web