# HG changeset patch # User bsw # Date 1259578800 -3600 # Node ID 768faea1096db7ad6f07873029c59069ce4b256d # Parent 5c601807d39719860b6db47869204e52dfed4ffd Version alpha4 Members interested in an issue or supporting an initiative have a weight information attached. Browsing the members causing that weight is possible. Initiatives may provide a link to an external discussion platform Direct link on every initiative page to create an alternative initiative Bugfix: No error when clicking "neutral", when "neutral" is currently selected diff -r 5c601807d397 -r 768faea1096d app/main/_filter/20_session.lua --- a/app/main/_filter/20_session.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/_filter/20_session.lua Mon Nov 30 12:00:00 2009 +0100 @@ -8,6 +8,6 @@ request.set_csrf_secret(app.session.additional_secret) -locale.set{lang = app.session.lang or "en"} +locale.set{lang = app.session.lang or "de"} execute.inner() diff -r 5c601807d397 -r 768faea1096d app/main/admin/_action/member_update.lua --- a/app/main/admin/_action/member_update.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/admin/_action/member_update.lua Mon Nov 30 12:00:00 2009 +0100 @@ -12,7 +12,7 @@ member = Member:new() end -param.update(member, "login", "admin", "name", "ident_number", "active") +param.update(member, "login", "admin", "name", "active") local password = param.get("password") if password == "********" or #password == 0 then diff -r 5c601807d397 -r 768faea1096d app/main/admin/member_edit.lua --- a/app/main/admin/member_edit.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/admin/member_edit.lua Mon Nov 30 12:00:00 2009 +0100 @@ -28,7 +28,6 @@ ui.field.password{ label = _"Password", name = "password", value = (member and member.password) and "********" or "" } ui.field.boolean{ label = _"Admin?", name = "admin" } ui.field.boolean{ label = _"Active?", name = "active" } - ui.field.text{ label = _"Ident number", name = "ident_number" } ui.submit{ text = _"Save" } end } diff -r 5c601807d397 -r 768faea1096d app/main/contact/_action/add_member.lua --- a/app/main/contact/_action/add_member.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/contact/_action/add_member.lua Mon Nov 30 12:00:00 2009 +0100 @@ -21,7 +21,7 @@ contact:save() if public then - slot.put_into("notice", _"Member has been saved as public contact") +-- slot.put_into("notice", _"Member has been saved as public contact") else - slot.put_into("notice", _"Member has been saved as private contact") +-- slot.put_into("notice", _"Member has been saved as private contact") end diff -r 5c601807d397 -r 768faea1096d app/main/contact/_action/remove_member.lua --- a/app/main/contact/_action/remove_member.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/contact/_action/remove_member.lua Mon Nov 30 12:00:00 2009 +0100 @@ -4,4 +4,4 @@ local contact = Contact:by_pk(member.id, other_member.id) contact:destroy() -slot.put_into("notice", _"Member has been removed from your contacts") +--slot.put_into("notice", _"Member has been removed from your contacts") diff -r 5c601807d397 -r 768faea1096d app/main/index/_action/login.lua --- a/app/main/index/_action/login.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/index/_action/login.lua Mon Nov 30 12:00:00 2009 +0100 @@ -8,7 +8,7 @@ end) trace.debug('User authenticated') else - slot.select("notice", function() + slot.select("error", function() ui.tag{ content = _'Invalid username or password!' } end) trace.debug('User NOT authenticated') diff -r 5c601807d397 -r 768faea1096d app/main/index/login.lua --- a/app/main/index/login.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/index/login.lua Mon Nov 30 12:00:00 2009 +0100 @@ -2,7 +2,7 @@ ui.tag{ tag = 'p', - content = 'You need to be logged in, to use this system.' + content = _'You need to be logged in, to use this system.' } ui.form{ diff -r 5c601807d397 -r 768faea1096d app/main/initiative/_action/create.lua --- a/app/main/initiative/_action/create.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/initiative/_action/create.lua Mon Nov 30 12:00:00 2009 +0100 @@ -23,7 +23,8 @@ end initiative.issue_id = issue.id -param.update(initiative, "name") + +param.update(initiative, "name", "discussion_url") initiative:save() local draft = Draft:new() diff -r 5c601807d397 -r 768faea1096d app/main/initiative/_action/update.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/_action/update.lua Mon Nov 30 12:00:00 2009 +0100 @@ -0,0 +1,6 @@ +local initiative = Initiative:by_id(param.get_id()) +param.update(initiative, "discussion_url") +initiative:save() + +slot.put_into("notice", _"Initiative successfully updated") + diff -r 5c601807d397 -r 768faea1096d app/main/initiative/_list.lua --- a/app/main/initiative/_list.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/initiative/_list.lua Mon Nov 30 12:00:00 2009 +0100 @@ -55,7 +55,13 @@ columns[#columns+1] = { content = function(record) if record.issue.accepted and record.issue.closed and record.issue.ranks_available then - ui.field.rank{ value = record.rank } + ui.field.rank{ attr = { class = "rank" }, value = record.rank } + end + end + } + columns[#columns+1] = { + content = function(record) + if record.issue.accepted and record.issue.closed and record.issue.ranks_available then if record.negative_votes and record.positive_votes then local max_value = record.issue.voter_count ui.bargraph{ diff -r 5c601807d397 -r 768faea1096d app/main/initiative/edit.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/initiative/edit.lua Mon Nov 30 12:00:00 2009 +0100 @@ -0,0 +1,23 @@ +local initiative = Initiative:by_id(param.get_id()) + +slot.put_into("title", _"Edit initiative") + +ui.form{ + record = initiative, + module = "initiative", + action = "update", + id = initiative.id, + attr = { class = "vertical" }, + routing = { + default = { + mode = "redirect", + module = "initiative", + view = "show", + id = initiative.id + } + }, + content = function() + ui.field.text{ label = _"Discussion URL", name = "discussion_url" } + ui.submit{ text = _"Save" } + end +} \ No newline at end of file diff -r 5c601807d397 -r 768faea1096d app/main/initiative/new.lua --- a/app/main/initiative/new.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/initiative/new.lua Mon Nov 30 12:00:00 2009 +0100 @@ -39,6 +39,7 @@ } end ui.field.text{ label = _"Name", name = "name" } + ui.field.text{ label = _"Discussion URL", name = "discussion_url" } ui.field.text{ label = _"Draft", name = "draft", multiline = true, attr = { style = "height: 50ex;" } } ui.submit{ text = _"Save" } end diff -r 5c601807d397 -r 768faea1096d app/main/initiative/show.lua --- a/app/main/initiative/show.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/initiative/show.lua Mon Nov 30 12:00:00 2009 +0100 @@ -1,6 +1,6 @@ local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec() -slot.put_into("html_head", '') +--slot.put_into("html_head", '') execute.view{ module = "supporter", @@ -40,7 +40,9 @@ slot.select("actions", function() - if Initiator:by_pk(initiative.id, app.session.member.id) then + local initiator = Initiator:by_pk(initiative.id, app.session.member.id) + + if initiator then ui.link{ content = function() ui.image{ static = "icons/16/script_add.png" } @@ -52,8 +54,41 @@ } end - ui.twitter("http://example.com/i" .. tostring(initiative.id) .. " " .. initiative.name) + if not initiative.issue.fully_frozen and not initiative.issue.closed then + ui.link{ + attr = { class = "action" }, + content = function() + ui.image{ static = "icons/16/script_add.png" } + slot.put(_"Create alternative initiative" ) + end, + module = "initiative", + view = "new", + params = { issue_id = initiative.issue.id } + } + end +-- ui.twitter("http://example.com/i" .. tostring(initiative.id) .. " " .. initiative.name) + if initiative.discussion_url and #initiative.discussion_url > 0 then + ui.link{ + attr = { + target = _"blank", + title = initiative.discussion_url + }, + content = function() + ui.image{ static = "icons/16/comments.png" } + slot.put(_"External discussion") + end, + external = initiative.discussion_url + } + end + if initiator then + ui.link{ + content = _"(change)", + module = "initiative", + view = "edit", + id = initiative.id + } + end end) @@ -178,7 +213,18 @@ name = "supporter", label = _"Supporter", content = function() - execute.view{ module = "member", view = "_list", params = { members_selector = initiative:get_reference_selector("supporting_members") } } + execute.view{ + module = "member", + view = "_list", + params = { + initiative = initiative, + members_selector = initiative:get_reference_selector("supporting_members_snapshot") + :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id") + :join("direct_population_snapshot", nil, "direct_population_snapshot.event = issue.latest_snapshot_event AND direct_population_snapshot.issue_id = issue.id AND direct_population_snapshot.member_id = member.id") + :add_field("direct_population_snapshot.weight") + :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event") + } + } end }, { diff -r 5c601807d397 -r 768faea1096d app/main/interest/_show_box.lua --- a/app/main/interest/_show_box.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/interest/_show_box.lua Mon Nov 30 12:00:00 2009 +0100 @@ -22,6 +22,14 @@ ui.container{ attr = { class = "content", id = "interest_content" }, content = function() + ui.container{ + attr = { + class = "close", + style = "cursor: pointer;", + onclick = "document.getElementById('interest_content').style.display = 'none';" + }, + content = _"X" + } if interest then ui.link{ content = _"Remove my interest", @@ -30,6 +38,8 @@ params = { issue_id = issue.id, delete = true }, routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } } + slot.put("
") + slot.put("
") if interest.autoreject then ui.field.text{ value = _"Autoreject is on." } ui.link{ @@ -58,14 +68,6 @@ routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } } end - ui.container{ - attr = { - class = "head", - style = "cursor: pointer;", - onclick = "document.getElementById('interest_content').style.display = 'none';" - }, - content = _"Click here to close." - } end } end) diff -r 5c601807d397 -r 768faea1096d app/main/interest/show_incoming.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/interest/show_incoming.lua Mon Nov 30 12:00:00 2009 +0100 @@ -0,0 +1,19 @@ +local issue = Issue:by_id(param.get("issue_id", atom.integer)) +local member = Member:by_id(param.get("member_id", atom.integer)) + +local members_selector = Member:new_selector() + :join("delegating_interest_snapshot", nil, "delegating_interest_snapshot.member_id = member.id") + :add_where{ "delegating_interest_snapshot.issue_id = ?", issue.id } + :add_where{ "delegating_interest_snapshot.event = ?", issue.latest_snapshot_event } + :add_where{ "delegating_interest_snapshot.delegate_member_ids[1] = ?", member.id } + :add_field{ "delegating_interest_snapshot.weight" } + +execute.view{ + module = "member", + view = "_list", + params = { + members_selector = members_selector, + issue = issue, + trustee = member + } +} \ No newline at end of file diff -r 5c601807d397 -r 768faea1096d app/main/issue/_show_box.lua --- a/app/main/issue/_show_box.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/issue/_show_box.lua Mon Nov 30 12:00:00 2009 +0100 @@ -8,14 +8,14 @@ local time_left = issue.state_time_left if time_left then ui.field.text{ - label = "Time left", + label = _"Time left", value = time_left } end local next_state_names = issue.next_states_names if next_state_names then ui.field.text{ - label = _"Next states", + label = _"Next state", value = next_state_names } end diff -r 5c601807d397 -r 768faea1096d app/main/issue/show.lua --- a/app/main/issue/show.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/issue/show.lua Mon Nov 30 12:00:00 2009 +0100 @@ -61,7 +61,7 @@ } } slot.put("
") - if not issue.frozen and not issue.closed then + if not issue.fully_frozen and not issue.closed then ui.link{ attr = { class = "action" }, content = function() @@ -88,6 +88,23 @@ }, --]] { + name = "interested_members", + label = _"Interested members", + content = function() + execute.view{ + module = "member", + view = "_list", + params = { + issue = issue, + members_selector = issue:get_reference_selector("interested_members_snapshot") + :join("issue", nil, "issue.id = direct_interest_snapshot.issue_id") + :add_field("direct_interest_snapshot.weight") + :add_where("direct_interest_snapshot.event = issue.latest_snapshot_event") + } + } + end + }, + { name = "delegations", label = _"Delegations", content = function() @@ -110,19 +127,23 @@ content = function() ui.field.text{ label = _"State", name = "state" } ui.field.timestamp{ label = _"Created at", name = "created" } - ui.field.text{ label = _"admission_time", value = policy.admission_time } - ui.field.integer{ label = _"issue_quorum_num", value = policy.issue_quorum_num } - ui.field.integer{ label = _"issue_quorum_den", value = policy.issue_quorum_den } - ui.field.timestamp{ label = _"Accepted", name = "accepted" } - ui.field.text{ label = _"discussion_time", value = policy.discussion_time } + ui.field.text{ label = _"Admission time", value = policy.admission_time } + ui.field.text{ + label = _"Issue quorum", + value = format.percentage(policy.issue_quorum_num / policy.issue_quorum_den) + } + ui.field.timestamp{ label = _"Accepted at", name = "accepted" } + ui.field.text{ label = _"Discussion time", value = policy.discussion_time } ui.field.vote_now{ label = _"Vote now", name = "vote_now" } ui.field.vote_later{ label = _"Vote later", name = "vote_later" } - ui.field.timestamp{ label = _"Half frozen", name = "half_frozen" } - ui.field.text{ label = _"verification_time", value = policy.verification_time } - ui.field.integer{ label = _"initiative_quorum_num", value = policy.initiative_quorum_num } - ui.field.integer{ label = _"initiative_quorum_den", value = policy.initiative_quorum_den } - ui.field.timestamp{ label = _"Fully frozen", name = "fully_frozen" } - ui.field.text{ label = _"voting_time", value = policy.voting_time } + ui.field.timestamp{ label = _"Half frozen at", name = "half_frozen" } + ui.field.text{ label = _"Verification time", value = policy.verification_time } + ui.field.text{ + label = _"Initiative quorum", + value = format.percentage(policy.initiative_quorum_num / policy.initiative_quorum_den) + } + ui.field.timestamp{ label = _"Fully frozen at", name = "fully_frozen" } + ui.field.text{ label = _"Voting time", value = policy.voting_time } ui.field.timestamp{ label = _"Closed", name = "closed" } end } diff -r 5c601807d397 -r 768faea1096d app/main/member/_action/update_avatar.lua --- a/app/main/member/_action/update_avatar.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/member/_action/update_avatar.lua Mon Nov 30 12:00:00 2009 +0100 @@ -16,7 +16,7 @@ local data = param.get("avatar") -local data_scaled, err, status = os.pfilter(data, "convert", "-", "-thumbnail", "48x48", "-") +local data_scaled, err, status = os.pfilter(data, "convert", "-", "-thumbnail", "48x48", "jpeg:-") if status ~= 0 or data_scaled == nil then error("error while converting image") diff -r 5c601807d397 -r 768faea1096d app/main/member/_list.lua --- a/app/main/member/_list.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/member/_list.lua Mon Nov 30 12:00:00 2009 +0100 @@ -1,20 +1,33 @@ local members_selector = param.get("members_selector", "table") +local initiative = param.get("initiative", "table") +local issue = param.get("issue", "table") +local trustee = param.get("trustee", "table") + +local options = { + { + name = "name", + label = _"A-Z", + order_by = "name" + }, + { + name = "name_desc", + label = _"Z-A", + order_by = "name DESC" + }, +} + +if initiative then + options[#options+1] = { + name = "delegations", + label = _"Delegations", + order_by = "weight DESC" + } +end ui.order{ name = "member_list", selector = members_selector, - options = { - { - name = "name", - label = _"A-Z", - order_by = "name" - }, - { - name = "name_desc", - label = _"Z-A", - order_by = "name DESC" - }, - }, + options = options, content = function() ui.paginate{ selector = members_selector, @@ -23,16 +36,100 @@ ui.container{ attr = { class = "member_list" }, content = function() - for i, member in ipairs(members_selector:exec()) do + local members = members_selector:exec() + local columns = { + { + label = _"Name", + content = function(member) + ui.link{ + module = "member", + view = "show", + id = member.id, + content = function() + ui.image{ + attr = { width = 48, height = 48 }, + module = "member", + view = "avatar", + id = member.id, + extension = "jpg" + } + end + } + end + }, + { + label = _"Name", + content = function(member) + ui.link{ + module = "member", + view = "show", + id = member.id, + content = member.name + } + if member.admin then + ui.image{ + attr = { + alt = _"Administrator", + title = _"Administrator" + }, + static = "icons/16/cog.png" + } + end + -- TODO performance + local contact = Contact:by_pk(app.session.member.id, member.id) + if contact then + ui.image{ + attr = { + alt = _"Saved as contact", + title = _"Saved as contact" + }, + static = "icons/16/book_edit.png" + } + end + end + } + } + + if initiative then + columns[#columns+1] = { + label = _"Delegations", + field_attr = { style = "text-align: right;" }, + content = function(member) + if member.weight > 1 then + ui.link{ + content = member.weight, + module = "support", + view = "show_incoming", + params = { member_id = member.id, initiative_id = initiative.id } + } + end + end + } + end + +--[[ ui.list{ + records = members, + columns = columns + } +--]] +---[[ + for i, member in ipairs(members) do execute.view{ module = "member", view = "_show_thumb", - params = { member = member } + params = { member = member, initiative = initiative, issue = issue, trustee = trustee } } end +---]] end } - slot.put('
') + slot.put('
') + if issue then + ui.field.timestamp{ label = _"Last snapshot:", value = issue.snapshot } + end + if initiative then + ui.field.timestamp{ label = _"Last snapshot:", value = initiative.issue.snapshot } + end end } end diff -r 5c601807d397 -r 768faea1096d app/main/member/_show.lua --- a/app/main/member/_show.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/member/_show.lua Mon Nov 30 12:00:00 2009 +0100 @@ -5,8 +5,12 @@ record = member, readonly = true, content = function() - ui.field.boolean{ label = _"Admin?", name = "admin" } - ui.field.boolean{ label = _"Locked?", name = "locked" } + if member.admin then + ui.field.boolean{ label = _"Admin?", name = "admin" } + end + if member.locked then + ui.field.boolean{ label = _"Locked?", name = "locked" } + end if member.ident_number then ui.field.text{ label = _"Ident number", name = "ident_number" } end diff -r 5c601807d397 -r 768faea1096d app/main/member/_show_thumb.lua --- a/app/main/member/_show_thumb.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/member/_show_thumb.lua Mon Nov 30 12:00:00 2009 +0100 @@ -1,5 +1,9 @@ local member = param.get("member", "table") +local issue = param.get("issue", "table") +local initiative = param.get("initiative", "table") +local trustee = param.get("trustee", "table") + local name if member.name_highlighted then name = encode.highlight(member.name_highlighted) @@ -7,19 +11,74 @@ name = encode.html(member.name) end -ui.link{ +ui.container{ attr = { class = "member_thumb" }, - module = "member", - view = "show", - id = member.id, content = function() - ui.image{ - attr = { width = 48, height = 48 }, - module = "member", - view = "avatar", - id = member.id, - extension = "jpg" + ui.container{ + attr = { class = "flags" }, + content = function() + if (issue or initiative) and member.weight > 1 then + local module + if issue then + module = "interest" + elseif initiative then + module = "supporter" + end + ui.link{ + attr = { title = _"Number of incoming delegations, follow link to see more details" }, + content = _("+ #{weight}", { weight = member.weight - 1 }), + module = module, + view = "show_incoming", + params = { + member_id = member.id, + initiative_id = initiative and initiative.id or nil, + issue_id = issue and issue.id or nil + } + } + end + if member.admin then + ui.image{ + attr = { + alt = _"Member is administrator", + title = _"Member is administrator" + }, + static = "icons/16/cog.png" + } + end + -- TODO performance + local contact = Contact:by_pk(app.session.member.id, member.id) + if contact then + ui.image{ + attr = { + alt = _"You have saved this member as contact", + title = _"You have saved this member as contact" + }, + static = "icons/16/bullet_disk.png" + } + end + end } - slot.put(name) + + ui.link{ + attr = { title = _"Show member" }, + module = "member", + view = "show", + id = member.id, + content = function() + ui.image{ + attr = { width = 48, height = 48 }, + module = "member", + view = "avatar", + id = member.id, + extension = "jpg" + } + ui.container{ + attr = { class = "member_name" }, + content = function() + slot.put(name) + end + } + end + } end -} \ No newline at end of file +} diff -r 5c601807d397 -r 768faea1096d app/main/member/show.lua --- a/app/main/member/show.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/member/show.lua Mon Nov 30 12:00:00 2009 +0100 @@ -15,17 +15,49 @@ if member.id == app.session.member.id then slot.put_into("actions", _"That's me!") else - slot.select("actions", function() - ui.link{ - content = function() - ui.image{ static = "icons/16/book_add.png" } - slot.put(encode.html(_"Add to my contacts")) - end, - module = "contact", - action = "add_member", - id = member.id - } - end) + --TODO performance + local contact = Contact:by_pk(app.session.member.id, member.id) + if contact then + slot.select("actions", function() + ui.field.text{ value = _"You have saved this member as contact." } + ui.link{ + text = _"Remove from contacts", + module = "contact", + action = "remove_member", + id = contact.other_member_id, + routing = { + default = { + mode = "redirect", + module = request.get_module(), + view = request.get_view(), + id = param.get_id_cgi(), + params = param.get_all_cgi() + } + } + } + end) + else + slot.select("actions", function() + ui.link{ + content = function() + ui.image{ static = "icons/16/book_add.png" } + slot.put(encode.html(_"Add to my contacts")) + end, + module = "contact", + action = "add_member", + id = member.id, + routing = { + default = { + mode = "redirect", + module = request.get_module(), + view = request.get_view(), + id = param.get_id_cgi(), + params = param.get_all_cgi() + } + } + } + end) + end end diff -r 5c601807d397 -r 768faea1096d app/main/opinion/_action/update.lua --- a/app/main/opinion/_action/update.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/opinion/_action/update.lua Mon Nov 30 12:00:00 2009 +0100 @@ -4,9 +4,11 @@ local opinion = Opinion:by_pk(member_id, suggestion_id) -if opinion and param.get("delete") then - opinion:destroy() - slot.put_into("notice", _"Your opinion has been updated") +if param.get("delete") then + if opinion then + opinion:destroy() + end + slot.put_into("notice", _"Your opinion has been deleted") return end diff -r 5c601807d397 -r 768faea1096d app/main/suggestion/_list.lua --- a/app/main/suggestion/_list.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/app/main/suggestion/_list.lua Mon Nov 30 12:00:00 2009 +0100 @@ -8,7 +8,7 @@ records = suggestions_selector:exec(), columns = { { - label = _"Name", + label = _"Suggestion", content = function(record) ui.link{ text = record.name, @@ -19,7 +19,8 @@ end }, { - label = _"Support", + label = _"Collective opinion", + label_attr = { style = "width: 101px;" }, content = function(record) if record.minus2_unfulfilled_count then local max_value = record.initiative.issue.population @@ -39,6 +40,7 @@ end }, { + label = _"My opinion", content = function(record) local degree local opinion = Opinion:by_pk(app.session.member.id, record.id) @@ -103,6 +105,14 @@ end }, { + content = function(record) + local opinion = Opinion:by_pk(app.session.member.id, record.id) + if opinion and not opinion.fulfilled then + ui.image{ static = "icons/16/cross.png" } + end + end + }, + { label = _"Suggestion currently not implemented", label_attr = { style = "width: 101px;" }, content = function(record) @@ -124,6 +134,14 @@ end }, { + content = function(record) + local opinion = Opinion:by_pk(app.session.member.id, record.id) + if opinion and opinion.fulfilled then + ui.image{ static = "icons/16/tick.png" } + end + end + }, + { label = _"Suggestion currently implemented", label_attr = { style = "width: 101px;" }, content = function(record) @@ -145,6 +163,7 @@ end }, { + label_attr = { style = "width: 200px;" }, content = function(record) local degree local opinion = Opinion:by_pk(app.session.member.id, record.id) @@ -153,10 +172,15 @@ end if opinion then if not opinion.fulfilled then - ui.image{ static = "icons/16/cross.png" } + local text = "" + if opinion.degree > 0 then + text = _"Mark suggestion as implemented and express satisfaction" + else + text = _"Mark suggestion as implemented and express dissatisfaction" + end ui.link{ attr = { class = "action" }, - text = _"set implented", + text = text, module = "opinion", action = "update", routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, @@ -166,10 +190,14 @@ } } else - ui.image{ static = "icons/16/tick.png" } + if opinion.degree > 0 then + text = _"Mark suggestion as not implemented and express dissatisfaction" + else + text = _"Mark suggestion as not implemented and express satisfaction" + end ui.link{ attr = { class = "action" }, - text = _"remove implemented", + text = text, module = "opinion", action = "update", routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, @@ -182,6 +210,18 @@ end end }, + { + content = function(record) + local opinion = Opinion:by_pk(app.session.member.id, record.id) + if opinion then + if (opinion.fulfilled and opinion.degree > 0) or (not opinion.fulfilled and opinion.degree < 0) then + ui.image{ static = "icons/16/thumb_up_green.png" } + else + ui.image{ static = "icons/16/thumb_down_red.png" } + end + end + end + }, } } end diff -r 5c601807d397 -r 768faea1096d app/main/supporter/show_incoming.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/main/supporter/show_incoming.lua Mon Nov 30 12:00:00 2009 +0100 @@ -0,0 +1,20 @@ +local initiative = Initiative:by_id(param.get("initiative_id", atom.integer)) +local issue = initiative.issue +local member = Member:by_id(param.get("member_id", atom.integer)) + +local members_selector = Member:new_selector() + :join("delegating_population_snapshot", nil, "delegating_population_snapshot.member_id = member.id") + :add_where{ "delegating_population_snapshot.issue_id = ?", issue.id } + :add_where{ "delegating_population_snapshot.event = ?", issue.latest_snapshot_event } + :add_where{ "delegating_population_snapshot.delegate_member_ids[1] = ?", member.id } + :add_field{ "delegating_population_snapshot.weight" } + +execute.view{ + module = "member", + view = "_list", + params = { + members_selector = members_selector, + issue = issue, + trustee = member + } +} \ No newline at end of file diff -r 5c601807d397 -r 768faea1096d config/default.lua --- a/config/default.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/config/default.lua Mon Nov 30 12:00:00 2009 +0100 @@ -1,12 +1,12 @@ config.app_name = "LiquidFeedback" -config.app_version = "alpha3" +config.app_version = "alpha4" config.app_title = config.app_name .. " (" .. request.get_config_name() .. " environment)" config.app_service_provider = "Snake Oil
10000 Berlin
Germany" config.member_image_convert = { - avatar = { "convert", "-", "-thumbnail", "48x48", "-" } + avatar = { "convert", "-", "-thumbnail", "48x48", "jpeg:-" } } -- uncomment the following two lines to use C implementations of chosen diff -r 5c601807d397 -r 768faea1096d locale/translations.de.lua --- a/locale/translations.de.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/locale/translations.de.lua Mon Nov 30 12:00:00 2009 +0100 @@ -1,5 +1,7 @@ #!/usr/bin/env lua return { +["(change)"] = "(ändern)"; +["+ #{weight}"] = false; ["A-Z"] = false; ["About"] = false; ["About LiquidFeedback"] = "Über LiquidFeedback"; @@ -15,6 +17,7 @@ ["Admin"] = "Admin"; ["Admin menu"] = "Admin Menü"; ["Admin?"] = "Admin?"; +["Administrator"] = false; ["Admitted"] = "zugelassen"; ["Any"] = "Alle"; ["Area"] = "Themenbereich"; @@ -36,10 +39,12 @@ ["Click here to close."] = "Zum Schließen hier klicken"; ["Close"] = "Schließen"; ["Closed"] = "geschlossen"; +["Collective opinion"] = "Meinungsbild"; ["Commit suggestion"] = "Anregung speichern"; ["Compare"] = "Vergleichen"; ["Contacts"] = "Kontakte"; ["Content"] = "Inhalt"; +["Create alternative initiative"] = "Alternative Initiative hinzufügen"; ["Create new area"] = "Neuen Themenbereich anlegen"; ["Create new issue"] = "Neues Thema anlegen"; ["Created at"] = "Erzeugt am/um"; @@ -52,11 +57,15 @@ ["Diff"] = false; ["Direct member count"] = "Anzahl Direktmitglieder"; ["Direct supporter [change]"] = "Direkte Unterstützung [ändern]"; +["Discussion"] = "Diskussion"; +["Discussion URL"] = "Diskussions-URL"; ["Draft"] = "Entwurf"; ["Edit"] = "Bearbeiten"; ["Edit draft"] = "Entwurf bearbeiten"; +["Edit initiative"] = "Initiative bearbeiten"; ["Edit my page"] = "Meine Seite bearbeiten"; ["Error while updating member, database reported:

