| rev | line source | 
| bsw@1045 | 1 local issue = param.get("issue", "table") | 
| bsw@1045 | 2 local initiative = param.get("initiative", "table") | 
| bsw@1045 | 3 | 
| bsw@1045 | 4 local view_module | 
| bsw@1045 | 5 local view_id | 
| bsw@1045 | 6 | 
| bsw@1045 | 7 if initiative then | 
| bsw@1045 | 8   issue = initiative.issue | 
| bsw@1045 | 9   view_module = "initiative" | 
| bsw@1045 | 10   view_id = initiative.id | 
| bsw@1045 | 11 else | 
| bsw@1045 | 12   view_module = "issue" | 
| bsw@1045 | 13   view_id = issue.id | 
| bsw@1045 | 14 end | 
| bsw@1045 | 15 | 
| bsw/jbe@1309 | 16 local current_occured = false | 
| bsw/jbe@1309 | 17 local failed = false | 
| bsw/jbe@1309 | 18 | 
| bsw/jbe@1309 | 19 ui.tag{ tag = "table", content = function() | 
| bsw@1045 | 20 | 
| bsw/jbe@1309 | 21 local function quorum_text(policy, quorum) | 
| bsw/jbe@1309 | 22   local num | 
| bsw/jbe@1309 | 23   local den | 
| bsw@1481 | 24 | 
| bsw/jbe@1309 | 25   if quorum == 1 then | 
| bsw/jbe@1309 | 26     return math.max(policy.issue_quorum or 0, issue.issue_quorum or 0) | 
| bsw/jbe@1309 | 27   elseif quorum == 2 then | 
| bsw/jbe@1309 | 28     num = policy.initiative_quorum_num | 
| bsw/jbe@1309 | 29     den = policy.initiative_quorum_den | 
| bsw/jbe@1309 | 30   end | 
| bsw@1481 | 31 | 
| bsw@1481 | 32   local quorums = {} | 
| bsw@1481 | 33 | 
| bsw@1481 | 34   if num and num > 0 and den == 100 or den == 10 then | 
| bsw@1481 | 35     table.insert(quorums, _("#{percentage}%", { percentage = num * 100 / den })) | 
| bsw@1481 | 36   elseif num and num > 0 and den and den > 0 then | 
| bsw@1481 | 37     table.insert(quorums, num .. "/" .. den) | 
| bsw/jbe@1309 | 38   end | 
| bsw@1481 | 39 | 
| bsw@1481 | 40   if policy.initiative_quorum then | 
| bsw@1481 | 41     table.insert(quorums, policy.initiative_quorum) | 
| bsw/jbe@1309 | 42   end | 
| bsw@1481 | 43 | 
| bsw@1481 | 44   return table.concat(quorums, " / ") | 
| bsw/jbe@1309 | 45 end | 
| bsw@1045 | 46 | 
| bsw/jbe@1309 | 47 local phases = { "admission", "discussion", "verification", "voting" } | 
| bsw/jbe@1309 | 48 | 
| bsw/jbe@1309 | 49 for i, state in ipairs(phases) do | 
| bsw/jbe@1309 | 50   local current = state == issue.state | 
| bsw/jbe@1309 | 51 | 
| bsw/jbe@1309 | 52   if current then | 
| bsw/jbe@1309 | 53     current_occured = true | 
| bsw/jbe@1309 | 54   end | 
| bsw@1045 | 55 | 
| bsw/jbe@1309 | 56   local phase_success = ( | 
| bsw/jbe@1309 | 57     (state == "admission" and issue.accepted) | 
| bsw/jbe@1309 | 58       or (state == "discussion" and issue.half_frozen) | 
| bsw/jbe@1309 | 59       or (state == "verification" and issue.fully_frozen and issue.state ~= "canceled_no_initiative_admitted") | 
| bsw/jbe@1309 | 60       or (state == "voting" and issue.closed and issue.state ~= "canceled_no_initiative_admitted" and issue.state ~= "canceled_by_admin") | 
| bsw/jbe@1309 | 61   ) | 
| bsw/jbe@1309 | 62 | 
| bsw/jbe@1309 | 63   if not failed then | 
| bsw/jbe@1309 | 64     ui.container{ tag = "div", attr = { id = "phase-" .. state, class = current and "phase-current" or nil }, content = function() | 
| bsw@1045 | 65 | 
| bsw/jbe@1309 | 66       local state_names = { | 
| bsw/jbe@1309 | 67         admission = _"Admission", | 
| bsw/jbe@1309 | 68         discussion = _"Discussion", | 
| bsw/jbe@1309 | 69         verification = _"Verification", | 
| bsw/jbe@1309 | 70         voting = _"Voting" | 
| bsw/jbe@1309 | 71       } | 
| bsw@1045 | 72 | 
| bsw/jbe@1309 | 73       local state_name = state_names[state] or state | 
| bsw/jbe@1309 | 74 | 
| bsw/jbe@1309 | 75       local quorum | 
| bsw/jbe@1309 | 76       if state == "admission" then | 
| bsw/jbe@1309 | 77         quorum = quorum_text(issue.policy, 1) | 
| bsw/jbe@1309 | 78       elseif state == "verification" then | 
| bsw/jbe@1309 | 79         quorum = quorum_text(issue.policy, 2) | 
| bsw/jbe@1309 | 80       end | 
| bsw/jbe@1309 | 81 | 
| bsw/jbe@1309 | 82       local time_text | 
| bsw/jbe@1309 | 83       if current then | 
| bsw/jbe@1309 | 84         local time_left | 
| bsw/jbe@1309 | 85         if issue.state_time_left:sub(1,1) ~= "-" then | 
| bsw/jbe@1309 | 86           time_text = format.interval_text(issue.state_time_left, { mode = "time_left" }) | 
| bsw/jbe@1309 | 87         else | 
| bsw/jbe@1309 | 88           time_text = "phase ends soon" | 
| bsw/jbe@1309 | 89         end | 
| bsw/jbe@1309 | 90       elseif current_occured then | 
| bsw/jbe@1309 | 91         local phase_duration = issue[state .. "_time_text"] | 
| bsw/jbe@1309 | 92         time_text = _("#{duration}", { duration = format.interval_text(phase_duration) } ) | 
| bsw/jbe@1309 | 93       else | 
| bsw/jbe@1309 | 94         local text = "failed" | 
| bsw/jbe@1309 | 95         if quorum then | 
| bsw/jbe@1309 | 96           text = _("failed #{quorum}", { quorum = quorum }) | 
| bsw/jbe@1309 | 97         end | 
| bsw/jbe@1309 | 98         if phase_success then | 
| bsw/jbe@1309 | 99           if quorum == 0 then | 
| bsw/jbe@1309 | 100             text = _"without quorum" | 
| bsw/jbe@1309 | 101           elseif quorum then | 
| bsw/jbe@1309 | 102             text = _("reached #{quorum}", { quorum = quorum }) | 
| bsw/jbe@1309 | 103           else | 
| bsw/jbe@1309 | 104             text = _"finished" | 
| bsw/jbe@1309 | 105           end | 
| bsw/jbe@1309 | 106         elseif issue.state == "canceled_revoked_before_accepted" or | 
| bsw/jbe@1309 | 107             issue.state == "canceled_after_revocation_during_discussion" or | 
| bsw/jbe@1309 | 108             issue.state == "canceled_after_revocation_during_verification" | 
| bsw/jbe@1309 | 109         then | 
| bsw/jbe@1309 | 110           text = _"revoked" | 
| bsw/jbe@1309 | 111         elseif issue.state == "canceled_by_admin" then | 
| bsw/jbe@1309 | 112           text = _"canceled" | 
| bsw/jbe@1309 | 113         end | 
| bsw/jbe@1309 | 114         time_text = text | 
| bsw/jbe@1309 | 115       end | 
| bsw@1045 | 116 | 
| bsw/jbe@1309 | 117       if not config.voting_only or state == "voting" then | 
| bsw/jbe@1309 | 118         if current then | 
| bsw/jbe@1309 | 119           ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "play_arrow" } | 
| bsw/jbe@1309 | 120         elseif not current_occured and not phase_success then | 
| bsw/jbe@1309 | 121           ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "clear" } | 
| bsw/jbe@1309 | 122         elseif current_occured and issue.accepted then | 
| bsw/jbe@1309 | 123           ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "schedule" } | 
| bsw/jbe@1309 | 124         elseif current_occured then | 
| bsw/jbe@1309 | 125           ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "lock" } | 
| bsw/jbe@1309 | 126         else | 
| bsw/jbe@1309 | 127           ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "check" } | 
| bsw@1045 | 128         end | 
| bsw@1045 | 129 | 
| bsw/jbe@1309 | 130         if not config.voting_only then | 
| bsw/jbe@1309 | 131           slot.put(" ") | 
| bsw@1045 | 132         end | 
| bsw@1045 | 133 | 
| bsw/jbe@1309 | 134         ui.tag{ attr = { class = "mdl-data-table__cell--non-numeric" }, content = function() | 
| bsw/jbe@1309 | 135           if not config.voting_only then | 
| bsw/jbe@1309 | 136             ui.tag{ content = i .. "." } | 
| bsw@1045 | 137           end | 
| bsw@1045 | 138           slot.put(" ") | 
| bsw/jbe@1309 | 139           ui.tag{ content = state_name  } | 
| bsw/jbe@1309 | 140         end} | 
| bsw/jbe@1309 | 141         ui.tag{ content = " (" .. time_text .. ")"} | 
| bsw/jbe@1309 | 142 | 
| bsw/jbe@1309 | 143         slot.put(" ") | 
| bsw/jbe@1309 | 144 | 
| bsw/jbe@1309 | 145         if not current then | 
| bsw/jbe@1309 | 146           ui.tag{ tag = "i", attr = { onclick = "document.getElementById('phase-info-" .. i .. "').classList.toggle('hidden');", class = "material-icons material-icons-small clickable" }, content = "info_outline" } | 
| bsw/jbe@1309 | 147         end | 
| bsw/jbe@1309 | 148       end | 
| bsw/jbe@1309 | 149 | 
| bsw/jbe@1309 | 150     end } | 
| bsw/jbe@1309 | 151 | 
| bsw/jbe@1309 | 152     local help_texts = { | 
| bsw/jbe@1309 | 153       admission = _("As soon as one initiative of this issue reaches the 1st quorum of #{quorum} support, the issue will proceed to discussion phase.", { quorum = quorum_text(issue.policy, 1) }), | 
| bsw/jbe@1309 | 154       discussion = _"During the discussion phase, the issue is debated on while the initiators improve the proposals and reasons in their initiatives. Supporters of initiatives can write and rate suggestions for improvement.", | 
| bsw/jbe@1309 | 155       verification = _("During the verification phase, existing initiatives cannot be changed anymore. Initiatives need to pass the 2nd quorum of #{quorum} at end of verification phase to become admitted for voting.", { quorum = quorum_text(issue.policy, 2) }), | 
| bsw/jbe@1309 | 156       voting = _"During the voting phase, votes for all admitted initiatives in this issue can be cast. The final result will be calculated as soon as this phase ends." | 
| bsw/jbe@1309 | 157     } | 
| bsw/jbe@1309 | 158 | 
| bsw/jbe@1309 | 159     local class = "phase-info" | 
| bsw/jbe@1309 | 160     if not current then | 
| bsw/jbe@1309 | 161       class = class .. " hidden" | 
| bsw/jbe@1309 | 162     end | 
| bsw@1060 | 163 | 
| bsw/jbe@1309 | 164     if not config.voting_only then | 
| bsw/jbe@1309 | 165       ui.container { attr = { id = "phase-info-" .. i, class = class }, content = help_texts[state] } | 
| bsw@1045 | 166     end | 
| bsw@1045 | 167 | 
| bsw/jbe@1309 | 168   end | 
| bsw/jbe@1309 | 169 | 
| bsw/jbe@1309 | 170   if not phase_success and not current and not current_occured then | 
| bsw/jbe@1309 | 171     failed = true | 
| bsw@1045 | 172   end | 
| bsw/jbe@1309 | 173 end | 
| bsw/jbe@1309 | 174 | 
| bsw/jbe@1309 | 175 end } | 
| bsw/jbe@1309 | 176 | 
| bsw/jbe@1309 | 177 if issue.closed then | 
| bsw/jbe@1309 | 178   ui.tag{ content = issue.state_name } | 
| bsw/jbe@1309 | 179 end |