liquid_feedback_frontend

diff app/main/initiative/show.lua @ 19:00d1004545f1

Dynamic interface using XMLHttpRequests, and many other changes

Bugfixes:
- Only allow voting on admitted initiatives
- Repaired issue search
- Don't display delegations for closed issues on member page
- Don't show revoke link in initiative, when issue is already half_frozen
- Localization for voting JavaScript
- Display author of suggestions

Disclosure of voting data after voting is finished:
- Possibility to inspect every ballot including preferences
- Show number of voters preferring one initiative to another initiative

Interface behaviour changes:
- Reversed default order of drafts
- Default order of suggestions changed
- Show new drafts of initiatives only once per day in timeline

Accessibility:
- Barrier-free voting implemented
- POST links are now accessible without JavaScript
- Changed gray for unsatisfied supporters in bar graph to a lighter gray

Other interface improvements:
- Optical enhancements
- Dynamic interface using XMLHttpRequests
- Show usage terms in about section
- Show own membership in area listing
- Show uninformed supporters greyed out and marked with yellow question mark
- Warning box in non-admitted initiatives
- When voted, don't display voting notice and change label of voting link
- Show object counts in more tabulator heads
- Enlarged member statement input field

Miscellaneous:
- Code cleanup
- Added README file containing installation instructions
- Use new WebMCP function ui.filters{...} instead of own ui.filter and ui.order functions
author bsw/jbe
date Sat Feb 20 22:10:31 2010 +0100 (2010-02-20)
parents 77d58efe99fd
children 7d0f4721d2f3
line diff
     1.1 --- a/app/main/initiative/show.lua	Tue Feb 02 00:31:06 2010 +0100
     1.2 +++ b/app/main/initiative/show.lua	Sat Feb 20 22:10:31 2010 +0100
     1.3 @@ -1,535 +1,36 @@
     1.4 -local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
     1.5 -
     1.6 -slot.select("actions", function()
     1.7 -  ui.link{
     1.8 -    content = function()
     1.9 -      ui.image{ static = "icons/16/script.png" }
    1.10 -      slot.put(_"Show all initiatives")
    1.11 -    end,
    1.12 -    module = "issue",
    1.13 -    view = "show",
    1.14 -    id = initiative.issue.id
    1.15 -  }
    1.16 -end)
    1.17 -
    1.18 -execute.view{
    1.19 -  module = "issue",
    1.20 -  view = "_show_head",
    1.21 -  params = { issue = initiative.issue }
    1.22 -}
    1.23 -
    1.24 -if initiative.revoked then
    1.25 -  ui.container{
    1.26 -    attr = { class = "revoked_info" },
    1.27 -    content = function()
    1.28 -      slot.put(_("This initiative has been revoked at #{revoked}", { revoked = format.timestamp(initiative.revoked) }))
    1.29 -      local suggested_initiative = initiative.suggested_initiative
    1.30 -      if suggested_initiative then
    1.31 -        slot.put("<br /><br />")
    1.32 -        slot.put(_("The initiators suggest to support the following initiative:"))
    1.33 -        slot.put("<br />")
    1.34 -        ui.link{
    1.35 -          content = _("Issue ##{id}", { id = suggested_initiative.issue.id } ) .. ": " .. encode.html(suggested_initiative.name),
    1.36 -          module = "initiative",
    1.37 -          view = "show",
    1.38 -          id = suggested_initiative.id
    1.39 -        }
    1.40 -      end
    1.41 -    end
    1.42 -  }
    1.43 -end
    1.44 -
    1.45 -local initiator = Initiator:by_pk(initiative.id, app.session.member.id)
    1.46 -
    1.47 ---slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(initiative.id) .. '.rss" />')
    1.48 -
    1.49 -
    1.50 -slot.select("actions", function()
    1.51 -  if not initiative.issue.fully_frozen and not initiative.issue.closed then
    1.52 -    ui.link{
    1.53 -      attr = { class = "action" },
    1.54 -      content = function()
    1.55 -        ui.image{ static = "icons/16/script_add.png" }
    1.56 -        slot.put(_"Create alternative initiative")
    1.57 -      end,
    1.58 -      module = "initiative",
    1.59 -      view = "new",
    1.60 -      params = { issue_id = initiative.issue.id }
    1.61 -    }
    1.62 -  end
    1.63 -end)
    1.64 -
    1.65 -slot.put_into("sub_title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) ))
    1.66 -
    1.67 -slot.select("support", function()
    1.68 -  ui.container{
    1.69 -    attr = { class = "actions" },
    1.70 -    content = function()
    1.71 -      execute.view{
    1.72 -        module = "supporter",
    1.73 -        view = "_show_box",
    1.74 -        params = { initiative = initiative }
    1.75 -      }
    1.76 -      if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
    1.77 -        ui.link{
    1.78 -          attr = { class = "action", style = "float: left;" },
    1.79 -          content = function()
    1.80 -            ui.image{ static = "icons/16/script_delete.png" }
    1.81 -            slot.put(_"Revoke initiative")
    1.82 -          end,
    1.83 -          module = "initiative",
    1.84 -          view = "revoke",
    1.85 -          id = initiative.id
    1.86 -        }
    1.87 -      end
    1.88 -    end
    1.89 -  }
    1.90 -end)
    1.91 -
    1.92 -util.help("initiative.show")
    1.93 +local initiative = param.get("initiative", "table")
    1.94  
    1.95 -if initiator and initiator.accepted == nil then
    1.96 -  ui.container{
    1.97 -    attr = { class = "initiator_invite_info" },
    1.98 -    content = function()
    1.99 -      slot.put(_"You are invited to become initiator of this initiative.")
   1.100 -      slot.put(" ")
   1.101 -      ui.link{
   1.102 -        content = function()
   1.103 -          ui.image{ static = "icons/16/tick.png" }
   1.104 -          slot.put(_"Accept invitation")
   1.105 -        end,
   1.106 -        module = "initiative",
   1.107 -        action = "accept_invitation",
   1.108 -        id = initiative.id,
   1.109 -        routing = {
   1.110 -          default = {
   1.111 -            mode = "redirect",
   1.112 -            module = request.get_module(),
   1.113 -            view = request.get_view(),
   1.114 -            id = param.get_id_cgi(),
   1.115 -            params = param.get_all_cgi()
   1.116 -          }
   1.117 -        }
   1.118 -      }
   1.119 -      slot.put(" ")
   1.120 -      ui.link{
   1.121 -        content = function()
   1.122 -          ui.image{ static = "icons/16/cross.png" }
   1.123 -          slot.put(_"Refuse invitation")
   1.124 -        end,
   1.125 -        module = "initiative",
   1.126 -        action = "reject_initiator_invitation",
   1.127 -        params = {
   1.128 -          initiative_id = initiative.id,
   1.129 -          member_id = app.session.member.id
   1.130 -        },
   1.131 -        routing = {
   1.132 -          default = {
   1.133 -            mode = "redirect",
   1.134 -            module = request.get_module(),
   1.135 -            view = request.get_view(),
   1.136 -            id = param.get_id_cgi(),
   1.137 -            params = param.get_all_cgi()
   1.138 -          }
   1.139 -        }
   1.140 -      }
   1.141 -    end
   1.142 -  }
   1.143 -  slot.put("<br />")
   1.144 -end
   1.145 -
   1.146 -if (initiative.discussion_url and #initiative.discussion_url > 0)
   1.147 -  or (initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked) then
   1.148 -  ui.container{
   1.149 -    attr = { class = "vertical" },
   1.150 -    content = function()
   1.151 -      ui.container{
   1.152 -        attr = { class = "ui_field_label" },
   1.153 -        content = _"Discussion with initiators"
   1.154 -      }
   1.155 -      ui.tag{
   1.156 -        tag = "span",
   1.157 -        content = function()
   1.158 -          if initiative.discussion_url:find("^https?://") then
   1.159 -            if initiative.discussion_url and #initiative.discussion_url > 0 then
   1.160 -              ui.link{
   1.161 -                attr = {
   1.162 -                  class = "actions",
   1.163 -                  target = "_blank",
   1.164 -                  title = initiative.discussion_url
   1.165 -                },
   1.166 -                content = function()
   1.167 -                  slot.put(encode.html(initiative.discussion_url))
   1.168 -                end,
   1.169 -                external = initiative.discussion_url
   1.170 -              }
   1.171 -            end
   1.172 -          else
   1.173 -            slot.put(encode.html(initiative.discussion_url))
   1.174 -          end
   1.175 -          slot.put(" ")
   1.176 -          if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
   1.177 -            ui.link{
   1.178 -              attr = { class = "actions" },
   1.179 -              content = _"(change URL)",
   1.180 -              module = "initiative",
   1.181 -              view = "edit",
   1.182 -              id = initiative.id
   1.183 -            }
   1.184 -          end
   1.185 -        end
   1.186 -      }
   1.187 -    end
   1.188 -  }
   1.189 +if not initiative then
   1.190 +  initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec()
   1.191  end
   1.192  
   1.193 -
   1.194 -ui.container{
   1.195 -  attr = {  id = "add_suggestion_form", class = "hidden_inline_form" },
   1.196 -  content = function()
   1.197 -
   1.198 -    ui.link{
   1.199 -      content = _"Close",
   1.200 -      attr = {
   1.201 -        onclick = "document.getElementById('add_suggestion_form').style.display='none';return(false)",
   1.202 -        style = "float: right;"
   1.203 -      }
   1.204 -    }
   1.205 -
   1.206 -    ui.field.text{ attr = { class = "head" }, value = _"Add new suggestion" }
   1.207 -
   1.208 -
   1.209 -    ui.form{
   1.210 -      module = "suggestion",
   1.211 -      action = "add",
   1.212 -      params = { initiative_id = initiative.id },
   1.213 -      routing = {
   1.214 -        default = {
   1.215 -          mode = "redirect",
   1.216 -          module = "initiative",
   1.217 -          view = "show",
   1.218 -          id = initiative.id,
   1.219 -          params = { tab = "suggestion" }
   1.220 -        }
   1.221 -      },
   1.222 -      attr = { class = "vertical" },
   1.223 -      content = function()
   1.224 -        local supported = Supporter:by_pk(initiative.id, app.session.member.id) and true or false
   1.225 -        if not supported then
   1.226 -          ui.field.text{
   1.227 -            attr = { class = "warning" },
   1.228 -            value = _"You are currently not supporting this initiative. By adding suggestions to this initiative you will automatically become a potential supporter."
   1.229 -          }
   1.230 -        end
   1.231 -        ui.field.text{ label = _"Title (80 chars max)",        name = "name" }
   1.232 -        ui.field.text{ label = _"Description", name = "description", multiline = true }
   1.233 -        ui.field.select{ 
   1.234 -          label = _"Degree", 
   1.235 -          name = "degree",
   1.236 -          foreign_records = { 
   1.237 -            { id =  1, name = _"should"},
   1.238 -            { id =  2, name = _"must"},
   1.239 -          },
   1.240 -          foreign_id = "id",
   1.241 -          foreign_name = "name"
   1.242 -        }
   1.243 -        ui.submit{ text = _"Commit suggestion" }
   1.244 -      end
   1.245 -    }
   1.246 -  end
   1.247 -}
   1.248 -
   1.249 -local supporter = app.session.member:get_reference_selector("supporters")
   1.250 -  :add_where{ "initiative_id = ?", initiative.id }
   1.251 -  :optional_object_mode()
   1.252 -  :exec()
   1.253 -
   1.254 -if supporter then
   1.255 -  local old_draft_id = supporter.draft_id
   1.256 -  local new_draft_id = initiative.current_draft.id
   1.257 -  if old_draft_id ~= new_draft_id then
   1.258 -    ui.container{
   1.259 -      attr = { class = "draft_updated_info" },
   1.260 -      content = function()
   1.261 -        slot.put(_"The draft of this initiative has been updated!")
   1.262 -        slot.put(" ")
   1.263 -        ui.link{
   1.264 -          content = _"Show diff",
   1.265 -          module = "draft",
   1.266 -          view = "diff",
   1.267 -          params = {
   1.268 -            old_draft_id = old_draft_id,
   1.269 -            new_draft_id = new_draft_id
   1.270 -          }
   1.271 -        }
   1.272 -        slot.put(" ")
   1.273 -        ui.link{
   1.274 -          content = _"Refresh support to current draft",
   1.275 -          module = "initiative",
   1.276 -          action = "add_support",
   1.277 -          id = initiative.id,
   1.278 -          routing = {
   1.279 -            default = {
   1.280 -              mode = "redirect",
   1.281 -              module = "initiative",
   1.282 -              view = "show",
   1.283 -              id = initiative.id
   1.284 -            }
   1.285 -          }
   1.286 -        }
   1.287 -      end
   1.288 -    }
   1.289 -  end
   1.290 -end
   1.291 -
   1.292 -
   1.293 -local current_draft_name = _"Current draft"
   1.294 -if initiative.issue.half_frozen then
   1.295 -  current_draft_name = _"Voting proposal"
   1.296 -end
   1.297 -
   1.298 -if initiative.issue.state == "finished" then
   1.299 -  current_draft_name = _"Voted proposal"
   1.300 -end
   1.301 -
   1.302 -local tabs = {
   1.303 -  {
   1.304 -    name = "current_draft",
   1.305 -    label = current_draft_name,
   1.306 -    content = function()
   1.307 -      if initiator and initiator.accepted and not initiative.issue.half_frozen and not initiative.issue.closed and not initiative.revoked then
   1.308 -        ui.link{
   1.309 -          content = function()
   1.310 -            ui.image{ static = "icons/16/script_add.png" }
   1.311 -            slot.put(_"Edit draft")
   1.312 -          end,
   1.313 -          module = "draft",
   1.314 -          view = "new",
   1.315 -          params = { initiative_id = initiative.id }
   1.316 -        }
   1.317 -      end
   1.318 -      execute.view{ module = "draft", view = "_show", params = { draft = initiative.current_draft } }
   1.319 -    end
   1.320 -  }
   1.321 -}
   1.322 -
   1.323 -if initiative.issue.ranks_available then
   1.324 -  tabs[#tabs+1] = {
   1.325 -    name = "voter",
   1.326 -    label = _"Voter",
   1.327 -    content = function()
   1.328 -      execute.view{
   1.329 -        module = "member",
   1.330 -        view = "_list",
   1.331 -        params = {
   1.332 -          initiative = initiative,
   1.333 -          members_selector =  initiative.issue:get_reference_selector("direct_voters")
   1.334 -            :left_join("vote", nil, { "vote.initiative_id = ? AND vote.member_id = member.id", initiative.id })
   1.335 -            :add_field("direct_voter.weight as voter_weight")
   1.336 -            :add_field("coalesce(vote.grade, 0) as grade")
   1.337 -        }
   1.338 -      }
   1.339 -    end
   1.340 -  }
   1.341 -end
   1.342 -
   1.343 -local suggestion_count = initiative:get_reference_selector("suggestions"):count()
   1.344 -
   1.345 -tabs[#tabs+1] = {
   1.346 -  name = "suggestion",
   1.347 -  label = _"Suggestions" .. " (" .. tostring(suggestion_count) .. ")",
   1.348 -  content = function()
   1.349 -    execute.view{
   1.350 -      module = "suggestion",
   1.351 -      view = "_list",
   1.352 -      params = {
   1.353 -        initiative = initiative,
   1.354 -        suggestions_selector = initiative:get_reference_selector("suggestions")
   1.355 -      }
   1.356 +if request.get_json_request_slots() then
   1.357 +  execute.view{
   1.358 +    module = "initiative",
   1.359 +    view   = "show_partial",
   1.360 +    params = {
   1.361 +      initiative = initiative
   1.362      }
   1.363 -    slot.put("<br />")
   1.364 -    if not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
   1.365 -      ui.link{
   1.366 -        content = function()
   1.367 -          ui.image{ static = "icons/16/comment_add.png" }
   1.368 -          slot.put(_"Add new suggestion")
   1.369 -        end,
   1.370 -        attr = { onclick = "document.getElementById('add_suggestion_form').style.display='block';return(false)" },
   1.371 -        static = "#"
   1.372 -      }
   1.373 -    end
   1.374 -  end
   1.375 -}
   1.376 -
   1.377 -local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
   1.378 -          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
   1.379 -          :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")
   1.380 -          :add_field("direct_interest_snapshot.weight")
   1.381 -          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
   1.382 -          :add_where("direct_supporter_snapshot.satisfied")
   1.383 -
   1.384 -local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
   1.385 -local direct_satisfied_supporter_count = tmp.count
   1.386 -local indirect_satisfied_supporter_count = (tmp.weight or 0) - tmp.count
   1.387 -
   1.388 -local count_string
   1.389 -if indirect_satisfied_supporter_count > 0 then
   1.390 -  count_string = "(" .. tostring(direct_satisfied_supporter_count) .. "+" .. tostring(indirect_satisfied_supporter_count) .. ")"
   1.391 -else
   1.392 -  count_string = "(" .. tostring(direct_satisfied_supporter_count) .. ")"
   1.393 -end
   1.394 -
   1.395 -tabs[#tabs+1] = {
   1.396 -  name = "satisfied_supporter",
   1.397 -  label = _"Supporter" .. " " .. count_string,
   1.398 -  content = function()
   1.399 -    execute.view{
   1.400 -      module = "member",
   1.401 -      view = "_list",
   1.402 -      params = {
   1.403 -        initiative = initiative,
   1.404 -        members_selector = members_selector
   1.405 -      }
   1.406 -    }
   1.407 -  end
   1.408 -}
   1.409 -
   1.410 -local members_selector = initiative:get_reference_selector("supporting_members_snapshot")
   1.411 -          :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id")
   1.412 -          :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")
   1.413 -          :add_field("direct_interest_snapshot.weight")
   1.414 -          :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event")
   1.415 -          :add_where("NOT direct_supporter_snapshot.satisfied")
   1.416 -
   1.417 -local tmp = db:query("SELECT count(1) AS count, sum(weight) AS weight FROM (" .. tostring(members_selector) .. ") as subquery", "object")
   1.418 -local direct_potential_supporter_count = tmp.count
   1.419 -local indirect_potential_supporter_count = (tmp.weight or 0) - tmp.count
   1.420 -
   1.421 -local count_string
   1.422 -if indirect_potential_supporter_count > 0 then
   1.423 -  count_string = "(" .. tostring(direct_potential_supporter_count) .. "+" .. tostring(indirect_potential_supporter_count) .. ")"
   1.424 -else
   1.425 -  count_string = "(" .. tostring(direct_potential_supporter_count) .. ")"
   1.426 -end
   1.427 -
   1.428 -tabs[#tabs+1] = {
   1.429 -  name = "supporter",
   1.430 -  label = _"Potential supporter" .. " " .. count_string,
   1.431 -  content = function()
   1.432 -    execute.view{
   1.433 -      module = "member",
   1.434 -      view = "_list",
   1.435 -      params = {
   1.436 -        initiative = initiative,
   1.437 -        members_selector = members_selector
   1.438 -      }
   1.439 +  }
   1.440 +elseif
   1.441 +  config.user_tab_mode == "accordeon" or
   1.442 +  config.user_tab_mode == "accordeon_first_expanded" or
   1.443 +  config.user_tab_mode == "accordeon_all_expanded"
   1.444 +then
   1.445 +  execute.view{
   1.446 +    module = "issue",
   1.447 +    view   = "show",
   1.448 +    id     = initiative.issue_id,
   1.449 +    params = {
   1.450 +      for_initiative_id = initiative.id
   1.451      }
   1.452 -  end
   1.453 -}
   1.454 -
   1.455 -local initiator_count = initiative:get_reference_selector("initiators"):add_where("accepted"):count()
   1.456 -
   1.457 -tabs[#tabs+1] = {
   1.458 -  name = "initiators",
   1.459 -  label = _"Initiators" .. " (" .. tostring(initiator_count) .. ")",
   1.460 -  content = function()
   1.461 -     if initiator and initiator.accepted and not initiative.issue.fully_frozen and not initiative.issue.closed and not initiative.revoked then
   1.462 -      ui.link{
   1.463 -        attr = { class = "action" },
   1.464 -        content = function()
   1.465 -          ui.image{ static = "icons/16/user_add.png" }
   1.466 -          slot.put(_"Invite initiator")
   1.467 -        end,
   1.468 -        module = "initiative",
   1.469 -        view = "add_initiator",
   1.470 -        params = { initiative_id = initiative.id }
   1.471 -      }
   1.472 -      if initiator_count > 1 then
   1.473 -        ui.link{
   1.474 -          content = function()
   1.475 -            ui.image{ static = "icons/16/user_delete.png" }
   1.476 -            slot.put(_"Remove initiator")
   1.477 -          end,
   1.478 -          module = "initiative",
   1.479 -          view = "remove_initiator",
   1.480 -          params = { initiative_id = initiative.id }
   1.481 -        }
   1.482 -      end
   1.483 -    end
   1.484 -    if initiator and initiator.accepted == false then
   1.485 -        ui.link{
   1.486 -          content = function()
   1.487 -            ui.image{ static = "icons/16/user_delete.png" }
   1.488 -            slot.put(_"Cancel refuse of invitation")
   1.489 -          end,
   1.490 -          module = "initiative",
   1.491 -          action = "remove_initiator",
   1.492 -          params = {
   1.493 -            initiative_id = initiative.id,
   1.494 -            member_id = app.session.member.id
   1.495 -          },
   1.496 -          routing = {
   1.497 -            ok = {
   1.498 -              mode = "redirect",
   1.499 -              module = "initiative",
   1.500 -              view = "show",
   1.501 -              id = initiative.id
   1.502 -            }
   1.503 -          }
   1.504 -        }
   1.505 -    end
   1.506 -    local members_selector = initiative:get_reference_selector("initiating_members")
   1.507 -      :add_field("initiator.accepted", "accepted")
   1.508 -    if not (initiator and initiator.accepted) then
   1.509 -      members_selector:add_where("accepted")
   1.510 -    end
   1.511 -    execute.view{
   1.512 -      module = "member",
   1.513 -      view = "_list",
   1.514 -      params = {
   1.515 -        members_selector = members_selector,
   1.516 -        initiator = initiator
   1.517 -      }
   1.518 +  }
   1.519 +else
   1.520 +  execute.view{
   1.521 +    module = "initiative",
   1.522 +    view   = "show_static",
   1.523 +    params = {
   1.524 +      initiative = initiative
   1.525      }
   1.526 -  end
   1.527 -}
   1.528 -
   1.529 -local drafts_count = initiative:get_reference_selector("drafts"):count()
   1.530 -
   1.531 -tabs[#tabs+1] = {
   1.532 -  name = "drafts",
   1.533 -  label = _"Draft history" .. " (" .. tostring(drafts_count) .. ")",
   1.534 -  content = function()
   1.535 -    execute.view{ module = "draft", view = "_list", params = { drafts = initiative.drafts } }
   1.536 -  end
   1.537 -}
   1.538 -
   1.539 -tabs[#tabs+1] = {
   1.540 -  name = "details",
   1.541 -  label = _"Details",
   1.542 -  content = function()
   1.543 -    ui.form{
   1.544 -      attr = { class = "vertical" },
   1.545 -      record = initiative,
   1.546 -      readonly = true,
   1.547 -      content = function()
   1.548 -        ui.field.text{ label = _"Issue policy", value = initiative.issue.policy.name }
   1.549 -        ui.field.text{
   1.550 -          label = _"Created at",
   1.551 -          value = tostring(initiative.created)
   1.552 -        }
   1.553 -        ui.field.text{
   1.554 -          label = _"Created at",
   1.555 -          value = format.timestamp(initiative.created)
   1.556 -        }
   1.557 ---         ui.field.date{ label = _"Revoked at", name = "revoked" }
   1.558 -        ui.field.boolean{ label = _"Admitted", name = "admitted" }
   1.559 -      end
   1.560 -    }
   1.561 -  end
   1.562 -}
   1.563 -
   1.564 -
   1.565 -ui.tabs(tabs)
   1.566 -
   1.567 +  }
   1.568 +end
   1.569 \ No newline at end of file

Impressum / About Us