liquid_feedback_frontend
diff app/main/initiative/show.lua @ 1045:701a5cf6b067
Imported LiquidFeedback Frontend 3.0 branch
| author | bsw |
|---|---|
| date | Thu Jul 10 01:19:48 2014 +0200 (2014-07-10) |
| parents | 344e5fdce8c9 |
| children | 7188f8a45b3d |
line diff
1.1 --- a/app/main/initiative/show.lua Thu Jul 10 01:02:43 2014 +0200 1.2 +++ b/app/main/initiative/show.lua Thu Jul 10 01:19:48 2014 +0200 1.3 @@ -1,7 +1,541 @@ 1.4 -local initiative = Initiative:by_id(param.get_id()) 1.5 +local initiative = Initiative:by_id ( param.get_id() ) 1.6 +local member = app.session.member 1.7 + 1.8 +if not initiative then 1.9 + execute.view { module = "index", view = "404" } 1.10 + request.set_status("404 Not Found") 1.11 + return 1.12 +end 1.13 + 1.14 +local issue_info 1.15 + 1.16 +if member then 1.17 + initiative:load_everything_for_member_id(member.id) 1.18 + initiative.issue:load_everything_for_member_id(member.id) 1.19 + issue_info = initiative.issue.member_info 1.20 +end 1.21 + 1.22 +execute.view { 1.23 + module = "issue", view = "_head", 1.24 + params = { 1.25 + issue = initiative.issue, 1.26 + initiative = initiative, 1.27 + member = app.session.member 1.28 + } 1.29 +} 1.30 + 1.31 +if app.session.member_id then 1.32 + direct_supporter = initiative.issue.member_info.own_participation and initiative.member_info.supported 1.33 +end 1.34 1.35 -execute.view{ 1.36 - module = "initiative", view = "_show", params = { 1.37 - initiative = initiative 1.38 +ui.script { script = [[ 1.39 + function showTab(tabId) { 1.40 + $('.tab').hide(); 1.41 + $('.main').hide(); 1.42 + $('.main, .slot_extra .section').hide(); 1.43 + $('.' + tabId).show(); 1.44 + if (tabId == "main") $('.slot_extra .section').show(); 1.45 + }; 1.46 + showTab('main'); 1.47 +]]} 1.48 + 1.49 +execute.view{ module = "issue", view = "_sidebar_state", params = { 1.50 + initiative = initiative 1.51 +} } 1.52 + 1.53 +execute.view { 1.54 + module = "issue", view = "_sidebar_issue", 1.55 + params = { 1.56 + issue = initiative.issue, 1.57 + highlight_initiative_id = initiative.id 1.58 + } 1.59 +} 1.60 + 1.61 +execute.view { 1.62 + module = "issue", view = "_sidebar_whatcanido", 1.63 + params = { initiative = initiative } 1.64 +} 1.65 + 1.66 +execute.view { 1.67 + module = "issue", view = "_sidebar_members", params = { 1.68 + issue = initiative.issue, initiative = initiative 1.69 } 1.70 } 1.71 + 1.72 +ui.section( function () 1.73 + execute.view{ 1.74 + module = "initiative", view = "_head", params = { 1.75 + initiative = initiative 1.76 + } 1.77 + } 1.78 + 1.79 + if direct_supporter and not initiative.issue.closed then 1.80 + local supporter = app.session.member:get_reference_selector("supporters") 1.81 + :add_where{ "initiative_id = ?", initiative.id } 1.82 + :optional_object_mode() 1.83 + :exec() 1.84 + 1.85 + if supporter then 1.86 + 1.87 + local old_draft_id = supporter.draft_id 1.88 + local new_draft_id = initiative.current_draft.id 1.89 + 1.90 + if old_draft_id ~= new_draft_id then 1.91 + ui.sectionRow( "draft_updated_info", function () 1.92 + ui.container{ 1.93 + attr = { class = "info" }, 1.94 + content = _"The draft of this initiative has been updated!" 1.95 + } 1.96 + slot.put(" ") 1.97 + ui.link{ 1.98 + content = _"show differences", 1.99 + module = "draft", 1.100 + view = "diff", 1.101 + params = { 1.102 + old_draft_id = old_draft_id, 1.103 + new_draft_id = new_draft_id 1.104 + } 1.105 + } 1.106 + if not initiative.revoked then 1.107 + slot.put(" | ") 1.108 + ui.link{ 1.109 + text = _"refresh my support", 1.110 + module = "initiative", 1.111 + action = "add_support", 1.112 + id = initiative.id, 1.113 + params = { draft_id = initiative.current_draft.id }, 1.114 + routing = { 1.115 + default = { 1.116 + mode = "redirect", 1.117 + module = "initiative", 1.118 + view = "show", 1.119 + id = initiative.id 1.120 + } 1.121 + } 1.122 + } 1.123 + slot.put(" | ") 1.124 + end 1.125 + 1.126 + ui.link{ 1.127 + text = _"remove my support", 1.128 + module = "initiative", 1.129 + action = "remove_support", 1.130 + id = initiative.id, 1.131 + routing = { 1.132 + default = { 1.133 + mode = "redirect", 1.134 + module = "initiative", 1.135 + view = "show", 1.136 + id = initiative.id 1.137 + } 1.138 + } 1.139 + } 1.140 + 1.141 + end ) 1.142 + end 1.143 + end 1.144 + end 1.145 + 1.146 + 1.147 + ui.sectionRow( function () 1.148 + ui.container { 1.149 + attr = { class = "draft" }, 1.150 + content = function () 1.151 + slot.put ( initiative.current_draft:get_content ( "html" ) ) 1.152 + end 1.153 + } 1.154 + end ) 1.155 + 1.156 +end) 1.157 + 1.158 +ui.link { attr = { name = "suggestions" }, text = "" } 1.159 + 1.160 + 1.161 +ui.container { 1.162 + attr = { class = "section suggestions" }, 1.163 + content = function () 1.164 + 1.165 + if # ( initiative.suggestions ) > 0 then 1.166 + 1.167 + ui.sectionHead( function () 1.168 + ui.heading { 1.169 + level = 1, 1.170 + content = _("Suggestions for improvement (#{count})", { count = # ( initiative.suggestions ) } ) 1.171 + } 1.172 + ui.container { content = _"written and rated by the supportes of this initiative to improve the proposal and its reasons" } 1.173 + end ) 1.174 + 1.175 + for i, suggestion in ipairs(initiative.suggestions) do 1.176 + 1.177 + local opinion = Opinion:by_pk(app.session.member_id, suggestion.id) 1.178 + 1.179 + local class = "sectionRow suggestion" 1.180 + if suggestion.id == param.get("suggestion_id", atom.number) then 1.181 + class = class .. " highlighted" 1.182 + end 1.183 + if member and not initiative.issue.fully_frozen and not initiative.issue.closed and initiative.member_info.supported then 1.184 + class = class .. " rateable" 1.185 + end 1.186 + 1.187 + 1.188 + ui.tag { tag = "div", attr = { class = class, id = "s" .. suggestion.id }, content = function () 1.189 + 1.190 + if opinion then 1.191 + 1.192 + ui.container { attr = { class = "opinion"}, content = function() 1.193 + local class = "" 1.194 + local text = "" 1.195 + 1.196 + if opinion.degree == 2 then 1.197 + class = "must" 1.198 + text = _"must" 1.199 + elseif opinion.degree == 1 then 1.200 + class = "should" 1.201 + text = _"should" 1.202 + elseif opinion.degree == 0 then 1.203 + class = "neutral" 1.204 + text = _"neutral" 1.205 + elseif opinion.degree == -1 then 1.206 + class = "shouldnot" 1.207 + text = _"should not" 1.208 + elseif opinion.degree == -2 then 1.209 + class = "mustnot" 1.210 + text = _"must not" 1.211 + end 1.212 + 1.213 + ui.tag { 1.214 + attr = { class = class }, 1.215 + content = text 1.216 + } 1.217 + 1.218 + slot.put ( " " ) 1.219 + 1.220 + if 1.221 + (opinion.degree > 0 and not opinion.fulfilled) 1.222 + or (opinion.degree < 0 and opinion.fulfilled) 1.223 + then 1.224 + ui.tag{ content = _"but" } 1.225 + else 1.226 + ui.tag{ content = _"and" } 1.227 + end 1.228 + 1.229 + slot.put ( " " ) 1.230 + 1.231 + local class = "" 1.232 + local text = "" 1.233 + 1.234 + if opinion.fulfilled then 1.235 + class = "implemented" 1.236 + text = _"is implemented" 1.237 + else 1.238 + class = "notimplemented" 1.239 + text = _"is not implemented" 1.240 + end 1.241 + 1.242 + ui.tag { 1.243 + attr = { class = class }, 1.244 + content = text 1.245 + } 1.246 + 1.247 + if 1.248 + (opinion.degree > 0 and not opinion.fulfilled) 1.249 + or (opinion.degree < 0 and opinion.fulfilled) 1.250 + then 1.251 + if math.abs(opinion.degree) > 1 then 1.252 + slot.put(" !!") 1.253 + else 1.254 + slot.put(" !") 1.255 + end 1.256 + else 1.257 + slot.put(" ✓") 1.258 + end 1.259 + 1.260 + end } 1.261 + 1.262 + end 1.263 + 1.264 + 1.265 + ui.link { attr = { name = "s" .. suggestion.id }, text = "" } 1.266 + ui.heading { level = 2, 1.267 + attr = { class = "suggestionHead" }, 1.268 + content = format.string(suggestion.name, { 1.269 + truncate_at = 160, truncate_suffix = true 1.270 + }) } 1.271 + 1.272 + 1.273 + local plus2 = (suggestion.plus2_unfulfilled_count or 0) 1.274 + + (suggestion.plus2_fulfilled_count or 0) 1.275 + local plus1 = (suggestion.plus1_unfulfilled_count or 0) 1.276 + + (suggestion.plus1_fulfilled_count or 0) 1.277 + local minus1 = (suggestion.minus1_unfulfilled_count or 0) 1.278 + + (suggestion.minus1_fulfilled_count or 0) 1.279 + local minus2 = (suggestion.minus2_unfulfilled_count or 0) 1.280 + + (suggestion.minus2_fulfilled_count or 0) 1.281 + 1.282 + local with_opinion = plus2 + plus1 + minus1 + minus2 1.283 + 1.284 + local neutral = (suggestion.initiative.supporter_count or 0) 1.285 + - with_opinion 1.286 + 1.287 + local neutral2 = with_opinion 1.288 + - (suggestion.plus2_fulfilled_count or 0) 1.289 + - (suggestion.plus1_fulfilled_count or 0) 1.290 + - (suggestion.minus1_fulfilled_count or 0) 1.291 + - (suggestion.minus2_fulfilled_count or 0) 1.292 + 1.293 + ui.container { 1.294 + attr = { class = "suggestionInfo" }, 1.295 + content = function () 1.296 + 1.297 + if with_opinion > 0 then 1.298 + ui.container { attr = { class = "suggestion-rating" }, content = function () 1.299 + ui.tag { content = _"collective rating:" } 1.300 + slot.put(" ") 1.301 + ui.bargraph{ 1.302 + max_value = suggestion.initiative.supporter_count, 1.303 + width = 100, 1.304 + bars = { 1.305 + { color = "#0a0", value = plus2 }, 1.306 + { color = "#8a8", value = plus1 }, 1.307 + { color = "#eee", value = neutral }, 1.308 + { color = "#a88", value = minus1 }, 1.309 + { color = "#a00", value = minus2 }, 1.310 + } 1.311 + } 1.312 + slot.put(" | ") 1.313 + ui.tag { content = _"implemented:" } 1.314 + slot.put ( " " ) 1.315 + ui.bargraph{ 1.316 + max_value = with_opinion, 1.317 + width = 100, 1.318 + bars = { 1.319 + { color = "#0a0", value = suggestion.plus2_fulfilled_count }, 1.320 + { color = "#8a8", value = suggestion.plus1_fulfilled_count }, 1.321 + { color = "#eee", value = neutral2 }, 1.322 + { color = "#a88", value = suggestion.minus1_fulfilled_count }, 1.323 + { color = "#a00", value = suggestion.minus2_fulfilled_count }, 1.324 + } 1.325 + } 1.326 + end } 1.327 + end 1.328 + 1.329 + if app.session:has_access("authors_pseudonymous") then 1.330 + util.micro_avatar ( suggestion.author ) 1.331 + else 1.332 + slot.put("<br />") 1.333 + end 1.334 + 1.335 + ui.container { 1.336 + attr = { class = "suggestion-text" }, 1.337 + content = function () 1.338 + slot.put ( suggestion:get_content( "html" ) ) 1.339 + 1.340 + if direct_supporter then 1.341 + 1.342 + ui.container { 1.343 + attr = { class = "rating" }, 1.344 + content = function () 1.345 + 1.346 + if not opinion then 1.347 + opinion = {} 1.348 + end 1.349 + ui.form { 1.350 + module = "opinion", action = "update", params = { 1.351 + suggestion_id = suggestion.id 1.352 + }, 1.353 + routing = { default = { 1.354 + mode = "redirect", 1.355 + module = "initiative", view = "show", id = suggestion.initiative_id, 1.356 + params = { suggestion_id = suggestion.id }, 1.357 + anchor = "s" .. suggestion.id -- TODO webmcp 1.358 + } }, 1.359 + content = function () 1.360 + 1.361 + 1.362 + ui.heading { level = 3, content = _"Should the initiator implement this suggestion?" } 1.363 + ui.container { content = function () 1.364 + 1.365 + local active = opinion.degree == 2 1.366 + ui.tag { tag = "input", attr = { 1.367 + type = "radio", name = "degree", value = 2, 1.368 + id = "s" .. suggestion.id .. "_degree2", 1.369 + checked = active and "checked" or nil 1.370 + } } 1.371 + ui.tag { 1.372 + tag = "label", 1.373 + attr = { 1.374 + ["for"] = "s" .. suggestion.id .. "_degree2", 1.375 + class = active and "active-plus2" or nil, 1.376 + }, 1.377 + content = _"must" 1.378 + } 1.379 + 1.380 + local active = opinion.degree == 1 1.381 + ui.tag { tag = "input", attr = { 1.382 + type = "radio", name = "degree", value = 1, 1.383 + id = "s" .. suggestion.id .. "_degree1", 1.384 + checked = active and "checked" or nil 1.385 + } } 1.386 + ui.tag { 1.387 + tag = "label", 1.388 + attr = { 1.389 + ["for"] = "s" .. suggestion.id .. "_degree1", 1.390 + class = active and "active-plus1" or nil, 1.391 + }, 1.392 + content = _"should" 1.393 + } 1.394 + 1.395 + local active = not opinion.member_id 1.396 + ui.tag { tag = "input", attr = { 1.397 + type = "radio", name = "degree", value = 0, 1.398 + id = "s" .. suggestion.id .. "_degree0", 1.399 + checked = active and "checked" or nil 1.400 + } } 1.401 + ui.tag { 1.402 + tag = "label", 1.403 + attr = { 1.404 + ["for"] = "s" .. suggestion.id .. "_degree0", 1.405 + class = active and "active-neutral" or nil, 1.406 + }, 1.407 + content = _"neutral" 1.408 + } 1.409 + 1.410 + local active = opinion.degree == -1 1.411 + ui.tag { tag = "input", attr = { 1.412 + type = "radio", name = "degree", value = -1, 1.413 + id = "s" .. suggestion.id .. "_degree-1", 1.414 + checked = active and "checked" or nil 1.415 + } } 1.416 + ui.tag { 1.417 + tag = "label", 1.418 + attr = { 1.419 + ["for"] = "s" .. suggestion.id .. "_degree-1", 1.420 + class = active and "active-minus1" or nil, 1.421 + }, 1.422 + content = _"should not" 1.423 + } 1.424 + 1.425 + local active = opinion.degree == -2 1.426 + ui.tag { tag = "input", attr = { 1.427 + type = "radio", name = "degree", value = -2, 1.428 + id = "s" .. suggestion.id .. "_degree-2", 1.429 + checked = active and "checked" or nil 1.430 + } } 1.431 + ui.tag { 1.432 + tag = "label", 1.433 + attr = { 1.434 + ["for"] = "s" .. suggestion.id .. "_degree-2", 1.435 + class = active and "active-minus2" or nil, 1.436 + }, 1.437 + content = _"must not" 1.438 + } 1.439 + end } 1.440 + 1.441 + slot.put("<br />") 1.442 + 1.443 + ui.heading { level = 3, content = _"Did the initiator implement this suggestion?" } 1.444 + ui.container { content = function () 1.445 + local active = opinion.fulfilled == false 1.446 + ui.tag { tag = "input", attr = { 1.447 + type = "radio", name = "fulfilled", value = "false", 1.448 + id = "s" .. suggestion.id .. "_notfulfilled", 1.449 + checked = active and "checked" or nil 1.450 + } } 1.451 + ui.tag { 1.452 + tag = "label", 1.453 + attr = { 1.454 + ["for"] = "s" .. suggestion.id .. "_notfulfilled", 1.455 + class = active and "active-notfulfilled" or nil, 1.456 + }, 1.457 + content = _"No (not yet)" 1.458 + } 1.459 + 1.460 + local active = opinion.fulfilled 1.461 + ui.tag { tag = "input", attr = { 1.462 + type = "radio", name = "fulfilled", value = "true", 1.463 + id = "s" .. suggestion.id .. "_fulfilled", 1.464 + checked = active and "checked" or nil 1.465 + } } 1.466 + ui.tag { 1.467 + tag = "label", 1.468 + attr = { 1.469 + ["for"] = "s" .. suggestion.id .. "_fulfilled", 1.470 + class = active and "active-fulfilled" or nil, 1.471 + }, 1.472 + content = _"Yes, it's implemented" 1.473 + } 1.474 + end } 1.475 + slot.put("<br />") 1.476 + 1.477 + ui.tag{ 1.478 + tag = "input", 1.479 + attr = { 1.480 + type = "submit", 1.481 + class = "btn btn-default", 1.482 + value = _"publish my rating" 1.483 + }, 1.484 + content = "" 1.485 + } 1.486 + 1.487 + end 1.488 + } 1.489 + 1.490 + end -- if not issue,fully_frozen or closed 1.491 + } 1.492 + end 1.493 + 1.494 + local text = _"Read more" 1.495 + 1.496 + if direct_supporter then 1.497 + text = _"Show more and rate this" 1.498 + end 1.499 + 1.500 + ui.link { 1.501 + attr = { 1.502 + class = "suggestion-more", 1.503 + onclick = "$('#s" .. suggestion.id .. "').removeClass('folded').addClass('unfolded'); return false;" 1.504 + }, 1.505 + text = text 1.506 + } 1.507 + 1.508 + ui.link { 1.509 + attr = { 1.510 + class = "suggestion-less", 1.511 + onclick = "$('#s" .. suggestion.id .. "').addClass('folded').removeClass('unfolded'); return false;" 1.512 + }, 1.513 + text = _"Show less" 1.514 + } 1.515 + end 1.516 + } 1.517 + 1.518 + ui.script{ script = [[ 1.519 + var textEl = $('#s]] .. suggestion.id .. [[ .suggestion-text'); 1.520 + var height = textEl.height(); 1.521 + if (height > 150) $('#s]] .. suggestion.id .. [[').addClass('folded'); 1.522 + ]] } 1.523 + 1.524 + end 1.525 + } -- ui.paragraph 1.526 + 1.527 + 1.528 + 1.529 + end } -- ui.tag "li" 1.530 + 1.531 + end -- for i, suggestion 1.532 + 1.533 + else -- if #initiative.suggestions > 0 1.534 + 1.535 + local text 1.536 + if initiative.issue.closed then 1.537 + text = "No suggestions" 1.538 + else 1.539 + text = "No suggestions (yet)" 1.540 + end 1.541 + ui.sectionHead( function() 1.542 + ui.heading { level = 1, content = text } 1.543 + end) 1.544 + 1.545 + end -- if #initiative.suggestions > 0 1.546 + 1.547 + end 1.548 +}