# HG changeset patch # User bsw # Date 1632989095 -7200 # Node ID 80c101b08bf91cac2db330b692f615464cd9154c # Parent 899fdfb23465aec2d6a6b156961505ea8680a007# Parent dc54e50a70b9ee0bcc24753446598af51b8dff19 merge diff -r 899fdfb23465 -r 80c101b08bf9 app/main/_filter/21_auth.lua --- a/app/main/_filter/21_auth.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/_filter/21_auth.lua Thu Sep 30 10:04:55 2021 +0200 @@ -137,14 +137,22 @@ error("array type params not implemented") end end - request.redirect{ - module = 'index', view = 'login', params = { - redirect_module = module, - redirect_view = view, - redirect_id = param.get_id(), - redirect_params = params + if config.login and config.login.method == "oauth2" then + request.redirect{ + module = "oauth2_client", + view = "redirect", + params = { provider = config.login.provider } } - } + else + request.redirect{ + module = 'index', view = 'login', params = { + redirect_module = module, + redirect_view = view, + redirect_id = param.get_id(), + redirect_params = params + } + } + end elseif auth_needed and app.session.member.locked then trace.debug("Member locked.") request.redirect{ module = 'index', view = 'login' } diff -r 899fdfb23465 -r 80c101b08bf9 app/main/area/_sidebar_whatcanido.lua --- a/app/main/area/_sidebar_whatcanido.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/area/_sidebar_whatcanido.lua Thu Sep 30 10:04:55 2021 +0200 @@ -84,19 +84,6 @@ end } end - if app.session.member:has_voting_right_for_unit_id ( area.unit_id ) then - ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() - ui.tag{ content = _"I want to vote" } - ui.tag { tag = "ul", attr = { class = "ul" }, content = function () - 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." } - end } - end } - end - - if app.session.member and not app.session.member:has_voting_right_for_unit_id(area.unit_id) then - ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = _"You are not entitled to vote in this unit" } - end - if app.session.member and app.session.member:has_voting_right_for_unit_id(area.unit_id) then if not config.disable_delegations then @@ -175,16 +162,27 @@ end } end } end - + end + if app.session.member:has_voting_right_for_unit_id ( area.unit_id ) then + ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() + ui.tag{ content = _"I want to vote" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + 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." } + end } + end } end else ui.container { attr = { class = "mdl-card__content mdl-card--border" }, content = function () - ui.tag{ content = _"You are not entitled to vote in this unit" } - ui.tag{ tag = "ul", content = function() - ui.tag{ tag = "li", content = function() - ui.link{ module = "index", view = "login", content = _"Login" } + if not app.session.member_id then + ui.tag{ content = _"Login to participate" } + ui.tag{ tag = "ul", content = function() + ui.tag{ tag = "li", content = function() + ui.link{ module = "index", view = "login", content = _"Login" } + end } end } - end } + else + ui.tag{ content = _"You are not entitled to vote in this unit" } + end end } end end } diff -r 899fdfb23465 -r 80c101b08bf9 app/main/draft/new.lua --- a/app/main/draft/new.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/draft/new.lua Thu Sep 30 10:04:55 2021 +0200 @@ -128,13 +128,14 @@ -- -------- PREVIEW if param.get("preview") and slot.get_content("error") == "" then ui.sectionRow( function() - if not issue and not initiative then + if not issue and not initiative and #area.allowed_policies > 1 then ui.container { content = policy and policy.name or "" } + slot.put("
") end if param.get("free_timing") then ui.container { content = param.get("free_timing") } + slot.put("
") end - slot.put("
") ui.field.hidden{ name = "policy_id", value = param.get("policy_id") } ui.field.hidden{ name = "name", value = param.get("name") } if config.initiative_abstract then @@ -253,14 +254,21 @@ tmp[#tmp+1] = allowed_policy end end - ui.container{ content = _"Please choose a policy for the new issue:" } - ui.field.select{ - name = "policy_id", - foreign_records = tmp, - foreign_id = "id", - foreign_name = "name", - value = param.get("policy_id", atom.integer) or area.default_policy and area.default_policy.id - } + if #area.allowed_policies > 1 then + ui.container{ content = _"Please choose a policy for the new issue:" } + ui.field.select{ + name = "policy_id", + foreign_records = tmp, + foreign_id = "id", + foreign_name = "name", + value = param.get("policy_id", atom.integer) or area.default_policy and area.default_policy.id + } + else + ui.field.hidden{ + name = "policy_id", + value = area.allowed_policies[1].id + } + end if policy and policy.free_timeable then local available_timings if config.free_timing and config.free_timing.available_func then diff -r 899fdfb23465 -r 80c101b08bf9 app/main/help/introduction.lua --- a/app/main/help/introduction.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/help/introduction.lua Thu Sep 30 10:04:55 2021 +0200 @@ -5,30 +5,39 @@ ui.container{ attr = { class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp" }, content = function() ui.container{ attr = { class = "mdl-card__title mdl-card--has-fab mdl-card--border" }, content = function () - ui.heading { attr = { class = "mdl-card__title-text" }, level = 1, content = _"Quick guide" } + ui.heading { attr = { class = "mdl-card__title-text" }, level = 1, content = function() + if config.quick_guide and config.quick_guide.title then + slot.put(config.quick_guide.title) + else + ui.tag{ content = _"Quick guide" } + end + end } end } ui.container { attr = { class = "draft mdl-card__content mdl-card--border" }, content = function() - ui.heading{ level = 2, content = _"Initiatives and issues" } - ui.tag{ tag = "p", content = _"[introduction] iniatives and issues" } - ui.heading{ level = 2, content = _"Subject areas" } - ui.tag{ tag = "p", content = _"[introduction] subject areas" } - ui.heading{ level = 2, content = _"Organizational units" } - ui.tag{ tag = "p", content = _"[introduction] organizational units" } - ui.heading{ level = 2, content = _"Rules of procedure" } - ui.tag{ tag = "p", content = _"[introduction] rules of procedure" } - ui.heading{ level = 2, content = _"Admission phase" } - ui.tag{ tag = "p", content = _"[introduction] phase 1 admission" } - ui.heading{ level = 2, content = _"Discussion phase" } - ui.tag{ tag = "p", content = _"[introduction] phase 2 discussion" } - ui.heading{ level = 2, content = _"Verification phase" } - ui.tag{ tag = "p", content = _"[introduction] phase 3 verification" } - ui.heading{ level = 2, content = _"Voting phase" } - ui.tag{ tag = "p", content = _"[introduction] phase 4 voting" } - ui.heading{ level = 2, content = _"Vote delegation" } - ui.tag{ tag = "p", content = _"[introduction] vote delegation" } - ui.heading{ level = 2, content = _"Preference voting" } - ui.tag{ tag = "p", content = _"[introduction] preference voting" } - + if config.quick_guide and config.quick_guide.content then + slot.put(config.quick_guide.content) + else + ui.heading{ level = 2, content = _"Initiatives and issues" } + ui.tag{ tag = "p", content = _"[introduction] iniatives and issues" } + ui.heading{ level = 2, content = _"Subject areas" } + ui.tag{ tag = "p", content = _"[introduction] subject areas" } + ui.heading{ level = 2, content = _"Organizational units" } + ui.tag{ tag = "p", content = _"[introduction] organizational units" } + ui.heading{ level = 2, content = _"Rules of procedure" } + ui.tag{ tag = "p", content = _"[introduction] rules of procedure" } + ui.heading{ level = 2, content = _"Admission phase" } + ui.tag{ tag = "p", content = _"[introduction] phase 1 admission" } + ui.heading{ level = 2, content = _"Discussion phase" } + ui.tag{ tag = "p", content = _"[introduction] phase 2 discussion" } + ui.heading{ level = 2, content = _"Verification phase" } + ui.tag{ tag = "p", content = _"[introduction] phase 3 verification" } + ui.heading{ level = 2, content = _"Voting phase" } + ui.tag{ tag = "p", content = _"[introduction] phase 4 voting" } + ui.heading{ level = 2, content = _"Vote delegation" } + ui.tag{ tag = "p", content = _"[introduction] vote delegation" } + ui.heading{ level = 2, content = _"Preference voting" } + ui.tag{ tag = "p", content = _"[introduction] preference voting" } + end end } end } end } diff -r 899fdfb23465 -r 80c101b08bf9 app/main/index/_head.lua --- a/app/main/index/_head.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/index/_head.lua Thu Sep 30 10:04:55 2021 +0200 @@ -28,13 +28,17 @@ ui.container{ attr = { class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp" }, content = function() ui.container{ attr = { class = "mdl-card__title mdl-card--border" }, content = function() ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = unit.name } - if unit.description and #(unit.description) > 0 then - ui.container{ attr = { class = "mdl-card__subtitle-text" }, content = unit.description } - end - if config.render_external_reference_unit then + end } + if unit.description and #(unit.description) > 0 then + ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() + slot.put(format.text_with_links(unit.description)) + end } + end + if config.render_external_reference_unit then + ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() config.render_external_reference_unit(unit) - end - end } + end } + end if not (config.voting_only and config.disable_delegations) and app.session.member_id and ( @@ -80,10 +84,12 @@ if unit then ui.container{ attr = { class = "mdl-card__title mdl-card--border" }, content = function() ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = area.name } - if area.description and #(area.description) > 0 then - ui.container{ attr = { class = "mdl-card__subtitle-text" }, content = area.description } - end end } + if area.description and #(area.description) > 0 then + ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() + slot.put(format.text_with_links(area.description)) + end } + end end if not (config.voting_only and config.disable_delegations) and app.session.member_id and ( app.session.member:has_voting_right_for_unit_id(area.unit_id) diff -r 899fdfb23465 -r 80c101b08bf9 app/main/index/_sidebar_motd_intern_top.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/index/_sidebar_motd_intern_top.lua Thu Sep 30 10:04:55 2021 +0200 @@ -0,0 +1,12 @@ +if app.session.member and config.motd_intern_top then + ui.container{ attr = { class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp" }, content = function() + ui.container{ attr = { class = "mdl-card__content" }, content = function() + ui.container{ + attr = { class = "motd" }, + content = function() + slot.put(config.motd_intern_top) + end + } + end } + end } +end diff -r 899fdfb23465 -r 80c101b08bf9 app/main/index/_sidebar_whatcanido.lua --- a/app/main/index/_sidebar_whatcanido.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/index/_sidebar_whatcanido.lua Thu Sep 30 10:04:55 2021 +0200 @@ -30,6 +30,14 @@ end end } end } + if not config.voting_only and app.session.member.has_initiative_right then + ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() + ui.tag{ content = _"I want to start a new initiative" } + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = _"open the appropriate subject area for your issue and follow the instruction on that page." } + end } + end } + end if app.session.member.has_voting_right then ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() ui.tag{ content = _"I want to vote" } @@ -46,15 +54,7 @@ end } end end - if not config.voting_only and app.session.member.has_initiative_right then - ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() - ui.tag{ content = _"I want to start a new initiative" } - ui.tag { tag = "ul", attr = { class = "ul" }, content = function () - ui.tag { tag = "li", content = _"open the appropriate subject area for your issue and follow the instruction on that page." } - end } - end } - end - if not config.single_unit_id then + if not config.single_unit_id and not config.do_not_show_other_units_link then ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() ui.tag{ content = _"I want to take a look at other organizational units" } ui.tag { tag = "ul", attr = { class = "ul" }, content = function () @@ -94,22 +94,26 @@ if not config.voting_only then ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() ui.tag{ content = _"I want to learn more about LiquidFeedback" } - ui.tag { tag = "ul", attr = { class = "ul" }, content = function () - ui.tag { tag = "li", content = function() - ui.link { module = "help", view = "introduction", content = _"structured discussion" } - end } - ui.tag { tag = "li", content = function() - ui.link { module = "help", view = "introduction", content = _"4 phases of a decision" } - end } - if not config.disable_delegations then + if config.quick_guide and config.quick_guide.links then + ui.container{ content = config.quick_guide.links } + else + ui.tag { tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = function() + ui.link { module = "help", view = "introduction", content = _"structured discussion" } + end } ui.tag { tag = "li", content = function() - ui.link { module = "help", view = "introduction", content = _"vote delegation" } + ui.link { module = "help", view = "introduction", content = _"4 phases of a decision" } end } - end - ui.tag { tag = "li", content = function() - ui.link { module = "help", view = "introduction", content = _"preference voting" } - end } - end } + if not config.disable_delegations then + ui.tag { tag = "li", content = function() + ui.link { module = "help", view = "introduction", content = _"vote delegation" } + end } + end + ui.tag { tag = "li", content = function() + ui.link { module = "help", view = "introduction", content = _"preference voting" } + end } + end } + end end } end end } diff -r 899fdfb23465 -r 80c101b08bf9 app/main/index/index.lua --- a/app/main/index/index.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/index/index.lua Thu Sep 30 10:04:55 2021 +0200 @@ -45,11 +45,17 @@ ui.cell_main{ content = function() execute.view{ module = "index", view = "_sidebar_motd_public" } + if not unit_id and not area_id then + execute.view{ module = "index", view = "_sidebar_motd_intern_top" } + end execute.view{ module = "issue", view = "_list" } end } ui.cell_sidebar{ content = function() + if not unit and not area and config.logo_startpage then + config.logo_startpage() + end execute.view{ module = "index", view = "_head" } execute.view{ module = "index", view = "_sidebar_motd" } diff -r 899fdfb23465 -r 80c101b08bf9 app/main/initiative/_suggestions.lua --- a/app/main/initiative/_suggestions.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/initiative/_suggestions.lua Thu Sep 30 10:04:55 2021 +0200 @@ -133,214 +133,226 @@ attr = { class = "section suggestions" }, content = function () - if # ( initiative.suggestions ) > 0 then - - ui.heading { - level = 1, - content = _("Suggestions for improvement (#{count})", { count = # ( initiative.suggestions ) } ) + ui.heading { + level = 1, + content = _("Suggestions for improvement (#{count})", { count = # ( initiative.suggestions ) } ) + } + + ui.container { content = _"written and rated by the supportes of this initiative to improve the proposal and its reasons" } + + if app.session.member_id and initiative.member_info.supported and not active_trustee_id then + ui.link { + attr = { + style = "margin-top: 1ex;", + class = "mdl-button mdl-js-button mdl-button--raised mdl-button--colored", + }, + module = "suggestion", view = "new", params = { + initiative_id = initiative.id + }, + content = _"write a new suggestion" } - ui.container { content = _"written and rated by the supportes of this initiative to improve the proposal and its reasons" } - slot.put("
") - - for i, suggestion in ipairs(initiative.suggestions) do - - local opinion = Opinion:by_pk(app.session.member_id, suggestion.id) + end + + slot.put("

") + + for i, suggestion in ipairs(initiative.suggestions) do + + local opinion = Opinion:by_pk(app.session.member_id, suggestion.id) - local class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp not-folded" - if suggestion.id == param.get("suggestion_id", atom.number) then - class = class .. " highlighted" - end - if member and not initiative.issue.fully_frozen and not initiative.issue.closed and initiative.member_info.supported then - class = class .. " rateable" - end + local class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp not-folded" + if suggestion.id == param.get("suggestion_id", atom.number) then + class = class .. " highlighted" + end + if member and not initiative.issue.fully_frozen and not initiative.issue.closed and initiative.member_info.supported then + class = class .. " rateable" + end + + ui.link { attr = { name = "s" .. suggestion.id }, text = "" } + ui.tag { tag = "div", attr = { class = class, id = "s" .. suggestion.id }, content = function () + ui.tag{ attr = { class = "mdl-card__title mdl-card--border" }, content = function() + ui.heading { level = 2, + attr = { class = "mdl-card__title-text" }, + content = function() + ui.tag{ content = format.string(suggestion.name, { + truncate_at = 160, truncate_suffix = true }) + } + end + } + end } + + + + ui.container{ attr = { class = "suggestion-content" }, content = function() - ui.link { attr = { name = "s" .. suggestion.id }, text = "" } - ui.tag { tag = "div", attr = { class = class, id = "s" .. suggestion.id }, content = function () - ui.tag{ attr = { class = "mdl-card__title mdl-card--border" }, content = function() - ui.heading { level = 2, - attr = { class = "mdl-card__title-text" }, - content = function() - ui.tag{ content = format.string(suggestion.name, { - truncate_at = 160, truncate_suffix = true }) + ui.container { + attr = { class = "mdl-card__content mdl-card--border suggestionInfo" }, + content = function () + + if app.session:has_access("authors_pseudonymous") then + ui.tag{ content = _"by" } + slot.put(" ") + ui.link{ + module = "member", view = "show", id = suggestion.author_id, + content = suggestion.author.name } end - } - end } + + execute.view{ + module = "suggestion", view = "_collective_rating", params = { + suggestion = suggestion + } + } - - - ui.container{ attr = { class = "suggestion-content" }, content = function() - - ui.container { - attr = { class = "mdl-card__content mdl-card--border suggestionInfo" }, - content = function () + end + } - if app.session:has_access("authors_pseudonymous") then - ui.tag{ content = _"by" } - slot.put(" ") - ui.link{ - module = "member", view = "show", id = suggestion.author_id, - content = suggestion.author.name - } - end - - execute.view{ - module = "suggestion", view = "_collective_rating", params = { - suggestion = suggestion - } + ui.container { + attr = { class = "mdl-card__content suggestion-text draft" }, + content = function () + slot.put ( suggestion:get_content( "html" ) ) + + ui.container { attr = { class = "floatx-right" }, content = function() + + ui.link { + attr = { + class = "mdl-button mdl-js-button mdl-button--icon suggestion-more", + onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.remove('folded');document.querySelector('#s" .. suggestion.id .. "').classList.add('unfolded'); return false;" + }, + content = function() + ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_more" } + end } - - end - } - ui.container { - attr = { class = "mdl-card__content suggestion-text draft" }, - content = function () - slot.put ( suggestion:get_content( "html" ) ) + ui.link { + attr = { + class = "mdl-button mdl-js-button mdl-button--icon suggestion-less", + onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.add('folded');document.querySelector('#s" .. suggestion.id .. "').classList.remove('unfolded'); return false;" + }, + content = function() + ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_less" } + end + } + --[[ + ui.link{ + attr = { class = "mdl-button" }, + content = _"Details", + module = "suggestion", view = "show", id = suggestion.id + } + --]] + end } + + end + } + + end } + + ui.container { attr = { class = "mdl-card__actions mdl-card--border" }, content = function() - ui.container { attr = { class = "floatx-right" }, content = function() - - ui.link { - attr = { - class = "mdl-button mdl-js-button mdl-button--icon suggestion-more", - onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.remove('folded');document.querySelector('#s" .. suggestion.id .. "').classList.add('unfolded'); return false;" - }, - content = function() - ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_more" } - end - } - - ui.link { - attr = { - class = "mdl-button mdl-js-button mdl-button--icon suggestion-less", - onclick = "document.querySelector('#s" .. suggestion.id .. "').classList.add('folded');document.querySelector('#s" .. suggestion.id .. "').classList.remove('unfolded'); return false;" - }, - content = function() - ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "expand_less" } - end - } - --[[ - ui.link{ - attr = { class = "mdl-button" }, - content = _"Details", - module = "suggestion", view = "show", id = suggestion.id - } - --]] - end } - + if direct_supporter then + ui.container{ attr = { class = "suggestion_rating_info" }, content = function() + ui.tag{ attr = { id = "s" .. suggestion.id .. "_rating_text" }, content = function() + local text = "" + if opinion then + if opinion.degree == 2 then + text = _"must" + elseif opinion.degree == 1 then + text = _"should" + elseif opinion.degree == 0 then + text = _"neutral" + elseif opinion.degree == -1 then + text = _"should not" + elseif opinion.degree == -2 then + text = _"must not" + end + ui.tag { content = text } + slot.put ( " " ) + if + (opinion.degree > 0 and not opinion.fulfilled) + or (opinion.degree < 0 and opinion.fulfilled) + then + ui.tag{ content = _"but" } + else + ui.tag{ content = _"and" } + end + slot.put ( " " ) + local text = "" + if opinion.fulfilled then + text = _"is implemented" + else + text = _"is not implemented" + end + ui.tag { content = text } + end + end } + local id = "s" .. suggestion.id .. "_rating_icon" + if opinion and ( + (opinion.degree > 0 and not opinion.fulfilled) + or (opinion.degree < 0 and opinion.fulfilled) + ) + then + slot.put(" ") + if math.abs(opinion.degree) > 1 then + ui.icon("warning", "red", id) + else + ui.icon("warning", nil, id) + end + elseif opinion then + slot.put(" ") + ui.icon("done", nil, id) + else + slot.put(" ") + ui.icon("blank", nil, id) + end + end } + + ui.link{ + attr = { + id = "s" .. suggestion.id .. "_rate_button", + class = "mdl-button", + onclick = "rateSuggestion(" .. suggestion.id .. ", " .. (opinion and opinion.degree or 0) .. ", " .. (opinion and (opinion.fulfilled and "true" or "false") or "null") .. ");return false;" + }, + content = function() + if opinion then + ui.tag { content = _"update rating" } + else + ui.tag { content = _"rate suggestion" } + end end } - - end } - - ui.container { attr = { class = "mdl-card__actions mdl-card--border" }, content = function() + end + + ui.link{ + attr = { class = "mdl-button" }, + content = _"Details", + module = "suggestion", view = "show", id = suggestion.id + } - if direct_supporter then - ui.container{ attr = { class = "suggestion_rating_info" }, content = function() - ui.tag{ attr = { id = "s" .. suggestion.id .. "_rating_text" }, content = function() - local text = "" - if opinion then - if opinion.degree == 2 then - text = _"must" - elseif opinion.degree == 1 then - text = _"should" - elseif opinion.degree == 0 then - text = _"neutral" - elseif opinion.degree == -1 then - text = _"should not" - elseif opinion.degree == -2 then - text = _"must not" - end - ui.tag { content = text } - slot.put ( " " ) - if - (opinion.degree > 0 and not opinion.fulfilled) - or (opinion.degree < 0 and opinion.fulfilled) - then - ui.tag{ content = _"but" } - else - ui.tag{ content = _"and" } - end - slot.put ( " " ) - local text = "" - if opinion.fulfilled then - text = _"is implemented" - else - text = _"is not implemented" - end - ui.tag { content = text } - end - end } - local id = "s" .. suggestion.id .. "_rating_icon" - if opinion and ( - (opinion.degree > 0 and not opinion.fulfilled) - or (opinion.degree < 0 and opinion.fulfilled) - ) - then - slot.put(" ") - if math.abs(opinion.degree) > 1 then - ui.icon("warning", "red", id) - else - ui.icon("warning", nil, id) - end - elseif opinion then - slot.put(" ") - ui.icon("done", nil, id) - else - slot.put(" ") - ui.icon("blank", nil, id) - end - end } - - ui.link{ - attr = { - id = "s" .. suggestion.id .. "_rate_button", - class = "mdl-button", - onclick = "rateSuggestion(" .. suggestion.id .. ", " .. (opinion and opinion.degree or 0) .. ", " .. (opinion and (opinion.fulfilled and "true" or "false") or "null") .. ");return false;" - }, - content = function() - if opinion then - ui.tag { content = _"update rating" } - else - ui.tag { content = _"rate suggestion" } - end - end - } - end - - ui.link{ - attr = { class = "mdl-button" }, - content = _"Details", - module = "suggestion", view = "show", id = suggestion.id + end } + ui.script{ script = [[ + var rateSuggestionRateText = "]] .. _"rate suggestion" .. [["; + var rateSuggestionUpdateRatingText = "]] .. _"update rating" .. [["; + var rateSuggestionDegreeTexts = { + "-2": "]] .. _"must not" .. [[", + "-1": "]] .. _"should not" .. [[", + "1": "]] .. _"should" .. [[", + "2": "]] .. _"must" .. [[" + } + var rateSuggestionAndText = "]] .. _"and" .. [["; + var rateSuggestionButText = "]] .. _"but" .. [["; + var rateSuggestionFulfilledText = "]] .. _"is implemented" .. [["; + var rateSuggestionNotFulfilledText = "]] .. _"is not implemented" .. [["; + window.addEventListener("load", function() { + var textEl = document.querySelector('#s]] .. suggestion.id .. [[ .suggestion-content'); + var height = textEl.clientHeight; + if (height > 250) { + document.querySelector('#s]] .. suggestion.id .. [[').classList.add('folded'); } + }); + ]] } + + end } - end } - ui.script{ script = [[ - var rateSuggestionRateText = "]] .. _"rate suggestion" .. [["; - var rateSuggestionUpdateRatingText = "]] .. _"update rating" .. [["; - var rateSuggestionDegreeTexts = { - "-2": "]] .. _"must not" .. [[", - "-1": "]] .. _"should not" .. [[", - "1": "]] .. _"should" .. [[", - "2": "]] .. _"must" .. [[" - } - var rateSuggestionAndText = "]] .. _"and" .. [["; - var rateSuggestionButText = "]] .. _"but" .. [["; - var rateSuggestionFulfilledText = "]] .. _"is implemented" .. [["; - var rateSuggestionNotFulfilledText = "]] .. _"is not implemented" .. [["; - window.addEventListener("load", function() { - var textEl = document.querySelector('#s]] .. suggestion.id .. [[ .suggestion-content'); - var height = textEl.clientHeight; - if (height > 250) { - document.querySelector('#s]] .. suggestion.id .. [[').classList.add('folded'); - } - }); - ]] } - - end } - - end -- for i, suggestion - - end -- if #initiative.suggestions > 0 + end -- for i, suggestion + end } diff -r 899fdfb23465 -r 80c101b08bf9 app/main/issue/_list.lua --- a/app/main/issue/_list.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/issue/_list.lua Thu Sep 30 10:04:55 2021 +0200 @@ -16,7 +16,11 @@ end if app.single_unit_id then - for_unit = Unit:by_id(app.single_unit_id) + if request.get_param{ name = "unit" } then + for_unit = Unit:by_id(request.get_param{ name = "unit" }) + else + for_unit = Unit:by_id(app.single_unit_id) + end end local selector diff -r 899fdfb23465 -r 80c101b08bf9 app/main/issue/_sidebar_whatcanido.lua --- a/app/main/issue/_sidebar_whatcanido.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/issue/_sidebar_whatcanido.lua Thu Sep 30 10:04:55 2021 +0200 @@ -603,12 +603,16 @@ if not app.session.member or not privileged_to_vote then ui.container { attr = { class = "mdl-card__content mdl-card--border" }, content = function () - ui.tag{ content = _"You are not entitled to vote in this unit" } - ui.tag{ tag = "ul", content = function() - ui.tag{ tag = "li", content = function() - ui.link{ module = "index", view = "login", content = _"Login" } + if not app.session.member_id then + ui.tag{ content = _"Login to participate" } + ui.tag{ tag = "ul", content = function() + ui.tag{ tag = "li", content = function() + ui.link{ module = "index", view = "login", content = _"Login" } + end } end } - end } + else + ui.tag{ content = _"You are not entitled to vote in this unit" } + end end } end diff -r 899fdfb23465 -r 80c101b08bf9 app/main/oauth2_client/callback.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/oauth2_client/callback.lua Thu Sep 30 10:04:55 2021 +0200 @@ -0,0 +1,88 @@ +local provider = param.get("provider") +local provider_config = config.oauth2_providers[provider] +if not provider_config then + return +end + + +local error = param.get("error") + +if error then + ui.heading{ content = "OAuth error" } + ui.container{ content = error } + return +end + +local state = param.get("state") + +if state ~= app.session:additional_secret_for("oauth") then + ui.heading{ content = "OAuth error" } + ui.container{ content = "state invalid" } + return +end + +local code = param.get("code") + +local params = { + code = code, + client_id = provider_config.client_id, + client_secret = provider_config.client_secret, + redirect_uri = request.get_absolute_baseurl() .. "oauth2_client/callback.html?provider=" .. provider, + grant_type = "authorization_code" +} + +local params_list = {} +for key, val in pairs(params) do + table.insert(params_list, encode.url_part(key) .. "=" .. encode.url_part(val)) +end + +local r = table.concat(params_list, "&") + +local output, err, status = extos.pfilter(nil, "curl", "-X", "POST", "-d", r, provider_config.token_url) + +local result = json.import(output) + +local url = provider_config.id_url .. "?access_token=" .. encode.url_part(result.access_token) + +local output, err, status = extos.pfilter(nil, "curl", url) + +local id_result = json.import(output) + +local id = id_result[provider_config.id_field] +local email = id_result[provider_config.email_field] + +if id then + local member = Member:new_selector() + :add_where{ "authority = ?", "oauth2_" .. provider } + :add_where{ "authority_uid = ?", id } + :optional_object_mode() + :exec() + + if not member then + member = Member:new() + member.authority = "oauth2_" .. provider + member.authority_uid = id + member.notify_email = email + member.name = "Member " .. id + member.identification = "Member " .. id + member.activated = "now" + member:save() + for i, unit_id in ipairs(provider_config.unit_ids) do + local privilege = Privilege:new() + privilege.member_id = member.id + privilege.unit_id = unit_id + privilege.initiative_right = true + privilege.voting_right = true + privilege:save() + end + end + member.last_login = "now" + member.last_activity = "now" + member.active = true + member:save() + app.session.member = member + app.session:save() + request.redirect{ external = request.get_absolute_baseurl() } + +end + diff -r 899fdfb23465 -r 80c101b08bf9 app/main/oauth2_client/redirect.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/oauth2_client/redirect.lua Thu Sep 30 10:04:55 2021 +0200 @@ -0,0 +1,29 @@ +local provider = param.get("provider") +local provider_config = config.oauth2_providers[provider] +if not provider_config then + return +end + +local params = { + response_type = "code", + redirect_uri = request.get_absolute_baseurl() .. "oauth2_client/callback.html?provider=" .. provider, + client_id = provider_config.client_id, + --scope = provider_config.scope, + state = app.session:additional_secret_for("oauth"), +} + +if provider_config.additional_auth_params then + for key, val in pairs(provider_config.additional_auth_params) do + params[key] = val + end +end + +local params_list = {} +for key, val in pairs(params) do + table.insert(params_list, encode.url_part(key) .. "=" .. encode.url_part(val)) +end + +local url = provider_config.auth_url .. "?" .. table.concat(params_list, "&") + +request.redirect{ external = url } + diff -r 899fdfb23465 -r 80c101b08bf9 app/main/unit/_sidebar_whatcanido.lua --- a/app/main/unit/_sidebar_whatcanido.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/app/main/unit/_sidebar_whatcanido.lua Thu Sep 30 10:04:55 2021 +0200 @@ -61,7 +61,14 @@ end end } end - + if not config.voting_only and app.session.member_id and app.session.member:has_initiative_right_for_unit_id ( unit.id ) then + ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() + ui.tag{ content = _"I want to start a new initiative" } + ui.tag{ tag = "ul", attr = { class = "ul" }, content = function () + ui.tag { tag = "li", content = _"open the appropriate subject area for your issue and follow the instruction on that page." } + end } + end } + end ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() ui.tag{ content = _"I want to vote" @@ -73,26 +80,17 @@ else ui.container { attr = { class = "mdl-card__content mdl-card--border" }, content = function () - ui.tag{ content = _"You are not entitled to vote in this unit" } if not app.session.member_id then + ui.tag{ content = _"Login to participate" } ui.tag{ tag = "ul", content = function() ui.tag{ tag = "li", content = function() ui.link{ module = "index", view = "login", content = _"Login" } end } end } + else + ui.tag{ content = _"You are not entitled to vote in this unit" } end end } end - - if not config.voting_only and app.session.member_id and app.session.member:has_initiative_right_for_unit_id ( unit.id ) then - ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function() - ui.tag{ content = _"I want to start a new initiative" } - ui.tag{ tag = "ul", attr = { class = "ul" }, content = function () - ui.tag { tag = "li", content = _"open the appropriate subject area for your issue and follow the instruction on that page." } - end } - end } - end - end } - end } diff -r 899fdfb23465 -r 80c101b08bf9 env/format/text_with_links.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/format/text_with_links.lua Thu Sep 30 10:04:55 2021 +0200 @@ -0,0 +1,8 @@ +function format.text_with_links(value) + value = encode.html(value) + value = encode.html_newlines(value) + value = string.gsub(value, "http[^%s:]*://[^%s]+", function(match) + return "" .. match .. "" + end) + return value +end diff -r 899fdfb23465 -r 80c101b08bf9 locale/translations.en-city.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/locale/translations.en-city.lua Thu Sep 30 10:04:55 2021 +0200 @@ -0,0 +1,47 @@ +#!/usr/bin/env lua +local translations = loadcached(encode.file_path(WEBMCP_BASE_PATH, "locale", "translations.en.lua"))() + +local additional_translations = { +["Abandon unit and area delegations for this issue"] = "Abandon city and subject area delegations for this issue"; +["Abandon unit delegation"] = "Abandon city delegation"; +["Abandon unit delegation for this area"] = "Abandon city delegation for this subject area"; +["All units"] = "All cities"; +["Apply unit delegation for this area (Currently: #{delegate_name} [#{scope}])"] = "Apply city delegation for this subject area (Currently: #{delegate_name} [#{scope}])"; +["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}])"; +["Create new unit"] = "Create new city"; +["Current unit and area delegations need confirmation"] = "Current city and subject area delegations need confirmation"; +["Delegate unit"] = "Delegate city"; +["I want to delegate this organizational unit"] = "I want to delegate this city"; +["I want to take a look at other organizational units"] = "I want to take a look at other cities"; +["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."; +["New organizational unit"] = "New organizational city"; +["Organizational unit"] = "City"; +["Organizational units"] = "Cities"; +["Organizational units and subject areas"] = "Cities and subject areas"; +["Parent unit"] = "Parent city"; +["Select unit first"] = "Select city first"; +["Set unit delegation"] = "Set city delegation"; +["Trustee has no voting right in this unit"] = "Trustee has no voting right in this city"; +["Unit"] = "City"; +["Unit delegation"] = "City delegation"; +["Unit list"] = "City list"; +["You are not entitled to vote in this unit"] = "You are not entitled to vote in this city"; +["You delegated this organizational unit"] = "You delegated this city"; +["You delegated this unit"] = "You delegated this city"; +["[event mail] Unit: #{name}"] = " City: #{name}"; +["[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."; +["[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."; +["change/revoke delegation of organizational unit"] = "change/revoke delegation of city"; +["in my units"] = "in my cities"; +["new unit created"] = "new city created"; +["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."; +["show all units"] = "Show all cities"; +["unit"] = "city"; +["unit updated"] = "city updated"; +["update unit"] = "update city"; +} + +for k, v in pairs(additional_translations) do + translations[k] = v +end +return translations; diff -r 899fdfb23465 -r 80c101b08bf9 locale/translations.en.lua --- a/locale/translations.en.lua Thu Sep 30 10:04:31 2021 +0200 +++ b/locale/translations.en.lua Thu Sep 30 10:04:55 2021 +0200 @@ -882,7 +882,7 @@ ["by"] = false; ["by A-Z"] = false; ["by Z-A"] = false; -["by default only those issues are shown, for which your are eligible to participate (change filters on top of the list)"] = false; +["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)"; ["by latest activity"] = false; ["cancel"] = false; ["cancel issue"] = false; @@ -1013,8 +1013,8 @@ ["notifications settings"] = "notification settings"; ["oldest first"] = false; ["one step back"] = false; -["open the appropriate subject area for your issue and follow the instruction on that page."] = false; -["open the organizational unit, subject area or issue you like to delegate and follow the instruction on that page."] = false; +["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."; +["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."; ["opened a new issue"] = false; ["ordered by delegation count"] = false; ["other reasons (#{count})"] = false; @@ -1065,14 +1065,14 @@ ["start an initiative in a new issue"] = "start a new issue"; ["structured discussion"] = "Structured discussion"; ["subscribe for update emails about this area"] = false; -["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; +["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)"; ["supporter"] = false; ["supporter with restricting suggestions"] = false; ["switch to: #{member_name}"] = false; ["take a look at the competing initiatives"] = false; ["take a look at the suggestions (see right) and rate them"] = false; ["take a look at the suggestions of your supporters"] = false; -["take a look on the issues (see right)"] = false; +["take a look on the issues (see right)"] = "take a look at the issues (see right)"; ["the following login is connected to this email address:\n\n"] = false; ["this issue is in verification phase, therefore the initiative text cannot be updated anymore"] = false; ["this issue is in voting phase, therefore the initiative text cannot be updated anymore"] = false; diff -r 899fdfb23465 -r 80c101b08bf9 static/lf4.css --- a/static/lf4.css Thu Sep 30 10:04:31 2021 +0200 +++ b/static/lf4.css Thu Sep 30 10:04:55 2021 +0200 @@ -123,6 +123,10 @@ font-size: 18px; line-height: normal; } +.mdl-list__item .revoked .initiative_name { + text-decoration: line-through; +} + .initiatives.mdl-list { margin-top: 5px; margin-bottom: 5px;