liquid_feedback_frontend
diff app/main/initiative/_suggestions.lua @ 1309:32cc544d5a5b
Cumulative patch for upcoming frontend version 4
| author | bsw/jbe | 
|---|---|
| date | Sun Jul 15 14:07:29 2018 +0200 (2018-07-15) | 
| parents | |
| children | 4badb51649f7 | 
   line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/app/main/initiative/_suggestions.lua Sun Jul 15 14:07:29 2018 +0200 1.3 @@ -0,0 +1,358 @@ 1.4 +local initiative = param.get("initiative", "table") 1.5 +local direct_supporter 1.6 +if app.session.member_id then 1.7 + direct_supporter = initiative.issue.member_info.own_participation and initiative.member_info.supported 1.8 +end 1.9 + 1.10 + 1.11 +ui.link { attr = { name = "suggestions" }, text = "" } 1.12 + 1.13 + 1.14 +ui.container { 1.15 + attr = { class = "section suggestions" }, 1.16 + content = function () 1.17 + 1.18 + if # ( initiative.suggestions ) > 0 then 1.19 + 1.20 + ui.heading { 1.21 + level = 1, 1.22 + content = _("Suggestions for improvement (#{count})", { count = # ( initiative.suggestions ) } ) 1.23 + } 1.24 + ui.container { content = _"written and rated by the supportes of this initiative to improve the proposal and its reasons" } 1.25 + slot.put("<br />") 1.26 + 1.27 + for i, suggestion in ipairs(initiative.suggestions) do 1.28 + 1.29 + local opinion = Opinion:by_pk(app.session.member_id, suggestion.id) 1.30 + 1.31 + local class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp not-folded" 1.32 + if suggestion.id == param.get("suggestion_id", atom.number) then 1.33 + class = class .. " highlighted" 1.34 + end 1.35 + if member and not initiative.issue.fully_frozen and not initiative.issue.closed and initiative.member_info.supported then 1.36 + class = class .. " rateable" 1.37 + end 1.38 + 1.39 + ui.link { attr = { name = "s" .. suggestion.id }, text = "" } 1.40 + ui.tag { tag = "div", attr = { class = class, id = "s" .. suggestion.id }, content = function () 1.41 + ui.tag{ attr = { class = "mdl-card__title mdl-card--border" }, content = function() 1.42 + ui.heading { level = 2, 1.43 + attr = { class = "mdl-card__title-text" }, 1.44 + content = format.string(suggestion.name, { 1.45 + truncate_at = 160, truncate_suffix = true 1.46 + }) } 1.47 + 1.48 + if opinion then 1.49 + 1.50 + ui.container { attr = { class = "mdl-card__content"}, content = function() 1.51 + local class = "" 1.52 + local text = "" 1.53 + 1.54 + if opinion.degree == 2 then 1.55 + class = "must" 1.56 + text = _"must" 1.57 + elseif opinion.degree == 1 then 1.58 + class = "should" 1.59 + text = _"should" 1.60 + elseif opinion.degree == 0 then 1.61 + class = "neutral" 1.62 + text = _"neutral" 1.63 + elseif opinion.degree == -1 then 1.64 + class = "shouldnot" 1.65 + text = _"should not" 1.66 + elseif opinion.degree == -2 then 1.67 + class = "mustnot" 1.68 + text = _"must not" 1.69 + end 1.70 + 1.71 + ui.tag { 1.72 + attr = { class = class }, 1.73 + content = text 1.74 + } 1.75 + 1.76 + slot.put ( " " ) 1.77 + 1.78 + if 1.79 + (opinion.degree > 0 and not opinion.fulfilled) 1.80 + or (opinion.degree < 0 and opinion.fulfilled) 1.81 + then 1.82 + ui.tag{ content = _"but" } 1.83 + else 1.84 + ui.tag{ content = _"and" } 1.85 + end 1.86 + 1.87 + slot.put ( " " ) 1.88 + 1.89 + local class = "" 1.90 + local text = "" 1.91 + 1.92 + if opinion.fulfilled then 1.93 + class = "implemented" 1.94 + text = _"is implemented" 1.95 + else 1.96 + class = "notimplemented" 1.97 + text = _"is not implemented" 1.98 + end 1.99 + 1.100 + ui.tag { 1.101 + attr = { class = class }, 1.102 + content = text 1.103 + } 1.104 + 1.105 + if 1.106 + (opinion.degree > 0 and not opinion.fulfilled) 1.107 + or (opinion.degree < 0 and opinion.fulfilled) 1.108 + then 1.109 + if math.abs(opinion.degree) > 1 then 1.110 + slot.put(" !!") 1.111 + else 1.112 + slot.put(" !") 1.113 + end 1.114 + else 1.115 + slot.put(" ✓") 1.116 + end 1.117 + 1.118 + end } 1.119 + 1.120 + end 1.121 + 1.122 + end } 1.123 + 1.124 + ui.container{ attr = { class = "suggestion-content" }, content = function() 1.125 + 1.126 + local plus2 = (suggestion.plus2_unfulfilled_count or 0) 1.127 + + (suggestion.plus2_fulfilled_count or 0) 1.128 + local plus1 = (suggestion.plus1_unfulfilled_count or 0) 1.129 + + (suggestion.plus1_fulfilled_count or 0) 1.130 + local minus1 = (suggestion.minus1_unfulfilled_count or 0) 1.131 + + (suggestion.minus1_fulfilled_count or 0) 1.132 + local minus2 = (suggestion.minus2_unfulfilled_count or 0) 1.133 + + (suggestion.minus2_fulfilled_count or 0) 1.134 + 1.135 + local with_opinion = plus2 + plus1 + minus1 + minus2 1.136 + 1.137 + local neutral = (suggestion.initiative.supporter_count or 0) 1.138 + - with_opinion 1.139 + 1.140 + local neutral2 = with_opinion 1.141 + - (suggestion.plus2_fulfilled_count or 0) 1.142 + - (suggestion.plus1_fulfilled_count or 0) 1.143 + - (suggestion.minus1_fulfilled_count or 0) 1.144 + - (suggestion.minus2_fulfilled_count or 0) 1.145 + 1.146 + ui.container { 1.147 + attr = { class = "mdl-card__content mdl-card--border suggestionInfo" }, 1.148 + content = function () 1.149 + 1.150 + if app.session:has_access("authors_pseudonymous") then 1.151 + util.micro_avatar ( suggestion.author ) 1.152 + end 1.153 + 1.154 + if with_opinion > 0 then 1.155 + ui.container { attr = { class = "suggestion-rating" }, content = function () 1.156 + ui.tag { content = _"collective rating:" } 1.157 + slot.put(" ") 1.158 + ui.bargraph{ 1.159 + max_value = suggestion.initiative.supporter_count, 1.160 + width = 100, 1.161 + bars = { 1.162 + { color = "#0a0", value = plus2 }, 1.163 + { color = "#8a8", value = plus1 }, 1.164 + { color = "#eee", value = neutral }, 1.165 + { color = "#a88", value = minus1 }, 1.166 + { color = "#a00", value = minus2 }, 1.167 + } 1.168 + } 1.169 + slot.put(" | ") 1.170 + ui.tag { content = _"implemented:" } 1.171 + slot.put ( " " ) 1.172 + ui.bargraph{ 1.173 + max_value = with_opinion, 1.174 + width = 100, 1.175 + bars = { 1.176 + { color = "#0a0", value = suggestion.plus2_fulfilled_count }, 1.177 + { color = "#8a8", value = suggestion.plus1_fulfilled_count }, 1.178 + { color = "#eee", value = neutral2 }, 1.179 + { color = "#a88", value = suggestion.minus1_fulfilled_count }, 1.180 + { color = "#a00", value = suggestion.minus2_fulfilled_count }, 1.181 + } 1.182 + } 1.183 + end } 1.184 + end 1.185 + 1.186 + end 1.187 + } 1.188 + 1.189 + ui.container { 1.190 + attr = { class = "mdl-card__content mdl-card--border suggestion-text draft" }, 1.191 + content = function () 1.192 + slot.put ( suggestion:get_content( "html" ) ) 1.193 + 1.194 + end 1.195 + } 1.196 + 1.197 + if direct_supporter then 1.198 + ui.container{ attr = { class = "mdl-card__content rating" }, content = function () 1.199 + 1.200 + if not opinion then 1.201 + opinion = {} 1.202 + end 1.203 + ui.form { 1.204 + module = "opinion", action = "update", params = { 1.205 + suggestion_id = suggestion.id 1.206 + }, 1.207 + routing = { default = { 1.208 + mode = "redirect", 1.209 + module = "initiative", view = "show", id = suggestion.initiative_id, 1.210 + params = { suggestion_id = suggestion.id }, 1.211 + anchor = "s" .. suggestion.id -- TODO webmcp 1.212 + } }, 1.213 + content = function () 1.214 + 1.215 + ui.container{ attr = { class = "opinon-question" }, content = _"Should the initiator implement this suggestion?" } 1.216 + ui.container { content = function () 1.217 + 1.218 + local options = { 1.219 + { degree = 2, label = _"must" }, 1.220 + { degree = 1, label = _"should" }, 1.221 + { degree = 0, label = _"neutral" }, 1.222 + { degree = -1, label = _"should not" }, 1.223 + { degree = -2, label = _"must not" }, 1.224 + } 1.225 + 1.226 + for i, option in ipairs(options) do 1.227 + local active = opinion.degree == option.degree 1.228 + ui.tag{ 1.229 + tag = "label", 1.230 + attr = { class = "mdl-radio mdl-js-radio mdl-js-ripple-effect" }, 1.231 + ["for"] = "s" .. suggestion.id .. "_degree" .. option.degree, 1.232 + content = function() 1.233 + ui.tag{ 1.234 + tag = "input", 1.235 + attr = { 1.236 + class = "mdl-radio__button", 1.237 + type = "radio", 1.238 + name = "degree", 1.239 + value = option.degree, 1.240 + id = "s" .. suggestion.id .. "_degree" .. option.degree, 1.241 + checked = active and "checked" or nil 1.242 + } 1.243 + } 1.244 + ui.tag{ 1.245 + attr = { class = "mdl-radio__label" }, 1.246 + content = option.label 1.247 + } 1.248 + end 1.249 + } 1.250 + slot.put("     ") 1.251 + end 1.252 + end } 1.253 + 1.254 + slot.put("<br />") 1.255 + 1.256 + ui.container{ attr = { class = "opinon-question" }, content = _"Did the initiator implement this suggestion?" } 1.257 + ui.container { content = function () 1.258 + 1.259 + local options = { 1.260 + { degree = "false", id = "notfulfilled", label = _"No (not yet)" }, 1.261 + { degree = "true", id = "fulfilled", label = _"Yes, it's implemented" }, 1.262 + } 1.263 + 1.264 + for i, option in ipairs(options) do 1.265 + local active = opinion.fulfilled == (option.degree == "true" and true or false) 1.266 + ui.tag{ 1.267 + tag = "label", 1.268 + attr = { class = "mdl-radio mdl-js-radio mdl-js-ripple-effect" }, 1.269 + ["for"] = "s" .. suggestion.id .. "_" .. option.id, 1.270 + content = function() 1.271 + ui.tag{ 1.272 + tag = "input", 1.273 + attr = { 1.274 + class = "mdl-radio__button", 1.275 + type = "radio", 1.276 + name = "fulfilled", 1.277 + value = option.degree, 1.278 + id = "s" .. suggestion.id .. "_" .. option.id, 1.279 + checked = active and "checked" or nil 1.280 + } 1.281 + } 1.282 + ui.tag{ 1.283 + attr = { class = "mdl-radio__label" }, 1.284 + content = option.label 1.285 + } 1.286 + end 1.287 + } 1.288 + slot.put("     ") 1.289 + end 1.290 + end } 1.291 + 1.292 + slot.put("<br />") 1.293 + 1.294 + ui.tag{ 1.295 + tag = "input", 1.296 + attr = { 1.297 + type = "submit", 1.298 + class = "mdl-button mdl-js-button mdl-button--raised mdl-button--colored", 1.299 + value = _"publish my rating" 1.300 + }, 1.301 + content = "" 1.302 + } 1.303 + 1.304 + end 1.305 + } 1.306 + 1.307 + end } 1.308 + end 1.309 + 1.310 + end } 1.311 + 1.312 + ui.container { attr = { class = "rating-button" }, content = function() 1.313 + 1.314 + local text = _"Read more" 1.315 + 1.316 + if direct_supporter then 1.317 + text = text .. " / " .. _"Rate suggestion" 1.318 + end 1.319 + 1.320 + ui.link { 1.321 + attr = { 1.322 + class = "mdl-button mdl-js-button suggestion-more", 1.323 + onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.remove('folded');document.querySelector('#s" .. suggestion.id .. "').classList.add('unfolded'); return false;" 1.324 + }, 1.325 + text = text 1.326 + } 1.327 + 1.328 + ui.link { 1.329 + attr = { 1.330 + class = "mdl-button suggestion-less", 1.331 + onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.add('folded');document.querySelector('#s" .. suggestion.id .. "').classList.remove('unfolded'); return false;" 1.332 + }, 1.333 + text = _"Show less" 1.334 + } 1.335 + --[[ 1.336 + ui.link{ 1.337 + attr = { class = "mdl-button" }, 1.338 + content = _"Details", 1.339 + module = "suggestion", view = "show", id = suggestion.id 1.340 + } 1.341 + --]] 1.342 + end } 1.343 + ui.script{ script = [[ 1.344 + window.addEventListener("load", function() { 1.345 + var textEl = document.querySelector('#s]] .. suggestion.id .. [[ .suggestion-content'); 1.346 + var height = textEl.clientHeight; 1.347 + if (height > 180) { 1.348 + document.querySelector('#s]] .. suggestion.id .. [[').classList.add('folded'); 1.349 + document.querySelector('#s]] .. suggestion.id .. [[ .rating-button').classList.add('mdl-card__actions'); 1.350 + document.querySelector('#s]] .. suggestion.id .. [[ .rating-button').classList.add('mdl-card--border'); 1.351 + } 1.352 + }); 1.353 + ]] } 1.354 + 1.355 + end } 1.356 + 1.357 + end -- for i, suggestion 1.358 + 1.359 + end -- if #initiative.suggestions > 0 1.360 + end 1.361 +}