liquid_feedback_frontend
diff app/main/initiative/_suggestions.lua @ 1649:4188405c2425
Rework of suggestion views
| author | bsw |
|---|---|
| date | Thu Feb 11 15:48:02 2021 +0100 (2021-02-11) |
| parents | 4badb51649f7 |
| children | c08690678b2d |
line diff
1.1 --- a/app/main/initiative/_suggestions.lua Thu Feb 11 15:45:56 2021 +0100 1.2 +++ b/app/main/initiative/_suggestions.lua Thu Feb 11 15:48:02 2021 +0100 1.3 @@ -5,9 +5,130 @@ 1.4 end 1.5 1.6 1.7 +if direct_supporter then 1.8 + ui.tag{ tag = "dialog", attr = { id = "rating_dialog" }, content = function () 1.9 + 1.10 + local opinion = {} 1.11 + ui.form { 1.12 + attr = { onsubmit = "updateOpinion(); return false;" }, 1.13 + module = "opinion", action = "update", 1.14 + routing = { default = { 1.15 + mode = "redirect", 1.16 + module = "initiative", view = "show", id = initiative.id 1.17 + } }, 1.18 + content = function () 1.19 + ui.field.hidden{ attr = { id = "rating_suggestion_id" }, name = "suggestion_id" } 1.20 + ui.container{ attr = { class = "opinon-question" }, content = _"Should the initiator implement this suggestion?" } 1.21 + ui.container { content = function () 1.22 + 1.23 + local options = { 1.24 + { degree = 2, label = _"must" }, 1.25 + { degree = 1, label = _"should" }, 1.26 + { degree = 0, label = _"neutral" }, 1.27 + { degree = -1, label = _"should not" }, 1.28 + { degree = -2, label = _"must not" }, 1.29 + } 1.30 + 1.31 + for i, option in ipairs(options) do 1.32 + ui.tag{ 1.33 + tag = "label", 1.34 + attr = { 1.35 + id = "rating_degree" .. option.degree, 1.36 + class = "mdl-radio mdl-js-radio mdl-js-ripple-effect" 1.37 + }, 1.38 + ["for"] = "rating_degree" .. option.degree, 1.39 + content = function() 1.40 + ui.tag{ 1.41 + tag = "input", 1.42 + attr = { 1.43 + class = "mdl-radio__button", 1.44 + type = "radio", 1.45 + name = "degree", 1.46 + value = option.degree 1.47 + } 1.48 + } 1.49 + ui.tag{ 1.50 + attr = { class = "mdl-radio__label" }, 1.51 + content = option.label 1.52 + } 1.53 + end 1.54 + } 1.55 + slot.put(" ") 1.56 + end 1.57 + end } 1.58 + 1.59 + slot.put("<br />") 1.60 + 1.61 + ui.container{ attr = { class = "opinon-question" }, content = _"Did the initiator implement this suggestion?" } 1.62 + ui.container { content = function () 1.63 + 1.64 + local options = { 1.65 + { degree = "false", id = "notfulfilled", label = _"No (not yet)" }, 1.66 + { degree = "true", id = "fulfilled", label = _"Yes, it's implemented" }, 1.67 + } 1.68 + 1.69 + for i, option in ipairs(options) do 1.70 + ui.tag{ 1.71 + tag = "label", 1.72 + attr = { 1.73 + id = "rating_" .. option.id, 1.74 + class = "mdl-radio mdl-js-radio mdl-js-ripple-effect" 1.75 + }, 1.76 + ["for"] = "rating_" .. option.id, 1.77 + content = function() 1.78 + ui.tag{ 1.79 + tag = "input", 1.80 + attr = { 1.81 + class = "mdl-radio__button", 1.82 + type = "radio", 1.83 + name = "fulfilled", 1.84 + value = option.degree, 1.85 + } 1.86 + } 1.87 + ui.tag{ 1.88 + attr = { class = "mdl-radio__label" }, 1.89 + content = option.label 1.90 + } 1.91 + end 1.92 + } 1.93 + slot.put(" ") 1.94 + end 1.95 + end } 1.96 + 1.97 + slot.put("<br />") 1.98 + 1.99 + ui.tag{ 1.100 + tag = "input", 1.101 + attr = { 1.102 + type = "submit", 1.103 + class = "mdl-button mdl-js-button mdl-button--raised mdl-button--colored", 1.104 + value = _"publish my rating" 1.105 + }, 1.106 + content = "" 1.107 + } 1.108 + 1.109 + slot.put(" ") 1.110 + 1.111 + ui.tag{ 1.112 + tag = "input", 1.113 + attr = { 1.114 + onclick = "document.getElementById('rating_dialog').close(); return false;", 1.115 + type = "submit", 1.116 + class = "mdl-button mdl-js-button", 1.117 + value = _"cancel" 1.118 + }, 1.119 + content = "" 1.120 + } 1.121 + 1.122 + end 1.123 + } 1.124 + 1.125 + end } 1.126 +end 1.127 + 1.128 + 1.129 ui.link { attr = { name = "suggestions" }, text = "" } 1.130 1.131 - 1.132 ui.container { 1.133 attr = { class = "section suggestions" }, 1.134 content = function () 1.135 @@ -38,108 +159,18 @@ 1.136 ui.tag{ attr = { class = "mdl-card__title mdl-card--border" }, content = function() 1.137 ui.heading { level = 2, 1.138 attr = { class = "mdl-card__title-text" }, 1.139 - content = format.string(suggestion.name, { 1.140 - truncate_at = 160, truncate_suffix = true 1.141 - }) } 1.142 - 1.143 - if opinion then 1.144 - 1.145 - ui.container { attr = { class = "mdl-card__content"}, content = function() 1.146 - local class = "" 1.147 - local text = "" 1.148 - 1.149 - if opinion.degree == 2 then 1.150 - class = "must" 1.151 - text = _"must" 1.152 - elseif opinion.degree == 1 then 1.153 - class = "should" 1.154 - text = _"should" 1.155 - elseif opinion.degree == 0 then 1.156 - class = "neutral" 1.157 - text = _"neutral" 1.158 - elseif opinion.degree == -1 then 1.159 - class = "shouldnot" 1.160 - text = _"should not" 1.161 - elseif opinion.degree == -2 then 1.162 - class = "mustnot" 1.163 - text = _"must not" 1.164 - end 1.165 - 1.166 - ui.tag { 1.167 - attr = { class = class }, 1.168 - content = text 1.169 + content = function() 1.170 + ui.tag{ content = format.string(suggestion.name, { 1.171 + truncate_at = 160, truncate_suffix = true }) 1.172 } 1.173 - 1.174 - slot.put ( " " ) 1.175 - 1.176 - if 1.177 - (opinion.degree > 0 and not opinion.fulfilled) 1.178 - or (opinion.degree < 0 and opinion.fulfilled) 1.179 - then 1.180 - ui.tag{ content = _"but" } 1.181 - else 1.182 - ui.tag{ content = _"and" } 1.183 - end 1.184 - 1.185 - slot.put ( " " ) 1.186 - 1.187 - local class = "" 1.188 - local text = "" 1.189 - 1.190 - if opinion.fulfilled then 1.191 - class = "implemented" 1.192 - text = _"is implemented" 1.193 - else 1.194 - class = "notimplemented" 1.195 - text = _"is not implemented" 1.196 - end 1.197 + end 1.198 + } 1.199 + end } 1.200 1.201 - ui.tag { 1.202 - attr = { class = class }, 1.203 - content = text 1.204 - } 1.205 - 1.206 - if 1.207 - (opinion.degree > 0 and not opinion.fulfilled) 1.208 - or (opinion.degree < 0 and opinion.fulfilled) 1.209 - then 1.210 - if math.abs(opinion.degree) > 1 then 1.211 - slot.put(" !!") 1.212 - else 1.213 - slot.put(" !") 1.214 - end 1.215 - else 1.216 - slot.put(" ✓") 1.217 - end 1.218 - 1.219 - end } 1.220 - 1.221 - end 1.222 - 1.223 - end } 1.224 + 1.225 1.226 ui.container{ attr = { class = "suggestion-content" }, content = function() 1.227 1.228 - local plus2 = (suggestion.plus2_unfulfilled_count or 0) 1.229 - + (suggestion.plus2_fulfilled_count or 0) 1.230 - local plus1 = (suggestion.plus1_unfulfilled_count or 0) 1.231 - + (suggestion.plus1_fulfilled_count or 0) 1.232 - local minus1 = (suggestion.minus1_unfulfilled_count or 0) 1.233 - + (suggestion.minus1_fulfilled_count or 0) 1.234 - local minus2 = (suggestion.minus2_unfulfilled_count or 0) 1.235 - + (suggestion.minus2_fulfilled_count or 0) 1.236 - 1.237 - local with_opinion = plus2 + plus1 + minus1 + minus2 1.238 - 1.239 - local neutral = (suggestion.initiative.supporter_count or 0) 1.240 - - with_opinion 1.241 - 1.242 - local neutral2 = with_opinion 1.243 - - (suggestion.plus2_fulfilled_count or 0) 1.244 - - (suggestion.plus1_fulfilled_count or 0) 1.245 - - (suggestion.minus1_fulfilled_count or 0) 1.246 - - (suggestion.minus2_fulfilled_count or 0) 1.247 - 1.248 ui.container { 1.249 attr = { class = "mdl-card__content mdl-card--border suggestionInfo" }, 1.250 content = function () 1.251 @@ -148,203 +179,153 @@ 1.252 util.micro_avatar ( suggestion.author ) 1.253 end 1.254 1.255 - if with_opinion > 0 then 1.256 - ui.container { attr = { class = "suggestion-rating" }, content = function () 1.257 - ui.tag { content = _"collective rating:" } 1.258 - slot.put(" ") 1.259 - ui.bargraph{ 1.260 - max_value = suggestion.initiative.supporter_count, 1.261 - width = 100, 1.262 - bars = { 1.263 - { color = "#0a0", value = plus2 }, 1.264 - { color = "#8a8", value = plus1 }, 1.265 - { color = "#eee", value = neutral }, 1.266 - { color = "#a88", value = minus1 }, 1.267 - { color = "#a00", value = minus2 }, 1.268 - } 1.269 - } 1.270 - slot.put(" | ") 1.271 - ui.tag { content = _"implemented:" } 1.272 - slot.put ( " " ) 1.273 - ui.bargraph{ 1.274 - max_value = with_opinion, 1.275 - width = 100, 1.276 - bars = { 1.277 - { color = "#0a0", value = suggestion.plus2_fulfilled_count }, 1.278 - { color = "#8a8", value = suggestion.plus1_fulfilled_count }, 1.279 - { color = "#eee", value = neutral2 }, 1.280 - { color = "#a88", value = suggestion.minus1_fulfilled_count }, 1.281 - { color = "#a00", value = suggestion.minus2_fulfilled_count }, 1.282 - } 1.283 - } 1.284 - end } 1.285 - end 1.286 + execute.view{ 1.287 + module = "suggestion", view = "_collective_rating", params = { 1.288 + suggestion = suggestion 1.289 + } 1.290 + } 1.291 1.292 end 1.293 } 1.294 1.295 ui.container { 1.296 - attr = { class = "mdl-card__content mdl-card--border suggestion-text draft" }, 1.297 + attr = { class = "mdl-card__content suggestion-text draft" }, 1.298 content = function () 1.299 slot.put ( suggestion:get_content( "html" ) ) 1.300 + 1.301 + ui.container { attr = { class = "floatx-right" }, content = function() 1.302 + 1.303 + ui.link { 1.304 + attr = { 1.305 + class = "mdl-button mdl-js-button mdl-button--icon suggestion-more", 1.306 + onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.remove('folded');document.querySelector('#s" .. suggestion.id .. "').classList.add('unfolded'); return false;" 1.307 + }, 1.308 + content = function() 1.309 + ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_more" } 1.310 + end 1.311 + } 1.312 + 1.313 + ui.link { 1.314 + attr = { 1.315 + class = "mdl-button mdl-js-button mdl-button--icon suggestion-less", 1.316 + onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.add('folded');document.querySelector('#s" .. suggestion.id .. "').classList.remove('unfolded'); return false;" 1.317 + }, 1.318 + content = function() 1.319 + ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_less" } 1.320 + end 1.321 + } 1.322 + --[[ 1.323 + ui.link{ 1.324 + attr = { class = "mdl-button" }, 1.325 + content = _"Details", 1.326 + module = "suggestion", view = "show", id = suggestion.id 1.327 + } 1.328 + --]] 1.329 + end } 1.330 1.331 end 1.332 } 1.333 1.334 - if direct_supporter then 1.335 - ui.container{ attr = { class = "mdl-card__content rating" }, content = function () 1.336 - 1.337 - if not opinion then 1.338 - opinion = {} 1.339 - end 1.340 - ui.form { 1.341 - module = "opinion", action = "update", params = { 1.342 - suggestion_id = suggestion.id 1.343 - }, 1.344 - routing = { default = { 1.345 - mode = "redirect", 1.346 - module = "initiative", view = "show", id = suggestion.initiative_id, 1.347 - params = { suggestion_id = suggestion.id }, 1.348 - anchor = "s" .. suggestion.id -- TODO webmcp 1.349 - } }, 1.350 - content = function () 1.351 - 1.352 - ui.container{ attr = { class = "opinon-question" }, content = _"Should the initiator implement this suggestion?" } 1.353 - ui.container { content = function () 1.354 - 1.355 - local options = { 1.356 - { degree = 2, label = _"must" }, 1.357 - { degree = 1, label = _"should" }, 1.358 - { degree = 0, label = _"neutral" }, 1.359 - { degree = -1, label = _"should not" }, 1.360 - { degree = -2, label = _"must not" }, 1.361 - } 1.362 - 1.363 - for i, option in ipairs(options) do 1.364 - local active = opinion.degree == option.degree or opinion.degree == nil and option.degree == 0 1.365 - ui.tag{ 1.366 - tag = "label", 1.367 - attr = { class = "mdl-radio mdl-js-radio mdl-js-ripple-effect" }, 1.368 - ["for"] = "s" .. suggestion.id .. "_degree" .. option.degree, 1.369 - content = function() 1.370 - ui.tag{ 1.371 - tag = "input", 1.372 - attr = { 1.373 - class = "mdl-radio__button", 1.374 - type = "radio", 1.375 - name = "degree", 1.376 - value = option.degree, 1.377 - id = "s" .. suggestion.id .. "_degree" .. option.degree, 1.378 - checked = active and "checked" or nil 1.379 - } 1.380 - } 1.381 - ui.tag{ 1.382 - attr = { class = "mdl-radio__label" }, 1.383 - content = option.label 1.384 - } 1.385 - end 1.386 - } 1.387 - slot.put(" ") 1.388 - end 1.389 - end } 1.390 - 1.391 - slot.put("<br />") 1.392 - 1.393 - ui.container{ attr = { class = "opinon-question" }, content = _"Did the initiator implement this suggestion?" } 1.394 - ui.container { content = function () 1.395 - 1.396 - local options = { 1.397 - { degree = "false", id = "notfulfilled", label = _"No (not yet)" }, 1.398 - { degree = "true", id = "fulfilled", label = _"Yes, it's implemented" }, 1.399 - } 1.400 - 1.401 - for i, option in ipairs(options) do 1.402 - local active = opinion.fulfilled == (option.degree == "true" and true or false) 1.403 - ui.tag{ 1.404 - tag = "label", 1.405 - attr = { class = "mdl-radio mdl-js-radio mdl-js-ripple-effect" }, 1.406 - ["for"] = "s" .. suggestion.id .. "_" .. option.id, 1.407 - content = function() 1.408 - ui.tag{ 1.409 - tag = "input", 1.410 - attr = { 1.411 - class = "mdl-radio__button", 1.412 - type = "radio", 1.413 - name = "fulfilled", 1.414 - value = option.degree, 1.415 - id = "s" .. suggestion.id .. "_" .. option.id, 1.416 - checked = active and "checked" or nil 1.417 - } 1.418 - } 1.419 - ui.tag{ 1.420 - attr = { class = "mdl-radio__label" }, 1.421 - content = option.label 1.422 - } 1.423 - end 1.424 - } 1.425 - slot.put(" ") 1.426 - end 1.427 - end } 1.428 - 1.429 - slot.put("<br />") 1.430 - 1.431 - ui.tag{ 1.432 - tag = "input", 1.433 - attr = { 1.434 - type = "submit", 1.435 - class = "mdl-button mdl-js-button mdl-button--raised mdl-button--colored", 1.436 - value = _"publish my rating" 1.437 - }, 1.438 - content = "" 1.439 - } 1.440 - 1.441 - end 1.442 - } 1.443 - 1.444 - end } 1.445 - end 1.446 - 1.447 end } 1.448 1.449 - ui.container { attr = { class = "rating-button" }, content = function() 1.450 - 1.451 - local text = _"Read more" 1.452 + ui.container { attr = { class = "mdl-card__actions mdl-card--border" }, content = function() 1.453 + 1.454 + ui.container{ attr = { class = "float-right" }, content = function() 1.455 + ui.tag{ attr = { id = "s" .. suggestion.id .. "_rating_text" }, content = function() 1.456 + local text = "" 1.457 + if opinion then 1.458 + if opinion.degree == 2 then 1.459 + text = _"must" 1.460 + elseif opinion.degree == 1 then 1.461 + text = _"should" 1.462 + elseif opinion.degree == 0 then 1.463 + text = _"neutral" 1.464 + elseif opinion.degree == -1 then 1.465 + text = _"should not" 1.466 + elseif opinion.degree == -2 then 1.467 + text = _"must not" 1.468 + end 1.469 + ui.tag { content = text } 1.470 + slot.put ( " " ) 1.471 + if 1.472 + (opinion.degree > 0 and not opinion.fulfilled) 1.473 + or (opinion.degree < 0 and opinion.fulfilled) 1.474 + then 1.475 + ui.tag{ content = _"but" } 1.476 + else 1.477 + ui.tag{ content = _"and" } 1.478 + end 1.479 + slot.put ( " " ) 1.480 + local text = "" 1.481 + if opinion.fulfilled then 1.482 + text = _"is implemented" 1.483 + else 1.484 + text = _"is not implemented" 1.485 + end 1.486 + ui.tag { content = text } 1.487 + end 1.488 + end } 1.489 + local id = "s" .. suggestion.id .. "_rating_icon" 1.490 + if opinion and ( 1.491 + (opinion.degree > 0 and not opinion.fulfilled) 1.492 + or (opinion.degree < 0 and opinion.fulfilled) 1.493 + ) 1.494 + then 1.495 + slot.put(" ") 1.496 + if math.abs(opinion.degree) > 1 then 1.497 + ui.icon("warning", "red", id) 1.498 + else 1.499 + ui.icon("warning", nil, id) 1.500 + end 1.501 + elseif opinion then 1.502 + slot.put(" ") 1.503 + ui.icon("done", nil, id) 1.504 + else 1.505 + slot.put(" ") 1.506 + ui.icon("blank", nil, id) 1.507 + end 1.508 + end } 1.509 1.510 - if direct_supporter then 1.511 - text = text .. " / " .. _"Rate suggestion" 1.512 - end 1.513 - 1.514 - ui.link { 1.515 - attr = { 1.516 - class = "mdl-button mdl-js-button suggestion-more", 1.517 - onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.remove('folded');document.querySelector('#s" .. suggestion.id .. "').classList.add('unfolded'); return false;" 1.518 + ui.link{ 1.519 + attr = { 1.520 + id = "s" .. suggestion.id .. "_rate_button", 1.521 + class = "mdl-button", 1.522 + onclick = "rateSuggestion(" .. suggestion.id .. ", " .. (opinion and opinion.degree or 0) .. ", " .. (opinion and (opinion.fulfilled and "true" or "false") or "null") .. ");return false;" 1.523 }, 1.524 - text = text 1.525 + content = function() 1.526 + if opinion then 1.527 + ui.tag { content = _"update rating" } 1.528 + else 1.529 + ui.tag { content = _"rate suggestion" } 1.530 + end 1.531 + end 1.532 } 1.533 - 1.534 - ui.link { 1.535 - attr = { 1.536 - class = "mdl-button suggestion-less", 1.537 - onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.add('folded');document.querySelector('#s" .. suggestion.id .. "').classList.remove('unfolded'); return false;" 1.538 - }, 1.539 - text = _"Show less" 1.540 - } 1.541 - --[[ 1.542 + 1.543 ui.link{ 1.544 attr = { class = "mdl-button" }, 1.545 content = _"Details", 1.546 module = "suggestion", view = "show", id = suggestion.id 1.547 } 1.548 - --]] 1.549 + 1.550 end } 1.551 ui.script{ script = [[ 1.552 + var rateSuggestionRateText = "]] .. _"rate suggestion" .. [["; 1.553 + var rateSuggestionUpdateRatingText = "]] .. _"update rating" .. [["; 1.554 + var rateSuggestionDegreeTexts = { 1.555 + "-2": "]] .. _"must not" .. [[", 1.556 + "-1": "]] .. _"should not" .. [[", 1.557 + "1": "]] .. _"should" .. [[", 1.558 + "2": "]] .. _"must" .. [[" 1.559 + } 1.560 + var rateSuggestionAndText = "]] .. _"and" .. [["; 1.561 + var rateSuggestionButText = "]] .. _"but" .. [["; 1.562 + var rateSuggestionFulfilledText = "]] .. _"is implemented" .. [["; 1.563 + var rateSuggestionNotFulfilledText = "]] .. _"is not implemented" .. [["; 1.564 window.addEventListener("load", function() { 1.565 var textEl = document.querySelector('#s]] .. suggestion.id .. [[ .suggestion-content'); 1.566 var height = textEl.clientHeight; 1.567 - if (height > 180) { 1.568 + if (height > 250) { 1.569 document.querySelector('#s]] .. suggestion.id .. [[').classList.add('folded'); 1.570 - document.querySelector('#s]] .. suggestion.id .. [[ .rating-button').classList.add('mdl-card__actions'); 1.571 - document.querySelector('#s]] .. suggestion.id .. [[ .rating-button').classList.add('mdl-card--border'); 1.572 } 1.573 }); 1.574 ]] }