liquid_feedback_frontend

view app/main/draft/new.lua @ 1534:0d9bb3937310

Allow creating of a new issue based on a firstlife group id
author bsw
date Mon Oct 05 16:06:41 2020 +0200 (2020-10-05)
parents 97b7b783db42
children feeac2fd945e
line source
1 local issue
2 local area
3 local area_id
5 local issue_id = param.get("issue_id", atom.integer)
6 if issue_id then
7 issue = Issue:new_selector():add_where{"id=?",issue_id}:single_object_mode():exec()
8 issue:load_everything_for_member_id(app.session.member_id)
9 area = issue.area
10 else
11 area_id = param.get("area_id", atom.integer)
12 if area_id then
13 area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
14 area:load_delegation_info_once_for_member_id(app.session.member_id)
15 else
16 local firstlife_id = param.get("firstlife_id")
17 if firstlife_id then
18 area = Area:new_selector():join("unit", nil, "unit.id = area.unit_id"):add_where{"attr->>'firstlife_id'=?",firstlife_id}:single_object_mode():exec()
19 area:load_delegation_info_once_for_member_id(app.session.member_id)
20 area_id = area.id
21 end
22 end
23 end
25 local polling = param.get("polling", atom.boolean)
27 local policy_id = param.get("policy_id", atom.integer)
28 local policy
30 local preview = param.get("preview")
32 if #(slot.get_content("error")) > 0 then
33 preview = false
34 end
36 if policy_id then
37 policy = Policy:by_id(policy_id)
38 end
43 local initiative_id = param.get("initiative_id")
44 local initiative = Initiative:by_id(initiative_id)
45 local draft
46 if initiative then
47 initiative:load_everything_for_member_id(app.session.member_id)
48 initiative.issue:load_everything_for_member_id(app.session.member_id)
50 if initiative.issue.closed then
51 slot.put_into("error", _"This issue is already closed.")
52 return
53 elseif initiative.issue.half_frozen then
54 slot.put_into("error", _"This issue is already frozen.")
55 return
56 elseif initiative.issue.phase_finished then
57 slot.put_into("error", _"Current phase is already closed.")
58 return
59 end
61 draft = initiative.current_draft
62 if config.initiative_abstract then
63 draft.abstract = string.match(draft.content, "(.+)<!%--END_OF_ABSTRACT%-->")
64 if draft.abstract then
65 draft.content = string.match(draft.content, "<!%--END_OF_ABSTRACT%-->(.*)")
66 end
67 end
68 end
70 if not initiative and not issue and not area then
71 ui.heading{ content = _"Missing parameter" }
72 return false
73 end
75 ui.form{
76 record = draft,
77 attr = { class = "vertical section", enctype = 'multipart/form-data' },
78 module = "draft",
79 action = "add",
80 params = {
81 area_id = area and area.id,
82 issue_id = issue and issue.id or nil,
83 initiative_id = initiative_id
84 },
85 routing = {
86 ok = {
87 mode = "redirect",
88 module = "initiative",
89 view = "show",
90 id = initiative_id
91 }
92 },
93 content = function()
95 ui.grid{ content = function()
96 ui.cell_main{ content = function()
97 ui.container{ attr = { class = "mdl-card mdl-shadow--2dp mdl-card__fullwidth" }, content = function()
98 ui.container{ attr = { class = "mdl-card__title mdl-card--border" }, content = function()
99 if initiative then
100 ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = initiative.display_name }
101 elseif param.get("name") then
102 ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = param.get("name") }
103 elseif issue then
104 ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = _("New competing initiative in issue '#{issue}'", { issue = issue.name }) }
105 elseif area then
106 ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = _("New issue in area '#{area}'", { area = area.name }) }
107 end
108 end }
109 ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
111 -- -------- PREVIEW
112 if param.get("preview") then
113 ui.sectionRow( function()
114 if not issue and not initiative then
115 ui.container { content = policy.name }
116 end
117 if param.get("free_timing") then
118 ui.container { content = param.get("free_timing") }
119 end
120 slot.put("<br />")
121 ui.field.hidden{ name = "policy_id", value = param.get("policy_id") }
122 ui.field.hidden{ name = "name", value = param.get("name") }
123 if config.initiative_abstract then
124 ui.field.hidden{ name = "abstract", value = param.get("abstract") }
125 ui.container{
126 attr = { class = "abstract" },
127 content = param.get("abstract")
128 }
129 slot.put("<br />")
130 end
131 local draft_text = param.get("content")
132 local draft_text = util.wysihtml_preproc(draft_text)
133 ui.field.hidden{ name = "content", value = draft_text }
134 ui.container{
135 attr = { class = "draft" },
136 content = function()
137 slot.put(draft_text)
138 end
139 }
140 slot.put("<br />")
142 if config.attachments then
143 local file_upload_session = param.get("file_upload_session") or multirand.string(
144 32,
145 '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
146 )
147 file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
148 ui.field.hidden{ name = "file_upload_session", value = file_upload_session }
149 if initiative then
150 local files = File:new_selector()
151 :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
152 :add_where{ "draft_attachment.draft_id = ?", initiative.current_draft.id }
153 :reset_fields()
154 :add_field("file.id")
155 :add_field("draft_attachment.title")
156 :add_field("draft_attachment.description")
157 :add_order_by("draft_attachment.id")
158 :exec()
160 if #files > 0 then
161 ui.container {
162 content = function()
163 for i, file in ipairs(files) do
164 if param.get("file_delete_" .. file.id, atom.boolean) then
165 ui.field.hidden{ name = "file_delete_" .. file.id, value = "1" }
166 else
167 ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
168 ui.container{ content = function()
169 ui.tag{ tag = "strong", content = file.title or "" }
170 end }
171 ui.container{ content = file.description or "" }
172 slot.put("<br /><br />")
173 end
174 end
175 end
176 }
177 end
178 end
179 local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
180 local fh = io.open(filename, "r")
181 if fh then
182 local file_uploads = json.import(fh:read("*a"))
183 for i, file_upload in ipairs(file_uploads) do
184 ui.image{ module = "draft", view = "show_file_upload", params = {
185 file_upload_session = file_upload_session, file_id = file_upload.id, preview = true
186 } }
187 ui.container{ content = function()
188 ui.tag{ tag = "strong", content = file_upload.title or "" }
189 end }
190 ui.container{ content = file_upload.description or "" }
191 slot.put("<br />")
192 end
193 end
194 end
196 ui.tag{
197 tag = "input",
198 attr = {
199 type = "submit",
200 class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored",
201 value = _'Publish now'
202 },
203 content = ""
204 }
205 slot.put(" &nbsp; ")
207 ui.tag{
208 tag = "input",
209 attr = {
210 type = "submit",
211 name = "edit",
212 class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect",
213 value = _'Edit again'
214 },
215 content = ""
216 }
217 slot.put(" &nbsp; ")
219 ui.link{
220 attr = { class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect" },
221 content = _"Cancel",
222 module = initiative and "initiative" or "area",
223 view = "show",
224 id = initiative_id or area_id
225 }
226 end )
228 -- -------- EDIT
229 else
231 if not issue_id and not initiative_id then
232 local tmp = { { id = -1, name = "" } }
233 for i, allowed_policy in ipairs(area.allowed_policies) do
234 if not allowed_policy.polling or app.session.member:has_polling_right_for_unit_id(area.unit_id) then
235 tmp[#tmp+1] = allowed_policy
236 end
237 end
238 ui.container{ content = _"Please choose a policy for the new issue:" }
239 ui.field.select{
240 name = "policy_id",
241 foreign_records = tmp,
242 foreign_id = "id",
243 foreign_name = "name",
244 value = param.get("policy_id", atom.integer) or area.default_policy and area.default_policy.id
245 }
246 if policy and policy.free_timeable then
247 local available_timings
248 if config.free_timing and config.free_timing.available_func then
249 available_timings = config.free_timing.available_func(policy)
250 if available_timings == false then
251 slot.put_into("error", "error in free timing config")
252 return false
253 end
254 end
255 ui.heading{ level = 4, content = _"Free timing:" }
256 if available_timings then
257 ui.field.select{
258 name = "free_timing",
259 foreign_records = available_timings,
260 foreign_id = "id",
261 foreign_name = "name",
262 value = param.get("free_timing")
263 }
264 else
265 ui.field.text{
266 name = "free_timing",
267 value = param.get("free_timing")
268 }
269 end
270 end
271 end
273 if issue and issue.policy.polling and app.session.member:has_polling_right_for_unit_id(area.unit_id) then
274 slot.put("<br />")
275 ui.field.boolean{ name = "polling", label = _"No admission needed", value = polling }
276 end
278 if not initiative then
279 ui.container{ attr = { class = "mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdl-card__fullwidth" }, content = function ()
280 ui.field.text{
281 attr = { id = "lf-initiative__name", class = "mdl-textfield__input" },
282 label_attr = { class = "mdl-textfield__label", ["for"] = "lf-initiative__name" },
283 label = _"Title",
284 name = "name",
285 value = param.get("name")
286 }
287 end }
288 end
290 if config.initiative_abstract then
291 ui.container { content = _"Enter abstract:" }
292 ui.container{ attr = { class = "mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield__fullwidth" }, content = function()
293 ui.field.text{
294 name = "abstract",
295 multiline = true,
296 attr = { id = "abstract", style = "height: 20ex; width: 100%;" },
297 value = param.get("abstract")
298 }
299 end }
300 end
302 ui.container { content = _"Enter your proposal and/or reasons:" }
303 ui.field.wysihtml{
304 name = "content",
305 multiline = true,
306 attr = { id = "draft", style = "height: 50ex; width: 100%;" },
307 value = param.get("content")
308 }
309 if not issue or issue.state == "admission" or issue.state == "discussion" then
310 ui.container { content = _"You can change your text again anytime during admission and discussion phase" }
311 else
312 ui.container { content = _"You cannot change your text again later, because this issue is already in verfication phase!" }
313 end
315 slot.put("<br />")
316 if config.attachments then
317 local file_upload_session = param.get("file_upload_session") or multirand.string(
318 32,
319 '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
320 )
321 file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
322 ui.field.hidden{ name = "file_upload_session", value = file_upload_session }
323 if initiative then
324 local files = File:new_selector()
325 :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
326 :add_where{ "draft_attachment.draft_id = ?", initiative.current_draft.id }
327 :reset_fields()
328 :add_field("file.id")
329 :add_field("draft_attachment.title")
330 :add_field("draft_attachment.description")
331 :add_order_by("draft_attachment.id")
332 :exec()
334 if #files > 0 then
335 ui.container {
336 content = function()
337 for i, file in ipairs(files) do
338 ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
339 ui.container{ content = function()
340 ui.tag{ tag = "strong", content = file.title or "" }
341 end }
342 ui.container{ content = file.description or "" }
343 ui.field.boolean{ label = _"delete", name = "file_delete_" .. file.id, value = param.get("file_delete_" .. file.id) and true or false }
344 slot.put("<br /><br />")
345 end
346 end
347 }
348 end
349 end
350 local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
351 local fh = io.open(filename, "r")
352 if fh then
353 local file_uploads = json.import(fh:read("*a"))
354 for i, file_upload in ipairs(file_uploads) do
355 ui.image{ module = "draft", view = "show_file_upload", params = {
356 file_upload_session = file_upload_session, file_id = file_upload.id, preview = true
357 } }
358 ui.container{ content = function()
359 ui.tag{ tag = "strong", content = file_upload.title or "" }
360 end }
361 ui.container{ content = file_upload.description or "" }
362 ui.field.boolean{ label = _"delete", name = "file_upload_delete_" .. file_upload.id }
363 slot.put("<br />")
364 end
365 end
366 ui.container{ attr = { id = "file_upload_template", style = "display: none;" }, content = function()
367 ui.field.text{ label = _"Title", name = "__ID_title__" }
368 ui.field.text{ label = _"Description", name = "__ID_description__" }
369 ui.field.image{ field_name = "__ID_file__" }
370 end }
371 ui.container{ attr = { id = "file_upload" }, content = function()
372 end }
373 ui.field.hidden{ attr = { id = "file_upload_last_id" }, name = "file_upload_last_id" }
374 ui.script{ script = [[ var file_upload_id = 1; ]] }
375 ui.tag{ tag = "a", content = _"Attach image", attr = {
376 href = "#",
377 onclick = "var html = document.getElementById('file_upload_template').innerHTML; html = html.replace('__ID_file__', 'file_' + file_upload_id); html = html.replace('__ID_title__', 'title_' + file_upload_id); html = html.replace('__ID_description__', 'description_' + file_upload_id); var el = document.createElement('div'); el.innerHTML = html; document.getElementById('file_upload').appendChild(el); document.getElementById('file_upload_last_id').value = file_upload_id; file_upload_id++; return false;"
378 } }
379 slot.put("<br />")
381 slot.put("<br />")
383 end
385 ui.tag{
386 tag = "input",
387 attr = {
388 type = "submit",
389 name = "preview",
390 class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored",
391 value = _'Preview'
392 },
393 content = ""
394 }
395 slot.put(" &nbsp; ")
397 ui.link{
398 content = _"Cancel",
399 module = initiative and "initiative" or issue and "issue" or "index",
400 view = area and not issue and "index" or "show",
401 id = initiative_id or issue_id,
402 params = { area = area_id, unit = area and area.unit_id or nil },
403 attr = { class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect" }
404 }
406 end
407 end }
408 end }
409 end }
411 if config.map or config.firstlife then
412 ui.cell_sidebar{ content = function()
413 ui.container{ attr = { class = "mdl-special-card map mdl-shadow--2dp" }, content = function()
414 ui.field.location{ name = "location", value = param.get("location") }
415 end }
416 end }
417 end
419 end }
420 end
421 }

Impressum / About Us