(#{errormessage})"] = "Fehler beim aktualisieren des Mitglieds, die Datenbank berichtet folgenden Fehler:

(#{errormessage})"; +["External discussion"] = "Externe Diskussion"; ["External memberships"] = "Externe Mitgliedschaften"; ["External posts"] = "Externe Ämter"; ["Filter"] = false; @@ -73,12 +82,14 @@ ["In discussion"] = "In Diskussion"; ["Incoming delegations"] = "Eingehende Delegationen"; ["Initiative successfully created"] = "Initiative erfolgreich erzeugt"; +["Initiative successfully updated"] = "Initiative erfolgreich aktualisiert"; ["Initiative: '#{name}'"] = "Initiative: '#{name}'"; ["Initiatives"] = "Initiativen"; ["Initiators"] = "Initiatoren"; ["Interest not existant"] = "Interesse existiert nicht"; ["Interest removed"] = "Interesse entfernt"; ["Interest updated"] = "Interesse aktualisiert"; +["Interested members"] = "Interessierte Mitglieder"; ["Internal posts"] = "Interne Ämter"; ["Invalid username or password!"] = "Ungültiger Benutzername oder Kennwort"; ["Issue"] = "Thema"; @@ -87,6 +98,7 @@ ["Issue delegation"] = "Issue-Delegation"; ["Issue policy"] = "Regelwerk für Thema"; ["Issues"] = "Themen"; +["Last snapshot:"] = "Letzte Auszählung:"; ["License"] = "Lizenz"; ["Locked?"] = "Gesperrt?"; ["Logged in as:"] = "Angemeldet als:"; @@ -94,10 +106,15 @@ ["Login successful!"] = "Anmeldung erfolgreich"; ["Logout"] = "Abmelden"; ["Logout successful"] = "Abmeldung erfolgreich"; +["Mark suggestion as implemented and express dissatisfaction"] = "Anregung als umgesetzt markieren und Unzufriedenheit ausdrücken"; +["Mark suggestion as implemented and express satisfaction"] = "Anregung als umgesetzt markieren und Zufriedenheit ausdrücken"; +["Mark suggestion as not implemented and express dissatisfaction"] = "Anregung als nicht umgesetzt markieren und Unzufriedenheit ausdrücken"; +["Mark suggestion as not implemented and express satisfaction"] = "Anregung als nicht umgesetzt markieren und Zufriedenheit ausdrücken"; ["Member '#{member}'"] = "Mitglied '#{member}'"; ["Member has been removed from your contacts"] = "Mitglied wurde aus Deinen Kontakten entfernt"; ["Member has been saved as private contact"] = "Mitglied wurde als privater Kontakt gespeichert"; ["Member has been saved as public contact"] = "Mitglied wurde als öffentlicher Kontakt gespeichert"; +["Member is administrator"] = "Mitglied ist Administrator"; ["Member is already saved in your contacts!"] = "Mitglied ist schon in Deinen Kontakten!"; ["Member list"] = "Mitgliederliste"; ["Member login"] = "Mitglied Login"; @@ -110,6 +127,7 @@ ["Membership removed"] = "Mitgliedschaft entfernt"; ["Membership updated"] = "Mitgliedschaft aktualisiert"; ["Mobile phone"] = "Mobiltelefon"; +["My opinion"] = "Meine Meinung"; ["Name"] = "Name"; ["New"] = "Neu"; ["New draft has been added to initiative"] = "Neuer Entwurf wurde der Initiative hinzugefügt"; @@ -118,8 +136,9 @@ ["New passwords does not match."] = "Du hast nicht zweimal das gleiche Kennwort eingegeben"; ["New passwords is too short."] = "Das neue Kennwort ist zu kurz"; ["Newest"] = "Neueste"; -["Next states"] = "Nächste Statuse"; +["Next state"] = "Nächster Zustand"; ["No supporter [change]"] = "Keine Unterstützung (ändern)"; +["Number of incoming delegations, follow link to see more details"] = "Anzahl eingehender Delegationen, Link folgen für mehr Details"; ["OK"] = "OK"; ["Old draft revision"] = "Alte Revision des Entwurfs"; ["Old drafts"] = "Alte Entwürfe"; @@ -143,6 +162,7 @@ ["Register new member"] = "Neues Mitglied registrieren"; ["Remove"] = "Entfernen"; ["Remove autoreject"] = "Auto-Ablehnen abschalten"; +["Remove from contacts"] = "Aus den Kontakten entfernen"; ["Remove my interest"] = "Interesse abmelden"; ["Remove my membership"] = "Mitgliedschaft aufgeben"; ["Remove my support from this initiative"] = "Meine Unterstützung der Initiative entziehen"; @@ -150,6 +170,7 @@ ["Revoke"] = "Widerrufen"; ["Revoked at"] = "Zurückgezogen am/um"; ["Save"] = "Speichern"; +["Saved as contact"] = "Als Kontakt speichern"; ["Search"] = "Suchen"; ["Search initiatives"] = "Suche Initiativen"; ["Search issues"] = "Suche Themen"; @@ -164,9 +185,11 @@ ["Show areas not in use"] = "Zeige nicht verwendente Themenbereiche"; ["Show diff"] = "Änderungen anzeigen"; ["Show locked members"] = "Zeige gesperrte Mitglieder"; +["Show member"] = "Mitglied anzeigen"; ["Software"] = false; ["State"] = "Zustand"; ["Statement"] = false; +["Suggestion"] = "Anregung"; ["Suggestion currently implemented"] = "Anregung zur Zeit umgesetzt"; ["Suggestion currently not implemented"] = "Anregung zur Zeit nicht umgesetzt"; ["Suggestion for initiative: '#{name}'"] = "Anregung für Initiative '#{name}'"; @@ -177,6 +200,7 @@ ["Supporter"] = "Unterstützer"; ["That's me!"] = "Das bin ich"; ["The drafts do not differ"] = "Die Entwürfe unterscheiden sich nicht"; +["Time left"] = "Restzeit"; ["Trustee"] = "Bevollmächtigter"; ["Unknown author"] = "Unbekannter Autor"; ["Upload avatar"] = "Avatar hochladen"; @@ -195,12 +219,16 @@ ["You are not a member. [more]"] = "Du bist kein Mitglied. [mehr]"; ["You are not interested. [more]"] = "Du bist nicht interessiert. [mehr]"; ["You didn't saved any member as contact yet."] = "Du hast noch kein Mitglied als Kontakt gespeichert!"; +["You have saved this member as contact"] = "Du hast das Mitglied als Kontakt gespeichert"; +["You have saved this member as contact."] = "Du hast das Mitglied als Kontakt gespeichert."; +["You need to be logged in, to use this system."] = "Du musst eingeloggt sein, um das System zu benutzen"; ["Your delegation for this area has been deleted."] = "Deine Delegation für dieses Themengebiet wurde gelöscht"; ["Your delegation for this area has been updated."] = "Deine Delegation für dieses Themengebiet wurde geändert"; ["Your delegation for this issue has been deleted."] = "Deine Delegation für dieses Thema wurde gelöscht"; ["Your delegation for this issue has been updated."] = "Deine Delegation für dieses Thema wurde geändert"; ["Your global delegation has been deleted."] = "Deine globale Delegation wurde gelöscht"; ["Your global delegation has been updated."] = "Deine globale Delegation würde geändert"; +["Your opinion has been deleted"] = "Deine Meinung wurde gelöscht"; ["Your opinion has been updated"] = "Deine Meinung wurde aktualisiert"; ["Your page has been updated"] = "Deine Seite wurde aktualisiert"; ["Your password has been updated successfully"] = "Das Kennwort wurde erfolgreich geändert"; @@ -211,6 +239,7 @@ ["Your vote is delegated. [more]"] = "Deine Stimme ist delegiert. [mehr]"; ["Z-A"] = false; ["admission_time"] = false; +["blank"] = false; ["delete

"] = false; ["discussion_time"] = false; ["email"] = false; @@ -221,8 +250,6 @@ ["must"] = "muss"; ["must not"] = "darf nicht"; ["neutral"] = "neutral"; -["remove implemented"] = "entferne umgesetzt"; -["set implented"] = "setze umgesetzt"; ["should"] = "soll"; ["should not"] = "soll nicht"; ["verification_time"] = false; diff -r 5c601807d397 -r 768faea1096d model/initiative.lua --- a/model/initiative.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/model/initiative.lua Mon Nov 30 12:00:00 2009 +0100 @@ -91,6 +91,17 @@ ref = 'supporting_members' } +Initiative:add_reference{ + mode = 'mm', + to = "Member", + this_key = 'id', + that_key = 'id', + connected_by_table = 'direct_supporter_snapshot', + connected_by_this_key = 'initiative_id', + connected_by_that_key = 'member_id', + ref = 'supporting_members_snapshot' +} + function Initiative:get_search_selector(search_string) return self:new_selector() :add_field( {'"highlight"("initiative"."name", ?)', search_string }, "name_highlighted") diff -r 5c601807d397 -r 768faea1096d model/issue.lua --- a/model/issue.lua Mon Nov 23 12:00:00 2009 +0100 +++ b/model/issue.lua Mon Nov 30 12:00:00 2009 +0100 @@ -86,10 +86,21 @@ ref = 'members' } +Issue:add_reference{ + mode = 'mm', + to = "Member", + this_key = 'id', + that_key = 'id', + connected_by_table = 'direct_interest_snapshot', + connected_by_this_key = 'issue_id', + connected_by_that_key = 'member_id', + ref = 'interested_members_snapshot' +} + function Issue:get_state_name_for_state(value) local state_name_table = { new = _"New", - accepted = _"Accepted", + accepted = _"Discussion", frozen = _"Frozen", voting = _"Voting", finished = _"Finished", @@ -107,16 +118,16 @@ function Issue.object_get:state() if self.accepted then - if self.fully_frozen then - return "voting" - elseif self.half_frozen then - return "frozen" - elseif self.closed then + if self.closed then if self.ranks_available then return "finished" else return "cancelled" end + elseif self.fully_frozen then + return "voting" + elseif self.half_frozen then + return "frozen" else return "accepted" end diff -r 5c601807d397 -r 768faea1096d static/icons/16/bullet_disk.png Binary file static/icons/16/bullet_disk.png has changed diff -r 5c601807d397 -r 768faea1096d static/icons/16/comments.png Binary file static/icons/16/comments.png has changed diff -r 5c601807d397 -r 768faea1096d static/style.css --- a/static/style.css Mon Nov 23 12:00:00 2009 +0100 +++ b/static/style.css Mon Nov 30 12:00:00 2009 +0100 @@ -637,20 +637,37 @@ border: 1px solid #ccc; } -.member_thumb:hover { - border: 1px solid #000; +.member_thumb a:hover div { + background-color: #444; + color: #fff; +} + +.member_thumb .flags a:hover { + background-color: #444; + color: #fff; } .member_thumb img { margin-right: 0.5em; vertical-align: bottom; + float: left; } .member_thumb div { display: inline; +} + +.member_thumb .member_name { + display: block; + margin-top: 3ex; margin-right: 0.5em; } +.member_thumb .flags { + float: right; + font-size: 75%; +} + .draft_content { background-color: #eee; border: 1px solid #ccc; @@ -696,4 +713,5 @@ border: 2px solid #faa; background-color: #fee; padding: 1ex; -} \ No newline at end of file +} +