liquid_feedback_frontend

changeset 1732:80c101b08bf9

merge
author bsw
date Thu Sep 30 10:04:55 2021 +0200 (2021-09-30)
parents 899fdfb23465 dc54e50a70b9
children 30017c87369e
files
line diff
     1.1 --- a/app/main/_filter/21_auth.lua	Thu Sep 30 10:04:31 2021 +0200
     1.2 +++ b/app/main/_filter/21_auth.lua	Thu Sep 30 10:04:55 2021 +0200
     1.3 @@ -137,14 +137,22 @@
     1.4        error("array type params not implemented")
     1.5      end
     1.6    end
     1.7 -  request.redirect{
     1.8 -    module = 'index', view = 'login', params = {
     1.9 -      redirect_module = module,
    1.10 -      redirect_view = view,
    1.11 -      redirect_id = param.get_id(),
    1.12 -      redirect_params = params
    1.13 +  if config.login and config.login.method == "oauth2" then
    1.14 +    request.redirect{
    1.15 +      module = "oauth2_client",
    1.16 +      view = "redirect",
    1.17 +      params = { provider = config.login.provider }
    1.18      }
    1.19 -  }
    1.20 +  else
    1.21 +    request.redirect{
    1.22 +      module = 'index', view = 'login', params = {
    1.23 +        redirect_module = module,
    1.24 +        redirect_view = view,
    1.25 +        redirect_id = param.get_id(),
    1.26 +        redirect_params = params
    1.27 +      }
    1.28 +    }
    1.29 +  end
    1.30  elseif auth_needed and app.session.member.locked then
    1.31    trace.debug("Member locked.")
    1.32    request.redirect{ module = 'index', view = 'login' }
     2.1 --- a/app/main/area/_sidebar_whatcanido.lua	Thu Sep 30 10:04:31 2021 +0200
     2.2 +++ b/app/main/area/_sidebar_whatcanido.lua	Thu Sep 30 10:04:55 2021 +0200
     2.3 @@ -84,19 +84,6 @@
     2.4          end }
     2.5        end
     2.6        
     2.7 -      if app.session.member:has_voting_right_for_unit_id ( area.unit_id ) then
     2.8 -        ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
     2.9 -          ui.tag{ content = _"I want to vote" }
    2.10 -          ui.tag { tag = "ul", attr = { class = "ul" }, content = function ()
    2.11 -            ui.tag { tag = "li", content = _"check the issues on the right, and click on 'Vote now' to vote on an issue which is in voting phase." }
    2.12 -          end }
    2.13 -        end }
    2.14 -      end
    2.15 -      
    2.16 -      if app.session.member and not app.session.member:has_voting_right_for_unit_id(area.unit_id) then
    2.17 -        ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = _"You are not entitled to vote in this unit" }
    2.18 -      end
    2.19 -      
    2.20        if app.session.member and app.session.member:has_voting_right_for_unit_id(area.unit_id) then
    2.21  
    2.22          if not config.disable_delegations then
    2.23 @@ -175,16 +162,27 @@
    2.24              end }
    2.25            end }
    2.26          end
    2.27 -            
    2.28 +      end
    2.29 +      if app.session.member:has_voting_right_for_unit_id ( area.unit_id ) then
    2.30 +        ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
    2.31 +          ui.tag{ content = _"I want to vote" }
    2.32 +          ui.tag { tag = "ul", attr = { class = "ul" }, content = function ()
    2.33 +            ui.tag { tag = "li", content = _"check the issues on the right, and click on 'Vote now' to vote on an issue which is in voting phase." }
    2.34 +          end }
    2.35 +        end }
    2.36        end
    2.37      else
    2.38        ui.container { attr = { class = "mdl-card__content mdl-card--border" }, content = function ()
    2.39 -        ui.tag{ content = _"You are not entitled to vote in this unit" }
    2.40 -        ui.tag{ tag = "ul", content = function()
    2.41 -          ui.tag{ tag = "li", content = function()
    2.42 -            ui.link{ module = "index", view = "login", content = _"Login" }
    2.43 +        if not app.session.member_id then
    2.44 +          ui.tag{ content = _"Login to participate" }
    2.45 +          ui.tag{ tag = "ul", content = function()
    2.46 +            ui.tag{ tag = "li", content = function()
    2.47 +              ui.link{ module = "index", view = "login", content = _"Login" }
    2.48 +            end }
    2.49            end }
    2.50 -        end }
    2.51 +        else
    2.52 +          ui.tag{ content = _"You are not entitled to vote in this unit" }
    2.53 +        end
    2.54        end }
    2.55      end
    2.56    end }
     3.1 --- a/app/main/draft/new.lua	Thu Sep 30 10:04:31 2021 +0200
     3.2 +++ b/app/main/draft/new.lua	Thu Sep 30 10:04:55 2021 +0200
     3.3 @@ -128,13 +128,14 @@
     3.4  -- -------- PREVIEW
     3.5              if param.get("preview") and slot.get_content("error") == "" then
     3.6                ui.sectionRow( function()
     3.7 -                if not issue and not initiative then
     3.8 +                if not issue and not initiative and #area.allowed_policies > 1 then
     3.9                    ui.container { content = policy and policy.name or "" }
    3.10 +                  slot.put("<br />")
    3.11                  end
    3.12                  if param.get("free_timing") then
    3.13                    ui.container { content = param.get("free_timing") }
    3.14 +                  slot.put("<br />")
    3.15                  end
    3.16 -                slot.put("<br />")
    3.17                  ui.field.hidden{ name = "policy_id", value = param.get("policy_id") }
    3.18                  ui.field.hidden{ name = "name", value = param.get("name") }
    3.19                  if config.initiative_abstract then
    3.20 @@ -253,14 +254,21 @@
    3.21                      tmp[#tmp+1] = allowed_policy
    3.22                    end
    3.23                  end
    3.24 -                ui.container{ content = _"Please choose a policy for the new issue:" }
    3.25 -                ui.field.select{
    3.26 -                  name = "policy_id",
    3.27 -                  foreign_records = tmp,
    3.28 -                  foreign_id = "id",
    3.29 -                  foreign_name = "name",
    3.30 -                  value = param.get("policy_id", atom.integer) or area.default_policy and area.default_policy.id
    3.31 -                }
    3.32 +                if #area.allowed_policies > 1 then
    3.33 +                  ui.container{ content = _"Please choose a policy for the new issue:" }
    3.34 +                  ui.field.select{
    3.35 +                    name = "policy_id",
    3.36 +                    foreign_records = tmp,
    3.37 +                    foreign_id = "id",
    3.38 +                    foreign_name = "name",
    3.39 +                    value = param.get("policy_id", atom.integer) or area.default_policy and area.default_policy.id
    3.40 +                  }
    3.41 +                else
    3.42 +                  ui.field.hidden{
    3.43 +                    name = "policy_id",
    3.44 +                    value = area.allowed_policies[1].id
    3.45 +                  }
    3.46 +                end
    3.47                  if policy and policy.free_timeable then
    3.48                    local available_timings
    3.49                    if config.free_timing and config.free_timing.available_func then
     4.1 --- a/app/main/help/introduction.lua	Thu Sep 30 10:04:31 2021 +0200
     4.2 +++ b/app/main/help/introduction.lua	Thu Sep 30 10:04:55 2021 +0200
     4.3 @@ -5,30 +5,39 @@
     4.4  
     4.5      ui.container{ attr = { class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp" }, content = function()
     4.6        ui.container{ attr = { class = "mdl-card__title mdl-card--has-fab mdl-card--border" }, content = function ()
     4.7 -        ui.heading { attr = { class = "mdl-card__title-text" }, level = 1, content = _"Quick guide" }
     4.8 +        ui.heading { attr = { class = "mdl-card__title-text" }, level = 1, content = function()
     4.9 +          if config.quick_guide and config.quick_guide.title then
    4.10 +            slot.put(config.quick_guide.title)
    4.11 +          else
    4.12 +            ui.tag{ content = _"Quick guide" }
    4.13 +          end
    4.14 +        end }
    4.15        end }
    4.16        ui.container { attr = { class = "draft mdl-card__content mdl-card--border" }, content = function()
    4.17 -        ui.heading{ level = 2, content = _"Initiatives and issues" }
    4.18 -        ui.tag{ tag = "p", content = _"[introduction] iniatives and issues" }
    4.19 -        ui.heading{ level = 2, content = _"Subject areas" }
    4.20 -        ui.tag{ tag = "p", content = _"[introduction] subject areas" }
    4.21 -        ui.heading{ level = 2, content = _"Organizational units" }
    4.22 -        ui.tag{ tag = "p", content = _"[introduction] organizational units" }
    4.23 -        ui.heading{ level = 2, content = _"Rules of procedure" }
    4.24 -        ui.tag{ tag = "p", content = _"[introduction] rules of procedure" }
    4.25 -        ui.heading{ level = 2, content = _"Admission phase" }
    4.26 -        ui.tag{ tag = "p", content = _"[introduction] phase 1 admission" }
    4.27 -        ui.heading{ level = 2, content = _"Discussion phase" }
    4.28 -        ui.tag{ tag = "p", content = _"[introduction] phase 2 discussion" }
    4.29 -        ui.heading{ level = 2, content = _"Verification phase" }
    4.30 -        ui.tag{ tag = "p", content = _"[introduction] phase 3 verification" }
    4.31 -        ui.heading{ level = 2, content = _"Voting phase" }
    4.32 -        ui.tag{ tag = "p", content = _"[introduction] phase 4 voting" }
    4.33 -        ui.heading{ level = 2, content = _"Vote delegation" }
    4.34 -        ui.tag{ tag = "p", content = _"[introduction] vote delegation" }
    4.35 -        ui.heading{ level = 2, content = _"Preference voting" }
    4.36 -        ui.tag{ tag = "p", content = _"[introduction] preference voting" }
    4.37 -
    4.38 +        if config.quick_guide and config.quick_guide.content then
    4.39 +          slot.put(config.quick_guide.content)
    4.40 +        else
    4.41 +          ui.heading{ level = 2, content = _"Initiatives and issues" }
    4.42 +          ui.tag{ tag = "p", content = _"[introduction] iniatives and issues" }
    4.43 +          ui.heading{ level = 2, content = _"Subject areas" }
    4.44 +          ui.tag{ tag = "p", content = _"[introduction] subject areas" }
    4.45 +          ui.heading{ level = 2, content = _"Organizational units" }
    4.46 +          ui.tag{ tag = "p", content = _"[introduction] organizational units" }
    4.47 +          ui.heading{ level = 2, content = _"Rules of procedure" }
    4.48 +          ui.tag{ tag = "p", content = _"[introduction] rules of procedure" }
    4.49 +          ui.heading{ level = 2, content = _"Admission phase" }
    4.50 +          ui.tag{ tag = "p", content = _"[introduction] phase 1 admission" }
    4.51 +          ui.heading{ level = 2, content = _"Discussion phase" }
    4.52 +          ui.tag{ tag = "p", content = _"[introduction] phase 2 discussion" }
    4.53 +          ui.heading{ level = 2, content = _"Verification phase" }
    4.54 +          ui.tag{ tag = "p", content = _"[introduction] phase 3 verification" }
    4.55 +          ui.heading{ level = 2, content = _"Voting phase" }
    4.56 +          ui.tag{ tag = "p", content = _"[introduction] phase 4 voting" }
    4.57 +          ui.heading{ level = 2, content = _"Vote delegation" }
    4.58 +          ui.tag{ tag = "p", content = _"[introduction] vote delegation" }
    4.59 +          ui.heading{ level = 2, content = _"Preference voting" }
    4.60 +          ui.tag{ tag = "p", content = _"[introduction] preference voting" }
    4.61 +        end
    4.62        end }
    4.63      end }
    4.64    end }
     5.1 --- a/app/main/index/_head.lua	Thu Sep 30 10:04:31 2021 +0200
     5.2 +++ b/app/main/index/_head.lua	Thu Sep 30 10:04:55 2021 +0200
     5.3 @@ -28,13 +28,17 @@
     5.4    ui.container{ attr = { class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp" }, content = function()
     5.5      ui.container{ attr = { class = "mdl-card__title mdl-card--border" }, content = function()
     5.6        ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = unit.name }
     5.7 -      if unit.description and #(unit.description) > 0 then
     5.8 -        ui.container{ attr = { class = "mdl-card__subtitle-text" }, content = unit.description }
     5.9 -      end
    5.10 -      if config.render_external_reference_unit then
    5.11 +    end }
    5.12 +    if unit.description and #(unit.description) > 0 then
    5.13 +      ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
    5.14 +        slot.put(format.text_with_links(unit.description))
    5.15 +      end }
    5.16 +    end
    5.17 +    if config.render_external_reference_unit then
    5.18 +      ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
    5.19          config.render_external_reference_unit(unit)
    5.20 -      end
    5.21 -    end }
    5.22 +      end }
    5.23 +    end
    5.24  
    5.25  
    5.26      if not (config.voting_only and config.disable_delegations) and app.session.member_id and (
    5.27 @@ -80,10 +84,12 @@
    5.28      if unit then
    5.29        ui.container{ attr = { class = "mdl-card__title mdl-card--border" }, content = function()
    5.30          ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = area.name }
    5.31 -        if area.description and #(area.description) > 0 then
    5.32 -          ui.container{ attr = { class = "mdl-card__subtitle-text" }, content = area.description }
    5.33 -        end
    5.34        end }
    5.35 +      if area.description and #(area.description) > 0 then
    5.36 +        ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
    5.37 +          slot.put(format.text_with_links(area.description))
    5.38 +        end }
    5.39 +      end
    5.40      end
    5.41      if not (config.voting_only and config.disable_delegations) and app.session.member_id and (
    5.42        app.session.member:has_voting_right_for_unit_id(area.unit_id) 
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/app/main/index/_sidebar_motd_intern_top.lua	Thu Sep 30 10:04:55 2021 +0200
     6.3 @@ -0,0 +1,12 @@
     6.4 +if app.session.member and config.motd_intern_top then
     6.5 +  ui.container{ attr = { class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp" }, content = function()
     6.6 +    ui.container{ attr = { class = "mdl-card__content" }, content = function()
     6.7 +      ui.container{
     6.8 +        attr = { class = "motd" },
     6.9 +        content = function()
    6.10 +          slot.put(config.motd_intern_top)
    6.11 +        end
    6.12 +      }
    6.13 +    end }
    6.14 +  end }
    6.15 +end
     7.1 --- a/app/main/index/_sidebar_whatcanido.lua	Thu Sep 30 10:04:31 2021 +0200
     7.2 +++ b/app/main/index/_sidebar_whatcanido.lua	Thu Sep 30 10:04:55 2021 +0200
     7.3 @@ -30,6 +30,14 @@
     7.4            end
     7.5          end } 
     7.6        end }
     7.7 +      if not config.voting_only and app.session.member.has_initiative_right then
     7.8 +        ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
     7.9 +          ui.tag{ content = _"I want to start a new initiative" }
    7.10 +          ui.tag { tag = "ul", attr = { class = "ul" }, content = function ()
    7.11 +            ui.tag { tag = "li", content = _"open the appropriate subject area for your issue and follow the instruction on that page." }
    7.12 +          end } 
    7.13 +        end }
    7.14 +      end
    7.15        if app.session.member.has_voting_right then
    7.16          ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
    7.17            ui.tag{ content = _"I want to vote" }
    7.18 @@ -46,15 +54,7 @@
    7.19            end }
    7.20          end
    7.21        end
    7.22 -      if not config.voting_only and app.session.member.has_initiative_right then
    7.23 -        ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
    7.24 -          ui.tag{ content = _"I want to start a new initiative" }
    7.25 -          ui.tag { tag = "ul", attr = { class = "ul" }, content = function ()
    7.26 -            ui.tag { tag = "li", content = _"open the appropriate subject area for your issue and follow the instruction on that page." }
    7.27 -          end } 
    7.28 -        end }
    7.29 -      end
    7.30 -      if not config.single_unit_id then
    7.31 +      if not config.single_unit_id and not config.do_not_show_other_units_link then
    7.32          ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
    7.33            ui.tag{ content = _"I want to take a look at other organizational units" }
    7.34            ui.tag { tag = "ul", attr = { class = "ul" }, content = function ()
    7.35 @@ -94,22 +94,26 @@
    7.36      if not config.voting_only then
    7.37        ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
    7.38          ui.tag{ content = _"I want to learn more about LiquidFeedback" }
    7.39 -        ui.tag { tag = "ul", attr = { class = "ul" }, content = function ()
    7.40 -          ui.tag { tag = "li", content = function()
    7.41 -            ui.link { module = "help", view = "introduction", content = _"structured discussion" }
    7.42 -          end }
    7.43 -          ui.tag { tag = "li", content = function()
    7.44 -            ui.link { module = "help", view = "introduction", content = _"4 phases of a decision" }
    7.45 -          end }
    7.46 -          if not config.disable_delegations then
    7.47 +        if config.quick_guide and config.quick_guide.links then
    7.48 +          ui.container{ content = config.quick_guide.links }
    7.49 +        else
    7.50 +          ui.tag { tag = "ul", attr = { class = "ul" }, content = function ()
    7.51 +            ui.tag { tag = "li", content = function()
    7.52 +              ui.link { module = "help", view = "introduction", content = _"structured discussion" }
    7.53 +            end }
    7.54              ui.tag { tag = "li", content = function()
    7.55 -              ui.link { module = "help", view = "introduction", content = _"vote delegation" }
    7.56 +              ui.link { module = "help", view = "introduction", content = _"4 phases of a decision" }
    7.57              end }
    7.58 -          end
    7.59 -          ui.tag { tag = "li", content = function()
    7.60 -            ui.link { module = "help", view = "introduction", content = _"preference voting" }
    7.61 -          end }
    7.62 -        end } 
    7.63 +            if not config.disable_delegations then
    7.64 +              ui.tag { tag = "li", content = function()
    7.65 +                ui.link { module = "help", view = "introduction", content = _"vote delegation" }
    7.66 +              end }
    7.67 +            end
    7.68 +            ui.tag { tag = "li", content = function()
    7.69 +              ui.link { module = "help", view = "introduction", content = _"preference voting" }
    7.70 +            end }
    7.71 +          end } 
    7.72 +        end
    7.73        end }
    7.74      end
    7.75    end }
     8.1 --- a/app/main/index/index.lua	Thu Sep 30 10:04:31 2021 +0200
     8.2 +++ b/app/main/index/index.lua	Thu Sep 30 10:04:55 2021 +0200
     8.3 @@ -45,11 +45,17 @@
     8.4    ui.cell_main{ content = function()
     8.5  
     8.6      execute.view{ module = "index", view = "_sidebar_motd_public" }
     8.7 +    if not unit_id and not area_id then
     8.8 +      execute.view{ module = "index", view = "_sidebar_motd_intern_top" }
     8.9 +    end
    8.10  
    8.11      execute.view{ module = "issue", view = "_list" }
    8.12    end }
    8.13  
    8.14    ui.cell_sidebar{ content = function()
    8.15 +    if not unit and not area and config.logo_startpage then
    8.16 +      config.logo_startpage()
    8.17 +    end
    8.18      execute.view{ module = "index", view = "_head" }
    8.19      
    8.20      execute.view{ module = "index", view = "_sidebar_motd" }
     9.1 --- a/app/main/initiative/_suggestions.lua	Thu Sep 30 10:04:31 2021 +0200
     9.2 +++ b/app/main/initiative/_suggestions.lua	Thu Sep 30 10:04:55 2021 +0200
     9.3 @@ -133,214 +133,226 @@
     9.4    attr = { class = "section suggestions" },
     9.5    content = function ()
     9.6  
     9.7 -    if # ( initiative.suggestions ) > 0 then
     9.8 -  
     9.9 -      ui.heading { 
    9.10 -        level = 1, 
    9.11 -        content = _("Suggestions for improvement (#{count})", { count = # ( initiative.suggestions ) } ) 
    9.12 +    ui.heading { 
    9.13 +      level = 1, 
    9.14 +      content = _("Suggestions for improvement (#{count})", { count = # ( initiative.suggestions ) } ) 
    9.15 +    }
    9.16 +
    9.17 +    ui.container { content = _"written and rated by the supportes of this initiative to improve the proposal and its reasons" }
    9.18 +
    9.19 +    if app.session.member_id and initiative.member_info.supported and not active_trustee_id then
    9.20 +      ui.link {
    9.21 +        attr = {
    9.22 +            style = "margin-top: 1ex;",
    9.23 +            class = "mdl-button mdl-js-button mdl-button--raised mdl-button--colored",
    9.24 +        },
    9.25 +        module = "suggestion", view = "new", params = {
    9.26 +          initiative_id = initiative.id
    9.27 +        },
    9.28 +        content = _"write a new suggestion" 
    9.29        }
    9.30 -      ui.container { content = _"written and rated by the supportes of this initiative to improve the proposal and its reasons" }
    9.31 -      slot.put("<br />")
    9.32 -      
    9.33 -      for i, suggestion in ipairs(initiative.suggestions) do
    9.34 -        
    9.35 -        local opinion = Opinion:by_pk(app.session.member_id, suggestion.id)
    9.36 +    end
    9.37 +
    9.38 +    slot.put("<br /><br />")
    9.39 +
    9.40 +    for i, suggestion in ipairs(initiative.suggestions) do
    9.41 +
    9.42 +      local opinion = Opinion:by_pk(app.session.member_id, suggestion.id)
    9.43  
    9.44 -        local class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp not-folded"
    9.45 -        if suggestion.id == param.get("suggestion_id", atom.number) then
    9.46 -          class = class .. " highlighted"
    9.47 -        end
    9.48 -        if member and not initiative.issue.fully_frozen and not initiative.issue.closed and initiative.member_info.supported then
    9.49 -          class = class .. " rateable"
    9.50 -        end
    9.51 +      local class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp not-folded"
    9.52 +      if suggestion.id == param.get("suggestion_id", atom.number) then
    9.53 +        class = class .. " highlighted"
    9.54 +      end
    9.55 +      if member and not initiative.issue.fully_frozen and not initiative.issue.closed and initiative.member_info.supported then
    9.56 +        class = class .. " rateable"
    9.57 +      end
    9.58 +    
    9.59 +      ui.link { attr = { name = "s" .. suggestion.id }, text = "" }
    9.60 +      ui.tag { tag = "div", attr = { class = class, id = "s" .. suggestion.id }, content = function ()
    9.61 +        ui.tag{ attr = { class = "mdl-card__title mdl-card--border" }, content = function()
    9.62 +          ui.heading { level = 2, 
    9.63 +            attr = { class = "mdl-card__title-text" },
    9.64 +            content = function()
    9.65 +              ui.tag{ content = format.string(suggestion.name, {
    9.66 +                truncate_at = 160, truncate_suffix = true })
    9.67 +              }
    9.68 +            end
    9.69 +          }
    9.70 +        end }
    9.71 +
    9.72 +          
    9.73 +    
    9.74 +        ui.container{ attr = { class = "suggestion-content" }, content = function()
    9.75        
    9.76 -        ui.link { attr = { name = "s" .. suggestion.id }, text = "" }
    9.77 -        ui.tag { tag = "div", attr = { class = class, id = "s" .. suggestion.id }, content = function ()
    9.78 -          ui.tag{ attr = { class = "mdl-card__title mdl-card--border" }, content = function()
    9.79 -            ui.heading { level = 2, 
    9.80 -              attr = { class = "mdl-card__title-text" },
    9.81 -              content = function()
    9.82 -                ui.tag{ content = format.string(suggestion.name, {
    9.83 -                  truncate_at = 160, truncate_suffix = true })
    9.84 +          ui.container { 
    9.85 +            attr = { class = "mdl-card__content mdl-card--border suggestionInfo" },
    9.86 +            content = function ()
    9.87 +            
    9.88 +              if app.session:has_access("authors_pseudonymous") then
    9.89 +                ui.tag{ content = _"by" }
    9.90 +                slot.put(" ")
    9.91 +                ui.link{
    9.92 +                  module = "member", view = "show", id = suggestion.author_id,
    9.93 +                  content = suggestion.author.name
    9.94                  }
    9.95                end
    9.96 -            }
    9.97 -          end }
    9.98 +              
    9.99 +              execute.view{
   9.100 +                module = "suggestion", view = "_collective_rating", params = {
   9.101 +                  suggestion = suggestion
   9.102 +                }
   9.103 +              }
   9.104  
   9.105 -            
   9.106 -      
   9.107 -          ui.container{ attr = { class = "suggestion-content" }, content = function()
   9.108 -        
   9.109 -            ui.container { 
   9.110 -              attr = { class = "mdl-card__content mdl-card--border suggestionInfo" },
   9.111 -              content = function ()
   9.112 +            end 
   9.113 +          }
   9.114                
   9.115 -                if app.session:has_access("authors_pseudonymous") then
   9.116 -                  ui.tag{ content = _"by" }
   9.117 -                  slot.put(" ")
   9.118 -                  ui.link{
   9.119 -                    module = "member", view = "show", id = suggestion.author_id,
   9.120 -                    content = suggestion.author.name
   9.121 -                  }
   9.122 -                end
   9.123 -                
   9.124 -                execute.view{
   9.125 -                  module = "suggestion", view = "_collective_rating", params = {
   9.126 -                    suggestion = suggestion
   9.127 -                  }
   9.128 +          ui.container {
   9.129 +            attr = { class = "mdl-card__content suggestion-text draft" },
   9.130 +            content = function ()
   9.131 +              slot.put ( suggestion:get_content( "html" ) )
   9.132 +
   9.133 +              ui.container { attr = { class = "floatx-right" }, content = function()
   9.134 +              
   9.135 +                ui.link { 
   9.136 +                  attr = { 
   9.137 +                    class = "mdl-button mdl-js-button mdl-button--icon suggestion-more",
   9.138 +                    onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.remove('folded');document.querySelector('#s" .. suggestion.id .. "').classList.add('unfolded'); return false;"
   9.139 +                  },
   9.140 +                  content = function()
   9.141 +                    ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_more" }
   9.142 +                  end
   9.143                  }
   9.144 -
   9.145 -              end 
   9.146 -            }
   9.147                  
   9.148 -            ui.container {
   9.149 -              attr = { class = "mdl-card__content suggestion-text draft" },
   9.150 -              content = function ()
   9.151 -                slot.put ( suggestion:get_content( "html" ) )
   9.152 +                ui.link { 
   9.153 +                  attr = { 
   9.154 +                    class = "mdl-button mdl-js-button mdl-button--icon suggestion-less",
   9.155 +                    onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.add('folded');document.querySelector('#s" .. suggestion.id .. "').classList.remove('unfolded'); return false;"
   9.156 +                  },
   9.157 +                  content = function()
   9.158 +                    ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_less" }
   9.159 +                  end
   9.160 +                }
   9.161 +                --[[
   9.162 +                ui.link{
   9.163 +                  attr = { class = "mdl-button" },
   9.164 +                  content = _"Details",
   9.165 +                  module = "suggestion", view = "show", id = suggestion.id
   9.166 +                }
   9.167 +                --]]
   9.168 +              end }
   9.169 +             
   9.170 +            end
   9.171 +          }
   9.172 +
   9.173 +        end }
   9.174 +
   9.175 +        ui.container { attr = { class = "mdl-card__actions mdl-card--border" }, content = function()
   9.176  
   9.177 -                ui.container { attr = { class = "floatx-right" }, content = function()
   9.178 -                
   9.179 -                  ui.link { 
   9.180 -                    attr = { 
   9.181 -                      class = "mdl-button mdl-js-button mdl-button--icon suggestion-more",
   9.182 -                      onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.remove('folded');document.querySelector('#s" .. suggestion.id .. "').classList.add('unfolded'); return false;"
   9.183 -                    },
   9.184 -                    content = function()
   9.185 -                      ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_more" }
   9.186 -                    end
   9.187 -                  }
   9.188 -                  
   9.189 -                  ui.link { 
   9.190 -                    attr = { 
   9.191 -                      class = "mdl-button mdl-js-button mdl-button--icon suggestion-less",
   9.192 -                      onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.add('folded');document.querySelector('#s" .. suggestion.id .. "').classList.remove('unfolded'); return false;"
   9.193 -                    },
   9.194 -                    content = function()
   9.195 -                      ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_less" }
   9.196 -                    end
   9.197 -                  }
   9.198 -                  --[[
   9.199 -                  ui.link{
   9.200 -                    attr = { class = "mdl-button" },
   9.201 -                    content = _"Details",
   9.202 -                    module = "suggestion", view = "show", id = suggestion.id
   9.203 -                  }
   9.204 -                  --]]
   9.205 -                end }
   9.206 -               
   9.207 +          if direct_supporter then
   9.208 +            ui.container{ attr = { class = "suggestion_rating_info" }, content = function()
   9.209 +              ui.tag{ attr = { id = "s" .. suggestion.id .. "_rating_text" }, content = function()
   9.210 +                local text = ""
   9.211 +                if opinion then
   9.212 +                  if opinion.degree == 2 then
   9.213 +                    text = _"must"
   9.214 +                  elseif opinion.degree == 1 then
   9.215 +                    text = _"should"
   9.216 +                  elseif opinion.degree == 0 then
   9.217 +                    text = _"neutral"
   9.218 +                  elseif opinion.degree == -1 then
   9.219 +                    text = _"should not"
   9.220 +                  elseif opinion.degree == -2 then
   9.221 +                    text = _"must not"
   9.222 +                  end
   9.223 +                  ui.tag { content = text }
   9.224 +                  slot.put ( " " )
   9.225 +                  if 
   9.226 +                    (opinion.degree > 0 and not opinion.fulfilled)
   9.227 +                    or (opinion.degree < 0 and opinion.fulfilled)
   9.228 +                  then
   9.229 +                    ui.tag{ content = _"but" }
   9.230 +                  else
   9.231 +                    ui.tag{ content = _"and" }
   9.232 +                  end
   9.233 +                  slot.put ( " " )
   9.234 +                  local text = ""
   9.235 +                  if opinion.fulfilled then
   9.236 +                    text = _"is implemented"
   9.237 +                  else
   9.238 +                    text = _"is not implemented"
   9.239 +                  end
   9.240 +                  ui.tag { content = text }
   9.241 +                end
   9.242 +              end }
   9.243 +              local id = "s" .. suggestion.id .. "_rating_icon"
   9.244 +              if opinion and (
   9.245 +                  (opinion.degree > 0 and not opinion.fulfilled)
   9.246 +                  or (opinion.degree < 0 and opinion.fulfilled)
   9.247 +                )
   9.248 +              then
   9.249 +                slot.put(" ")
   9.250 +                if math.abs(opinion.degree) > 1 then
   9.251 +                  ui.icon("warning", "red", id)
   9.252 +                else
   9.253 +                  ui.icon("warning", nil, id)
   9.254 +                end
   9.255 +              elseif opinion then
   9.256 +                slot.put(" ")
   9.257 +                ui.icon("done", nil, id)
   9.258 +              else
   9.259 +                slot.put(" ")
   9.260 +                ui.icon("blank", nil, id)
   9.261 +              end
   9.262 +            end }
   9.263 +            
   9.264 +            ui.link{
   9.265 +              attr = {
   9.266 +                id = "s" .. suggestion.id .. "_rate_button",
   9.267 +                class = "mdl-button",
   9.268 +                onclick = "rateSuggestion(" .. suggestion.id .. ", " .. (opinion and opinion.degree or 0) .. ", " .. (opinion and (opinion.fulfilled and "true" or "false") or "null") .. ");return false;"
   9.269 +              },
   9.270 +              content = function()
   9.271 +                if opinion then
   9.272 +                  ui.tag { content = _"update rating" }
   9.273 +                else
   9.274 +                  ui.tag { content = _"rate suggestion" }
   9.275 +                end
   9.276                end
   9.277              }
   9.278 - 
   9.279 -          end }
   9.280 -
   9.281 -          ui.container { attr = { class = "mdl-card__actions mdl-card--border" }, content = function()
   9.282 +          end
   9.283 +                    
   9.284 +          ui.link{
   9.285 +            attr = { class = "mdl-button" },
   9.286 +            content = _"Details",
   9.287 +            module = "suggestion", view = "show", id = suggestion.id
   9.288 +          }
   9.289  
   9.290 -            if direct_supporter then
   9.291 -              ui.container{ attr = { class = "suggestion_rating_info" }, content = function()
   9.292 -                ui.tag{ attr = { id = "s" .. suggestion.id .. "_rating_text" }, content = function()
   9.293 -                  local text = ""
   9.294 -                  if opinion then
   9.295 -                    if opinion.degree == 2 then
   9.296 -                      text = _"must"
   9.297 -                    elseif opinion.degree == 1 then
   9.298 -                      text = _"should"
   9.299 -                    elseif opinion.degree == 0 then
   9.300 -                      text = _"neutral"
   9.301 -                    elseif opinion.degree == -1 then
   9.302 -                      text = _"should not"
   9.303 -                    elseif opinion.degree == -2 then
   9.304 -                      text = _"must not"
   9.305 -                    end
   9.306 -                    ui.tag { content = text }
   9.307 -                    slot.put ( " " )
   9.308 -                    if 
   9.309 -                      (opinion.degree > 0 and not opinion.fulfilled)
   9.310 -                      or (opinion.degree < 0 and opinion.fulfilled)
   9.311 -                    then
   9.312 -                      ui.tag{ content = _"but" }
   9.313 -                    else
   9.314 -                      ui.tag{ content = _"and" }
   9.315 -                    end
   9.316 -                    slot.put ( " " )
   9.317 -                    local text = ""
   9.318 -                    if opinion.fulfilled then
   9.319 -                      text = _"is implemented"
   9.320 -                    else
   9.321 -                      text = _"is not implemented"
   9.322 -                    end
   9.323 -                    ui.tag { content = text }
   9.324 -                  end
   9.325 -                end }
   9.326 -                local id = "s" .. suggestion.id .. "_rating_icon"
   9.327 -                if opinion and (
   9.328 -                    (opinion.degree > 0 and not opinion.fulfilled)
   9.329 -                    or (opinion.degree < 0 and opinion.fulfilled)
   9.330 -                  )
   9.331 -                then
   9.332 -                  slot.put(" ")
   9.333 -                  if math.abs(opinion.degree) > 1 then
   9.334 -                    ui.icon("warning", "red", id)
   9.335 -                  else
   9.336 -                    ui.icon("warning", nil, id)
   9.337 -                  end
   9.338 -                elseif opinion then
   9.339 -                  slot.put(" ")
   9.340 -                  ui.icon("done", nil, id)
   9.341 -                else
   9.342 -                  slot.put(" ")
   9.343 -                  ui.icon("blank", nil, id)
   9.344 -                end
   9.345 -              end }
   9.346 -              
   9.347 -              ui.link{
   9.348 -                attr = {
   9.349 -                  id = "s" .. suggestion.id .. "_rate_button",
   9.350 -                  class = "mdl-button",
   9.351 -                  onclick = "rateSuggestion(" .. suggestion.id .. ", " .. (opinion and opinion.degree or 0) .. ", " .. (opinion and (opinion.fulfilled and "true" or "false") or "null") .. ");return false;"
   9.352 -                },
   9.353 -                content = function()
   9.354 -                  if opinion then
   9.355 -                    ui.tag { content = _"update rating" }
   9.356 -                  else
   9.357 -                    ui.tag { content = _"rate suggestion" }
   9.358 -                  end
   9.359 -                end
   9.360 -              }
   9.361 -            end
   9.362 -                      
   9.363 -            ui.link{
   9.364 -              attr = { class = "mdl-button" },
   9.365 -              content = _"Details",
   9.366 -              module = "suggestion", view = "show", id = suggestion.id
   9.367 +        end }
   9.368 +        ui.script{ script = [[
   9.369 +          var rateSuggestionRateText = "]] .. _"rate suggestion" .. [[";
   9.370 +          var rateSuggestionUpdateRatingText = "]] .. _"update rating" .. [[";
   9.371 +          var rateSuggestionDegreeTexts = {
   9.372 +            "-2": "]] .. _"must not" .. [[",
   9.373 +            "-1": "]] .. _"should not" .. [[",
   9.374 +            "1": "]] .. _"should" .. [[",
   9.375 +            "2": "]] .. _"must" .. [["
   9.376 +          }
   9.377 +          var rateSuggestionAndText = "]] .. _"and" .. [[";
   9.378 +          var rateSuggestionButText = "]] .. _"but" .. [[";
   9.379 +          var rateSuggestionFulfilledText = "]] .. _"is implemented" .. [[";
   9.380 +          var rateSuggestionNotFulfilledText = "]] .. _"is not implemented" .. [[";
   9.381 +          window.addEventListener("load", function() {
   9.382 +            var textEl = document.querySelector('#s]] .. suggestion.id .. [[ .suggestion-content');
   9.383 +            var height = textEl.clientHeight;
   9.384 +            if (height > 250) {
   9.385 +              document.querySelector('#s]] .. suggestion.id .. [[').classList.add('folded');
   9.386              }
   9.387 +          });
   9.388 +        ]] }
   9.389 +        
   9.390 +      end } 
   9.391  
   9.392 -          end }
   9.393 -          ui.script{ script = [[
   9.394 -            var rateSuggestionRateText = "]] .. _"rate suggestion" .. [[";
   9.395 -            var rateSuggestionUpdateRatingText = "]] .. _"update rating" .. [[";
   9.396 -            var rateSuggestionDegreeTexts = {
   9.397 -              "-2": "]] .. _"must not" .. [[",
   9.398 -              "-1": "]] .. _"should not" .. [[",
   9.399 -              "1": "]] .. _"should" .. [[",
   9.400 -              "2": "]] .. _"must" .. [["
   9.401 -            }
   9.402 -            var rateSuggestionAndText = "]] .. _"and" .. [[";
   9.403 -            var rateSuggestionButText = "]] .. _"but" .. [[";
   9.404 -            var rateSuggestionFulfilledText = "]] .. _"is implemented" .. [[";
   9.405 -            var rateSuggestionNotFulfilledText = "]] .. _"is not implemented" .. [[";
   9.406 -            window.addEventListener("load", function() {
   9.407 -              var textEl = document.querySelector('#s]] .. suggestion.id .. [[ .suggestion-content');
   9.408 -              var height = textEl.clientHeight;
   9.409 -              if (height > 250) {
   9.410 -                document.querySelector('#s]] .. suggestion.id .. [[').classList.add('folded');
   9.411 -              }
   9.412 -            });
   9.413 -          ]] }
   9.414 -          
   9.415 -        end } 
   9.416 -
   9.417 -      end -- for i, suggestion
   9.418 -    
   9.419 -    end -- if #initiative.suggestions > 0
   9.420 +    end -- for i, suggestion
   9.421 +  
   9.422    end
   9.423  }
    10.1 --- a/app/main/issue/_list.lua	Thu Sep 30 10:04:31 2021 +0200
    10.2 +++ b/app/main/issue/_list.lua	Thu Sep 30 10:04:55 2021 +0200
    10.3 @@ -16,7 +16,11 @@
    10.4  end
    10.5  
    10.6  if app.single_unit_id then
    10.7 -  for_unit = Unit:by_id(app.single_unit_id)
    10.8 +  if request.get_param{ name = "unit" } then
    10.9 +    for_unit = Unit:by_id(request.get_param{ name = "unit" })
   10.10 +  else
   10.11 +    for_unit = Unit:by_id(app.single_unit_id)
   10.12 +  end
   10.13  end
   10.14  
   10.15  local selector
    11.1 --- a/app/main/issue/_sidebar_whatcanido.lua	Thu Sep 30 10:04:31 2021 +0200
    11.2 +++ b/app/main/issue/_sidebar_whatcanido.lua	Thu Sep 30 10:04:55 2021 +0200
    11.3 @@ -603,12 +603,16 @@
    11.4      
    11.5      if not app.session.member or not privileged_to_vote then
    11.6        ui.container { attr = { class = "mdl-card__content mdl-card--border" }, content = function ()
    11.7 -        ui.tag{ content = _"You are not entitled to vote in this unit" }
    11.8 -        ui.tag{ tag = "ul", content = function()
    11.9 -          ui.tag{ tag = "li", content = function()
   11.10 -            ui.link{ module = "index", view = "login", content = _"Login" }
   11.11 +        if not app.session.member_id then
   11.12 +          ui.tag{ content = _"Login to participate" }
   11.13 +          ui.tag{ tag = "ul", content = function()
   11.14 +            ui.tag{ tag = "li", content = function()
   11.15 +              ui.link{ module = "index", view = "login", content = _"Login" }
   11.16 +            end }
   11.17            end }
   11.18 -        end }
   11.19 +        else
   11.20 +          ui.tag{ content = _"You are not entitled to vote in this unit" }
   11.21 +        end
   11.22        end }
   11.23      end
   11.24      
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/app/main/oauth2_client/callback.lua	Thu Sep 30 10:04:55 2021 +0200
    12.3 @@ -0,0 +1,88 @@
    12.4 +local provider = param.get("provider")
    12.5 +local provider_config = config.oauth2_providers[provider]
    12.6 +if not provider_config then
    12.7 +  return
    12.8 +end
    12.9 +
   12.10 +
   12.11 +local error = param.get("error")
   12.12 +
   12.13 +if error then
   12.14 +  ui.heading{ content = "OAuth error" }
   12.15 +  ui.container{ content = error }
   12.16 +  return
   12.17 +end
   12.18 +
   12.19 +local state = param.get("state")
   12.20 +
   12.21 +if state ~= app.session:additional_secret_for("oauth") then
   12.22 +  ui.heading{ content = "OAuth error" }
   12.23 +  ui.container{ content = "state invalid" }
   12.24 +  return
   12.25 +end
   12.26 +
   12.27 +local code = param.get("code")
   12.28 +
   12.29 +local params = {
   12.30 +  code = code,
   12.31 +  client_id = provider_config.client_id,
   12.32 +  client_secret = provider_config.client_secret,
   12.33 +  redirect_uri = request.get_absolute_baseurl() .. "oauth2_client/callback.html?provider=" .. provider,
   12.34 +  grant_type = "authorization_code"
   12.35 +}
   12.36 +
   12.37 +local params_list = {}
   12.38 +for key, val in pairs(params) do
   12.39 +  table.insert(params_list, encode.url_part(key) .. "=" .. encode.url_part(val))
   12.40 +end
   12.41 +
   12.42 +local r = table.concat(params_list, "&")
   12.43 +
   12.44 +local output, err, status = extos.pfilter(nil, "curl", "-X", "POST", "-d", r, provider_config.token_url)
   12.45 +
   12.46 +local result = json.import(output)
   12.47 +
   12.48 +local url = provider_config.id_url .. "?access_token=" .. encode.url_part(result.access_token)
   12.49 +
   12.50 +local output, err, status = extos.pfilter(nil, "curl", url)
   12.51 +
   12.52 +local id_result = json.import(output)
   12.53 +
   12.54 +local id = id_result[provider_config.id_field]
   12.55 +local email = id_result[provider_config.email_field]
   12.56 +
   12.57 +if id then
   12.58 +  local member = Member:new_selector()
   12.59 +    :add_where{ "authority = ?", "oauth2_" .. provider }
   12.60 +    :add_where{ "authority_uid = ?", id }
   12.61 +    :optional_object_mode()
   12.62 +    :exec()
   12.63 +    
   12.64 +  if not member then
   12.65 +    member = Member:new()
   12.66 +    member.authority = "oauth2_" .. provider
   12.67 +    member.authority_uid = id
   12.68 +    member.notify_email = email
   12.69 +    member.name = "Member " .. id
   12.70 +    member.identification = "Member " .. id
   12.71 +    member.activated = "now"
   12.72 +    member:save()
   12.73 +    for i, unit_id in ipairs(provider_config.unit_ids) do
   12.74 +      local privilege = Privilege:new()
   12.75 +      privilege.member_id = member.id
   12.76 +      privilege.unit_id = unit_id
   12.77 +      privilege.initiative_right = true
   12.78 +      privilege.voting_right = true
   12.79 +      privilege:save()
   12.80 +    end
   12.81 +  end
   12.82 +  member.last_login = "now"
   12.83 +  member.last_activity = "now"
   12.84 +  member.active = true
   12.85 +  member:save()
   12.86 +  app.session.member = member
   12.87 +  app.session:save()
   12.88 +  request.redirect{ external = request.get_absolute_baseurl() }
   12.89 +  
   12.90 +end
   12.91 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/app/main/oauth2_client/redirect.lua	Thu Sep 30 10:04:55 2021 +0200
    13.3 @@ -0,0 +1,29 @@
    13.4 +local provider = param.get("provider")
    13.5 +local provider_config = config.oauth2_providers[provider]
    13.6 +if not provider_config then
    13.7 +  return
    13.8 +end
    13.9 +
   13.10 +local params = {
   13.11 +  response_type = "code",
   13.12 +  redirect_uri = request.get_absolute_baseurl() .. "oauth2_client/callback.html?provider=" .. provider,
   13.13 +  client_id = provider_config.client_id,
   13.14 +  --scope = provider_config.scope,
   13.15 +  state = app.session:additional_secret_for("oauth"),
   13.16 +}
   13.17 +
   13.18 +if provider_config.additional_auth_params then
   13.19 +  for key, val in pairs(provider_config.additional_auth_params) do
   13.20 +    params[key] = val
   13.21 +  end
   13.22 +end
   13.23 +
   13.24 +local params_list = {}
   13.25 +for key, val in pairs(params) do
   13.26 +  table.insert(params_list, encode.url_part(key) .. "=" .. encode.url_part(val))
   13.27 +end
   13.28 +
   13.29 +local url = provider_config.auth_url .. "?" .. table.concat(params_list, "&")
   13.30 +
   13.31 +request.redirect{ external = url }
   13.32 +
    14.1 --- a/app/main/unit/_sidebar_whatcanido.lua	Thu Sep 30 10:04:31 2021 +0200
    14.2 +++ b/app/main/unit/_sidebar_whatcanido.lua	Thu Sep 30 10:04:55 2021 +0200
    14.3 @@ -61,7 +61,14 @@
    14.4            end
    14.5          end }
    14.6        end
    14.7 -      
    14.8 +      if not config.voting_only and app.session.member_id and app.session.member:has_initiative_right_for_unit_id ( unit.id ) then
    14.9 +        ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
   14.10 +          ui.tag{ content = _"I want to start a new initiative" }
   14.11 +          ui.tag{ tag = "ul", attr = { class = "ul" }, content = function ()
   14.12 +            ui.tag { tag = "li", content = _"open the appropriate subject area for your issue and follow the instruction on that page." }
   14.13 +          end } 
   14.14 +        end }
   14.15 +      end
   14.16        ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
   14.17          ui.tag{
   14.18            content = _"I want to vote" 
   14.19 @@ -73,26 +80,17 @@
   14.20  
   14.21      else
   14.22        ui.container { attr = { class = "mdl-card__content mdl-card--border" }, content = function ()
   14.23 -        ui.tag{ content = _"You are not entitled to vote in this unit" }
   14.24          if not app.session.member_id then
   14.25 +          ui.tag{ content = _"Login to participate" }
   14.26            ui.tag{ tag = "ul", content = function()
   14.27              ui.tag{ tag = "li", content = function()
   14.28                ui.link{ module = "index", view = "login", content = _"Login" }
   14.29              end }
   14.30            end }
   14.31 +        else
   14.32 +          ui.tag{ content = _"You are not entitled to vote in this unit" }
   14.33          end
   14.34        end }
   14.35      end
   14.36 -    
   14.37 -    if not config.voting_only and app.session.member_id and app.session.member:has_initiative_right_for_unit_id ( unit.id ) then
   14.38 -      ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
   14.39 -        ui.tag{ content = _"I want to start a new initiative" }
   14.40 -        ui.tag{ tag = "ul", attr = { class = "ul" }, content = function ()
   14.41 -          ui.tag { tag = "li", content = _"open the appropriate subject area for your issue and follow the instruction on that page." }
   14.42 -        end } 
   14.43 -      end }
   14.44 -    end
   14.45 -   
   14.46    end }
   14.47 -  
   14.48  end }
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/env/format/text_with_links.lua	Thu Sep 30 10:04:55 2021 +0200
    15.3 @@ -0,0 +1,8 @@
    15.4 +function format.text_with_links(value)
    15.5 +  value = encode.html(value)
    15.6 +  value = encode.html_newlines(value)
    15.7 +  value = string.gsub(value, "http[^%s:]*://[^%s]+", function(match)
    15.8 +    return "<a href=\"" .. match .. "\">" .. match .. "</a>"
    15.9 +  end)
   15.10 +  return value
   15.11 +end
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/locale/translations.en-city.lua	Thu Sep 30 10:04:55 2021 +0200
    16.3 @@ -0,0 +1,47 @@
    16.4 +#!/usr/bin/env lua
    16.5 +local translations = loadcached(encode.file_path(WEBMCP_BASE_PATH, "locale", "translations.en.lua"))()
    16.6 +
    16.7 +local additional_translations = {
    16.8 +["Abandon unit and area delegations for this issue"] = "Abandon city and subject area delegations for this issue";
    16.9 +["Abandon unit delegation"] = "Abandon city delegation";
   16.10 +["Abandon unit delegation for this area"] = "Abandon city delegation for this subject area";
   16.11 +["All units"] = "All cities";
   16.12 +["Apply unit delegation for this area (Currently: #{delegate_name} [#{scope}])"] = "Apply city delegation for this subject area (Currently: #{delegate_name} [#{scope}])";
   16.13 +["Apply unit or area delegation for this issue (Currently: #{delegate_name} [#{scope}])"] = "Apply city or subject area delegation for this issue (Currently: #{delegate_name} [#{scope}])";
   16.14 +["Create new unit"] = "Create new city";
   16.15 +["Current unit and area delegations need confirmation"] = "Current city and subject area delegations need confirmation";
   16.16 +["Delegate unit"] = "Delegate city";
   16.17 +["I want to delegate this organizational unit"] = "I want to delegate this city";
   16.18 +["I want to take a look at other organizational units"] = "I want to take a look at other cities";
   16.19 +["Minimum number of supporters relative to the number of active participants in the organizational unit."] = "Minimum number of supporters relative to the number of active participants in the city.";
   16.20 +["New organizational unit"] = "New organizational city";
   16.21 +["Organizational unit"] = "City";
   16.22 +["Organizational units"] = "Cities";
   16.23 +["Organizational units and subject areas"] = "Cities and subject areas";
   16.24 +["Parent unit"] = "Parent city";
   16.25 +["Select unit first"] = "Select city first";
   16.26 +["Set unit delegation"] = "Set city delegation";
   16.27 +["Trustee has no voting right in this unit"] = "Trustee has no voting right in this city";
   16.28 +["Unit"] = "City";
   16.29 +["Unit delegation"] = "City delegation";
   16.30 +["Unit list"] = "City list";
   16.31 +["You are not entitled to vote in this unit"] = "You are not entitled to vote in this city";
   16.32 +["You delegated this organizational unit"] = "You delegated this city";
   16.33 +["You delegated this unit"] = "You delegated this city";
   16.34 +["[event mail]      Unit: #{name}"] = "      City: #{name}";
   16.35 +["[introduction] organizational units"] = "To allow discussions and decisions by sub groups of participants (e.g. by the members of a subdivision of an organization), participants can be assigned to different units. Every organizational unit can have its own subject areas.";
   16.36 +["[introduction] vote delegation"] = "Delegations allow for a dynamic division of labor. A delegation is a proxy statement (voting power under a power of attorney), can be altered at any time, is not bound to directives and can be delegated onward. Delegations can be used for a whole organizational unit, for a subject area within an organizational unit, or for a specific issue. More specific delegations overrule more general delegations. Delegations are used in both the discourse (phase 1 to 3) and the voting phase. Any activity suspends existing delegations for the given activity.";
   16.37 +["change/revoke delegation of organizational unit"] = "change/revoke delegation of city";
   16.38 +["in my units"] = "in my cities";
   16.39 +["new unit created"] = "new city created";
   16.40 +["open the organizational unit, subject area or issue you like to delegate and follow the instruction on that page."] = "open the city, subject area or issue you want to delegate and follow the instruction on that page.";
   16.41 +["show all units"] = "Show all cities";
   16.42 +["unit"] = "city";
   16.43 +["unit updated"] = "city updated";
   16.44 +["update unit"] = "update city";
   16.45 +}
   16.46 +
   16.47 +for k, v in pairs(additional_translations) do
   16.48 +  translations[k] = v
   16.49 +end
   16.50 +return translations;
    17.1 --- a/locale/translations.en.lua	Thu Sep 30 10:04:31 2021 +0200
    17.2 +++ b/locale/translations.en.lua	Thu Sep 30 10:04:55 2021 +0200
    17.3 @@ -882,7 +882,7 @@
    17.4  ["by"] = false;
    17.5  ["by A-Z"] = false;
    17.6  ["by Z-A"] = false;
    17.7 -["by default only those issues are shown, for which your are eligible to participate (change filters on top of the list)"] = false;
    17.8 +["by default only those issues are shown, for which your are eligible to participate (change filters on top of the list)"] = "by default only those issues which you are eligible to participate are shown (change filters on top of the list)";
    17.9  ["by latest activity"] = false;
   17.10  ["cancel"] = false;
   17.11  ["cancel issue"] = false;
   17.12 @@ -1013,8 +1013,8 @@
   17.13  ["notifications settings"] = "notification settings";
   17.14  ["oldest first"] = false;
   17.15  ["one step back"] = false;
   17.16 -["open the appropriate subject area for your issue and follow the instruction on that page."] = false;
   17.17 -["open the organizational unit, subject area or issue you like to delegate and follow the instruction on that page."] = false;
   17.18 +["open the appropriate subject area for your issue and follow the instruction on that page."] = "open the appropriate subject area for your issue and follow the instructions on that page.";
   17.19 +["open the organizational unit, subject area or issue you like to delegate and follow the instruction on that page."] = "open the organizational unit, subject area or issue you want to delegate and follow the instruction on that page.";
   17.20  ["opened a new issue"] = false;
   17.21  ["ordered by delegation count"] = false;
   17.22  ["other reasons (#{count})"] = false;
   17.23 @@ -1065,14 +1065,14 @@
   17.24  ["start an initiative in a new issue"] = "start a new issue";
   17.25  ["structured discussion"] = "Structured discussion";
   17.26  ["subscribe for update emails about this area"] = false;
   17.27 -["subscribe subject areas or add your interested to issues and you will be notified about changes (follow the instruction on the area or issue page)"] = false;
   17.28 +["subscribe subject areas or add your interested to issues and you will be notified about changes (follow the instruction on the area or issue page)"] = "subscribe to subject areas or add your interest to issues and you will be notified about changes (follow the instruction on the area or issue page)";
   17.29  ["supporter"] = false;
   17.30  ["supporter with restricting suggestions"] = false;
   17.31  ["switch to: #{member_name}"] = false;
   17.32  ["take a look at the competing initiatives"] = false;
   17.33  ["take a look at the suggestions (see right) and rate them"] = false;
   17.34  ["take a look at the suggestions of your supporters"] = false;
   17.35 -["take a look on the issues (see right)"] = false;
   17.36 +["take a look on the issues (see right)"] = "take a look at the issues (see right)";
   17.37  ["the following login is connected to this email address:\n\n"] = false;
   17.38  ["this issue is in verification phase, therefore the initiative text cannot be updated anymore"] = false;
   17.39  ["this issue is in voting phase, therefore the initiative text cannot be updated anymore"] = false;
    18.1 --- a/static/lf4.css	Thu Sep 30 10:04:31 2021 +0200
    18.2 +++ b/static/lf4.css	Thu Sep 30 10:04:55 2021 +0200
    18.3 @@ -123,6 +123,10 @@
    18.4    font-size: 18px;
    18.5    line-height: normal;
    18.6  }
    18.7 +.mdl-list__item .revoked .initiative_name {
    18.8 +  text-decoration: line-through;
    18.9 +}
   18.10 +
   18.11  .initiatives.mdl-list  {
   18.12    margin-top: 5px;
   18.13    margin-bottom: 5px;

Impressum / About Us