liquid_feedback_frontend

annotate app/main/initiative/show.lua @ 11:77d58efe99fd

Version beta7

Important security fixes:
- Added missing HTML encoding to postal address of member
- Link to discussion URL only if it starts with http(s)://

Other bugfixes:
- Fixed wrong display of 2nd level delegating voters for an initiative
- Do not display invited initiators as initiators while voting
- Added missing translation

New features:
- Public message of the day
- Both direct and indirect supporter count is shown in tab heads
- Support shown in initiative lists

Language chooser at the login page has been added (again)
author bsw
date Fri Jan 22 12:00:00 2010 +0100 (2010-01-22)
parents 72c5e0ee7c98
children 00d1004545f1
rev   line source
bsw/jbe@0 1 local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
bsw/jbe@0 2
bsw/jbe@5 3 slot.select("actions", function()
bsw/jbe@5 4 ui.link{
bsw/jbe@5 5 content = function()
bsw/jbe@5 6 ui.image{ static = "icons/16/script.png" }
bsw/jbe@5 7 slot.put(_"Show all initiatives")
bsw/jbe@5 8 end,
bsw/jbe@5 9 module = "issue",
bsw/jbe@5 10 view = "show",
bsw/jbe@5 11 id = initiative.issue.id
bsw/jbe@5 12 }
bsw/jbe@5 13 end)
bsw/jbe@4 14
bsw/jbe@4 15 execute.view{
bsw/jbe@4 16 module = "issue",
bsw/jbe@4 17 view = "_show_head",
bsw/jbe@4 18 params = { issue = initiative.issue }
bsw/jbe@4 19 }
bsw/jbe@4 20
bsw@10 21 if initiative.revoked then
bsw@10 22 ui.container{
bsw@10 23 attr = { class = "revoked_info" },
bsw@10 24 content = function()
bsw@10 25 slot.put(_("This initiative has been revoked at #{revoked}", { revoked = format.timestamp(initiative.revoked) }))
bsw@10 26 local suggested_initiative = initiative.suggested_initiative
bsw@10 27 if suggested_initiative then
bsw@10 28 slot.put("<br /><br />")
bsw@10 29 slot.put(_("The initiators suggest to support the following initiative:"))
bsw@10 30 slot.put("<br />")
bsw@10 31 ui.link{
bsw@10 32 content = _("Issue ##{id}", { id = suggested_initiative.issue.id } ) .. ": " .. encode.html(suggested_initiative.name),
bsw@10 33 module = "initiative",
bsw@10 34 view = "show",
bsw@10 35 id = suggested_initiative.id
bsw@10 36 }
bsw@10 37 end
bsw@10 38 end
bsw@10 39 }
bsw@10 40 end
bsw@10 41
bsw/jbe@4 42 local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
bsw/jbe@4 43
bsw@3 44 --slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(initiative.id) .. '.rss" />')
bsw/jbe@0 45
bsw/jbe@0 46
bsw/jbe@0 47 slot.select("actions", function()
bsw/jbe@4 48 if not initiative.issue.fully_frozen and not initiative.issue.closed then
bsw@2 49 ui.link{
bsw@3 50 attr = { class = "action" },
bsw@3 51 content = function()
bsw@3 52 ui.image{ static = "icons/16/script_add.png" }
bsw/jbe@4 53 slot.put(_"Create alternative initiative")
bsw@3 54 end,
bsw@3 55 module = "initiative",
bsw@3 56 view = "new",
bsw@3 57 params = { issue_id = initiative.issue.id }
bsw@3 58 }
bsw@3 59 end
bsw/jbe@4 60 end)
bsw/jbe@4 61
bsw@10 62 slot.put_into("sub_title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) ))
bsw@10 63
bsw@10 64 slot.select("support", function()
bsw@10 65 ui.container{
bsw@10 66 attr = { class = "actions" },
bsw@10 67 content = function()
bsw@10 68 execute.view{
bsw@10 69 module = "supporter",
bsw@10 70 view = "_show_box",
bsw@10 71 params = { initiative = initiative }
bsw@10 72 }
bsw@10 73 if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
bsw@10 74 ui.link{
bsw@10 75 attr = { class = "action", style = "float: left;" },
bsw@10 76 content = function()
bsw@10 77 ui.image{ static = "icons/16/script_delete.png" }
bsw@10 78 slot.put(_"Revoke initiative")
bsw@10 79 end,
bsw@10 80 module = "initiative",
bsw@10 81 view = "revoke",
bsw@10 82 id = initiative.id
bsw@10 83 }
bsw@10 84 end
bsw@10 85 end
bsw@10 86 }
bsw@10 87 end)
bsw/jbe@4 88
bsw/jbe@4 89 util.help("initiative.show")
bsw/jbe@4 90
bsw@10 91 if initiator and initiator.accepted == nil then
bsw@10 92 ui.container{
bsw@10 93 attr = { class = "initiator_invite_info" },
bsw@10 94 content = function()
bsw@10 95 slot.put(_"You are invited to become initiator of this initiative.")
bsw@10 96 slot.put(" ")
bsw@10 97 ui.link{
bsw@10 98 content = function()
bsw@10 99 ui.image{ static = "icons/16/tick.png" }
bsw@10 100 slot.put(_"Accept invitation")
bsw@10 101 end,
bsw@10 102 module = "initiative",
bsw@10 103 action = "accept_invitation",
bsw@10 104 id = initiative.id,
bsw@10 105 routing = {
bsw@10 106 default = {
bsw@10 107 mode = "redirect",
bsw@10 108 module = request.get_module(),
bsw@10 109 view = request.get_view(),
bsw@10 110 id = param.get_id_cgi(),
bsw@10 111 params = param.get_all_cgi()
bsw@10 112 }
bsw@10 113 }
bsw@10 114 }
bsw@10 115 slot.put(" ")
bsw@10 116 ui.link{
bsw@10 117 content = function()
bsw@10 118 ui.image{ static = "icons/16/cross.png" }
bsw@10 119 slot.put(_"Refuse invitation")
bsw@10 120 end,
bsw@10 121 module = "initiative",
bsw@10 122 action = "reject_initiator_invitation",
bsw@10 123 params = {
bsw@10 124 initiative_id = initiative.id,
bsw@10 125 member_id = app.session.member.id
bsw@10 126 },
bsw@10 127 routing = {
bsw@10 128 default = {
bsw@10 129 mode = "redirect",
bsw@10 130 module = request.get_module(),
bsw@10 131 view = request.get_view(),
bsw@10 132 id = param.get_id_cgi(),
bsw@10 133 params = param.get_all_cgi()
bsw@10 134 }
bsw@10 135 }
bsw@10 136 }
bsw@10 137 end
bsw@10 138 }
bsw@10 139 slot.put("<br />")
bsw@10 140 end
bsw/jbe@4 141
bsw@10 142 if (initiative.discussion_url and #initiative.discussion_url > 0)
bsw@10 143 or (initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked) then
bsw@10 144 ui.container{
bsw@10 145 attr = { class = "vertical" },
bsw@10 146 content = function()
bsw@10 147 ui.container{
bsw@10 148 attr = { class = "ui_field_label" },
bsw@10 149 content = _"Discussion with initiators"
bsw@10 150 }
bsw@10 151 ui.tag{
bsw@10 152 tag = "span",
bsw@10 153 content = function()
bsw@11 154 if initiative.discussion_url:find("^https?://") then
bsw@11 155 if initiative.discussion_url and #initiative.discussion_url > 0 then
bsw@11 156 ui.link{
bsw@11 157 attr = {
bsw@11 158 class = "actions",
bsw@11 159 target = "_blank",
bsw@11 160 title = initiative.discussion_url
bsw@11 161 },
bsw@11 162 content = function()
bsw@11 163 slot.put(encode.html(initiative.discussion_url))
bsw@11 164 end,
bsw@11 165 external = initiative.discussion_url
bsw@11 166 }
bsw@11 167 end
bsw@11 168 else
bsw@11 169 slot.put(encode.html(initiative.discussion_url))
bsw@10 170 end
bsw@10 171 slot.put(" ")
bsw@10 172 if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
bsw@10 173 ui.link{
bsw@10 174 attr = { class = "actions" },
bsw@10 175 content = _"(change URL)",
bsw@10 176 module = "initiative",
bsw@10 177 view = "edit",
bsw@10 178 id = initiative.id
bsw@10 179 }
bsw@10 180 end
bsw/jbe@4 181 end
bsw@10 182 }
bsw@10 183 end
bsw@10 184 }
bsw@10 185 end
bsw/jbe@0 186
bsw/jbe@0 187
bsw/jbe@0 188 ui.container{
bsw/jbe@0 189 attr = { id = "add_suggestion_form", class = "hidden_inline_form" },
bsw/jbe@0 190 content = function()
bsw/jbe@0 191
bsw/jbe@0 192 ui.link{
bsw/jbe@0 193 content = _"Close",
bsw/jbe@0 194 attr = {
bsw/jbe@0 195 onclick = "document.getElementById('add_suggestion_form').style.display='none';return(false)",
bsw/jbe@0 196 style = "float: right;"
bsw/jbe@0 197 }
bsw/jbe@0 198 }
bsw/jbe@0 199
bsw/jbe@0 200 ui.field.text{ attr = { class = "head" }, value = _"Add new suggestion" }
bsw/jbe@0 201
bsw/jbe@0 202
bsw/jbe@0 203 ui.form{
bsw/jbe@0 204 module = "suggestion",
bsw/jbe@0 205 action = "add",
bsw/jbe@0 206 params = { initiative_id = initiative.id },
bsw/jbe@0 207 routing = {
bsw/jbe@0 208 default = {
bsw/jbe@0 209 mode = "redirect",
bsw/jbe@0 210 module = "initiative",
bsw/jbe@0 211 view = "show",
bsw/jbe@0 212 id = initiative.id,
bsw/jbe@0 213 params = { tab = "suggestion" }
bsw/jbe@0 214 }
bsw/jbe@0 215 },
bsw/jbe@0 216 attr = { class = "vertical" },
bsw/jbe@0 217 content = function()
bsw/jbe@4 218 local supported = Supporter:by_pk(initiative.id, app.session.member.id) and true or false
bsw/jbe@4 219 if not supported then
bsw/jbe@4 220 ui.field.text{
bsw/jbe@4 221 attr = { class = "warning" },
bsw/jbe@4 222 value = _"You are currently not supporting this initiative. By adding suggestions to this initiative you will automatically become a potential supporter."
bsw/jbe@4 223 }
bsw/jbe@4 224 end
bsw/jbe@4 225 ui.field.text{ label = _"Title (80 chars max)", name = "name" }
bsw/jbe@0 226 ui.field.text{ label = _"Description", name = "description", multiline = true }
bsw/jbe@0 227 ui.field.select{
bsw/jbe@0 228 label = _"Degree",
bsw/jbe@0 229 name = "degree",
bsw/jbe@0 230 foreign_records = {
bsw/jbe@0 231 { id = 1, name = _"should"},
bsw/jbe@0 232 { id = 2, name = _"must"},
bsw/jbe@0 233 },
bsw/jbe@0 234 foreign_id = "id",
bsw/jbe@0 235 foreign_name = "name"
bsw/jbe@0 236 }
bsw/jbe@0 237 ui.submit{ text = _"Commit suggestion" }
bsw/jbe@0 238 end
bsw/jbe@0 239 }
bsw/jbe@0 240 end
bsw/jbe@0 241 }
bsw/jbe@0 242
bsw@2 243 local supporter = app.session.member:get_reference_selector("supporters")
bsw@2 244 :add_where{ "initiative_id = ?", initiative.id }
bsw@2 245 :optional_object_mode()
bsw@2 246 :exec()
bsw@2 247
bsw@2 248 if supporter then
bsw@2 249 local old_draft_id = supporter.draft_id
bsw@2 250 local new_draft_id = initiative.current_draft.id
bsw@2 251 if old_draft_id ~= new_draft_id then
bsw@2 252 ui.container{
bsw@2 253 attr = { class = "draft_updated_info" },
bsw@2 254 content = function()
bsw@11 255 slot.put(_"The draft of this initiative has been updated!")
bsw@2 256 slot.put(" ")
bsw@2 257 ui.link{
bsw@2 258 content = _"Show diff",
bsw@2 259 module = "draft",
bsw@2 260 view = "diff",
bsw@2 261 params = {
bsw@2 262 old_draft_id = old_draft_id,
bsw@2 263 new_draft_id = new_draft_id
bsw@2 264 }
bsw@2 265 }
bsw@2 266 slot.put(" ")
bsw@2 267 ui.link{
bsw@2 268 content = _"Refresh support to current draft",
bsw@2 269 module = "initiative",
bsw@2 270 action = "add_support",
bsw@2 271 id = initiative.id,
bsw@2 272 routing = {
bsw@2 273 default = {
bsw@2 274 mode = "redirect",
bsw@2 275 module = "initiative",
bsw@2 276 view = "show",
bsw@2 277 id = initiative.id
bsw@2 278 }
bsw@2 279 }
bsw@2 280 }
bsw@2 281 end
bsw@2 282 }
bsw@2 283 end
bsw@2 284 end
bsw/jbe@0 285
bsw/jbe@4 286
bsw/jbe@6 287 local current_draft_name = _"Current draft"
bsw/jbe@6 288 if initiative.issue.half_frozen then
bsw/jbe@6 289 current_draft_name = _"Voting proposal"
bsw/jbe@6 290 end
bsw/jbe@6 291
bsw/jbe@6 292 if initiative.issue.state == "finished" then
bsw/jbe@6 293 current_draft_name = _"Voted proposal"
bsw/jbe@6 294 end
bsw/jbe@6 295
bsw/jbe@6 296 local tabs = {
bsw/jbe@0 297 {
bsw/jbe@0 298 name = "current_draft",
bsw/jbe@6 299 label = current_draft_name,
bsw/jbe@0 300 content = function()
bsw@10 301 if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
bsw/jbe@4 302 ui.link{
bsw/jbe@4 303 content = function()
bsw/jbe@4 304 ui.image{ static = "icons/16/script_add.png" }
bsw/jbe@4 305 slot.put(_"Edit draft")
bsw/jbe@4 306 end,
bsw/jbe@4 307 module = "draft",
bsw/jbe@4 308 view = "new",
bsw/jbe@4 309 params = { initiative_id = initiative.id }
bsw/jbe@4 310 }
bsw/jbe@4 311 end
bsw/jbe@0 312 execute.view{ module = "draft", view = "_show", params = { draft = initiative.current_draft } }
bsw/jbe@0 313 end
bsw/jbe@6 314 }
bsw/jbe@6 315 }
bsw/jbe@6 316
bsw/jbe@6 317 if initiative.issue.ranks_available then
bsw/jbe@6 318 tabs[#tabs+1] = {
bsw/jbe@6 319 name = "voter",
bsw/jbe@6 320 label = _"Voter",
bsw/jbe@0 321 content = function()
bsw@3 322 execute.view{
bsw@3 323 module = "member",
bsw@3 324 view = "_list",
bsw@3 325 params = {
bsw@3 326 initiative = initiative,
bsw/jbe@6 327 members_selector = initiative.issue:get_reference_selector("direct_voters")
bsw/jbe@6 328 :left_join("vote", nil, { "vote.initiative_id = ? AND vote.member_id = member.id", initiative.id })
bsw/jbe@6 329 :add_field("direct_voter.weight as voter_weight")
bsw/jbe@6 330 :add_field("coalesce(vote.grade, 0) as grade")
bsw@3 331 }
bsw@3 332 }
bsw/jbe@0 333 end
bsw/jbe@6 334 }
bsw/jbe@6 335 end
bsw/jbe@6 336
bsw@10 337 local suggestion_count = initiative:get_reference_selector("suggestions"):count()
bsw@10 338
bsw/jbe@6 339 tabs[#tabs+1] = {
bsw/jbe@6 340 name = "suggestion",
bsw@10 341 label = _"Suggestions" .. " (" .. tostring(suggestion_count) .. ")",
bsw/jbe@6 342 content = function()
bsw/jbe@6 343 execute.view{
bsw/jbe@6 344 module = "suggestion",
bsw/jbe@6 345 view = "_list",
bsw/jbe@6 346 params = {
bsw/jbe@6 347 initiative = initiative,
bsw/jbe@6 348 suggestions_selector = initiative:get_reference_selector("suggestions")
bsw/jbe@6 349 }
bsw/jbe@6 350 }
bsw/jbe@6 351 slot.put("<br />")
bsw@10 352 if not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
bsw/jbe@6 353 ui.link{
bsw@2 354 content = function()
bsw/jbe@6 355 ui.image{ static = "icons/16/comment_add.png" }
bsw/jbe@6 356 slot.put(_"Add new suggestion")
bsw/jbe@6 357 end,
bsw/jbe@6 358 attr = { onclick = "document.getElementById('add_suggestion_form').style.display='block';return(false)" },
bsw/jbe@6 359 static = "#"
bsw@2 360 }
bsw@2 361 end
bsw/jbe@6 362 end
bsw/jbe@6 363 }
bsw/jbe@6 364
bsw@11 365 local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
bsw@10 366 :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
bsw@10 367 :join("direct_interest_snapshot", nil, "direct_interest_snapshot.event = issue.latest_snapshot_event AND direct_interest_snapshot.issue_id = issue.id AND direct_interest_snapshot.member_id = member.id")
bsw@10 368 :add_field("direct_interest_snapshot.weight")
bsw@10 369 :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
bsw@10 370 :add_where("direct_supporter_snapshot.satisfied")
bsw@10 371
bsw@11 372 local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
bsw@11 373 local direct_satisfied_supporter_count = tmp.count
bsw@11 374 local indirect_satisfied_supporter_count = (tmp.weight or 0) - tmp.count
bsw@11 375
bsw@11 376 local count_string
bsw@11 377 if indirect_satisfied_supporter_count > 0 then
bsw@11 378 count_string = "(" .. tostring(direct_satisfied_supporter_count) .. "+" .. tostring(indirect_satisfied_supporter_count) .. ")"
bsw@11 379 else
bsw@11 380 count_string = "(" .. tostring(direct_satisfied_supporter_count) .. ")"
bsw@11 381 end
bsw@10 382
bsw/jbe@6 383 tabs[#tabs+1] = {
bsw/jbe@6 384 name = "satisfied_supporter",
bsw@11 385 label = _"Supporter" .. " " .. count_string,
bsw@10 386 content = function()
bsw@10 387 execute.view{
bsw@10 388 module = "member",
bsw@10 389 view = "_list",
bsw@10 390 params = {
bsw@10 391 initiative = initiative,
bsw@10 392 members_selector = members_selector
bsw@10 393 }
bsw@10 394 }
bsw@10 395 end
bsw@10 396 }
bsw@10 397
bsw@10 398 local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
bsw@10 399 :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
bsw@10 400 :join("direct_interest_snapshot", nil, "direct_interest_snapshot.event = issue.latest_snapshot_event AND direct_interest_snapshot.issue_id = issue.id AND direct_interest_snapshot.member_id = member.id")
bsw@10 401 :add_field("direct_interest_snapshot.weight")
bsw@10 402 :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
bsw@10 403 :add_where("NOT direct_supporter_snapshot.satisfied")
bsw@10 404
bsw@11 405 local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
bsw@11 406 local direct_potential_supporter_count = tmp.count
bsw@11 407 local indirect_potential_supporter_count = (tmp.weight or 0) - tmp.count
bsw@11 408
bsw@11 409 local count_string
bsw@11 410 if indirect_potential_supporter_count > 0 then
bsw@11 411 count_string = "(" .. tostring(direct_potential_supporter_count) .. "+" .. tostring(indirect_potential_supporter_count) .. ")"
bsw@11 412 else
bsw@11 413 count_string = "(" .. tostring(direct_potential_supporter_count) .. ")"
bsw@11 414 end
bsw@10 415
bsw@10 416 tabs[#tabs+1] = {
bsw@10 417 name = "supporter",
bsw@11 418 label = _"Potential supporter" .. " " .. count_string,
bsw/jbe@6 419 content = function()
bsw/jbe@6 420 execute.view{
bsw/jbe@6 421 module = "member",
bsw/jbe@6 422 view = "_list",
bsw/jbe@6 423 params = {
bsw/jbe@6 424 initiative = initiative,
bsw@10 425 members_selector = members_selector
bsw/jbe@6 426 }
bsw/jbe@6 427 }
bsw/jbe@6 428 end
bsw/jbe@6 429 }
bsw/jbe@6 430
bsw@10 431 local initiator_count = initiative:get_reference_selector("initiators"):add_where("accepted"):count()
bsw@10 432
bsw/jbe@6 433 tabs[#tabs+1] = {
bsw@10 434 name = "initiators",
bsw@10 435 label = _"Initiators" .. " (" .. tostring(initiator_count) .. ")",
bsw/jbe@6 436 content = function()
bsw@10 437 if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
bsw@10 438 ui.link{
bsw@10 439 attr = { class = "action" },
bsw@10 440 content = function()
bsw@10 441 ui.image{ static = "icons/16/user_add.png" }
bsw@10 442 slot.put(_"Invite initiator")
bsw@10 443 end,
bsw@10 444 module = "initiative",
bsw@10 445 view = "add_initiator",
bsw@10 446 params = { initiative_id = initiative.id }
bsw@10 447 }
bsw@10 448 if initiator_count > 1 then
bsw@10 449 ui.link{
bsw@10 450 content = function()
bsw@10 451 ui.image{ static = "icons/16/user_delete.png" }
bsw@10 452 slot.put(_"Remove initiator")
bsw@10 453 end,
bsw@10 454 module = "initiative",
bsw@10 455 view = "remove_initiator",
bsw@10 456 params = { initiative_id = initiative.id }
bsw@10 457 }
bsw@10 458 end
bsw@10 459 end
bsw@10 460 if initiator and initiator.accepted == false then
bsw@10 461 ui.link{
bsw@10 462 content = function()
bsw@10 463 ui.image{ static = "icons/16/user_delete.png" }
bsw@10 464 slot.put(_"Cancel refuse of invitation")
bsw@10 465 end,
bsw@10 466 module = "initiative",
bsw@10 467 action = "remove_initiator",
bsw@10 468 params = {
bsw@10 469 initiative_id = initiative.id,
bsw@10 470 member_id = app.session.member.id
bsw@10 471 },
bsw@10 472 routing = {
bsw@10 473 ok = {
bsw@10 474 mode = "redirect",
bsw@10 475 module = "initiative",
bsw@10 476 view = "show",
bsw@10 477 id = initiative.id
bsw@10 478 }
bsw@10 479 }
bsw@10 480 }
bsw@10 481 end
bsw@10 482 local members_selector = initiative:get_reference_selector("initiating_members")
bsw@10 483 :add_field("initiator.accepted", "accepted")
bsw@10 484 if not (initiator and initiator.accepted) then
bsw@10 485 members_selector:add_where("accepted")
bsw@10 486 end
bsw/jbe@6 487 execute.view{
bsw/jbe@6 488 module = "member",
bsw/jbe@6 489 view = "_list",
bsw/jbe@6 490 params = {
bsw@10 491 members_selector = members_selector,
bsw@10 492 initiator = initiator
bsw/jbe@6 493 }
bsw/jbe@6 494 }
bsw/jbe@6 495 end
bsw/jbe@6 496 }
bsw/jbe@6 497
bsw@10 498 local drafts_count = initiative:get_reference_selector("drafts"):count()
bsw/jbe@6 499
bsw/jbe@6 500 tabs[#tabs+1] = {
bsw/jbe@6 501 name = "drafts",
bsw@10 502 label = _"Draft history" .. " (" .. tostring(drafts_count) .. ")",
bsw/jbe@6 503 content = function()
bsw/jbe@6 504 execute.view{ module = "draft", view = "_list", params = { drafts = initiative.drafts } }
bsw/jbe@6 505 end
bsw/jbe@6 506 }
bsw/jbe@6 507
bsw/jbe@6 508 tabs[#tabs+1] = {
bsw/jbe@6 509 name = "details",
bsw/jbe@6 510 label = _"Details",
bsw/jbe@6 511 content = function()
bsw/jbe@6 512 ui.form{
bsw/jbe@6 513 attr = { class = "vertical" },
bsw/jbe@6 514 record = initiative,
bsw/jbe@6 515 readonly = true,
bsw/jbe@6 516 content = function()
bsw/jbe@6 517 ui.field.text{ label = _"Issue policy", value = initiative.issue.policy.name }
bsw/jbe@6 518 ui.field.text{
bsw/jbe@6 519 label = _"Created at",
bsw/jbe@6 520 value = tostring(initiative.created)
bsw/jbe@6 521 }
bsw/jbe@6 522 ui.field.text{
bsw/jbe@6 523 label = _"Created at",
bsw/jbe@6 524 value = format.timestamp(initiative.created)
bsw/jbe@6 525 }
bsw@10 526 -- ui.field.date{ label = _"Revoked at", name = "revoked" }
bsw/jbe@6 527 ui.field.boolean{ label = _"Admitted", name = "admitted" }
bsw/jbe@6 528 end
bsw/jbe@6 529 }
bsw/jbe@6 530 end
bsw/jbe@0 531 }
bsw/jbe@0 532
bsw/jbe@0 533
bsw/jbe@6 534 ui.tabs(tabs)
bsw/jbe@6 535

Impressum / About Us