bsw/jbe@1309: local initiative = param.get("initiative", "table") bsw/jbe@1309: local direct_supporter bsw/jbe@1309: if app.session.member_id then bsw/jbe@1309: direct_supporter = initiative.issue.member_info.own_participation and initiative.member_info.supported bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: bsw/jbe@1309: ui.link { attr = { name = "suggestions" }, text = "" } bsw/jbe@1309: bsw/jbe@1309: bsw/jbe@1309: ui.container { bsw/jbe@1309: attr = { class = "section suggestions" }, bsw/jbe@1309: content = function () bsw/jbe@1309: bsw/jbe@1309: if # ( initiative.suggestions ) > 0 then bsw/jbe@1309: bsw/jbe@1309: ui.heading { bsw/jbe@1309: level = 1, bsw/jbe@1309: content = _("Suggestions for improvement (#{count})", { count = # ( initiative.suggestions ) } ) bsw/jbe@1309: } bsw/jbe@1309: ui.container { content = _"written and rated by the supportes of this initiative to improve the proposal and its reasons" } bsw/jbe@1309: slot.put("
") bsw/jbe@1309: bsw/jbe@1309: for i, suggestion in ipairs(initiative.suggestions) do bsw/jbe@1309: bsw/jbe@1309: local opinion = Opinion:by_pk(app.session.member_id, suggestion.id) bsw/jbe@1309: bsw/jbe@1309: local class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp not-folded" bsw/jbe@1309: if suggestion.id == param.get("suggestion_id", atom.number) then bsw/jbe@1309: class = class .. " highlighted" bsw/jbe@1309: end bsw/jbe@1309: if member and not initiative.issue.fully_frozen and not initiative.issue.closed and initiative.member_info.supported then bsw/jbe@1309: class = class .. " rateable" bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: ui.link { attr = { name = "s" .. suggestion.id }, text = "" } bsw/jbe@1309: ui.tag { tag = "div", attr = { class = class, id = "s" .. suggestion.id }, content = function () bsw/jbe@1309: ui.tag{ attr = { class = "mdl-card__title mdl-card--border" }, content = function() bsw/jbe@1309: ui.heading { level = 2, bsw/jbe@1309: attr = { class = "mdl-card__title-text" }, bsw/jbe@1309: content = format.string(suggestion.name, { bsw/jbe@1309: truncate_at = 160, truncate_suffix = true bsw/jbe@1309: }) } bsw/jbe@1309: bsw/jbe@1309: if opinion then bsw/jbe@1309: bsw/jbe@1309: ui.container { attr = { class = "mdl-card__content"}, content = function() bsw/jbe@1309: local class = "" bsw/jbe@1309: local text = "" bsw/jbe@1309: bsw/jbe@1309: if opinion.degree == 2 then bsw/jbe@1309: class = "must" bsw/jbe@1309: text = _"must" bsw/jbe@1309: elseif opinion.degree == 1 then bsw/jbe@1309: class = "should" bsw/jbe@1309: text = _"should" bsw/jbe@1309: elseif opinion.degree == 0 then bsw/jbe@1309: class = "neutral" bsw/jbe@1309: text = _"neutral" bsw/jbe@1309: elseif opinion.degree == -1 then bsw/jbe@1309: class = "shouldnot" bsw/jbe@1309: text = _"should not" bsw/jbe@1309: elseif opinion.degree == -2 then bsw/jbe@1309: class = "mustnot" bsw/jbe@1309: text = _"must not" bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: ui.tag { bsw/jbe@1309: attr = { class = class }, bsw/jbe@1309: content = text bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: slot.put ( " " ) bsw/jbe@1309: bsw/jbe@1309: if bsw/jbe@1309: (opinion.degree > 0 and not opinion.fulfilled) bsw/jbe@1309: or (opinion.degree < 0 and opinion.fulfilled) bsw/jbe@1309: then bsw/jbe@1309: ui.tag{ content = _"but" } bsw/jbe@1309: else bsw/jbe@1309: ui.tag{ content = _"and" } bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: slot.put ( " " ) bsw/jbe@1309: bsw/jbe@1309: local class = "" bsw/jbe@1309: local text = "" bsw/jbe@1309: bsw/jbe@1309: if opinion.fulfilled then bsw/jbe@1309: class = "implemented" bsw/jbe@1309: text = _"is implemented" bsw/jbe@1309: else bsw/jbe@1309: class = "notimplemented" bsw/jbe@1309: text = _"is not implemented" bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: ui.tag { bsw/jbe@1309: attr = { class = class }, bsw/jbe@1309: content = text bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: if bsw/jbe@1309: (opinion.degree > 0 and not opinion.fulfilled) bsw/jbe@1309: or (opinion.degree < 0 and opinion.fulfilled) bsw/jbe@1309: then bsw/jbe@1309: if math.abs(opinion.degree) > 1 then bsw/jbe@1309: slot.put(" !!") bsw/jbe@1309: else bsw/jbe@1309: slot.put(" !") bsw/jbe@1309: end bsw/jbe@1309: else bsw/jbe@1309: slot.put(" ✓") bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: end } bsw/jbe@1309: bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: end } bsw/jbe@1309: bsw/jbe@1309: ui.container{ attr = { class = "suggestion-content" }, content = function() bsw/jbe@1309: bsw/jbe@1309: local plus2 = (suggestion.plus2_unfulfilled_count or 0) bsw/jbe@1309: + (suggestion.plus2_fulfilled_count or 0) bsw/jbe@1309: local plus1 = (suggestion.plus1_unfulfilled_count or 0) bsw/jbe@1309: + (suggestion.plus1_fulfilled_count or 0) bsw/jbe@1309: local minus1 = (suggestion.minus1_unfulfilled_count or 0) bsw/jbe@1309: + (suggestion.minus1_fulfilled_count or 0) bsw/jbe@1309: local minus2 = (suggestion.minus2_unfulfilled_count or 0) bsw/jbe@1309: + (suggestion.minus2_fulfilled_count or 0) bsw/jbe@1309: bsw/jbe@1309: local with_opinion = plus2 + plus1 + minus1 + minus2 bsw/jbe@1309: bsw/jbe@1309: local neutral = (suggestion.initiative.supporter_count or 0) bsw/jbe@1309: - with_opinion bsw/jbe@1309: bsw/jbe@1309: local neutral2 = with_opinion bsw/jbe@1309: - (suggestion.plus2_fulfilled_count or 0) bsw/jbe@1309: - (suggestion.plus1_fulfilled_count or 0) bsw/jbe@1309: - (suggestion.minus1_fulfilled_count or 0) bsw/jbe@1309: - (suggestion.minus2_fulfilled_count or 0) bsw/jbe@1309: bsw/jbe@1309: ui.container { bsw/jbe@1309: attr = { class = "mdl-card__content mdl-card--border suggestionInfo" }, bsw/jbe@1309: content = function () bsw/jbe@1309: bsw/jbe@1309: if app.session:has_access("authors_pseudonymous") then bsw/jbe@1309: util.micro_avatar ( suggestion.author ) bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: if with_opinion > 0 then bsw/jbe@1309: ui.container { attr = { class = "suggestion-rating" }, content = function () bsw/jbe@1309: ui.tag { content = _"collective rating:" } bsw/jbe@1309: slot.put(" ") bsw/jbe@1309: ui.bargraph{ bsw/jbe@1309: max_value = suggestion.initiative.supporter_count, bsw/jbe@1309: width = 100, bsw/jbe@1309: bars = { bsw/jbe@1309: { color = "#0a0", value = plus2 }, bsw/jbe@1309: { color = "#8a8", value = plus1 }, bsw/jbe@1309: { color = "#eee", value = neutral }, bsw/jbe@1309: { color = "#a88", value = minus1 }, bsw/jbe@1309: { color = "#a00", value = minus2 }, bsw/jbe@1309: } bsw/jbe@1309: } bsw/jbe@1309: slot.put(" | ") bsw/jbe@1309: ui.tag { content = _"implemented:" } bsw/jbe@1309: slot.put ( " " ) bsw/jbe@1309: ui.bargraph{ bsw/jbe@1309: max_value = with_opinion, bsw/jbe@1309: width = 100, bsw/jbe@1309: bars = { bsw/jbe@1309: { color = "#0a0", value = suggestion.plus2_fulfilled_count }, bsw/jbe@1309: { color = "#8a8", value = suggestion.plus1_fulfilled_count }, bsw/jbe@1309: { color = "#eee", value = neutral2 }, bsw/jbe@1309: { color = "#a88", value = suggestion.minus1_fulfilled_count }, bsw/jbe@1309: { color = "#a00", value = suggestion.minus2_fulfilled_count }, bsw/jbe@1309: } bsw/jbe@1309: } bsw/jbe@1309: end } bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: end bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: ui.container { bsw/jbe@1309: attr = { class = "mdl-card__content mdl-card--border suggestion-text draft" }, bsw/jbe@1309: content = function () bsw/jbe@1309: slot.put ( suggestion:get_content( "html" ) ) bsw/jbe@1309: bsw/jbe@1309: end bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: if direct_supporter then bsw/jbe@1309: ui.container{ attr = { class = "mdl-card__content rating" }, content = function () bsw/jbe@1309: bsw/jbe@1309: if not opinion then bsw/jbe@1309: opinion = {} bsw/jbe@1309: end bsw/jbe@1309: ui.form { bsw/jbe@1309: module = "opinion", action = "update", params = { bsw/jbe@1309: suggestion_id = suggestion.id bsw/jbe@1309: }, bsw/jbe@1309: routing = { default = { bsw/jbe@1309: mode = "redirect", bsw/jbe@1309: module = "initiative", view = "show", id = suggestion.initiative_id, bsw/jbe@1309: params = { suggestion_id = suggestion.id }, bsw/jbe@1309: anchor = "s" .. suggestion.id -- TODO webmcp bsw/jbe@1309: } }, bsw/jbe@1309: content = function () bsw/jbe@1309: bsw/jbe@1309: ui.container{ attr = { class = "opinon-question" }, content = _"Should the initiator implement this suggestion?" } bsw/jbe@1309: ui.container { content = function () bsw/jbe@1309: bsw/jbe@1309: local options = { bsw/jbe@1309: { degree = 2, label = _"must" }, bsw/jbe@1309: { degree = 1, label = _"should" }, bsw/jbe@1309: { degree = 0, label = _"neutral" }, bsw/jbe@1309: { degree = -1, label = _"should not" }, bsw/jbe@1309: { degree = -2, label = _"must not" }, bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: for i, option in ipairs(options) do bsw@1491: local active = opinion.degree == option.degree or opinion.degree == nil and option.degree == 0 bsw/jbe@1309: ui.tag{ bsw/jbe@1309: tag = "label", bsw/jbe@1309: attr = { class = "mdl-radio mdl-js-radio mdl-js-ripple-effect" }, bsw/jbe@1309: ["for"] = "s" .. suggestion.id .. "_degree" .. option.degree, bsw/jbe@1309: content = function() bsw/jbe@1309: ui.tag{ bsw/jbe@1309: tag = "input", bsw/jbe@1309: attr = { bsw/jbe@1309: class = "mdl-radio__button", bsw/jbe@1309: type = "radio", bsw/jbe@1309: name = "degree", bsw/jbe@1309: value = option.degree, bsw/jbe@1309: id = "s" .. suggestion.id .. "_degree" .. option.degree, bsw/jbe@1309: checked = active and "checked" or nil bsw/jbe@1309: } bsw/jbe@1309: } bsw/jbe@1309: ui.tag{ bsw/jbe@1309: attr = { class = "mdl-radio__label" }, bsw/jbe@1309: content = option.label bsw/jbe@1309: } bsw/jbe@1309: end bsw/jbe@1309: } bsw/jbe@1309: slot.put("     ") bsw/jbe@1309: end bsw/jbe@1309: end } bsw/jbe@1309: bsw/jbe@1309: slot.put("
") bsw/jbe@1309: bsw/jbe@1309: ui.container{ attr = { class = "opinon-question" }, content = _"Did the initiator implement this suggestion?" } bsw/jbe@1309: ui.container { content = function () bsw/jbe@1309: bsw/jbe@1309: local options = { bsw/jbe@1309: { degree = "false", id = "notfulfilled", label = _"No (not yet)" }, bsw/jbe@1309: { degree = "true", id = "fulfilled", label = _"Yes, it's implemented" }, bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: for i, option in ipairs(options) do bsw/jbe@1309: local active = opinion.fulfilled == (option.degree == "true" and true or false) bsw/jbe@1309: ui.tag{ bsw/jbe@1309: tag = "label", bsw/jbe@1309: attr = { class = "mdl-radio mdl-js-radio mdl-js-ripple-effect" }, bsw/jbe@1309: ["for"] = "s" .. suggestion.id .. "_" .. option.id, bsw/jbe@1309: content = function() bsw/jbe@1309: ui.tag{ bsw/jbe@1309: tag = "input", bsw/jbe@1309: attr = { bsw/jbe@1309: class = "mdl-radio__button", bsw/jbe@1309: type = "radio", bsw/jbe@1309: name = "fulfilled", bsw/jbe@1309: value = option.degree, bsw/jbe@1309: id = "s" .. suggestion.id .. "_" .. option.id, bsw/jbe@1309: checked = active and "checked" or nil bsw/jbe@1309: } bsw/jbe@1309: } bsw/jbe@1309: ui.tag{ bsw/jbe@1309: attr = { class = "mdl-radio__label" }, bsw/jbe@1309: content = option.label bsw/jbe@1309: } bsw/jbe@1309: end bsw/jbe@1309: } bsw/jbe@1309: slot.put("     ") bsw/jbe@1309: end bsw/jbe@1309: end } bsw/jbe@1309: bsw/jbe@1309: slot.put("
") bsw/jbe@1309: bsw/jbe@1309: ui.tag{ bsw/jbe@1309: tag = "input", bsw/jbe@1309: attr = { bsw/jbe@1309: type = "submit", bsw/jbe@1309: class = "mdl-button mdl-js-button mdl-button--raised mdl-button--colored", bsw/jbe@1309: value = _"publish my rating" bsw/jbe@1309: }, bsw/jbe@1309: content = "" bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: end bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: end } bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: end } bsw/jbe@1309: bsw/jbe@1309: ui.container { attr = { class = "rating-button" }, content = function() bsw/jbe@1309: bsw/jbe@1309: local text = _"Read more" bsw/jbe@1309: bsw/jbe@1309: if direct_supporter then bsw/jbe@1309: text = text .. " / " .. _"Rate suggestion" bsw/jbe@1309: end bsw/jbe@1309: bsw/jbe@1309: ui.link { bsw/jbe@1309: attr = { bsw/jbe@1309: class = "mdl-button mdl-js-button suggestion-more", bsw/jbe@1309: onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.remove('folded');document.querySelector('#s" .. suggestion.id .. "').classList.add('unfolded'); return false;" bsw/jbe@1309: }, bsw/jbe@1309: text = text bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: ui.link { bsw/jbe@1309: attr = { bsw/jbe@1309: class = "mdl-button suggestion-less", bsw/jbe@1309: onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.add('folded');document.querySelector('#s" .. suggestion.id .. "').classList.remove('unfolded'); return false;" bsw/jbe@1309: }, bsw/jbe@1309: text = _"Show less" bsw/jbe@1309: } bsw/jbe@1309: --[[ bsw/jbe@1309: ui.link{ bsw/jbe@1309: attr = { class = "mdl-button" }, bsw/jbe@1309: content = _"Details", bsw/jbe@1309: module = "suggestion", view = "show", id = suggestion.id bsw/jbe@1309: } bsw/jbe@1309: --]] bsw/jbe@1309: end } bsw/jbe@1309: ui.script{ script = [[ bsw/jbe@1309: window.addEventListener("load", function() { bsw/jbe@1309: var textEl = document.querySelector('#s]] .. suggestion.id .. [[ .suggestion-content'); bsw/jbe@1309: var height = textEl.clientHeight; bsw/jbe@1309: if (height > 180) { bsw/jbe@1309: document.querySelector('#s]] .. suggestion.id .. [[').classList.add('folded'); bsw/jbe@1309: document.querySelector('#s]] .. suggestion.id .. [[ .rating-button').classList.add('mdl-card__actions'); bsw/jbe@1309: document.querySelector('#s]] .. suggestion.id .. [[ .rating-button').classList.add('mdl-card--border'); bsw/jbe@1309: } bsw/jbe@1309: }); bsw/jbe@1309: ]] } bsw/jbe@1309: bsw/jbe@1309: end } bsw/jbe@1309: bsw/jbe@1309: end -- for i, suggestion bsw/jbe@1309: bsw/jbe@1309: end -- if #initiative.suggestions > 0 bsw/jbe@1309: end bsw/jbe@1309: }