liquid_feedback_frontend
changeset 4:80c215dbf076 alpha5
Version alpha5
Many optical changes and improved usability
Support for different wiki-formatting-engines
Help system
Many optical changes and improved usability
Support for different wiki-formatting-engines
Help system
line diff
1.1 --- a/app/main/_filter_view/30_navigation.lua Mon Nov 30 12:00:00 2009 +0100 1.2 +++ b/app/main/_filter_view/30_navigation.lua Thu Dec 10 12:00:00 2009 +0100 1.3 @@ -71,6 +71,15 @@ 1.4 view = 'about' 1.5 } 1.6 1.7 + ui.link{ 1.8 + content = function() 1.9 + ui.image{ static = "icons/16/bug.png" } 1.10 + slot.put(_'Bug report') 1.11 + end, 1.12 + external = "http://trac.public-software-group.org/projects/lf" --/newticket?description=" .. encode.url_part("\n\n\n\nReport for: " .. os.getenv("REQUEST_URI") ) 1.13 + } 1.14 + 1.15 + 1.16 if app.session.member.admin then 1.17 1.18 slot.put(" ") 1.19 @@ -89,6 +98,12 @@ 1.20 1.21 end) 1.22 1.23 +if config.app_logo then 1.24 + slot.select("logo", function() 1.25 + ui.image{ static = config.app_logo } 1.26 + end) 1.27 +end 1.28 + 1.29 execute.inner() 1.30 1.31
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/app/main/_filter_view/33_help_hidden.lua Thu Dec 10 12:00:00 2009 +0100 2.3 @@ -0,0 +1,36 @@ 2.4 +execute.inner() 2.5 + 2.6 +if util._hidden_helps ~= nil then 2.7 + slot.select("help_hidden", function() 2.8 + for i, help in ipairs(util._hidden_helps) do 2.9 + ui.link{ 2.10 + attr = { 2.11 + class = "help_hidden", 2.12 + title = _("Help for: #{text}", { text = help.title }) 2.13 + }, 2.14 + module = "help", 2.15 + action = "update", 2.16 + params = { 2.17 + help_ident = help.id, 2.18 + hide = false 2.19 + }, 2.20 + routing = { 2.21 + default = { 2.22 + mode = "redirect", 2.23 + module = request.get_module(), 2.24 + view = request.get_view(), 2.25 + id = param.get_id_cgi(), 2.26 + params = param.get_all_cgi() 2.27 + } 2.28 + }, 2.29 + content = function() 2.30 + ui.image{ 2.31 + attr = { class = "help_icon" }, 2.32 + static = "icons/16/help.png" 2.33 + } 2.34 + end 2.35 + } 2.36 + end 2.37 + end) 2.38 +end 2.39 +
3.1 --- a/app/main/_layout/default.html Mon Nov 30 12:00:00 2009 +0100 3.2 +++ b/app/main/_layout/default.html Thu Dec 10 12:00:00 2009 +0100 3.3 @@ -18,29 +18,47 @@ 3.4 <!-- WEBMCP SLOT navigation --> 3.5 </div> 3.6 </div> 3.7 + <div class="layout_notice" id="layout_notice" onclick="document.getElementById('layout_notice').style.display='none';"> 3.8 + <!-- WEBMCP SLOT notice --> 3.9 + </div> 3.10 + <div class="layout_warning" id="layout_warning" onclick="document.getElementById('layout_warning').style.display='none';"> 3.11 + <!-- WEBMCP SLOT warning --> 3.12 + </div> 3.13 + <div class="layout_error" id="layout_error" onclick="document.getElementById('layout_error').style.display='none';"> 3.14 + <!-- WEBMCP SLOT error --> 3.15 + </div> 3.16 <div class="title_bar"> 3.17 - <div class="issue_info" id="issue_info"> 3.18 - <!-- WEBMCP SLOT issue_info --> 3.19 - </div> 3.20 - <div class="path" id="path"> 3.21 - <!-- WEBMCP SLOT path --> 3.22 - </div> 3.23 - <div class="title" id="title"> 3.24 - <!-- WEBMCP SLOT title --> 3.25 + <div class="title_bar_content"> 3.26 + <div class="logo" id="logo"> 3.27 + <!-- WEBMCP SLOT logo --> 3.28 + </div> 3.29 + <div class="issue_info" id="issue_info"> 3.30 + <!-- WEBMCP SLOT issue_info --> 3.31 + </div> 3.32 + <div class="path" id="path"> 3.33 + <!-- WEBMCP SLOT path --> 3.34 + </div> 3.35 + <div class="title" id="title"> 3.36 + <!-- WEBMCP SLOT title --> 3.37 + </div> 3.38 + <div class="help_hidden" id="help_hidden"> 3.39 + <!-- WEBMCP SLOT help_hidden --> 3.40 + </div> 3.41 + <div class="actions" id="actions"> 3.42 + <div class="interest vote_info" id="interest"> 3.43 + <!-- WEBMCP SLOT interest --> 3.44 + </div> 3.45 + <!-- WEBMCP SLOT actions --> 3.46 + </div> 3.47 + <br style="clear: left;" /> 3.48 + <div class="sub_title" id="sub_title"> 3.49 + <!-- WEBMCP SLOT sub_title --> 3.50 + </div> 3.51 + <div class="support vote_info" id="support"> 3.52 + <!-- WEBMCP SLOT support --> 3.53 + </div> 3.54 + <div style="clear: left;" /></div> 3.55 </div> 3.56 - <div class="interest vote_info" id="interest"> 3.57 - <!-- WEBMCP SLOT interest --> 3.58 - </div> 3.59 - <div class="support vote_info" id="support"> 3.60 - <!-- WEBMCP SLOT support --> 3.61 - </div> 3.62 - <div class="delegation vote_info" id="delegation"> 3.63 - <!-- WEBMCP SLOT delegation --> 3.64 - </div> 3.65 - <div class="actions" id="actions"> 3.66 - <!-- WEBMCP SLOT actions --> 3.67 - </div> 3.68 - <br style="clear: left;" /> 3.69 </div> 3.70 <div class="main" id="default"> 3.71 <!-- WEBMCP SLOT default --> 3.72 @@ -55,15 +73,6 @@ 3.73 </div> 3.74 </div> 3.75 </div> 3.76 - <div class="layout_notice" id="layout_notice" onclick="document.getElementById('layout_notice').style.display='none';"> 3.77 - <!-- WEBMCP SLOT notice --> 3.78 - </div> 3.79 - <div class="layout_warning" id="layout_warning" onclick="document.getElementById('layout_warning').style.display='none';"> 3.80 - <!-- WEBMCP SLOT warning --> 3.81 - </div> 3.82 - <div class="layout_error" id="layout_error" onclick="document.getElementById('layout_error').style.display='none';"> 3.83 - <!-- WEBMCP SLOT error --> 3.84 - </div> 3.85 </body> 3.86 <script> 3.87 </script>
4.1 --- a/app/main/area/_action/update.lua Mon Nov 30 12:00:00 2009 +0100 4.2 +++ b/app/main/area/_action/update.lua Thu Dec 10 12:00:00 2009 +0100 4.3 @@ -1,3 +1,7 @@ 4.4 +if not app.session.member.admin then 4.5 + error() 4.6 +end 4.7 + 4.8 local id = param.get_id() 4.9 4.10 local area
5.1 --- a/app/main/area/_list.lua Mon Nov 30 12:00:00 2009 +0100 5.2 +++ b/app/main/area/_list.lua Thu Dec 10 12:00:00 2009 +0100 5.3 @@ -35,7 +35,7 @@ 5.4 local max_value = MemberCount:get() 5.5 ui.bargraph{ 5.6 max_value = max_value, 5.7 - width = 200, 5.8 + width = 100, 5.9 bars = { 5.10 { color = "#444", value = record.direct_member_count }, 5.11 { color = "#777", value = record.member_weight - record.direct_member_count }, 5.12 @@ -58,4 +58,14 @@ 5.13 } 5.14 } 5.15 end 5.16 -} 5.17 \ No newline at end of file 5.18 +} 5.19 + 5.20 +ui.bargraph_legend{ 5.21 + width = 25, 5.22 + bars = { 5.23 + { color = "#444", label = _"Direct membership" }, 5.24 + { color = "#777", label = _"Membership by delegation" }, 5.25 + { color = "#ddd", label = _"No membership at all" }, 5.26 + } 5.27 +} 5.28 +
6.1 --- a/app/main/area/list.lua Mon Nov 30 12:00:00 2009 +0100 6.2 +++ b/app/main/area/list.lua Thu Dec 10 12:00:00 2009 +0100 6.3 @@ -1,5 +1,7 @@ 6.4 slot.put_into("title", _'Area list') 6.5 6.6 +util.help("area.list", _"Area list") 6.7 + 6.8 local areas_selector = Area:new_selector():add_where("active") 6.9 6.10 execute.view{ 6.11 @@ -8,7 +10,9 @@ 6.12 params = { areas_selector = areas_selector } 6.13 } 6.14 6.15 +--[[ 6.16 execute.view{ 6.17 module = "delegation", 6.18 view = "_show_box" 6.19 -} 6.20 \ No newline at end of file 6.21 +} 6.22 +--]]
7.1 --- a/app/main/area/show.lua Mon Nov 30 12:00:00 2009 +0100 7.2 +++ b/app/main/area/show.lua Thu Dec 10 12:00:00 2009 +0100 7.3 @@ -13,15 +13,6 @@ 7.4 slot.select("actions", function() 7.5 ui.link{ 7.6 content = function() 7.7 - ui.image{ static = "icons/16/table_go.png" } 7.8 - slot.put(_"Delegate") 7.9 - end, 7.10 - module = "delegation", 7.11 - view = "new", 7.12 - params = { area_id = area.id } 7.13 - } 7.14 - ui.link{ 7.15 - content = function() 7.16 ui.image{ static = "icons/16/folder_add.png" } 7.17 slot.put(_"Create new issue") 7.18 end, 7.19 @@ -31,6 +22,8 @@ 7.20 } 7.21 end) 7.22 7.23 +util.help("area.show") 7.24 + 7.25 execute.view{ 7.26 module = "membership", 7.27 view = "_show_box",
8.1 --- a/app/main/contact/_list.lua Mon Nov 30 12:00:00 2009 +0100 8.2 +++ b/app/main/contact/_list.lua Thu Dec 10 12:00:00 2009 +0100 8.3 @@ -2,7 +2,7 @@ 8.4 local contacts_selector = Contact:new_selector() 8.5 :add_where{ "member_id = ?", app.session.member.id } 8.6 :join("member", nil, "member.id = contact.other_member_id") 8.7 - :add_order_by("member.login") 8.8 + :add_order_by("member.name") 8.9 8.10 ui.paginate{ 8.11 selector = contacts_selector, 8.12 @@ -15,17 +15,6 @@ 8.13 records = contacts, 8.14 columns = { 8.15 { 8.16 - label = _"Login", 8.17 - content = function(record) 8.18 - ui.link{ 8.19 - text = record.other_member.login, 8.20 - module = "member", 8.21 - view = "show", 8.22 - id = record.other_member_id 8.23 - } 8.24 - end 8.25 - }, 8.26 - { 8.27 label = _"Name", 8.28 content = function(record) 8.29 ui.link{ 8.30 @@ -103,30 +92,8 @@ 8.31 } 8.32 end 8.33 }, 8.34 - { 8.35 - content = function(record) 8.36 - ui.link{ 8.37 - attr = { class = "action" }, 8.38 - text = _"Global delegation", 8.39 - module = "delegation", 8.40 - action = "update", 8.41 - params = { 8.42 - trustee_id = record.other_member_id, 8.43 - }, 8.44 - routing = { 8.45 - default = { 8.46 - mode = "redirect", 8.47 - module = request.get_module(), 8.48 - view = request.get_view(), 8.49 - id = param.get_id_cgi(), 8.50 - params = param.get_all_cgi() 8.51 - } 8.52 - } 8.53 - } 8.54 - end 8.55 - } 8.56 } 8.57 } 8.58 end 8.59 end 8.60 -} 8.61 \ No newline at end of file 8.62 +}
9.1 --- a/app/main/contact/list.lua Mon Nov 30 12:00:00 2009 +0100 9.2 +++ b/app/main/contact/list.lua Thu Dec 10 12:00:00 2009 +0100 9.3 @@ -1,5 +1,7 @@ 9.4 slot.put_into("title", _"Contacts") 9.5 9.6 +util.help("contact.list") 9.7 + 9.8 execute.view{ 9.9 module = "contact", 9.10 view = "_list",
10.1 --- a/app/main/delegation/_action/update.lua Mon Nov 30 12:00:00 2009 +0100 10.2 +++ b/app/main/delegation/_action/update.lua Thu Dec 10 12:00:00 2009 +0100 10.3 @@ -12,7 +12,7 @@ 10.4 10.5 local delegation = Delegation:by_pk(truster_id, area_id, issue_id) 10.6 10.7 -if param.get("delete") then 10.8 +if param.get("delete") or trustee_id == -1 then 10.9 10.10 if delegation then 10.11
11.1 --- a/app/main/delegation/_show_box.lua Mon Nov 30 12:00:00 2009 +0100 11.2 +++ b/app/main/delegation/_show_box.lua Thu Dec 10 12:00:00 2009 +0100 11.3 @@ -1,121 +1,192 @@ 11.4 -slot.select("delegation", function() 11.5 - 11.6 - local delegation 11.7 - local area_id 11.8 - local issue_id 11.9 - 11.10 - local scope = "global" 11.11 - 11.12 - if param.get("initiative_id", atom.integer) then 11.13 - issue_id = Initiative:by_id(param.get("initiative_id", atom.integer)).issue_id 11.14 - scope = "issue" 11.15 - end 11.16 - 11.17 - if param.get("issue_id", atom.integer) then 11.18 - issue_id = param.get("issue_id", atom.integer) 11.19 - scope = "issue" 11.20 - end 11.21 - 11.22 - if param.get("area_id", atom.integer) then 11.23 - area_id = param.get("area_id", atom.integer) 11.24 - scope = "area" 11.25 - end 11.26 - 11.27 - 11.28 +slot.select("actions", function() 11.29 11.30 - local delegation 11.31 - 11.32 - if issue_id then 11.33 - delegation = Delegation:by_pk(app.session.member.id, nil, issue_id) 11.34 - if not delegation then 11.35 - local issue = Issue:by_id(issue_id) 11.36 - delegation = Delegation:by_pk(app.session.member.id, issue.area_id) 11.37 - end 11.38 - elseif area_id then 11.39 - delegation = Delegation:by_pk(app.session.member.id, area_id) 11.40 - end 11.41 - 11.42 - if not delegation then 11.43 - delegation = Delegation:by_pk(app.session.member.id) 11.44 - end 11.45 - if delegation then 11.46 - ui.container{ 11.47 - attr = { 11.48 - class = "head", 11.49 - style = "cursor: pointer;", 11.50 - onclick = "document.getElementById('delegation_content').style.display = 'block';" 11.51 - }, 11.52 - content = _"Your vote is delegated. [more]" 11.53 - } 11.54 - ui.container{ 11.55 - attr = { class = "content", id = "delegation_content" }, 11.56 - content = function() 11.57 + ui.container{ 11.58 + attr = { class = "delegation vote_info"}, 11.59 + content = function() 11.60 + 11.61 + local delegation 11.62 + local area_id 11.63 + local issue_id 11.64 + 11.65 + local scope = "global" 11.66 + 11.67 + if param.get("initiative_id", atom.integer) then 11.68 + issue_id = Initiative:by_id(param.get("initiative_id", atom.integer)).issue_id 11.69 + scope = "issue" 11.70 + end 11.71 + 11.72 + if param.get("issue_id", atom.integer) then 11.73 + issue_id = param.get("issue_id", atom.integer) 11.74 + scope = "issue" 11.75 + end 11.76 + 11.77 + if param.get("area_id", atom.integer) then 11.78 + area_id = param.get("area_id", atom.integer) 11.79 + scope = "area" 11.80 + end 11.81 + 11.82 + 11.83 + 11.84 + local delegation 11.85 + 11.86 + if issue_id then 11.87 + delegation = Delegation:by_pk(app.session.member.id, nil, issue_id) 11.88 + if not delegation then 11.89 + local issue = Issue:by_id(issue_id) 11.90 + delegation = Delegation:by_pk(app.session.member.id, issue.area_id) 11.91 + end 11.92 + elseif area_id then 11.93 + delegation = Delegation:by_pk(app.session.member.id, area_id) 11.94 + end 11.95 + 11.96 + if not delegation then 11.97 + delegation = Delegation:by_pk(app.session.member.id) 11.98 + end 11.99 + if delegation then 11.100 ui.container{ 11.101 attr = { 11.102 - class = "close", 11.103 + title = _"Click for details", 11.104 + class = "head head_active", 11.105 style = "cursor: pointer;", 11.106 - onclick = "document.getElementById('delegation_content').style.display = 'none';" 11.107 + onclick = "document.getElementById('delegation_content').style.display = 'block';" 11.108 }, 11.109 - content = _"X" 11.110 + content = function() 11.111 + ui.image{ 11.112 + static = "icons/16/error.png" 11.113 + } 11.114 + if delegation.issue_id then 11.115 + slot.put(_"Issue delegation active") 11.116 + elseif delegation.area_id then 11.117 + slot.put(_"Area wide delegation active") 11.118 + else 11.119 + slot.put(_"Global delegation active") 11.120 + end 11.121 + ui.image{ 11.122 + static = "icons/16/dropdown.png" 11.123 + } 11.124 + end 11.125 } 11.126 - 11.127 - local delegation_chain = db:query{ "SELECT * FROM delegation_chain(?, ?, ?) JOIN member ON member.id = member_id ORDER BY index", app.session.member.id, area_id, issue_id } 11.128 - 11.129 - for i, record in ipairs(delegation_chain) do 11.130 - local style 11.131 - execute.view{ 11.132 - module = "member", 11.133 - view = "_show_thumb", 11.134 - params = { member = record } 11.135 - } 11.136 - slot.put("<br style='clear: left'/>") 11.137 - if record.scope_out then 11.138 + ui.container{ 11.139 + attr = { class = "content", id = "delegation_content" }, 11.140 + content = function() 11.141 ui.container{ 11.142 - attr = { class = "delegation_info" }, 11.143 + attr = { 11.144 + class = "close", 11.145 + style = "cursor: pointer;", 11.146 + onclick = "document.getElementById('delegation_content').style.display = 'none';" 11.147 + }, 11.148 content = function() 11.149 - ui.image{ 11.150 - attr = { class = "delegation_arrow" }, 11.151 - static = "delegation_arrow_vertical.jpg" 11.152 - } 11.153 + ui.image{ static = "icons/16/cross.png" } 11.154 + end 11.155 + } 11.156 + 11.157 + local delegation_chain = Member:new_selector() 11.158 + :add_field("delegation_chain.*") 11.159 + :join("delegation_chain(" .. tostring(app.session.member.id) .. ", " .. tostring(area_id or "NULL") .. ", " .. tostring(issue_id or "NULL") .. ")", "delegation_chain", "member.id = delegation_chain.member_id") 11.160 + :add_order_by("index") 11.161 + :exec() 11.162 + 11.163 + for i, record in ipairs(delegation_chain) do 11.164 + local style 11.165 + local overridden = record.overridden 11.166 + if record.scope_in then 11.167 ui.container{ 11.168 - attr = { class = "delegation_scope" }, 11.169 + attr = { class = "delegation_info" }, 11.170 content = function() 11.171 - if record.scope_out == "global" then 11.172 - slot.put(_"Global delegation") 11.173 - elseif record.scope_out == "area" then 11.174 - slot.put(_"Area delegation") 11.175 - elseif record.scope_out == "issue" then 11.176 - slot.put(_"Issue delegation") 11.177 + if not overridden then 11.178 + ui.image{ 11.179 + attr = { class = "delegation_arrow" }, 11.180 + static = "delegation_arrow_vertical.jpg" 11.181 + } 11.182 + else 11.183 + ui.image{ 11.184 + attr = { class = "delegation_arrow delegation_arrow_overridden" }, 11.185 + static = "delegation_arrow_vertical.jpg" 11.186 + } 11.187 + end 11.188 + ui.container{ 11.189 + attr = { class = "delegation_scope" .. (overridden and " delegation_scope_overridden" or "") }, 11.190 + content = function() 11.191 + if record.scope_in == "global" then 11.192 + slot.put(_"Global delegation") 11.193 + elseif record.scope_in == "area" then 11.194 + slot.put(_"Area delegation") 11.195 + elseif record.scope_in == "issue" then 11.196 + slot.put(_"Issue delegation") 11.197 + end 11.198 + end 11.199 + } 11.200 + if i == 2 then 11.201 + ui.link{ 11.202 + attr = { class = "revoke" }, 11.203 + content = function() 11.204 + ui.image{ static = "icons/16/delete.png" } 11.205 + slot.put(_"Revoke") 11.206 + end, 11.207 + module = "delegation", 11.208 + action = "update", 11.209 + params = { issue_id = delegation.issue_id, area_id = delegation.area_id, delete = true }, 11.210 + routing = { 11.211 + default = { 11.212 + mode = "redirect", 11.213 + module = request.get_module(), 11.214 + view = request.get_view(), 11.215 + id = param.get_id_cgi(), 11.216 + params = param.get_all_cgi() 11.217 + } 11.218 + } 11.219 + } 11.220 end 11.221 end 11.222 } 11.223 - if record.id == app.session.member.id then 11.224 - ui.link{ 11.225 - attr = { class = "revoke" }, 11.226 - content = function() 11.227 - ui.image{ static = "icons/16/delete.png" } 11.228 - slot.put(_"Revoke") 11.229 - end, 11.230 - module = "delegation", 11.231 - action = "update", 11.232 - params = { issue_id = delegation.issue_id, area_id = delegation.area_id, delete = true }, 11.233 - routing = { 11.234 - default = { 11.235 - mode = "redirect", 11.236 - module = request.get_module(), 11.237 - view = request.get_view(), 11.238 - id = param.get_id_cgi(), 11.239 - params = param.get_all_cgi() 11.240 - } 11.241 - } 11.242 + end 11.243 + ui.container{ 11.244 + attr = { class = overridden and "delegation_overridden" or "" }, 11.245 + content = function() 11.246 + execute.view{ 11.247 + module = "member", 11.248 + view = "_show_thumb", 11.249 + params = { member = record } 11.250 } 11.251 end 11.252 + } 11.253 + if record.participation and not record.overridden then 11.254 + ui.container{ 11.255 + attr = { class = "delegation_participation" }, 11.256 + content = function() 11.257 + slot.put("<br /><br />-----> Participation<br />") 11.258 + end 11.259 + } 11.260 end 11.261 - } 11.262 + slot.put("<br style='clear: left'/>") 11.263 + end 11.264 end 11.265 - end 11.266 + } 11.267 end 11.268 - } 11.269 - end 11.270 - 11.271 + ui.link{ 11.272 + content = function() 11.273 + ui.image{ static = "icons/16/table_go.png" } 11.274 + if scope == "global" and delegation then 11.275 + slot.put(_"Change global delegation") 11.276 + elseif scope == "global" and not delegation then 11.277 + slot.put(_"Set global delegation") 11.278 + elseif scope == "area" and delegation and delegation.area_id then 11.279 + slot.put(_"Change area delegation") 11.280 + elseif scope == "area" and not (delegation and delegation.area_id) then 11.281 + slot.put(_"Set area delegation") 11.282 + elseif scope == "issue" and delegation and delegation.issue_id then 11.283 + slot.put(_"Change issue delegation") 11.284 + elseif scope == "issue" and not (delegation and delegation.issue_id) then 11.285 + slot.put(_"Set issue delegation") 11.286 + end 11.287 + end, 11.288 + module = "delegation", 11.289 + view = "new", 11.290 + params = { 11.291 + area_id = area_id, 11.292 + issue_id = issue_id 11.293 + } 11.294 + } 11.295 + end 11.296 + } 11.297 end)
12.1 --- a/app/main/delegation/new.lua Mon Nov 30 12:00:00 2009 +0100 12.2 +++ b/app/main/delegation/new.lua Thu Dec 10 12:00:00 2009 +0100 12.3 @@ -1,18 +1,59 @@ 12.4 local area = Area:by_id(param.get("area_id", atom.integer)) 12.5 if area then 12.6 slot.put_into("title", encode.html(_"Set delegation for Area '#{name}'":gsub("#{name}", area.name))) 12.7 + util.help("delegation.new.area") 12.8 end 12.9 12.10 local issue = Issue:by_id(param.get("issue_id", atom.integer)) 12.11 if issue then 12.12 slot.put_into("title", encode.html(_"Set delegation for Issue ##{number} in Area '#{area_name}'":gsub("#{number}", issue.id):gsub("#{area_name}", issue.area.name))) 12.13 + util.help("delegation.new.issue") 12.14 end 12.15 12.16 +if not area and not issue then 12.17 + slot.put_into("title", encode.html(_"Set global delegation")) 12.18 + util.help("delegation.new.global") 12.19 +end 12.20 + 12.21 +slot.select("actions", function() 12.22 + if issue then 12.23 + ui.link{ 12.24 + module = "issue", 12.25 + view = "show", 12.26 + id = issue.id, 12.27 + content = function() 12.28 + ui.image{ static = "icons/16/cancel.png" } 12.29 + slot.put(_"Cancel") 12.30 + end, 12.31 + } 12.32 + elseif area then 12.33 + ui.link{ 12.34 + module = "area", 12.35 + view = "show", 12.36 + id = area.id, 12.37 + content = function() 12.38 + ui.image{ static = "icons/16/cancel.png" } 12.39 + slot.put(_"Cancel") 12.40 + end, 12.41 + } 12.42 + else 12.43 + ui.link{ 12.44 + module = "index", 12.45 + view = "index", 12.46 + content = function() 12.47 + ui.image{ static = "icons/16/cancel.png" } 12.48 + slot.put(_"Cancel") 12.49 + end, 12.50 + } 12.51 + end 12.52 +end) 12.53 + 12.54 + 12.55 12.56 local contact_members = Member:new_selector() 12.57 :add_where{ "contact.member_id = ?", app.session.member.id } 12.58 :join("contact", nil, "member.id = contact.other_member_id") 12.59 - :add_order_by("member.login") 12.60 + :add_order_by("member.name") 12.61 :exec() 12.62 12.63 12.64 @@ -27,19 +68,29 @@ 12.65 routing = { 12.66 default = { 12.67 mode = "redirect", 12.68 - module = area and "area" or "issue", 12.69 - view = "show", 12.70 - id = area and area.id or issue.id, 12.71 + module = area and "area" or issue and "issue" or "index", 12.72 + view = (area or issue) and "show" or "index", 12.73 + id = area and area.id or issue and issue.id or nil, 12.74 } 12.75 }, 12.76 content = function() 12.77 + records = { 12.78 + { 12.79 + id = "-1", 12.80 + name = _"No delegation" 12.81 + } 12.82 + } 12.83 + for i, record in ipairs(contact_members) do 12.84 + records[#records+1] = record 12.85 + end 12.86 + 12.87 ui.field.select{ 12.88 label = _"Trustee", 12.89 name = "trustee_id", 12.90 - foreign_records = contact_members, 12.91 + foreign_records = records, 12.92 foreign_id = "id", 12.93 - foreign_name = "name" 12.94 + foreign_name = "name", 12.95 } 12.96 ui.submit{ text = _"Save" } 12.97 end 12.98 -} 12.99 \ No newline at end of file 12.100 +}
13.1 --- a/app/main/draft/_action/add.lua Mon Nov 30 12:00:00 2009 +0100 13.2 +++ b/app/main/draft/_action/add.lua Thu Dec 10 12:00:00 2009 +0100 13.3 @@ -4,6 +4,17 @@ 13.4 local draft = Draft:new() 13.5 draft.author_id = app.session.member.id 13.6 draft.initiative_id = initiative.id 13.7 + local formatting_engine = param.get("formatting_engine") 13.8 + local formatting_engine_valid = false 13.9 + for fe, dummy in pairs(config.formatting_engine_executeables) do 13.10 + if formatting_engine == fe then 13.11 + formatting_engine_valid = true 13.12 + end 13.13 + end 13.14 + if not formatting_engine_valid then 13.15 + error("invalid formatting engine!") 13.16 + end 13.17 + draft.formatting_engine = formatting_engine 13.18 draft.content = param.get("content") 13.19 draft:save() 13.20
14.1 --- a/app/main/draft/_show.lua Mon Nov 30 12:00:00 2009 +0100 14.2 +++ b/app/main/draft/_show.lua Thu Dec 10 12:00:00 2009 +0100 14.3 @@ -9,9 +9,9 @@ 14.4 ui.field.text{ label = _"Author", name = "author_name" } 14.5 ui.field.timestamp{ label = _"Created at", name = "created" } 14.6 ui.container{ 14.7 - attr = { class = "draft_content" }, 14.8 + attr = { class = "draft_content wiki" }, 14.9 content = function() 14.10 - slot.put(format.wiki_text(draft.content)) 14.11 + slot.put(format.wiki_text(draft.content, draft.formatting_engine)) 14.12 end 14.13 } 14.14 end
15.1 --- a/app/main/draft/new.lua Mon Nov 30 12:00:00 2009 +0100 15.2 +++ b/app/main/draft/new.lua Thu Dec 10 12:00:00 2009 +0100 15.3 @@ -1,7 +1,19 @@ 15.4 -slot.put_into("title", _"Add new draft") 15.5 +slot.put_into("title", _"Edit draft") 15.6 15.7 local initiative = Initiative:by_id(param.get("initiative_id")) 15.8 15.9 +slot.select("actions", function() 15.10 + ui.link{ 15.11 + content = function() 15.12 + ui.image{ static = "icons/16/cancel.png" } 15.13 + slot.put(_"Cancel") 15.14 + end, 15.15 + module = "initiative", 15.16 + view = "show", 15.17 + id = initiative.id 15.18 + } 15.19 +end) 15.20 + 15.21 ui.form{ 15.22 record = initiative.current_draft, 15.23 attr = { class = "vertical" }, 15.24 @@ -19,6 +31,16 @@ 15.25 content = function() 15.26 15.27 ui.field.text{ label = _"Author", value = app.session.member.name, readonly = true } 15.28 + ui.field.select{ 15.29 + label = _"Wiki engine", 15.30 + name = "formatting_engine", 15.31 + foreign_records = { 15.32 + { id = "rocketwiki", name = "RocketWiki" }, 15.33 + { id = "compat", name = _"Traditional wiki syntax" } 15.34 + }, 15.35 + foreign_id = "id", 15.36 + foreign_name = "name" 15.37 + } 15.38 ui.field.text{ 15.39 label = _"Content", 15.40 name = "content",
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/app/main/help/_action/update.lua Thu Dec 10 12:00:00 2009 +0100 16.3 @@ -0,0 +1,15 @@ 16.4 +local help_ident = param.get("help_ident") 16.5 +local hide = param.get("hide", atom.boolean) 16.6 + 16.7 +local setting_key = "liquidfeedback_frontend_hidden_help_" .. help_ident 16.8 +local setting = Setting:by_pk(app.session.member.id, setting_key) 16.9 + 16.10 +if hide == true and not setting then 16.11 + setting = Setting:new() 16.12 + setting.member_id = app.session.member.id 16.13 + setting.key = setting_key 16.14 + setting.value = "hidden" 16.15 + setting:save() 16.16 +elseif hide == false and setting then 16.17 + setting:destroy() 16.18 +end
17.1 --- a/app/main/index/_action/set_lang.lua Mon Nov 30 12:00:00 2009 +0100 17.2 +++ b/app/main/index/_action/set_lang.lua Thu Dec 10 12:00:00 2009 +0100 17.3 @@ -1,3 +1,5 @@ 17.4 -app.session.lang = param.get("lang") 17.5 - 17.6 -app.session:save() 17.7 \ No newline at end of file 17.8 +local lang = param.get("lang") 17.9 +if lang == "de" or lang == "en" then 17.10 + app.session.lang = param.get("lang") 17.11 + app.session:save() 17.12 +end 17.13 \ No newline at end of file
18.1 --- a/app/main/index/change_password.lua Mon Nov 30 12:00:00 2009 +0100 18.2 +++ b/app/main/index/change_password.lua Thu Dec 10 12:00:00 2009 +0100 18.3 @@ -12,6 +12,8 @@ 18.4 } 18.5 end) 18.6 18.7 +util.help("index.change_password", _"Change password") 18.8 + 18.9 ui.form{ 18.10 attr = { class = "vertical" }, 18.11 module = "index",
19.1 --- a/app/main/index/index.lua Mon Nov 30 12:00:00 2009 +0100 19.2 +++ b/app/main/index/index.lua Thu Dec 10 12:00:00 2009 +0100 19.3 @@ -1,10 +1,11 @@ 19.4 slot.select("title", function() 19.5 - ui.image{ 19.6 - attr = { class = "avatar" }, 19.7 - module = "member", 19.8 - view = "avatar", 19.9 - extension = "jpg", 19.10 - id = app.session.member.id 19.11 + execute.view{ 19.12 + module = "member_image", 19.13 + view = "_show", 19.14 + params = { 19.15 + member = app.session.member, 19.16 + image_type = "avatar" 19.17 + } 19.18 } 19.19 end) 19.20 19.21 @@ -41,27 +42,28 @@ 19.22 slot.put_into("title", encode.html(config.app_title)) 19.23 19.24 slot.select("actions", function() 19.25 - slot.put(_"Logged in as:") 19.26 - slot.put(" <b>") 19.27 - slot.put(app.session.member.login) 19.28 - slot.put("</b> | ") 19.29 + 19.30 + ui.link{ 19.31 + content = function() 19.32 + ui.image{ static = "icons/16/application_form.png" } 19.33 + slot.put(_"Edit my profile") 19.34 + end, 19.35 + module = "member", 19.36 + view = "edit" 19.37 + } 19.38 19.39 ui.link{ 19.40 content = function() 19.41 ui.image{ static = "icons/16/user_gray.png" } 19.42 - slot.put(_"Upload avatar") 19.43 + slot.put(_"Upload images") 19.44 end, 19.45 module = "member", 19.46 - view = "edit_avatar" 19.47 + view = "edit_images" 19.48 } 19.49 19.50 - ui.link{ 19.51 - content = function() 19.52 - ui.image{ static = "icons/16/application_form.png" } 19.53 - slot.put(_"Edit my page") 19.54 - end, 19.55 - module = "member", 19.56 - view = "edit" 19.57 + execute.view{ 19.58 + module = "delegation", 19.59 + view = "_show_box" 19.60 } 19.61 19.62 ui.link{ 19.63 @@ -72,8 +74,28 @@ 19.64 module = "index", 19.65 view = "change_password" 19.66 } 19.67 + 19.68 end) 19.69 19.70 +local lang = locale.get("lang") 19.71 +local basepath = request.get_app_basepath() 19.72 +local file_name = basepath .. "/locale/motd/" .. lang .. ".txt" 19.73 +local file = io.open(file_name) 19.74 +if file ~= nil then 19.75 + local help_text = file:read("*a") 19.76 + if #help_text > 0 then 19.77 + ui.container{ 19.78 + attr = { class = "motd wiki" }, 19.79 + content = function() 19.80 + slot.put(format.wiki_text(help_text)) 19.81 + end 19.82 + } 19.83 + end 19.84 +end 19.85 + 19.86 + 19.87 +util.help("index.index", _"Home") 19.88 + 19.89 execute.view{ 19.90 module = "member", 19.91 view = "_show",
20.1 --- a/app/main/initiative/_action/create.lua Mon Nov 30 12:00:00 2009 +0100 20.2 +++ b/app/main/initiative/_action/create.lua Thu Dec 10 12:00:00 2009 +0100 20.3 @@ -29,6 +29,17 @@ 20.4 20.5 local draft = Draft:new() 20.6 draft.initiative_id = initiative.id 20.7 +local formatting_engine = param.get("formatting_engine") 20.8 +local formatting_engine_valid = false 20.9 +for fe, dummy in pairs(config.formatting_engine_executeables) do 20.10 + if formatting_engine == fe then 20.11 + formatting_engine_valid = true 20.12 + end 20.13 +end 20.14 +if not formatting_engine_valid then 20.15 + error("invalid formatting engine!") 20.16 +end 20.17 +draft.formatting_engine = formatting_engine 20.18 draft.content = param.get("draft") 20.19 draft.author_id = app.session.member.id 20.20 draft:save()
21.1 --- a/app/main/initiative/_list.lua Mon Nov 30 12:00:00 2009 +0100 21.2 +++ b/app/main/initiative/_list.lua Thu Dec 10 12:00:00 2009 +0100 21.3 @@ -66,7 +66,7 @@ 21.4 local max_value = record.issue.voter_count 21.5 ui.bargraph{ 21.6 max_value = max_value, 21.7 - width = 200, 21.8 + width = 100, 21.9 bars = { 21.10 { color = "#0a0", value = record.positive_votes }, 21.11 { color = "#aaa", value = max_value - record.negative_votes - record.positive_votes }, 21.12 @@ -78,7 +78,7 @@ 21.13 local max_value = (record.issue.population or 0) 21.14 ui.bargraph{ 21.15 max_value = max_value, 21.16 - width = 200, 21.17 + width = 100, 21.18 bars = { 21.19 { color = "#0a0", value = (record.satisfied_supporter_count or 0) }, 21.20 { color = "#8f8", value = (record.supporter_count or 0) - (record.satisfied_supporter_count or 0) },
22.1 --- a/app/main/initiative/edit.lua Mon Nov 30 12:00:00 2009 +0100 22.2 +++ b/app/main/initiative/edit.lua Thu Dec 10 12:00:00 2009 +0100 22.3 @@ -2,6 +2,18 @@ 22.4 22.5 slot.put_into("title", _"Edit initiative") 22.6 22.7 +slot.select("actions", function() 22.8 + ui.link{ 22.9 + content = function() 22.10 + ui.image{ static = "icons/16/cancel.png" } 22.11 + slot.put(_"Cancel") 22.12 + end, 22.13 + module = "initiative", 22.14 + view = "show", 22.15 + id = initiative.id 22.16 + } 22.17 +end) 22.18 + 22.19 ui.form{ 22.20 record = initiative, 22.21 module = "initiative",
23.1 --- a/app/main/initiative/new.lua Mon Nov 30 12:00:00 2009 +0100 23.2 +++ b/app/main/initiative/new.lua Thu Dec 10 12:00:00 2009 +0100 23.3 @@ -38,8 +38,18 @@ 23.4 foreign_name = "name" 23.5 } 23.6 end 23.7 - ui.field.text{ label = _"Name", name = "name" } 23.8 - ui.field.text{ label = _"Discussion URL", name = "discussion_url" } 23.9 + ui.field.text{ label = _"Name", name = "name" } 23.10 + ui.field.text{ label = _"Discussion URL", name = "discussion_url" } 23.11 + ui.field.select{ 23.12 + label = _"Wiki engine", 23.13 + name = "formatting_engine", 23.14 + foreign_records = { 23.15 + { id = "rocketwiki", name = "RocketWiki" }, 23.16 + { id = "compat", name = _"Traditional wiki syntax" } 23.17 + }, 23.18 + foreign_id = "id", 23.19 + foreign_name = "name" 23.20 + } 23.21 ui.field.text{ label = _"Draft", name = "draft", multiline = true, attr = { style = "height: 50ex;" } } 23.22 ui.submit{ text = _"Save" } 23.23 end
24.1 --- a/app/main/initiative/show.lua Mon Nov 30 12:00:00 2009 +0100 24.2 +++ b/app/main/initiative/show.lua Thu Dec 10 12:00:00 2009 +0100 24.3 @@ -1,5 +1,15 @@ 24.4 local initiative = Initiative:new_selector():add_where{ "id = ?", param.get_id()}:single_object_mode():exec() 24.5 24.6 + 24.7 + 24.8 +execute.view{ 24.9 + module = "issue", 24.10 + view = "_show_head", 24.11 + params = { issue = initiative.issue } 24.12 +} 24.13 + 24.14 +local initiator = Initiator:by_pk(initiative.id, app.session.member.id) 24.15 + 24.16 --slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(initiative.id) .. '.rss" />') 24.17 24.18 execute.view{ 24.19 @@ -8,6 +18,8 @@ 24.20 params = { initiative = initiative } 24.21 } 24.22 24.23 +--[[ 24.24 + 24.25 execute.view{ 24.26 module = "delegation", 24.27 view = "_show_box", 24.28 @@ -20,6 +32,7 @@ 24.29 params = { issue = initiative.issue } 24.30 } 24.31 24.32 + 24.33 slot.select("path", function() 24.34 ui.link{ 24.35 content = _"Area '#{name}'":gsub("#{name}", initiative.issue.area.name), 24.36 @@ -37,29 +50,27 @@ 24.37 end) 24.38 24.39 slot.put_into("title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) )) 24.40 +--]] 24.41 + 24.42 +slot.put_into("sub_title", encode.html(_"Initiative: '#{name}'":gsub("#{name}", initiative.shortened_name) )) 24.43 24.44 slot.select("actions", function() 24.45 24.46 - local initiator = Initiator:by_pk(initiative.id, app.session.member.id) 24.47 - 24.48 - if initiator then 24.49 + if not initiative.issue.fully_frozen and not initiative.issue.closed then 24.50 ui.link{ 24.51 content = function() 24.52 - ui.image{ static = "icons/16/script_add.png" } 24.53 - slot.put(_"Edit draft") 24.54 + ui.image{ static = "icons/16/script.png" } 24.55 + slot.put(_"Show other initiatives") 24.56 end, 24.57 - module = "draft", 24.58 - view = "new", 24.59 - params = { initiative_id = initiative.id } 24.60 + module = "issue", 24.61 + view = "show", 24.62 + id = initiative.issue.id 24.63 } 24.64 - end 24.65 - 24.66 - if not initiative.issue.fully_frozen and not initiative.issue.closed then 24.67 ui.link{ 24.68 attr = { class = "action" }, 24.69 content = function() 24.70 ui.image{ static = "icons/16/script_add.png" } 24.71 - slot.put(_"Create alternative initiative" ) 24.72 + slot.put(_"Create alternative initiative") 24.73 end, 24.74 module = "initiative", 24.75 view = "new", 24.76 @@ -68,28 +79,50 @@ 24.77 end 24.78 -- ui.twitter("http://example.com/i" .. tostring(initiative.id) .. " " .. initiative.name) 24.79 24.80 - if initiative.discussion_url and #initiative.discussion_url > 0 then 24.81 - ui.link{ 24.82 - attr = { 24.83 - target = _"blank", 24.84 - title = initiative.discussion_url 24.85 - }, 24.86 +end) 24.87 + 24.88 + 24.89 +util.help("initiative.show") 24.90 + 24.91 + 24.92 +ui.container{ 24.93 + attr = { class = "vertical" }, 24.94 + content = function() 24.95 + ui.container{ 24.96 + attr = { class = "ui_field_label" }, 24.97 + content = _"Discussion URL" 24.98 + } 24.99 + ui.tag{ 24.100 + tag = "span", 24.101 content = function() 24.102 - ui.image{ static = "icons/16/comments.png" } 24.103 - slot.put(_"External discussion") 24.104 - end, 24.105 - external = initiative.discussion_url 24.106 + if initiative.discussion_url and #initiative.discussion_url > 0 then 24.107 + ui.link{ 24.108 + attr = { 24.109 + class = "actions", 24.110 + target = _"blank", 24.111 + title = initiative.discussion_url 24.112 + }, 24.113 + content = function() 24.114 + slot.put(encode.html(initiative.discussion_url)) 24.115 + end, 24.116 + external = initiative.discussion_url 24.117 + } 24.118 + end 24.119 + slot.put(" ") 24.120 + if initiator then 24.121 + ui.link{ 24.122 + attr = { class = "actions" }, 24.123 + content = _"(change URL)", 24.124 + module = "initiative", 24.125 + view = "edit", 24.126 + id = initiative.id 24.127 + } 24.128 + end 24.129 + end 24.130 } 24.131 end 24.132 - if initiator then 24.133 - ui.link{ 24.134 - content = _"(change)", 24.135 - module = "initiative", 24.136 - view = "edit", 24.137 - id = initiative.id 24.138 - } 24.139 - end 24.140 -end) 24.141 +} 24.142 + 24.143 24.144 24.145 ui.container{ 24.146 @@ -122,7 +155,14 @@ 24.147 }, 24.148 attr = { class = "vertical" }, 24.149 content = function() 24.150 - ui.field.text{ label = _"Name", name = "name" } 24.151 + local supported = Supporter:by_pk(initiative.id, app.session.member.id) and true or false 24.152 + if not supported then 24.153 + ui.field.text{ 24.154 + attr = { class = "warning" }, 24.155 + value = _"You are currently not supporting this initiative. By adding suggestions to this initiative you will automatically become a potential supporter." 24.156 + } 24.157 + end 24.158 + ui.field.text{ label = _"Title (80 chars max)", name = "name" } 24.159 ui.field.text{ label = _"Description", name = "description", multiline = true } 24.160 ui.field.select{ 24.161 label = _"Degree", 24.162 @@ -183,11 +223,23 @@ 24.163 end 24.164 end 24.165 24.166 + 24.167 ui.tabs{ 24.168 { 24.169 name = "current_draft", 24.170 label = _"Current draft", 24.171 content = function() 24.172 + if initiator then 24.173 + ui.link{ 24.174 + content = function() 24.175 + ui.image{ static = "icons/16/script_add.png" } 24.176 + slot.put(_"Edit draft") 24.177 + end, 24.178 + module = "draft", 24.179 + view = "new", 24.180 + params = { initiative_id = initiative.id } 24.181 + } 24.182 + end 24.183 execute.view{ module = "draft", view = "_show", params = { draft = initiative.current_draft } } 24.184 end 24.185 }, 24.186 @@ -195,7 +247,14 @@ 24.187 name = "suggestion", 24.188 label = _"Suggestions", 24.189 content = function() 24.190 - execute.view{ module = "suggestion", view = "_list", params = { suggestions_selector = initiative:get_reference_selector("suggestions") } } 24.191 + execute.view{ 24.192 + module = "suggestion", 24.193 + view = "_list", 24.194 + params = { 24.195 + initiative = initiative, 24.196 + suggestions_selector = initiative:get_reference_selector("suggestions") 24.197 + } 24.198 + } 24.199 slot.put("<br />") 24.200 if not initiative.issue.frozen and not initiative.issue.closed then 24.201 ui.link{ 24.202 @@ -220,8 +279,8 @@ 24.203 initiative = initiative, 24.204 members_selector = initiative:get_reference_selector("supporting_members_snapshot") 24.205 :join("issue", nil, "issue.id = direct_supporter_snapshot.issue_id") 24.206 - :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") 24.207 - :add_field("direct_population_snapshot.weight") 24.208 + :join("direct_interest_snapshot", nil, "direct_interest_snapshot.event = issue.latest_snapshot_event AND direct_interest_snapshot.issue_id = issue.id AND direct_interest_snapshot.member_id = member.id") 24.209 + :add_field("direct_interest_snapshot.weight") 24.210 :add_where("direct_supporter_snapshot.event = issue.latest_snapshot_event") 24.211 } 24.212 }
25.1 --- a/app/main/interest/_show_box.lua Mon Nov 30 12:00:00 2009 +0100 25.2 +++ b/app/main/interest/_show_box.lua Thu Dec 10 12:00:00 2009 +0100 25.3 @@ -1,73 +1,71 @@ 25.4 25.5 local issue = param.get("issue", "table") 25.6 25.7 - 25.8 -slot.select("interest", function() 25.9 - local interest = Interest:by_pk(issue.id, app.session.member.id) 25.10 +local interest = Interest:by_pk(issue.id, app.session.member.id) 25.11 25.12 - ui.container{ 25.13 - attr = { 25.14 - class = "head", 25.15 - onclick = "document.getElementById('interest_content').style.display = 'block';" 25.16 - }, 25.17 - content = function() 25.18 - if interest then 25.19 - ui.field.text{ value = _"You are interested. [more]" } 25.20 - else 25.21 - ui.field.text{ value = _"You are not interested. [more]" } 25.22 - end 25.23 - end 25.24 - } 25.25 +if interest then 25.26 + slot.select("actions", function() 25.27 25.28 ui.container{ 25.29 - attr = { class = "content", id = "interest_content" }, 25.30 + attr = { class = "interest vote_info"}, 25.31 content = function() 25.32 - ui.container{ 25.33 - attr = { 25.34 - class = "close", 25.35 - style = "cursor: pointer;", 25.36 - onclick = "document.getElementById('interest_content').style.display = 'none';" 25.37 - }, 25.38 - content = _"X" 25.39 - } 25.40 - if interest then 25.41 - ui.link{ 25.42 - content = _"Remove my interest", 25.43 - module = "interest", 25.44 - action = "update", 25.45 - params = { issue_id = issue.id, delete = true }, 25.46 - routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } 25.47 + ui.container{ 25.48 + attr = { 25.49 + class = "head head_active", 25.50 + onclick = "document.getElementById('interest_content').style.display = 'block';" 25.51 + }, 25.52 + content = function() 25.53 + slot.put(_"Your are interested") 25.54 + ui.image{ 25.55 + static = "icons/16/dropdown.png" 25.56 + } 25.57 + end 25.58 } 25.59 - slot.put("<br />") 25.60 - slot.put("<br />") 25.61 - if interest.autoreject then 25.62 - ui.field.text{ value = _"Autoreject is on." } 25.63 - ui.link{ 25.64 - content = _"Remove autoreject", 25.65 - module = "interest", 25.66 - action = "update", 25.67 - params = { issue_id = issue.id, autoreject = false }, 25.68 - routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } 25.69 - } 25.70 - else 25.71 - ui.field.text{ value = _"Autoreject is off." } 25.72 - ui.link{ 25.73 - content = _"Set autoreject", 25.74 - module = "interest", 25.75 - action = "update", 25.76 - params = { issue_id = issue.id, autoreject = true }, 25.77 - routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } 25.78 - } 25.79 - end 25.80 - else 25.81 - ui.link{ 25.82 - content = _"Add my interest to this issue", 25.83 - module = "interest", 25.84 - action = "update", 25.85 - params = { issue_id = issue.id }, 25.86 - routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } 25.87 + 25.88 + ui.container{ 25.89 + attr = { class = "content", id = "interest_content" }, 25.90 + content = function() 25.91 + ui.container{ 25.92 + attr = { 25.93 + class = "close", 25.94 + style = "cursor: pointer;", 25.95 + onclick = "document.getElementById('interest_content').style.display = 'none';" 25.96 + }, 25.97 + content = function() 25.98 + ui.image{ static = "icons/16/cross.png" } 25.99 + end 25.100 + } 25.101 + ui.link{ 25.102 + content = _"Remove my interest", 25.103 + module = "interest", 25.104 + action = "update", 25.105 + params = { issue_id = issue.id, delete = true }, 25.106 + routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } 25.107 + } 25.108 + slot.put("<br />") 25.109 + slot.put("<br />") 25.110 + if interest.autoreject then 25.111 + ui.field.text{ value = _"Autoreject is on." } 25.112 + ui.link{ 25.113 + content = _"Remove autoreject", 25.114 + module = "interest", 25.115 + action = "update", 25.116 + params = { issue_id = issue.id, autoreject = false }, 25.117 + routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } 25.118 + } 25.119 + else 25.120 + ui.field.text{ value = _"Autoreject is off." } 25.121 + ui.link{ 25.122 + content = _"Set autoreject", 25.123 + module = "interest", 25.124 + action = "update", 25.125 + params = { issue_id = issue.id, autoreject = true }, 25.126 + routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } 25.127 + } 25.128 + end 25.129 + end 25.130 } 25.131 end 25.132 - end 25.133 - } 25.134 -end) 25.135 + } 25.136 + end) 25.137 +end 25.138 \ No newline at end of file
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/app/main/issue/_show_head.lua Thu Dec 10 12:00:00 2009 +0100 26.3 @@ -0,0 +1,56 @@ 26.4 +local issue = param.get("issue", "table") 26.5 + 26.6 +slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(issue.id) .. '.rss" />') 26.7 + 26.8 +slot.select("path", function() 26.9 + ui.link{ 26.10 + content = _"Area '#{name}'":gsub("#{name}", issue.area.name), 26.11 + module = "area", 26.12 + view = "show", 26.13 + id = issue.area.id 26.14 + } 26.15 +end) 26.16 + 26.17 +slot.put_into("title", encode.html(_"Issue ##{id} (#{policy_name})":gsub("#{id}", issue.id):gsub("#{policy_name}", issue.policy.name))) 26.18 + 26.19 +slot.select("actions", function() 26.20 + execute.view{ 26.21 + module = "interest", 26.22 + view = "_show_box", 26.23 + params = { issue = issue } 26.24 + } 26.25 + 26.26 + execute.view{ 26.27 + module = "delegation", 26.28 + view = "_show_box", 26.29 + params = { issue_id = issue.id } 26.30 + } 26.31 + 26.32 + -- TODO performance 26.33 + local interest = Interest:by_pk(issue.id, app.session.member.id) 26.34 + if not issue.closed and not issue.fully_frozen then 26.35 + if not interest then 26.36 + ui.link{ 26.37 + content = function() 26.38 + ui.image{ static = "icons/16/user_add.png" } 26.39 + slot.put(_"Add my interest") 26.40 + end, 26.41 + module = "interest", 26.42 + action = "update", 26.43 + params = { issue_id = issue.id }, 26.44 + routing = { default = { mode = "redirect", module = "issue", view = "show", id = issue.id } } 26.45 + } 26.46 + end 26.47 + end 26.48 + 26.49 + 26.50 +end) 26.51 + 26.52 + 26.53 +execute.view{ 26.54 + module = "issue", 26.55 + view = "_show_box", 26.56 + params = { issue = issue } 26.57 +} 26.58 + 26.59 +-- ui.twitter("http://example.com/t" .. tostring(issue.id))
27.1 --- a/app/main/issue/show.lua Mon Nov 30 12:00:00 2009 +0100 27.2 +++ b/app/main/issue/show.lua Thu Dec 10 12:00:00 2009 +0100 27.3 @@ -1,52 +1,12 @@ 27.4 local issue = Issue:by_id(param.get_id()) 27.5 27.6 -slot.put_into("html_head", '<link rel="alternate" type="application/rss+xml" title="RSS" href="../show/' .. tostring(issue.id) .. '.rss" />') 27.7 - 27.8 -slot.select("path", function() 27.9 - ui.link{ 27.10 - content = _"Area '#{name}'":gsub("#{name}", issue.area.name), 27.11 - module = "area", 27.12 - view = "show", 27.13 - id = issue.area.id 27.14 - } 27.15 -end) 27.16 - 27.17 -slot.put_into("title", encode.html(_"Issue ##{id} (#{policy_name})":gsub("#{id}", issue.id):gsub("#{policy_name}", issue.policy.name))) 27.18 - 27.19 -slot.select("actions", function() 27.20 - if not issue.closed then 27.21 - ui.link{ 27.22 - content = function() 27.23 - ui.image{ static = "icons/16/table_go.png" } 27.24 - slot.put(_"Delegate") 27.25 - end, 27.26 - module = "delegation", 27.27 - view = "new", 27.28 - params = { issue_id = issue.id } 27.29 - } 27.30 - end 27.31 - 27.32 - ui.twitter("http://example.com/t" .. tostring(issue.id)) 27.33 - 27.34 -end) 27.35 - 27.36 execute.view{ 27.37 - module = "interest", 27.38 - view = "_show_box", 27.39 + module = "issue", 27.40 + view = "_show_head", 27.41 params = { issue = issue } 27.42 } 27.43 27.44 -execute.view{ 27.45 - module = "delegation", 27.46 - view = "_show_box", 27.47 - params = { issue_id = issue.id } 27.48 -} 27.49 - 27.50 -execute.view{ 27.51 - module = "issue", 27.52 - view = "_show_box", 27.53 - params = { issue = issue } 27.54 -} 27.55 +util.help("issue.show") 27.56 27.57 ui.tabs{ 27.58 {
28.1 --- a/app/main/member/_action/update_avatar.lua Mon Nov 30 12:00:00 2009 +0100 28.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 28.3 @@ -1,52 +0,0 @@ 28.4 -local member_id = app.session.member_id 28.5 - 28.6 -local member_image = MemberImage:by_pk(member_id, "avatar", false) 28.7 -local member_image_scaled = MemberImage:by_pk(member_id, "avatar", true) 28.8 - 28.9 -if param.get("avatar_delete", atom.boolean) then 28.10 - if member_image then 28.11 - member_image:destroy() 28.12 - end 28.13 - if member_image_scaled then 28.14 - member_image_scaled:destroy() 28.15 - end 28.16 - slot.put_into("notice", _"Avatar has been deleted") 28.17 - return 28.18 -end 28.19 - 28.20 -local data = param.get("avatar") 28.21 - 28.22 -local data_scaled, err, status = os.pfilter(data, "convert", "-", "-thumbnail", "48x48", "jpeg:-") 28.23 - 28.24 -if status ~= 0 or data_scaled == nil then 28.25 - error("error while converting image") 28.26 -end 28.27 - 28.28 -if not member_image then 28.29 - member_image = MemberImage:new() 28.30 - member_image.member_id = member_id 28.31 - member_image.image_type = "avatar" 28.32 - member_image.scaled = false 28.33 - member_image.data = "" 28.34 - member_image:save() 28.35 -end 28.36 - 28.37 -if not member_image_scaled then 28.38 - member_image_scaled = MemberImage:new() 28.39 - member_image_scaled.member_id = member_id 28.40 - member_image_scaled.image_type = "avatar" 28.41 - member_image_scaled.scaled = true 28.42 - member_image_scaled.content_type = true 28.43 - member_image_scaled.data = "" 28.44 - member_image_scaled:save() 28.45 -end 28.46 - 28.47 -if data and #data > 0 then 28.48 - db:query{ "UPDATE member_image SET data = $ WHERE member_id = ? AND image_type='avatar' AND scaled=FALSE", { db:quote_binary(data) }, app.session.member.id } 28.49 -end 28.50 - 28.51 -if data_scaled and #data_scaled > 0 then 28.52 - db:query{ "UPDATE member_image SET data = $ WHERE member_id = ? AND image_type='avatar' AND scaled=TRUE", { db:quote_binary(data_scaled) }, app.session.member.id } 28.53 -end 28.54 - 28.55 -slot.put_into("notice", _"Avatar has been updated")
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/app/main/member/_action/update_images.lua Thu Dec 10 12:00:00 2009 +0100 29.3 @@ -0,0 +1,73 @@ 29.4 +local member_id = app.session.member_id 29.5 + 29.6 +local deleted = 0 29.7 +local updated = 0 29.8 + 29.9 +for i, image_type in ipairs{"avatar", "photo"} do 29.10 + 29.11 + local member_image = MemberImage:by_pk(member_id, image_type, false) 29.12 + local member_image_scaled = MemberImage:by_pk(member_id, image_type, true) 29.13 + 29.14 + if param.get(image_type .. "_delete", atom.boolean) then 29.15 + if member_image then 29.16 + member_image:destroy() 29.17 + end 29.18 + if member_image_scaled then 29.19 + member_image_scaled:destroy() 29.20 + end 29.21 + deleted = deleted + 1 29.22 + else 29.23 + 29.24 + local data = param.get(image_type) 29.25 + if data and #data > 0 and #data < 1024*1024 then 29.26 + local convert_func = config.member_image_convert_func[image_type] 29.27 + local data_scaled, err, status = convert_func(data) 29.28 + if status ~= 0 or data_scaled == nil then 29.29 + error("error while converting image") 29.30 + end 29.31 + 29.32 + if not member_image then 29.33 + member_image = MemberImage:new() 29.34 + member_image.member_id = member_id 29.35 + member_image.image_type = image_type 29.36 + member_image.scaled = false 29.37 + member_image.data = "" 29.38 + member_image:save() 29.39 + end 29.40 + 29.41 + if not member_image_scaled then 29.42 + member_image_scaled = MemberImage:new() 29.43 + member_image_scaled.member_id = member_id 29.44 + member_image_scaled.image_type = image_type 29.45 + member_image_scaled.scaled = true 29.46 + member_image_scaled.content_type = true 29.47 + member_image_scaled.data = "" 29.48 + member_image_scaled:save() 29.49 + end 29.50 + 29.51 + if data and #data > 0 then 29.52 + db:query{ "UPDATE member_image SET data = $ WHERE member_id = ? AND image_type='" .. image_type .. "' AND scaled=FALSE", { db:quote_binary(data) }, app.session.member.id } 29.53 + end 29.54 + 29.55 + if data_scaled and #data_scaled > 0 then 29.56 + db:query{ "UPDATE member_image SET data = $ WHERE member_id = ? AND image_type='" .. image_type .. "' AND scaled=TRUE", { db:quote_binary(data_scaled) }, app.session.member.id } 29.57 + end 29.58 + 29.59 + updated = updated + 1 29.60 + end 29.61 + end 29.62 +end 29.63 + 29.64 +if updated > 0 then 29.65 + slot.put_into("notice", _("#{number} Image(s) has been updated", { number = updated })) 29.66 +end 29.67 +if updated > 0 and deleted > 0 then 29.68 + slot.put_into("notice", " · ") 29.69 +end 29.70 +if deleted > 0 then 29.71 + slot.put_into("notice", _("#{number} Image(s) has been deleted", { number = deleted })) 29.72 +end 29.73 + 29.74 +if updated == 0 and deleted == 0 then 29.75 + slot.put_into("warning", _("No changes to your images were made")) 29.76 +end 29.77 \ No newline at end of file
30.1 --- a/app/main/member/_show.lua Mon Nov 30 12:00:00 2009 +0100 30.2 +++ b/app/main/member/_show.lua Thu Dec 10 12:00:00 2009 +0100 30.3 @@ -1,24 +1,116 @@ 30.4 local member = param.get("member", "table") 30.5 30.6 -ui.form{ 30.7 - attr = { class = "vertical" }, 30.8 - record = member, 30.9 - readonly = true, 30.10 - content = function() 30.11 - if member.admin then 30.12 - ui.field.boolean{ label = _"Admin?", name = "admin" } 30.13 +ui.tabs{ 30.14 + { 30.15 + name = "profile", 30.16 + label = _"Profile", 30.17 + content = function() 30.18 + ui.form{ 30.19 + attr = { class = "member vertical" }, 30.20 + record = member, 30.21 + readonly = true, 30.22 + content = function() 30.23 + 30.24 + ui.container{ 30.25 + attr = { class = "right" }, 30.26 + content = function() 30.27 + 30.28 + execute.view{ 30.29 + module = "member_image", 30.30 + view = "_show", 30.31 + params = { 30.32 + member = member, 30.33 + image_type = "photo" 30.34 + } 30.35 + } 30.36 + 30.37 + ui.container{ 30.38 + attr = { class = "contact_data" }, 30.39 + content = function() 30.40 + end 30.41 + } 30.42 + 30.43 + end 30.44 + } 30.45 + 30.46 + if member.admin then 30.47 + ui.field.boolean{ label = _"Admin?", name = "admin" } 30.48 + end 30.49 + if member.locked then 30.50 + ui.field.boolean{ label = _"Locked?", name = "locked" } 30.51 + end 30.52 + if member.ident_number then 30.53 + ui.field.text{ label = _"Ident number", name = "ident_number" } 30.54 + end 30.55 + ui.field.text{ label = _"Name", name = "name" } 30.56 + 30.57 + if member.realname and #member.realname > 0 then 30.58 + ui.field.text{ label = _"Real name", name = "realname" } 30.59 + end 30.60 + if member.email and #member.email > 0 then 30.61 + ui.field.text{ label = _"email", name = "email" } 30.62 + end 30.63 + if member.xmpp_address and #member.xmpp_address > 0 then 30.64 + ui.field.text{ label = _"xmpp", name = "xmpp_address" } 30.65 + end 30.66 + if member.website and #member.website > 0 then 30.67 + ui.field.text{ label = _"Website", name = "website" } 30.68 + end 30.69 + if member.phone and #member.phone > 0 then 30.70 + ui.field.text{ label = _"Phone", name = "phone" } 30.71 + end 30.72 + if member.mobile_phone and #member.mobile_phone > 0 then 30.73 + ui.field.text{ label = _"Mobile phone", name = "mobile_phone" } 30.74 + end 30.75 + if member.address and #member.address > 0 then 30.76 + ui.container{ 30.77 + content = function() 30.78 + ui.tag{ 30.79 + tag = "label", 30.80 + attr = { class = "ui_field_label" }, 30.81 + content = _"Address" 30.82 + } 30.83 + ui.tag{ 30.84 + tag = "span", 30.85 + content = function() 30.86 + slot.put(encode.html_newlines(member.address)) 30.87 + end 30.88 + } 30.89 + end 30.90 + } 30.91 + end 30.92 + if member.profession and #member.profession > 0 then 30.93 + ui.field.text{ label = _"Profession", name = "profession" } 30.94 + end 30.95 + if member.birthday and #member.birthday > 0 then 30.96 + ui.field.text{ label = _"Birthday", name = "birthday" } 30.97 + end 30.98 + if member.organizational_unit and #member.organizational_unit > 0 then 30.99 + ui.field.text{ label = _"Organizational unit", name = "organizational_unit" } 30.100 + end 30.101 + if member.internal_posts and #member.internal_posts > 0 then 30.102 + ui.field.text{ label = _"Internal posts", name = "internal_posts" } 30.103 + end 30.104 + if member.external_memberships and #member.external_memberships > 0 then 30.105 + ui.field.text{ label = _"Memberships", name = "external_memberships", multiline = true } 30.106 + end 30.107 + if member.external_posts and #member.external_posts > 0 then 30.108 + ui.field.text{ label = _"Posts", name = "external_posts", multiline = true } 30.109 + end 30.110 + slot.put('<br style="clear: right;" />') 30.111 + 30.112 + end 30.113 + } 30.114 + if member.statement and #member.statement > 0 then 30.115 + ui.container{ 30.116 + attr = { class = "member_statement wiki" }, 30.117 + content = function() 30.118 + slot.put(format.wiki_text(member.statement)) 30.119 + end 30.120 + } 30.121 + end 30.122 end 30.123 - if member.locked then 30.124 - ui.field.boolean{ label = _"Locked?", name = "locked" } 30.125 - end 30.126 - if member.ident_number then 30.127 - ui.field.text{ label = _"Ident number", name = "ident_number" } 30.128 - end 30.129 - ui.submit{ text = _"Save" } 30.130 - end 30.131 -} 30.132 - 30.133 -ui.tabs{ 30.134 + }, 30.135 { 30.136 name = "areas", 30.137 label = _"Areas", 30.138 @@ -42,8 +134,8 @@ 30.139 end 30.140 }, 30.141 { 30.142 - name = "initiatives", 30.143 - label = _"Initiatives", 30.144 + name = "supported_initiatives", 30.145 + label = _"Supported initiatives", 30.146 content = function() 30.147 execute.view{ 30.148 module = "initiative", 30.149 @@ -53,6 +145,17 @@ 30.150 end 30.151 }, 30.152 { 30.153 + name = "initiatied_initiatives", 30.154 + label = _"Initiated initiatives", 30.155 + content = function() 30.156 + execute.view{ 30.157 + module = "initiative", 30.158 + view = "_list", 30.159 + params = { initiatives_selector = member:get_reference_selector("initiated_initiatives") } 30.160 + } 30.161 + end 30.162 + }, 30.163 + { 30.164 name = "incoming_delegations", 30.165 label = _"Incoming delegations", 30.166 content = function() 30.167 @@ -64,7 +167,7 @@ 30.168 end 30.169 }, 30.170 { 30.171 - name = "outgoing_delegations", 30.172 + name = "Outgoing delegations", 30.173 label = _"Outgoing delegations", 30.174 content = function() 30.175 execute.view{
31.1 --- a/app/main/member/_show_thumb.lua Mon Nov 30 12:00:00 2009 +0100 31.2 +++ b/app/main/member/_show_thumb.lua Thu Dec 10 12:00:00 2009 +0100 31.3 @@ -58,19 +58,21 @@ 31.4 end 31.5 end 31.6 } 31.7 - 31.8 + 31.9 ui.link{ 31.10 attr = { title = _"Show member" }, 31.11 module = "member", 31.12 view = "show", 31.13 id = member.id, 31.14 content = function() 31.15 - ui.image{ 31.16 - attr = { width = 48, height = 48 }, 31.17 - module = "member", 31.18 - view = "avatar", 31.19 - id = member.id, 31.20 - extension = "jpg" 31.21 + execute.view{ 31.22 + module = "member_image", 31.23 + view = "_show", 31.24 + params = { 31.25 + member = member, 31.26 + image_type = "avatar", 31.27 + show_dummy = true 31.28 + } 31.29 } 31.30 ui.container{ 31.31 attr = { class = "member_name" },
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/app/main/member/_show_thumb.lua.orig Thu Dec 10 12:00:00 2009 +0100 32.3 @@ -0,0 +1,86 @@ 32.4 +local member = param.get("member", "table") 32.5 + 32.6 +local issue = param.get("issue", "table") 32.7 +local initiative = param.get("initiative", "table") 32.8 +local trustee = param.get("trustee", "table") 32.9 + 32.10 +local name 32.11 +if member.name_highlighted then 32.12 + name = encode.highlight(member.name_highlighted) 32.13 +else 32.14 + name = encode.html(member.name) 32.15 +end 32.16 + 32.17 +ui.container{ 32.18 + attr = { class = "member_thumb" }, 32.19 + content = function() 32.20 + ui.container{ 32.21 + attr = { class = "flags" }, 32.22 + content = function() 32.23 + if (issue or initiative) and member.weight > 1 then 32.24 + local module 32.25 + if issue then 32.26 + module = "interest" 32.27 + elseif initiative then 32.28 + module = "supporter" 32.29 + end 32.30 + ui.link{ 32.31 + attr = { title = _"Number of incoming delegations, follow link to see more details" }, 32.32 + content = _("+ #{weight}", { weight = member.weight - 1 }), 32.33 + module = module, 32.34 + view = "show_incoming", 32.35 + params = { 32.36 + member_id = member.id, 32.37 + initiative_id = initiative and initiative.id or nil, 32.38 + issue_id = issue and issue.id or nil 32.39 + } 32.40 + } 32.41 + end 32.42 + -- TODO performance 32.43 + local contact = Contact:by_pk(app.session.member.id, member.id) 32.44 + if contact then 32.45 + ui.image{ 32.46 + attr = { 32.47 + alt = _"You have saved this member as contact", 32.48 + title = _"You have saved this member as contact" 32.49 + }, 32.50 + static = "icons/16/bullet_disk.png" 32.51 + } 32.52 + end 32.53 + end 32.54 + } 32.55 + 32.56 + ui.link{ 32.57 + attr = { title = _"Show member" }, 32.58 + module = "member", 32.59 + view = "show", 32.60 + id = member.id, 32.61 + content = function() 32.62 + execute.view{ 32.63 + module = "member_image", 32.64 + view = "_show", 32.65 + params = { 32.66 + member = member, 32.67 + image_type = "avatar", 32.68 + show_dummy = true 32.69 + } 32.70 + } 32.71 + end 32.72 + } 32.73 + 32.74 + ui.link{ 32.75 + attr = { title = _"Show member" }, 32.76 + module = "member", 32.77 + view = "show", 32.78 + id = member.id, 32.79 + content = function() 32.80 + ui.container{ 32.81 + attr = { class = "member_name" }, 32.82 + content = function() 32.83 + slot.put(name) 32.84 + end 32.85 + } 32.86 + end 32.87 + } 32.88 + end 32.89 +}
33.1 --- a/app/main/member/avatar.lua Mon Nov 30 12:00:00 2009 +0100 33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 33.3 @@ -1,15 +0,0 @@ 33.4 -local record = MemberImage:by_pk(param.get_id(), "avatar", true) 33.5 - 33.6 -if record == nil then 33.7 - print('Location: ' .. encode.url{ static = 'avatar.jpg' } .. '\n\n') 33.8 - exit() 33.9 -end 33.10 - 33.11 -print('Content-type: ' .. record.content_type .. '\n') 33.12 - 33.13 -if record then 33.14 - io.stdout:write(record.data) 33.15 -else 33.16 -end 33.17 - 33.18 -exit()
34.1 --- a/app/main/member/edit.lua Mon Nov 30 12:00:00 2009 +0100 34.2 +++ b/app/main/member/edit.lua Thu Dec 10 12:00:00 2009 +0100 34.3 @@ -1,4 +1,4 @@ 34.4 -slot.put_into("title", _"Edit my page") 34.5 +slot.put_into("title", _"Edit my profile") 34.6 34.7 slot.select("actions", function() 34.8 ui.link{ 34.9 @@ -11,6 +11,8 @@ 34.10 } 34.11 end) 34.12 34.13 +util.help("member.edit", _"Edit my page") 34.14 + 34.15 ui.form{ 34.16 record = app.session.member, 34.17 attr = { class = "vertical" },
35.1 --- a/app/main/member/edit_avatar.lua Mon Nov 30 12:00:00 2009 +0100 35.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 35.3 @@ -1,33 +0,0 @@ 35.4 -slot.put_into("title", _"Upload avatar") 35.5 - 35.6 -slot.select("actions", function() 35.7 - ui.link{ 35.8 - content = function() 35.9 - ui.image{ static = "icons/16/cancel.png" } 35.10 - slot.put(_"Cancel") 35.11 - end, 35.12 - module = "index", 35.13 - view = "index" 35.14 - } 35.15 -end) 35.16 - 35.17 -ui.form{ 35.18 - record = app.session.member, 35.19 - attr = { 35.20 - class = "vertical", 35.21 - enctype = 'multipart/form-data' 35.22 - }, 35.23 - module = "member", 35.24 - action = "update_avatar", 35.25 - routing = { 35.26 - ok = { 35.27 - mode = "redirect", 35.28 - module = "index", 35.29 - view = "index" 35.30 - } 35.31 - }, 35.32 - content = function() 35.33 - ui.field.image{ field_name = "avatar", label = _"Avatar" } 35.34 - ui.submit{ value = _"Save" } 35.35 - end 35.36 -} 35.37 \ No newline at end of file
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/app/main/member/edit_images.lua Thu Dec 10 12:00:00 2009 +0100 36.3 @@ -0,0 +1,52 @@ 36.4 +slot.put_into("title", _"Upload images") 36.5 + 36.6 +slot.select("actions", function() 36.7 + ui.link{ 36.8 + content = function() 36.9 + ui.image{ static = "icons/16/cancel.png" } 36.10 + slot.put(_"Cancel") 36.11 + end, 36.12 + module = "index", 36.13 + view = "index" 36.14 + } 36.15 +end) 36.16 + 36.17 +util.help("member.edit_images", _"Images") 36.18 + 36.19 +ui.form{ 36.20 + record = app.session.member, 36.21 + attr = { 36.22 + class = "vertical", 36.23 + enctype = 'multipart/form-data' 36.24 + }, 36.25 + module = "member", 36.26 + action = "update_images", 36.27 + routing = { 36.28 + ok = { 36.29 + mode = "redirect", 36.30 + module = "index", 36.31 + view = "index" 36.32 + } 36.33 + }, 36.34 + content = function() 36.35 + execute.view{ 36.36 + module = "member_image", 36.37 + view = "_show", 36.38 + params = { 36.39 + member = app.session.member, 36.40 + image_type = "avatar" 36.41 + } 36.42 + } 36.43 + ui.field.image{ field_name = "avatar", label = _"Avatar" } 36.44 + execute.view{ 36.45 + module = "member_image", 36.46 + view = "_show", 36.47 + params = { 36.48 + member = app.session.member, 36.49 + image_type = "photo" 36.50 + } 36.51 + } 36.52 + ui.field.image{ field_name = "photo", label = _"Photo" } 36.53 + ui.submit{ value = _"Save" } 36.54 + end 36.55 +} 36.56 \ No newline at end of file
37.1 --- a/app/main/member/list.lua Mon Nov 30 12:00:00 2009 +0100 37.2 +++ b/app/main/member/list.lua Thu Dec 10 12:00:00 2009 +0100 37.3 @@ -1,7 +1,9 @@ 37.4 slot.put_into("title", _"Member list") 37.5 37.6 +util.help("member.list") 37.7 + 37.8 execute.view{ 37.9 module = "member", 37.10 view = "_list", 37.11 - params = { members_selector = Member:new_selector():add_order_by("login") } 37.12 + params = { members_selector = Member:new_selector():add_order_by("name") } 37.13 }
38.1 --- a/app/main/member/show.lua Mon Nov 30 12:00:00 2009 +0100 38.2 +++ b/app/main/member/show.lua Thu Dec 10 12:00:00 2009 +0100 38.3 @@ -1,12 +1,13 @@ 38.4 local member = Member:by_id(param.get_id()) 38.5 38.6 slot.select("title", function() 38.7 - ui.image{ 38.8 - attr = { class = "avatar" }, 38.9 - module = "member", 38.10 - view = "avatar", 38.11 - extension = "jpg", 38.12 - id = member.id 38.13 + execute.view{ 38.14 + module = "member_image", 38.15 + view = "_show", 38.16 + params = { 38.17 + member = member, 38.18 + image_type = "avatar" 38.19 + } 38.20 } 38.21 end) 38.22 38.23 @@ -19,9 +20,15 @@ 38.24 local contact = Contact:by_pk(app.session.member.id, member.id) 38.25 if contact then 38.26 slot.select("actions", function() 38.27 - ui.field.text{ value = _"You have saved this member as contact." } 38.28 + ui.container{ 38.29 + attr = { class = "interest" }, 38.30 + content = _"You have saved this member as contact." 38.31 + } 38.32 ui.link{ 38.33 - text = _"Remove from contacts", 38.34 + content = function() 38.35 + ui.image{ static = "icons/16/book_delete.png" } 38.36 + slot.put(encode.html(_"Remove from contacts")) 38.37 + end, 38.38 module = "contact", 38.39 action = "remove_member", 38.40 id = contact.other_member_id, 38.41 @@ -60,6 +67,7 @@ 38.42 end 38.43 end 38.44 38.45 +util.help("member.show", _"Member page") 38.46 38.47 execute.view{ 38.48 module = "member",
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/app/main/member_image/_show.lua Thu Dec 10 12:00:00 2009 +0100 39.3 @@ -0,0 +1,27 @@ 39.4 +local member = param.get("member", "table") 39.5 +local image_type = param.get("image_type") 39.6 +local show_dummy = param.get("show_dummy", atom.boolean) 39.7 + 39.8 +local image = member:get_reference_selector("images") 39.9 + :add_where{ "image_type = ?", image_type } 39.10 + :optional_object_mode() 39.11 + :exec() 39.12 +if image or show_dummy then 39.13 + if config.fastpath_url_func then 39.14 + ui.image{ 39.15 + attr = { class = "member_image member_image_" .. image_type }, 39.16 + external = config.fastpath_url_func(member.id, image_type) 39.17 + } 39.18 + else 39.19 + ui.image{ 39.20 + attr = { class = "member_image member_image_" .. image_type }, 39.21 + module = "member_image", 39.22 + view = "show", 39.23 + extension = "jpg", 39.24 + id = member.id, 39.25 + params = { 39.26 + image_type = image_type 39.27 + } 39.28 + } 39.29 + end 39.30 +end
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/app/main/member_image/show.lua Thu Dec 10 12:00:00 2009 +0100 40.3 @@ -0,0 +1,21 @@ 40.4 +local image_type = param.get("image_type") 40.5 +local record = MemberImage:by_pk(param.get_id(), image_type, true) 40.6 + 40.7 +if record == nil then 40.8 + local default_file = config.member_image_default_file[image_type] 40.9 + if default_file then 40.10 + print('Location: ' .. encode.url{ static = default_file } .. '\n\n') 40.11 + else 40.12 + print('Location: ' .. encode.url{ static = 'icons/16/lightning.png' } .. '\n\n') 40.13 + end 40.14 + exit() 40.15 +end 40.16 + 40.17 +print('Content-type: ' .. record.content_type .. '\n') 40.18 + 40.19 +if record then 40.20 + io.stdout:write(record.data) 40.21 +else 40.22 +end 40.23 + 40.24 +exit()
41.1 --- a/app/main/membership/_action/update.lua Mon Nov 30 12:00:00 2009 +0100 41.2 +++ b/app/main/membership/_action/update.lua Thu Dec 10 12:00:00 2009 +0100 41.3 @@ -25,4 +25,4 @@ 41.4 41.5 membership:save() 41.6 41.7 -slot.put_into("notice", _"Membership updated") 41.8 +--slot.put_into("notice", _"Membership updated")
42.1 --- a/app/main/membership/_show_box.lua Mon Nov 30 12:00:00 2009 +0100 42.2 +++ b/app/main/membership/_show_box.lua Thu Dec 10 12:00:00 2009 +0100 42.3 @@ -1,34 +1,40 @@ 42.4 local area = param.get("area", "table") 42.5 42.6 +local membership = Membership:by_pk(area.id, app.session.member.id) 42.7 + 42.8 slot.select("interest", function() 42.9 - local membership = Membership:by_pk(area.id, app.session.member.id) 42.10 42.11 - ui.container{ 42.12 - attr = { 42.13 - class = "head", 42.14 - onclick = "document.getElementById('membership_content').style.display = 'block';" 42.15 - }, 42.16 - content = function() 42.17 - if membership then 42.18 - ui.field.text{ value = _"You are member. [more]" } 42.19 - else 42.20 - ui.field.text{ value = _"You are not a member. [more]" } 42.21 + if membership then 42.22 + 42.23 + ui.container{ 42.24 + attr = { 42.25 + class = "head head_active", 42.26 + onclick = "document.getElementById('membership_content').style.display = 'block';" 42.27 + }, 42.28 + content = function() 42.29 + ui.image{ 42.30 + static = "icons/16/user_green.png" 42.31 + } 42.32 + slot.put(_"You are member") 42.33 + ui.image{ 42.34 + static = "icons/16/dropdown.png" 42.35 + } 42.36 end 42.37 - end 42.38 - } 42.39 - 42.40 - ui.container{ 42.41 - attr = { class = "content", id = "membership_content" }, 42.42 - content = function() 42.43 - ui.container{ 42.44 - attr = { 42.45 - class = "close", 42.46 - style = "cursor: pointer;", 42.47 - onclick = "document.getElementById('membership_content').style.display = 'none';" 42.48 - }, 42.49 - content = _"X" 42.50 - } 42.51 - if membership then 42.52 + } 42.53 + 42.54 + ui.container{ 42.55 + attr = { class = "content", id = "membership_content" }, 42.56 + content = function() 42.57 + ui.container{ 42.58 + attr = { 42.59 + class = "close", 42.60 + style = "cursor: pointer;", 42.61 + onclick = "document.getElementById('membership_content').style.display = 'none';" 42.62 + }, 42.63 + content = function() 42.64 + ui.image{ static = "icons/16/cross.png" } 42.65 + end 42.66 + } 42.67 ui.link{ 42.68 content = _"Remove my membership", 42.69 module = "membership", 42.70 @@ -55,15 +61,26 @@ 42.71 routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } } 42.72 } 42.73 end 42.74 - else 42.75 - ui.link{ 42.76 - content = _"Add my membership to this area", 42.77 - module = "membership", 42.78 - action = "update", 42.79 - params = { area_id = area.id }, 42.80 - routing = { default = { mode = "redirect", module = "area", view = "show", id = area.id } } 42.81 + end 42.82 + } 42.83 + else 42.84 + ui.link{ 42.85 + content = function() 42.86 + ui.image{ static = "icons/16/user_add.png" } 42.87 + slot.put(_"Become a member") 42.88 + end, 42.89 + module = "membership", 42.90 + action = "update", 42.91 + params = { area_id = area.id }, 42.92 + routing = { 42.93 + default = { 42.94 + mode = "redirect", 42.95 + module = "area", 42.96 + view = "show", 42.97 + id = area.id 42.98 } 42.99 - end 42.100 - end 42.101 - } 42.102 + } 42.103 + } 42.104 + end 42.105 + 42.106 end)
43.1 --- a/app/main/suggestion/_list.lua Mon Nov 30 12:00:00 2009 +0100 43.2 +++ b/app/main/suggestion/_list.lua Thu Dec 10 12:00:00 2009 +0100 43.3 @@ -1,228 +1,292 @@ 43.4 + 43.5 +local initiative = param.get("initiative", "table") 43.6 local suggestions_selector = param.get("suggestions_selector", "table") 43.7 43.8 -ui.paginate{ 43.9 +ui.order{ 43.10 + name = name, 43.11 selector = suggestions_selector, 43.12 + options = { 43.13 + { 43.14 + name = "all", 43.15 + label = _"all", 43.16 + order_by = "minus2_unfulfilled_count + minus1_unfulfilled_count + minus2_fulfilled_count + minus1_fulfilled_count + plus2_unfulfilled_count + plus1_unfulfilled_count + plus2_fulfilled_count + plus1_fulfilled_count DESC, id" 43.17 + }, 43.18 + { 43.19 + name = "plus2", 43.20 + label = _"must", 43.21 + order_by = "plus2_unfulfilled_count + plus2_fulfilled_count DESC, id" 43.22 + }, 43.23 + { 43.24 + name = "plus", 43.25 + label = _"must/should", 43.26 + order_by = "plus2_unfulfilled_count + plus1_unfulfilled_count + plus2_fulfilled_count + plus1_fulfilled_count DESC, id" 43.27 + }, 43.28 + { 43.29 + name = "minus", 43.30 + label = _"must/should not", 43.31 + order_by = "minus2_unfulfilled_count + minus1_unfulfilled_count + minus2_fulfilled_count + minus1_fulfilled_count DESC, id" 43.32 + }, 43.33 + { 43.34 + name = "minus2", 43.35 + label = _"must not", 43.36 + order_by = "minus2_unfulfilled_count + minus2_fulfilled_count DESC, id" 43.37 + }, 43.38 + { 43.39 + name = "unfulfilled", 43.40 + label = _"not implemented", 43.41 + order_by = "minus2_unfulfilled_count + minus1_unfulfilled_count + plus2_unfulfilled_count + plus1_unfulfilled_count DESC, id" 43.42 + }, 43.43 + { 43.44 + name = "plus2_unfulfilled", 43.45 + label = _"must", 43.46 + order_by = "plus2_unfulfilled_count DESC, id" 43.47 + }, 43.48 + { 43.49 + name = "plus_unfulfilled", 43.50 + label = _"must/should", 43.51 + order_by = "plus2_unfulfilled_count + plus1_unfulfilled_count DESC, id" 43.52 + }, 43.53 + { 43.54 + name = "minus_unfulfilled", 43.55 + label = _"must/should not", 43.56 + order_by = "minus2_unfulfilled_count + minus1_unfulfilled_count DESC, id" 43.57 + }, 43.58 + { 43.59 + name = "minus2_unfulfilled", 43.60 + label = _"must not", 43.61 + order_by = "minus2_unfulfilled_count DESC, id" 43.62 + }, 43.63 + }, 43.64 content = function() 43.65 - ui.list{ 43.66 - attr = { style = "table-layout: fixed;" }, 43.67 - records = suggestions_selector:exec(), 43.68 - columns = { 43.69 - { 43.70 - label = _"Suggestion", 43.71 - content = function(record) 43.72 - ui.link{ 43.73 - text = record.name, 43.74 - module = "suggestion", 43.75 - view = "show", 43.76 - id = record.id 43.77 - } 43.78 - end 43.79 - }, 43.80 - { 43.81 - label = _"Collective opinion", 43.82 - label_attr = { style = "width: 101px;" }, 43.83 - content = function(record) 43.84 - if record.minus2_unfulfilled_count then 43.85 - local max_value = record.initiative.issue.population 43.86 - ui.bargraph{ 43.87 - max_value = max_value, 43.88 - width = 100, 43.89 - bars = { 43.90 - { color = "#ddd", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count - record.minus2_fulfilled_count - record.minus1_fulfilled_count }, 43.91 - { color = "#f88", value = record.minus1_unfulfilled_count + record.minus1_fulfilled_count }, 43.92 - { color = "#a00", value = record.minus2_unfulfilled_count + record.minus2_fulfilled_count }, 43.93 - { color = "#0a0", value = record.plus2_unfulfilled_count + record.plus2_fulfilled_count }, 43.94 - { color = "#8f8", value = record.plus1_unfulfilled_count + record.plus1_fulfilled_count }, 43.95 - { color = "#ddd", value = max_value - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count - record.plus1_fulfilled_count - record.plus2_fulfilled_count }, 43.96 + ui.paginate{ 43.97 + selector = suggestions_selector, 43.98 + content = function() 43.99 + ui.list{ 43.100 + attr = { style = "table-layout: fixed;" }, 43.101 + records = suggestions_selector:exec(), 43.102 + columns = { 43.103 + { 43.104 + label = _"Suggestion", 43.105 + content = function(record) 43.106 + ui.link{ 43.107 + text = record.name, 43.108 + module = "suggestion", 43.109 + view = "show", 43.110 + id = record.id 43.111 } 43.112 - } 43.113 - end 43.114 - end 43.115 - }, 43.116 - { 43.117 - label = _"My opinion", 43.118 - content = function(record) 43.119 - local degree 43.120 - local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.121 - if opinion then 43.122 - degree = opinion.degree 43.123 - end 43.124 - ui.link{ 43.125 - attr = { class = "action" .. (degree == -2 and " active_red2" or "") }, 43.126 - text = _"must not", 43.127 - module = "opinion", 43.128 - action = "update", 43.129 - routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.130 - params = { 43.131 - suggestion_id = record.id, 43.132 - degree = -2 43.133 - } 43.134 - } 43.135 - ui.link{ 43.136 - attr = { class = "action" .. (degree == -1 and " active_red1" or "") }, 43.137 - text = _"should not", 43.138 - module = "opinion", 43.139 - action = "update", 43.140 - routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.141 - params = { 43.142 - suggestion_id = record.id, 43.143 - degree = -1 43.144 - } 43.145 - } 43.146 - ui.link{ 43.147 - attr = { class = "action" .. (degree == nil and " active" or "") }, 43.148 - text = _"neutral", 43.149 - module = "opinion", 43.150 - action = "update", 43.151 - routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.152 - params = { 43.153 - suggestion_id = record.id, 43.154 - delete = true 43.155 - } 43.156 - } 43.157 - ui.link{ 43.158 - attr = { class = "action" .. (degree == 1 and " active_green1" or "") }, 43.159 - text = _"should", 43.160 - module = "opinion", 43.161 - action = "update", 43.162 - routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.163 - params = { 43.164 - suggestion_id = record.id, 43.165 - degree = 1 43.166 - } 43.167 - } 43.168 - ui.link{ 43.169 - attr = { class = "action" .. (degree == 2 and " active_green2" or "") }, 43.170 - text = _"must", 43.171 - module = "opinion", 43.172 - action = "update", 43.173 - routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.174 - params = { 43.175 - suggestion_id = record.id, 43.176 - degree = 2 43.177 - } 43.178 - } 43.179 - end 43.180 - }, 43.181 - { 43.182 - content = function(record) 43.183 - local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.184 - if opinion and not opinion.fulfilled then 43.185 - ui.image{ static = "icons/16/cross.png" } 43.186 - end 43.187 - end 43.188 - }, 43.189 - { 43.190 - label = _"Suggestion currently not implemented", 43.191 - label_attr = { style = "width: 101px;" }, 43.192 - content = function(record) 43.193 - if record.minus2_unfulfilled_count then 43.194 - local max_value = record.initiative.issue.population 43.195 - ui.bargraph{ 43.196 - max_value = max_value, 43.197 - width = 100, 43.198 - bars = { 43.199 - { color = "#ddd", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count }, 43.200 - { color = "#f88", value = record.minus1_unfulfilled_count }, 43.201 - { color = "#a00", value = record.minus2_unfulfilled_count }, 43.202 - { color = "#0a0", value = record.plus2_unfulfilled_count }, 43.203 - { color = "#8f8", value = record.plus1_unfulfilled_count }, 43.204 - { color = "#ddd", value = max_value - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count }, 43.205 - } 43.206 - } 43.207 - end 43.208 - end 43.209 - }, 43.210 - { 43.211 - content = function(record) 43.212 - local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.213 - if opinion and opinion.fulfilled then 43.214 - ui.image{ static = "icons/16/tick.png" } 43.215 - end 43.216 - end 43.217 - }, 43.218 - { 43.219 - label = _"Suggestion currently implemented", 43.220 - label_attr = { style = "width: 101px;" }, 43.221 - content = function(record) 43.222 - if record.minus2_fulfilled_count then 43.223 - local max_value = record.initiative.issue.population 43.224 - ui.bargraph{ 43.225 - max_value = max_value, 43.226 - width = 100, 43.227 - bars = { 43.228 - { color = "#ddd", value = max_value - record.minus2_fulfilled_count - record.minus1_fulfilled_count }, 43.229 - { color = "#f88", value = record.minus1_fulfilled_count }, 43.230 - { color = "#a00", value = record.minus2_fulfilled_count }, 43.231 - { color = "#0a0", value = record.plus2_fulfilled_count }, 43.232 - { color = "#8f8", value = record.plus1_fulfilled_count }, 43.233 - { color = "#ddd", value = max_value - record.plus1_fulfilled_count - record.plus2_fulfilled_count }, 43.234 - } 43.235 - } 43.236 - end 43.237 - end 43.238 - }, 43.239 - { 43.240 - label_attr = { style = "width: 200px;" }, 43.241 - content = function(record) 43.242 - local degree 43.243 - local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.244 - if opinion then 43.245 - degree = opinion.degree 43.246 - end 43.247 - if opinion then 43.248 - if not opinion.fulfilled then 43.249 - local text = "" 43.250 - if opinion.degree > 0 then 43.251 - text = _"Mark suggestion as implemented and express satisfaction" 43.252 - else 43.253 - text = _"Mark suggestion as implemented and express dissatisfaction" 43.254 + end 43.255 + }, 43.256 + { 43.257 + label = _"Collective opinion", 43.258 + label_attr = { style = "width: 101px;" }, 43.259 + content = function(record) 43.260 + if record.minus2_unfulfilled_count then 43.261 + local max_value = record.initiative.issue.population 43.262 + ui.bargraph{ 43.263 + max_value = max_value, 43.264 + width = 50, 43.265 + bars = { 43.266 + { color = "#ddd", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count - record.minus2_fulfilled_count - record.minus1_fulfilled_count }, 43.267 + { color = "#f88", value = record.minus1_unfulfilled_count + record.minus1_fulfilled_count }, 43.268 + { color = "#a00", value = record.minus2_unfulfilled_count + record.minus2_fulfilled_count }, 43.269 + { color = "#0a0", value = record.plus2_unfulfilled_count + record.plus2_fulfilled_count }, 43.270 + { color = "#8f8", value = record.plus1_unfulfilled_count + record.plus1_fulfilled_count }, 43.271 + { color = "#ddd", value = max_value - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count - record.plus1_fulfilled_count - record.plus2_fulfilled_count }, 43.272 + } 43.273 + } 43.274 + end 43.275 + end 43.276 + }, 43.277 + { 43.278 + label = _"My opinion", 43.279 + content = function(record) 43.280 + local degree 43.281 + local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.282 + if opinion then 43.283 + degree = opinion.degree 43.284 end 43.285 ui.link{ 43.286 - attr = { class = "action" }, 43.287 - text = text, 43.288 + attr = { class = "action" .. (degree == -2 and " active_red2" or "") }, 43.289 + text = _"must not", 43.290 + module = "opinion", 43.291 + action = "update", 43.292 + routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.293 + params = { 43.294 + suggestion_id = record.id, 43.295 + degree = -2 43.296 + } 43.297 + } 43.298 + ui.link{ 43.299 + attr = { class = "action" .. (degree == -1 and " active_red1" or "") }, 43.300 + text = _"should not", 43.301 + module = "opinion", 43.302 + action = "update", 43.303 + routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.304 + params = { 43.305 + suggestion_id = record.id, 43.306 + degree = -1 43.307 + } 43.308 + } 43.309 + ui.link{ 43.310 + attr = { class = "action" .. (degree == nil and " active" or "") }, 43.311 + text = _"neutral", 43.312 module = "opinion", 43.313 action = "update", 43.314 routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.315 params = { 43.316 suggestion_id = record.id, 43.317 - fulfilled = true 43.318 + delete = true 43.319 } 43.320 } 43.321 - else 43.322 - if opinion.degree > 0 then 43.323 - text = _"Mark suggestion as not implemented and express dissatisfaction" 43.324 - else 43.325 - text = _"Mark suggestion as not implemented and express satisfaction" 43.326 - end 43.327 ui.link{ 43.328 - attr = { class = "action" }, 43.329 - text = text, 43.330 + attr = { class = "action" .. (degree == 1 and " active_green1" or "") }, 43.331 + text = _"should", 43.332 + module = "opinion", 43.333 + action = "update", 43.334 + routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.335 + params = { 43.336 + suggestion_id = record.id, 43.337 + degree = 1 43.338 + } 43.339 + } 43.340 + ui.link{ 43.341 + attr = { class = "action" .. (degree == 2 and " active_green2" or "") }, 43.342 + text = _"must", 43.343 module = "opinion", 43.344 action = "update", 43.345 routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.346 params = { 43.347 suggestion_id = record.id, 43.348 - fulfilled = false 43.349 + degree = 2 43.350 } 43.351 } 43.352 end 43.353 - end 43.354 - end 43.355 - }, 43.356 - { 43.357 - content = function(record) 43.358 - local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.359 - if opinion then 43.360 - if (opinion.fulfilled and opinion.degree > 0) or (not opinion.fulfilled and opinion.degree < 0) then 43.361 - ui.image{ static = "icons/16/thumb_up_green.png" } 43.362 - else 43.363 - ui.image{ static = "icons/16/thumb_down_red.png" } 43.364 + }, 43.365 + { 43.366 + content = function(record) 43.367 + local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.368 + if opinion and not opinion.fulfilled then 43.369 + ui.image{ static = "icons/16/cross.png" } 43.370 + end 43.371 + end 43.372 + }, 43.373 + { 43.374 + label = _"Suggestion currently not implemented", 43.375 + label_attr = { style = "width: 101px;" }, 43.376 + content = function(record) 43.377 + if record.minus2_unfulfilled_count then 43.378 + local max_value = record.initiative.issue.population 43.379 + ui.bargraph{ 43.380 + max_value = max_value, 43.381 + width = 50, 43.382 + bars = { 43.383 + { color = "#ddd", value = max_value - record.minus2_unfulfilled_count - record.minus1_unfulfilled_count }, 43.384 + { color = "#f88", value = record.minus1_unfulfilled_count }, 43.385 + { color = "#a00", value = record.minus2_unfulfilled_count }, 43.386 + { color = "#0a0", value = record.plus2_unfulfilled_count }, 43.387 + { color = "#8f8", value = record.plus1_unfulfilled_count }, 43.388 + { color = "#ddd", value = max_value - record.plus1_unfulfilled_count - record.plus2_unfulfilled_count }, 43.389 + } 43.390 + } 43.391 + end 43.392 + end 43.393 + }, 43.394 + { 43.395 + content = function(record) 43.396 + local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.397 + if opinion and opinion.fulfilled then 43.398 + ui.image{ static = "icons/16/tick.png" } 43.399 + end 43.400 + end 43.401 + }, 43.402 + { 43.403 + label = _"Suggestion currently implemented", 43.404 + label_attr = { style = "width: 101px;" }, 43.405 + content = function(record) 43.406 + if record.minus2_fulfilled_count then 43.407 + local max_value = record.initiative.issue.population 43.408 + ui.bargraph{ 43.409 + max_value = max_value, 43.410 + width = 50, 43.411 + bars = { 43.412 + { color = "#ddd", value = max_value - record.minus2_fulfilled_count - record.minus1_fulfilled_count }, 43.413 + { color = "#f88", value = record.minus1_fulfilled_count }, 43.414 + { color = "#a00", value = record.minus2_fulfilled_count }, 43.415 + { color = "#0a0", value = record.plus2_fulfilled_count }, 43.416 + { color = "#8f8", value = record.plus1_fulfilled_count }, 43.417 + { color = "#ddd", value = max_value - record.plus1_fulfilled_count - record.plus2_fulfilled_count }, 43.418 + } 43.419 + } 43.420 + end 43.421 end 43.422 - end 43.423 - end 43.424 - }, 43.425 - } 43.426 + }, 43.427 + { 43.428 + label_attr = { style = "width: 200px;" }, 43.429 + content = function(record) 43.430 + local degree 43.431 + local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.432 + if opinion then 43.433 + degree = opinion.degree 43.434 + end 43.435 + if opinion then 43.436 + if not opinion.fulfilled then 43.437 + local text = "" 43.438 + if opinion.degree > 0 then 43.439 + text = _"Mark suggestion as implemented and express satisfaction" 43.440 + else 43.441 + text = _"Mark suggestion as implemented and express dissatisfaction" 43.442 + end 43.443 + ui.link{ 43.444 + attr = { class = "action" }, 43.445 + text = text, 43.446 + module = "opinion", 43.447 + action = "update", 43.448 + routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.449 + params = { 43.450 + suggestion_id = record.id, 43.451 + fulfilled = true 43.452 + } 43.453 + } 43.454 + else 43.455 + if opinion.degree > 0 then 43.456 + text = _"Mark suggestion as not implemented and express dissatisfaction" 43.457 + else 43.458 + text = _"Mark suggestion as not implemented and express satisfaction" 43.459 + end 43.460 + ui.link{ 43.461 + attr = { class = "action" }, 43.462 + text = text, 43.463 + module = "opinion", 43.464 + action = "update", 43.465 + routing = { default = { mode = "redirect", module = request.get_module(), view = request.get_view(), id = param.get_id_cgi(), params = param.get_all_cgi() } }, 43.466 + params = { 43.467 + suggestion_id = record.id, 43.468 + fulfilled = false 43.469 + } 43.470 + } 43.471 + end 43.472 + end 43.473 + end 43.474 + }, 43.475 + { 43.476 + content = function(record) 43.477 + local opinion = Opinion:by_pk(app.session.member.id, record.id) 43.478 + if opinion then 43.479 + if (opinion.fulfilled and opinion.degree > 0) or (not opinion.fulfilled and opinion.degree < 0) then 43.480 + ui.image{ static = "icons/16/thumb_up_green.png" } 43.481 + else 43.482 + ui.image{ static = "icons/16/thumb_down_red.png" } 43.483 + end 43.484 + end 43.485 + end 43.486 + }, 43.487 + } 43.488 + } 43.489 + end 43.490 } 43.491 end 43.492 } 43.493 + 43.494 +if initiative then 43.495 + ui.field.timestamp{ label = _"Last snapshot:", value = initiative.issue.snapshot } 43.496 +end
44.1 --- a/app/main/suggestion/show.lua Mon Nov 30 12:00:00 2009 +0100 44.2 +++ b/app/main/suggestion/show.lua Thu Dec 10 12:00:00 2009 +0100 44.3 @@ -23,10 +23,9 @@ 44.4 view = "_list", 44.5 params = { 44.6 opinions_selector = Opinion:new_selector() 44.7 - :add_field("member.login", "member_login") 44.8 :add_field("member.name", "member_name") 44.9 :add_where{ "suggestion_id = ?", suggestion.id } 44.10 :join("member", nil, "member.id = opinion.member_id") 44.11 :add_order_by("member.id DESC") 44.12 } 44.13 -} 44.14 \ No newline at end of file 44.15 +}
45.1 --- a/app/main/supporter/_show_box.lua Mon Nov 30 12:00:00 2009 +0100 45.2 +++ b/app/main/supporter/_show_box.lua Thu Dec 10 12:00:00 2009 +0100 45.3 @@ -1,49 +1,64 @@ 45.4 - 45.5 45.6 slot.select("support", function() 45.7 - 45.8 local initiative = param.get("initiative", "table") 45.9 - 45.10 - if not initiative.issue.frozen and not initiative.issue.closed then 45.11 - 45.12 - local supported = Supporter:by_pk(initiative.id, app.session.member.id) and true or false 45.13 - 45.14 - local text 45.15 - if supported then 45.16 - text = _"Direct supporter [change]" 45.17 - else 45.18 - text = _"No supporter [change]" 45.19 - end 45.20 - ui.container{ 45.21 - attr = { 45.22 - class = "head", 45.23 - style = "cursor: pointer;", 45.24 - onclick = "document.getElementById('support_content').style.display = 'block';" 45.25 - }, 45.26 - content = text 45.27 - } 45.28 + local supported = Supporter:by_pk(initiative.id, app.session.member.id) and true or false 45.29 45.30 - 45.31 - ui.container{ 45.32 - attr = { class = "content", id = "support_content" }, 45.33 - content = function() 45.34 - ui.container{ 45.35 - attr = { 45.36 - class = "close", 45.37 - style = "cursor: pointer;", 45.38 - onclick = "document.getElementById('support_content').style.display = 'none';" 45.39 - }, 45.40 - content = _"X" 45.41 - } 45.42 + ui.container{ 45.43 + attr = { class = "actions" }, 45.44 + content = function() 45.45 + if not initiative.issue.frozen and not initiative.issue.closed then 45.46 if supported then 45.47 - ui.link{ 45.48 + ui.container{ 45.49 + attr = { 45.50 + class = "head head_active", 45.51 + style = "cursor: pointer;", 45.52 + onclick = "document.getElementById('support_content').style.display = 'block';" 45.53 + }, 45.54 + content = function() 45.55 + ui.image{ 45.56 + static = "icons/16/thumb_up_green.png" 45.57 + } 45.58 + slot.put(_"Your are supporter") 45.59 + ui.image{ 45.60 + static = "icons/16/dropdown.png" 45.61 + } 45.62 + end 45.63 + } 45.64 + ui.container{ 45.65 + attr = { class = "content", id = "support_content" }, 45.66 content = function() 45.67 - ui.image{ static = "icons/16/thumb_down_red.png" } 45.68 - slot.put(_"Remove my support from this initiative") 45.69 - end, 45.70 - module = "initiative", 45.71 - action = "remove_support", 45.72 - id = initiative.id 45.73 + ui.container{ 45.74 + attr = { 45.75 + class = "close", 45.76 + style = "cursor: pointer;", 45.77 + onclick = "document.getElementById('support_content').style.display = 'none';" 45.78 + }, 45.79 + content = function() 45.80 + ui.image{ static = "icons/16/cross.png" } 45.81 + end 45.82 + } 45.83 + if supported then 45.84 + ui.link{ 45.85 + content = function() 45.86 + ui.image{ static = "icons/16/thumb_down_red.png" } 45.87 + slot.put(_"Remove my support from this initiative") 45.88 + end, 45.89 + module = "initiative", 45.90 + action = "remove_support", 45.91 + id = initiative.id, 45.92 + routing = { 45.93 + default = { 45.94 + mode = "redirect", 45.95 + module = request.get_module(), 45.96 + view = request.get_view(), 45.97 + id = param.get_id_cgi(), 45.98 + params = param.get_all_cgi() 45.99 + } 45.100 + } 45.101 + } 45.102 + else 45.103 + end 45.104 + end 45.105 } 45.106 else 45.107 ui.link{ 45.108 @@ -53,11 +68,19 @@ 45.109 end, 45.110 module = "initiative", 45.111 action = "add_support", 45.112 - id = initiative.id 45.113 + id = initiative.id, 45.114 + routing = { 45.115 + default = { 45.116 + mode = "redirect", 45.117 + module = request.get_module(), 45.118 + view = request.get_view(), 45.119 + id = param.get_id_cgi(), 45.120 + params = param.get_all_cgi() 45.121 + } 45.122 + } 45.123 } 45.124 end 45.125 end 45.126 - } 45.127 - end 45.128 - 45.129 + end 45.130 + } 45.131 end)
46.1 --- a/app/main/supporter/show_incoming.lua Mon Nov 30 12:00:00 2009 +0100 46.2 +++ b/app/main/supporter/show_incoming.lua Thu Dec 10 12:00:00 2009 +0100 46.3 @@ -3,11 +3,11 @@ 46.4 local member = Member:by_id(param.get("member_id", atom.integer)) 46.5 46.6 local members_selector = Member:new_selector() 46.7 - :join("delegating_population_snapshot", nil, "delegating_population_snapshot.member_id = member.id") 46.8 - :add_where{ "delegating_population_snapshot.issue_id = ?", issue.id } 46.9 - :add_where{ "delegating_population_snapshot.event = ?", issue.latest_snapshot_event } 46.10 - :add_where{ "delegating_population_snapshot.delegate_member_ids[1] = ?", member.id } 46.11 - :add_field{ "delegating_population_snapshot.weight" } 46.12 + :join("delegating_interest_snapshot", nil, "delegating_interest_snapshot.member_id = member.id") 46.13 + :add_where{ "delegating_interest_snapshot.issue_id = ?", issue.id } 46.14 + :add_where{ "delegating_interest_snapshot.event = ?", issue.latest_snapshot_event } 46.15 + :add_where{ "delegating_interest_snapshot.delegate_member_ids[1] = ?", member.id } 46.16 + :add_field{ "delegating_interest_snapshot.weight" } 46.17 46.18 execute.view{ 46.19 module = "member",
47.1 --- a/config/default.lua Mon Nov 30 12:00:00 2009 +0100 47.2 +++ b/config/default.lua Thu Dec 10 12:00:00 2009 +0100 47.3 @@ -1,14 +1,25 @@ 47.4 config.app_name = "LiquidFeedback" 47.5 -config.app_version = "alpha4" 47.6 +config.app_version = "alpha5" 47.7 47.8 config.app_title = config.app_name .. " (" .. request.get_config_name() .. " environment)" 47.9 47.10 +config.app_logo = nil 47.11 + 47.12 config.app_service_provider = "Snake Oil<br/>10000 Berlin<br/>Germany" 47.13 47.14 -config.member_image_convert = { 47.15 - avatar = { "convert", "-", "-thumbnail", "48x48", "jpeg:-" } 47.16 +config.member_image_convert_func = { 47.17 + avatar = function(data) return os.pfilter(data, "convert", "jpeg:-", "-thumbnail", "48x48", "jpeg:-") end, 47.18 + photo = function(data) return os.pfilter(data, "convert", "jpeg:-", "-thumbnail", "240x240", "jpeg:-") end 47.19 } 47.20 47.21 +config.member_image_default_file = { 47.22 + avatar = "avatar.jpg", 47.23 + photo = nil 47.24 +} 47.25 + 47.26 +config.fastpath_url_func = nil 47.27 + 47.28 + 47.29 -- uncomment the following two lines to use C implementations of chosen 47.30 -- functions and to disable garbage collection during the request, to 47.31 -- increase speed:
48.1 --- a/config/development.lua Mon Nov 30 12:00:00 2009 +0100 48.2 +++ b/config/development.lua Thu Dec 10 12:00:00 2009 +0100 48.3 @@ -1,3 +1,6 @@ 48.4 execute.config("default") 48.5 48.6 -config.wiki_parser_executeable = "/opt/rocketwiki/rocketwiki" 48.7 +config.formatting_engine_executeables = { 48.8 + rocketwiki= "/opt/rocketwiki/rocketwiki-lqfb", 48.9 + compat = "/opt/rocketwiki/rocketwiki-lqfb-compat" 48.10 +}
49.1 --- a/config/testing.lua Mon Nov 30 12:00:00 2009 +0100 49.2 +++ b/config/testing.lua Thu Dec 10 12:00:00 2009 +0100 49.3 @@ -1,3 +1,10 @@ 49.4 execute.config("default") 49.5 49.6 -config.wiki_parser_executeable = "/opt/liquid_feedback_testing/rocketwiki/rocketwiki" 49.7 +config.formatting_engine_executeables = { 49.8 + rocketwiki= "/opt/liquid_feedback_testing/rocketwiki/rocketwiki-lqfb", 49.9 + compat = "/opt/liquid_feedback_testing/rocketwiki/rocketwiki-lqfb-compat" 49.10 +} 49.11 + 49.12 +config.fastpath_url_func = function(member_id, image_type) 49.13 + return "http://www.public-software-group.org/liquid_feedback_testing/fastpath/getpic?" .. tostring(member_id) .. "+" .. tostring(image_type) 49.14 +end 49.15 \ No newline at end of file
50.1 --- a/env/format/wiki_text.lua Mon Nov 30 12:00:00 2009 +0100 50.2 +++ b/env/format/wiki_text.lua Thu Dec 10 12:00:00 2009 +0100 50.3 @@ -1,6 +1,7 @@ 50.4 -function format.wiki_text(wiki_text) 50.5 +function format.wiki_text(wiki_text, formatting_engine) 50.6 + local formatting_engine = formatting_engine or "rocketwiki" 50.7 local html, errmsg, exitcode = assert( 50.8 - os.pfilter(wiki_text, config.wiki_parser_executeable) 50.9 + os.pfilter(wiki_text, config.formatting_engine_executeables[formatting_engine]) 50.10 ) 50.11 if exitcode > 0 then 50.12 error("Wiki parser process returned with error code " .. tostring(exitcode))
51.1 --- a/env/ui/bargraph.lua Mon Nov 30 12:00:00 2009 +0100 51.2 +++ b/env/ui/bargraph.lua Thu Dec 10 12:00:00 2009 +0100 51.3 @@ -6,7 +6,7 @@ 51.4 content = function() 51.5 for i, bar in ipairs(args.bars) do 51.6 if bar.value > 0 then 51.7 - local value = bar.value * args.width / args.max_value / 2 51.8 + local value = bar.value * args.width / args.max_value 51.9 ui.container{ 51.10 attr = { 51.11 style = "width: " .. tostring(value) .. "px; background-color: " .. bar.color .. ";",
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/env/ui/bargraph_legend.lua Thu Dec 10 12:00:00 2009 +0100 52.3 @@ -0,0 +1,32 @@ 52.4 +function ui.bargraph_legend(attr) 52.5 + local width = assert(attr.width) 52.6 + local bars = assert(attr.bars) 52.7 + 52.8 + ui.container{ 52.9 + attr = { class = "bargraph_legend" }, 52.10 + content = function() 52.11 + ui.container{ 52.12 + attr = { class = "bargraph_legend_label" }, 52.13 + content = _"Legend:" 52.14 + } 52.15 + for i, bar in ipairs(bars) do 52.16 + ui.bargraph{ 52.17 + max_value = 1, 52.18 + width = width, 52.19 + bars = { 52.20 + { 52.21 + color = bar.color, 52.22 + value = 1, 52.23 + } 52.24 + } 52.25 + } 52.26 + ui.container{ 52.27 + attr = { class = "bargraph_legend_label" }, 52.28 + content = bar.label 52.29 + } 52.30 + end 52.31 + end 52.32 + } 52.33 + 52.34 + slot.put('<br style="clear: left;" />') 52.35 +end 52.36 \ No newline at end of file
53.1 --- a/env/ui/tabs.lua Mon Nov 30 12:00:00 2009 +0100 53.2 +++ b/env/ui/tabs.lua Thu Dec 10 12:00:00 2009 +0100 53.3 @@ -23,6 +23,7 @@ 53.4 text = tab.label, 53.5 params = params 53.6 } 53.7 + slot.put(" ") 53.8 end 53.9 end 53.10 }
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 54.2 +++ b/env/util/help.lua Thu Dec 10 12:00:00 2009 +0100 54.3 @@ -0,0 +1,65 @@ 54.4 +function util.help(id, title) 54.5 + local setting_key = "liquidfeedback_frontend_hidden_help_" .. id 54.6 + local setting = Setting:by_pk(app.session.member.id, setting_key) 54.7 + if not setting then 54.8 + ui.container{ 54.9 + attr = { class = "help help_visible" }, 54.10 + content = function() 54.11 + ui.image{ 54.12 + attr = { class = "help_icon" }, 54.13 + static = "icons/16/help.png" 54.14 + } 54.15 + ui.container{ 54.16 + attr = { class = "help_actions" }, 54.17 + content = function() 54.18 + ui.link{ 54.19 + content = _"Hide this help message", 54.20 + module = "help", 54.21 + action = "update", 54.22 + params = { 54.23 + help_ident = id, 54.24 + hide = true 54.25 + }, 54.26 + routing = { 54.27 + default = { 54.28 + mode = "redirect", 54.29 + module = request.get_module(), 54.30 + view = request.get_view(), 54.31 + id = param.get_id_cgi(), 54.32 + params = param.get_all_cgi() 54.33 + } 54.34 + } 54.35 + } 54.36 + end 54.37 + } 54.38 + local lang = locale.get("lang") 54.39 + local basepath = request.get_app_basepath() 54.40 + local file_name = basepath .. "/locale/help/" .. id .. "." .. lang .. ".txt" 54.41 + local file = io.open(file_name) 54.42 + if file ~= nil then 54.43 + local help_text = file:read("*a") 54.44 + if #help_text > 0 then 54.45 + ui.container{ 54.46 + attr = { class = "wiki" }, 54.47 + content = function() 54.48 + slot.put(format.wiki_text(help_text)) 54.49 + end 54.50 + } 54.51 + else 54.52 + ui.field.text{ value = _("Empty help text: #{id}.#{lang}.txt", { id = id, lang = lang }) } 54.53 + end 54.54 + else 54.55 + ui.field.text{ value = _("Missing help text: #{id}.#{lang}.txt", { id = id, lang = lang }) } 54.56 + end 54.57 + end 54.58 + } 54.59 + else 54.60 + if util._hidden_helps == nil then 54.61 + util._hidden_helps = {} 54.62 + end 54.63 + util._hidden_helps[#util._hidden_helps+1] = { 54.64 + id = id, 54.65 + title = title 54.66 + } 54.67 + end 54.68 +end 54.69 \ No newline at end of file
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 55.2 +++ b/fastpath/Makefile Thu Dec 10 12:00:00 2009 +0100 55.3 @@ -0,0 +1,5 @@ 55.4 +getpic: getpic.c 55.5 + cc -g -Wall -o getpic getpic.c -I /usr/pkg/include/ -I /usr/include/postgresql -L /usr/pkg/lib -L /usr/lib/postgresql -lpq -Wl,-rpath,/usr/pkg/lib -Wl,-rpath,/usr/lib/postgresql 55.6 + 55.7 +clean:: 55.8 + rm -f getpic
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 56.2 +++ b/fastpath/getpic.c Thu Dec 10 12:00:00 2009 +0100 56.3 @@ -0,0 +1,157 @@ 56.4 +#include <stdlib.h> 56.5 +#include <stdio.h> 56.6 +#include <libpq-fe.h> 56.7 +#include <string.h> 56.8 +#include <regex.h> 56.9 +#include <sys/types.h> 56.10 +#include <sys/stat.h> 56.11 +#include <unistd.h> 56.12 + 56.13 +#ifndef GETPIC_CONNINFO 56.14 +#define GETPIC_CONNINFO "dbname=liquid_feedback" 56.15 +#endif 56.16 + 56.17 +#ifndef GETPIC_DEFAULT_AVATAR 56.18 +#define GETPIC_DEFAULT_AVATAR "/opt/liquid_feedback_testing/app/static/avatar.jpg" 56.19 +#endif 56.20 + 56.21 +int main(int argc, const char * const *argv) { 56.22 + PGconn *conn; 56.23 + PGresult *dbr; 56.24 + 56.25 + char *cookies = getenv("HTTP_COOKIE"); 56.26 + 56.27 + char *args_string; 56.28 + char *member_id; 56.29 + char *image_type; 56.30 + 56.31 + char *sql_session_params[1]; 56.32 + char *sql_member_image_params[2]; 56.33 + 56.34 + ssize_t start, length; 56.35 + 56.36 + char *session_ident; 56.37 + 56.38 + regex_t session_ident_regex; 56.39 + regmatch_t session_ident_regmatch[2]; 56.40 + 56.41 + cookies = getenv("HTTP_COOKIE"); 56.42 + 56.43 + args_string = getenv("QUERY_STRING"); 56.44 + 56.45 + if (!cookies || !args_string) { 56.46 + fputs("Status: 403 Access Denied\n\n", stdout); 56.47 + return 0; 56.48 + } 56.49 + 56.50 + member_id = strtok(args_string, "+"); 56.51 + image_type = strtok(NULL, "+"); 56.52 + 56.53 + sql_member_image_params[0] = member_id; 56.54 + sql_member_image_params[1] = image_type; 56.55 + 56.56 + // get session from cookie 56.57 + 56.58 + // TODO improve regex to fit better 56.59 + if (regcomp(&session_ident_regex, "liquid_feedback_session=([a-zA-Z0-9]+)", REG_EXTENDED) != 0) { 56.60 + // shouldn't happen 56.61 + abort(); 56.62 + } 56.63 + 56.64 + if (regexec(&session_ident_regex, cookies, 2, session_ident_regmatch, 0) != 0) { 56.65 + fputs("Status: 403 Access Denied\n\n", stdout); 56.66 + return 0; 56.67 + } 56.68 + 56.69 + start = session_ident_regmatch[1].rm_so; 56.70 + length = session_ident_regmatch[1].rm_eo - session_ident_regmatch[1].rm_so; 56.71 + 56.72 + session_ident = malloc(length + 1); 56.73 + 56.74 + strncpy(session_ident, cookies + start, length); 56.75 + 56.76 + session_ident[length] = 0; 56.77 + 56.78 + sql_session_params[0] = session_ident; 56.79 + 56.80 + 56.81 + // connect to database 56.82 + 56.83 + conn = PQconnectdb(GETPIC_CONNINFO); 56.84 + if (!conn) { 56.85 + fputs("Could not create PGconn structure.\n", stderr); 56.86 + return 1; 56.87 + } 56.88 + if (PQstatus(conn) != CONNECTION_OK) { 56.89 + fputs(PQerrorMessage(conn), stderr); 56.90 + return 1; 56.91 + } 56.92 + 56.93 + // check session 56.94 + dbr = PQexecParams(conn, 56.95 + "SELECT NULL FROM session JOIN member ON member.id = session.member_id WHERE session.ident = $1 AND member.active", 56.96 + 1, NULL, sql_session_params, NULL, NULL, 0 56.97 + ); 56.98 + 56.99 + if (PQresultStatus(dbr) != PGRES_TUPLES_OK) { 56.100 + fputs(PQresultErrorMessage(dbr), stderr); 56.101 + return 1; 56.102 + } 56.103 + 56.104 + if (PQntuples(dbr) != 1) { 56.105 + fputs("Status: 403 Access Denied\n\n", stdout); 56.106 + return 0; 56.107 + } 56.108 + 56.109 + 56.110 + // get picture 56.111 + dbr = PQexecParams(conn, 56.112 + "SELECT content_type, data " 56.113 + "FROM member_image " 56.114 + "WHERE member_id = $1 " 56.115 + "AND image_type = $2 " 56.116 + "AND scaled " 56.117 + "LIMIT 1;", 56.118 + 2, NULL, sql_member_image_params, NULL, NULL, 1 56.119 + ); 56.120 + 56.121 + if (PQresultStatus(dbr) != PGRES_TUPLES_OK) { 56.122 + fputs(PQresultErrorMessage(dbr), stderr); 56.123 + return 1; 56.124 + } 56.125 + if (PQntuples(dbr) > 1) { 56.126 + return 1; 56.127 + } 56.128 + fputs("Cache-Control: private; max-age=86400\n", stdout); 56.129 + if (PQntuples(dbr) == 0) { 56.130 + struct stat sb; 56.131 + PQclear(dbr); 56.132 + PQfinish(conn); 56.133 + fputs("Content-Type: image/jpeg\n\n", stdout); 56.134 + if (stat(GETPIC_DEFAULT_AVATAR, &sb)) return 1; 56.135 + fprintf(stdout, "Content-Length: %i\n", sb.st_size); 56.136 + execl("/bin/cat", "cat", GETPIC_DEFAULT_AVATAR, NULL); 56.137 + return 1; 56.138 + } else { 56.139 + if (PQnfields(dbr) < 0) { 56.140 + fputs("Too few columns returned by database.\n", stderr); 56.141 + return 1; 56.142 + } 56.143 + if (PQfformat(dbr, 0) != 1 || PQfformat(dbr, 1) != 1) { 56.144 + fputs("Database did not return data in binary format.\n", stderr); 56.145 + return 1; 56.146 + } 56.147 + if (PQgetisnull(dbr, 0, 0) || PQgetisnull(dbr, 0, 1)) { 56.148 + fputs("Unexpected NULL in database result.\n", stderr); 56.149 + return 1; 56.150 + } 56.151 + fputs("Content-Type: ", stdout); 56.152 + fprintf(stdout, "Content-Length: %i\n", PQgetlength(dbr, 0, 1)); 56.153 + fwrite(PQgetvalue(dbr, 0, 0), PQgetlength(dbr, 0, 0), 1, stdout); 56.154 + fputs("\n\n", stdout); 56.155 + fwrite(PQgetvalue(dbr, 0, 1), PQgetlength(dbr, 0, 1), 1, stdout); 56.156 + } 56.157 + PQclear(dbr); 56.158 + PQfinish(conn); 56.159 + return 0; 56.160 +}
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 57.2 +++ b/locale/help/area.list.de.txt Thu Dec 10 12:00:00 2009 +0100 57.3 @@ -0,0 +1,2 @@ 57.4 +=Themenbereiche= 57.5 +Die Balken zeigen dir an, wie hoch der Anteil der direkten Mitglieder bzw. der durch Delegation vertretenen Mitglieder des jeweiligen Themenbereichs im Verhältnis zur Gesamtzahl der Mitglieder dieses Systems ist. Für Testinitiativen (also Diskussionen, die nicht ernst gemeint sind) eignet sich übrigens der Themenbereich ,,Sandkasten/Spielwiese".
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 58.2 +++ b/locale/help/area.show.de.txt Thu Dec 10 12:00:00 2009 +0100 58.3 @@ -0,0 +1,6 @@ 58.4 +=Themenbereich, Mitgliedschaft= 58.5 +Für die Teilnahme an der Diskussion und Endabstimmung einzelner Themen ist die Mitgliedschaft im Themenbereich **keine** Voraussetzung. Mit der Mitgliedschaft erklärst du vielmehr ein generelles Interesse an diesem Themenbereich. 58.6 +=Delegation, Auto-Ablehnen= 58.7 +Du kannst deine Stimme für diesen Themenbereich (unabhängig von deiner Mitgliedschaft im Themenbereich) an eine Person in deiner Kontaktliste delegieren. Als Themenbereichsmitglied kannst du ,,Auto-Ablehnen'' als Standardabstimmverhalten festlegen. Diese Weisung gilt nur für den Fall, dass du nicht selbst an der Endabstimmung teilnimmst, es keine tatsächlich genutzte Delegation und keine Weisung für das jeweilige konkrete Thema gibt. 58.8 +=Neues Thema= 58.9 +Hier kannst du mit einer eigenen Initiative ein neues Thema eröffnen. **Bevor** du ein neues Thema eröffnest, solltest du prüfen, ob es dieses Thema vieleicht schon gibt. Eine Initiative zu einem bestehenden Thema (Alternativantrag) kannst du von der jeweilige Themenseite aus starten.
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 59.2 +++ b/locale/help/contact.list.de.txt Thu Dec 10 12:00:00 2009 +0100 59.3 @@ -0,0 +1,4 @@ 59.4 +=persönliche Kontaktliste= 59.5 +Um sie schneller auffinden zu können, kannst du andere Mitglieder deiner persönlichen Kontaktliste hinzufügen. Auf der Profilseite des jeweiligen Mitglieds findest du einen Link zum Hinzufügen. Falls du einen Kontakt veröffentlichst, können andere sehen, dass dieses Mitglied auf deiner Kontaktliste steht. 59.6 + 59.7 +**Wichtig:** Zur Verbesserung des Bedienkomforts wird dir beim Delegieren deine persönliche Kontaktliste angezeigt. Um an ein Mitglied delegieren zu können, musst du es zunächst als Kontakt hinzufügen. Das Löschen eines Kontaktes führt jedoch nicht zum Widerruf der Delegation.
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 60.2 +++ b/locale/help/delegation.new.area.de.txt Thu Dec 10 12:00:00 2009 +0100 60.3 @@ -0,0 +1,2 @@ 60.4 +=Delegation für diesen Themenbereich= 60.5 +Du kannst deine Stimme für diesen Themenbereich (unabhängig von deiner Mitgliedschaft im Themenbereich) an eine Person in deiner Kontaktliste delegieren. Diese Delegation hat gegenüber einer eventuell vorhandenen globalen Delegation Vorrang, gilt jedoch nur, wenn du dich nicht selbst beteiligst und für das jeweilige Thema keine themenspezifische Delegation erteilt hast. Für eine themenspezifische Delegation wechsele bitte auf die jeweilige Themenseite. Delegieren kannst du nur an Mitglieder in deiner Kontaktliste. Die Kontaktliste kannst du im Bereich ,,Mitglieder'' jederzeit erweitern.
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 61.2 +++ b/locale/help/delegation.new.global.de.txt Thu Dec 10 12:00:00 2009 +0100 61.3 @@ -0,0 +1,2 @@ 61.4 +=globale Delegation= 61.5 +Die globale Delegation gilt immer dann, wenn du dich nicht selbst beteiligst und es keine Delegation auf der Ebene des jeweiligen Themenbereichs oder des Themas gibt. Delegieren kannst du nur an Mitglieder in deiner Kontaktliste. Die Kontaktliste kannst du im Bereich ,,Mitglieder'' jederzeit erweitern.
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 62.2 +++ b/locale/help/delegation.new.issue.de.txt Thu Dec 10 12:00:00 2009 +0100 62.3 @@ -0,0 +1,2 @@ 62.4 +=Delegation für dieses Thema= 62.5 +Eine Delegation zu diesem Thema geht einer eventuell vorhandenen globalen Delegation und/oder Delegation für den übergeordneten Themenbereich vor. Bei angemeldetem Interesse werden ausgehende Delegationen während der Diskussionsphase ausgesetzt, gelten aber in der Endabstimmung. Delegieren kannst du nur an Mitglieder in deiner Kontaktliste. Die Kontaktliste kannst du im Bereich ,,Mitglieder'' jederzeit erweitern.
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 63.2 +++ b/locale/help/index.change_password.de.txt Thu Dec 10 12:00:00 2009 +0100 63.3 @@ -0,0 +1,2 @@ 63.4 +=Kennwort ändern= 63.5 +Dein neues Kennwort muss mindestens 8 Zeichen lang sein.
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 64.2 +++ b/locale/help/index.index.de.txt Thu Dec 10 12:00:00 2009 +0100 64.3 @@ -0,0 +1,8 @@ 64.4 +==Willkommen bei LiquidFeedback und auf deiner Startseite== 64.5 +Diese blauen Boxen werden dich verfolgen bis du sie nach und nach abschaltest. Deine Startseite wird sich (hoffentlich) im Laufe der Zeit füllen: 64.6 +- mit deinem Profil, 64.7 +- den Themenbereichen, Themen und Initiativen die dich interessieren, 64.8 +- deinen eingehenden und ausgehenden Delegationen, 64.9 +- deinen veröffentlichten Kontakten. 64.10 + 64.11 +Und weil Neugier eine wichtige menschliche Eigenschaft ist, kannst du übrigens diese Informationen auch über die anderen Mitglieder abrufen. Wenn du wissen möchtest, ob deine Freunde schon im System sind, schau doch einfach mal unter ,,Mitglieder'' (ganz oben) nach.
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 65.2 +++ b/locale/help/initiative.show.de.txt Thu Dec 10 12:00:00 2009 +0100 65.3 @@ -0,0 +1,10 @@ 65.4 +=Initiative, Unterstützung, Anregungen= 65.5 +Während der Diskussionsphase kannst du diese Initiative unterstützen und gibst damit den Initiatoren eine wichtige Rückmeldung, inwieweit der aktuelle Entwurf auf Zustimmung stößt. Darüber hinaus kannst du durch Anregungen (Änderungsvorschläge) mitteilen, was noch verbessert werden kann bzw. unter welchen Bedingungen du dir eine Unterstützung vorstellen kannst. 65.6 + 65.7 +Du kannst dich den Anregungen anderer Mitglieder anschließen (und damit das Gewicht dieser Anregungen erhöhen) und eigene (zusätzliche) Anregungen einbringen. Anregungen, die aus deiner Sicht unbedingt eingearbeitet werden müssen, damit du zustimmst, kennzeichnest du mit ,,muss'', wünschenswerte mit ,,soll''. Du kannst Anregungen auch kritisch gegenüber stehen und sie mit ,,soll nicht'' kennzeichnen. Eine Anregung, die bei Umsetzung zum Entzug deiner Zustimmung führen würde, kennzeichnest du mit ,,darf nicht''. 65.8 +=überarbeiteter Entwurf, Umsetzungsvermerk= 65.9 +Anhand der (klassifizierten und quantifizierten) Anregungen entscheiden die Initiatoren, was sie in einem neuen Entwurf besser dargestellen, ergänzen oder ändern. Der geänderte Entwurf wird den Unterstützern zur Bestätigung vorgelegt. Unterstützer können Anregungen als umgesetzt markieren, wenn die Anregung aus ihrer Sicht (hinreichend) umgesetzt wurde. Die einzelnen Unterstützer können diese Frage durchaus unterschiedlich beurteilen. 65.10 +=wenn du nicht gehört wirst= 65.11 +Wenn die Initiatoren deine Anregungen aus für dich nicht nachvollziehbaren Gründen nicht berücksichtigen, kannst du natürlich deine Änderungen in einer eigenen Initiative zur Diskussion stellen. 65.12 +=wenn du diese Initiative ablehnst= 65.13 +Wenn du diese Initiative grundsätzlich ablehnst, solltest du auf dieser Seite gar nichts machen, sondern die Initiative(n), der/denen du positiv gegenüber stehst, unterstützen und/oder deine eigene Initiative zu diesem Thema starten.
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 66.2 +++ b/locale/help/issue.show.de.txt Thu Dec 10 12:00:00 2009 +0100 66.3 @@ -0,0 +1,12 @@ 66.4 +=Thema, Interesse= 66.5 +Auf dieser Seite werden alle Initiativen zu diesem Thema aufgelistet. Wenn du ,,Interesse am Thema'' anmeldest, wirst du für dieses Thema den Mitgliedern des übergeordneten Themenbereichs gleichgestellt. Sobald du eine Initiative dieses Themas unterstützt, wird dein Interesse auch automatisch angemeldet. Sofern du allen Initiativen die Unterstützung entziehst, bleibt dein Interesse dennoch bestehen bis du es abmeldest. 66.6 +=Delegation, Auto-Ablehnung= 66.7 +Eine Delegation zu diesem Thema geht einer eventuell vorhandenen globalen Delegation und/oder Delegation für den übergeordneten Themenbereich vor. Eine eventuelle Weisung zur Auto-Ablehung gilt nur für den Fall, dass du nicht selbst an der Endabstimmung teilnimmst und es keine tatsächlich genutzte Delegation gibt. Bei angemeldetem Interesse werden ausgehende Delegationen während der Diskussionsphase ausgesetzt, gelten aber in der Endabstimmung. 66.8 +=Diskussionsphase= 66.9 +Während der Diskussionsphase (Zustände ,,Neu'' und ,,Diskussion'') solltest du **alle** Initiativen, die du grundsätzlich (oder unter bestimmten Bedingungen) für zustimmungsfähig hältst, unterstützen und Anregungen zur Verbesserung geben (Näheres dazu findest du auf der Initiativenseite). Hierdurch gibst du den Initiatoren die Chance, den Entwurf zu verbessern. Während dieser Phase hast du auch die Möglichkeit, eine eigene (konkurrierende) Initiative zu diesem Thema zu starten und um Unterstützung zu ringen. Deine Unterstützung für eine Initiative während der Diskussionsphase bedeutet keine Festlegung auf dein Verhalten in der Endabstimmung. 66.10 +=Endabstimmung= 66.11 +Initiativen, die ein bestimmtes Quorum erreichen, werden in die Endabstimmung übernommen. Du kannst dann alle Initiativen, denen du zustimmen möchtest, in eine Präferenzreihenfolge bringen. Bei den anderen Initiativen kannst Du dich enthalten oder auch dagegen stimmen (letzteres ebenfalls mit Präferenz). Beschlossen werden können nur Initiativen die insgesamt mehr Ja- als Nein-Stimmen erhalten. 66.12 + 66.13 +**Wichtig:** Es gibt keinen Grund mit Blick auf Mehrheitsverhältnisse (also aus Angst, deine Stimme zu ,,verschenken'') einen aus deiner Sicht suboptimalen Vorschlag vorzuziehen. Die Präferenzwahl führt (vereinfacht gesagt) dazu, dass sobald dein tatsächlicher Favorit nicht zum Zug kommt, deine Stimme voll für deinen ersten Ersatzwunsch zählt, danach für deinen zweiten Ersatzwunsch usw. 66.14 + 66.15 +Information zum genutzten Wahlverfahren: [http://en.wikipedia.org/wiki/Schulze_method Schulze-Methode]
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 67.2 +++ b/locale/help/member.edit.de.txt Thu Dec 10 12:00:00 2009 +0100 67.3 @@ -0,0 +1,2 @@ 67.4 +=Profil= 67.5 +Alle Angaben sind freiwillig. In Deinem Profil erscheinen nur die Felder, die nicht leer sind.
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 68.2 +++ b/locale/help/member.edit_images.de.txt Thu Dec 10 12:00:00 2009 +0100 68.3 @@ -0,0 +1,5 @@ 68.4 +=Bilder= 68.5 +Format: JPG 68.6 +Avatar: max. 48 x 48 Pixel, für den Avatar bevorzugt ein quadratisches Bild 68.7 +Foto: max. 250 x 250 Pixel 68.8 +Größere Bilder werden herunterskaliert, alle Bilder werden recodiert und von Profilen befreit.
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 69.2 +++ b/locale/help/member.list.de.txt Thu Dec 10 12:00:00 2009 +0100 69.3 @@ -0,0 +1,4 @@ 69.4 +=Profilseiten aufrufen= 69.5 +Hier kannst du die Profilseiten der einzelnen Mitglieder aufrufen und dich über ihre Beteiligung in Themenbereichen, an Themen und Initiativen informieren. Darüber hinaus werden dir ein- und ausgehende Delegationen und die veröffentlichten Kontakte des Mitglieds angezeigt. 69.6 +=Kontaktliste erweitern= 69.7 +Auf der Profilseite eines Mitglieds findest du auch einen Link, mit dem du das Mitglied zu deinen Kontakten hinzufügen kannst. Dies ist zum Beispiel erforderlich, wenn du deine Stimme an ein Mitglied delegieren möchtest.
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 70.2 +++ b/locale/help/member.show.de.txt Thu Dec 10 12:00:00 2009 +0100 70.3 @@ -0,0 +1,9 @@ 70.4 +=Profilseite= 70.5 +Hier kannst du erfahren, 70.6 +- was dieses Mitglied über sich selbst mitteilt, 70.7 +- in welchen Themenbereichen es Mitglied ist, 70.8 +- an welchen Themen und Initiativen es sich beteiligt 70.9 +- welche Delegationen das Mitglied erhalten und erteilt und 70.10 +- welche Kontakte das Mitglied veröffentlicht hat. 70.11 +=zu den Kontakten hinzufügen= 70.12 +Du kannst dieses Mitglied deiner Kontaktliste hinzufügen (und es natürlich auch wieder von dieser entfernen). Bitte beachte, dass du nur an Mitglieder delegieren kannst, die auf deiner Kontaktliste stehen.
72.1 --- a/locale/translations.de.lua Mon Nov 30 12:00:00 2009 +0100 72.2 +++ b/locale/translations.de.lua Thu Dec 10 12:00:00 2009 +0100 72.3 @@ -1,15 +1,15 @@ 72.4 #!/usr/bin/env lua 72.5 return { 72.6 -["(change)"] = "(ändern)"; 72.7 +["#{number} Image(s) has been deleted"] = "Es wurde(n) #{number} Bild(er) gelöscht"; 72.8 +["#{number} Image(s) has been updated"] = "Es wurde(n) #{number} Bild(er) aktualisiert"; 72.9 +["(change URL)"] = "(URL ändern)"; 72.10 ["+ #{weight}"] = false; 72.11 ["A-Z"] = false; 72.12 ["About"] = false; 72.13 ["About LiquidFeedback"] = "Über LiquidFeedback"; 72.14 -["Accepted"] = "Akzeptiert"; 72.15 +["Accepted at"] = "Angenommen am/um"; 72.16 ["Active?"] = "Aktiv?"; 72.17 -["Add my interest to this issue"] = "Mein Interesse am Thema anmelden"; 72.18 -["Add my membership to this area"] = "Mitglied im Themenbereich werden"; 72.19 -["Add new draft"] = "Neuen Entwurf hinzufügen"; 72.20 +["Add my interest"] = "Mein Interesse anmelden"; 72.21 ["Add new initiative to issue"] = "Neue Initiative zum Thema hinzufügen"; 72.22 ["Add new suggestion"] = "Neue Anregung hinzufügen"; 72.23 ["Add to my contacts"] = "Zu meinen Kontakten hinzufügen"; 72.24 @@ -18,6 +18,7 @@ 72.25 ["Admin menu"] = "Admin Menü"; 72.26 ["Admin?"] = "Admin?"; 72.27 ["Administrator"] = false; 72.28 +["Admission time"] = "Zeit für die Zulassung"; 72.29 ["Admitted"] = "zugelassen"; 72.30 ["Any"] = "Alle"; 72.31 ["Area"] = "Themenbereich"; 72.32 @@ -25,18 +26,22 @@ 72.33 ["Area delegation"] = "Area-Delegation"; 72.34 ["Area list"] = "Liste der Themenbereiche"; 72.35 ["Area successfully updated"] = "Themenbereich erfolgreich aktualisiert"; 72.36 +["Area wide delegation active"] = "Delegation für Themengebiet aktiv"; 72.37 ["Areas"] = "Themenbereiche"; 72.38 ["Author"] = "Autor"; 72.39 ["Autoreject is off."] = "Auto-Ablehnen ist aus"; 72.40 ["Autoreject is on."] = "Auto-Ablehnen ist an"; 72.41 ["Avatar"] = false; 72.42 -["Avatar has been deleted"] = "Avatar wurde gelöscht"; 72.43 -["Avatar has been updated"] = "Avatar wurde aktualisiert"; 72.44 +["Become a member"] = "Mitglied werden"; 72.45 ["Birthday"] = "Geburtstag"; 72.46 +["Bug report"] = "Fehlerbericht"; 72.47 ["Cancel"] = "Abbrechen"; 72.48 ["Cancelled"] = "Abgebrochen"; 72.49 +["Change area delegation"] = "Delegation für Themengebiet ändern"; 72.50 +["Change global delegation"] = "Globale Delegation ändern"; 72.51 +["Change issue delegation"] = "Delegation für Thema ändern"; 72.52 ["Change password"] = "Kennwort ändern"; 72.53 -["Click here to close."] = "Zum Schließen hier klicken"; 72.54 +["Click for details"] = "Klicke für Details"; 72.55 ["Close"] = "Schließen"; 72.56 ["Closed"] = "geschlossen"; 72.57 ["Collective opinion"] = "Meinungsbild"; 72.58 @@ -50,37 +55,44 @@ 72.59 ["Created at"] = "Erzeugt am/um"; 72.60 ["Current draft"] = "Aktueller Entwurf"; 72.61 ["Degree"] = "Grad"; 72.62 -["Delegate"] = "Delegieren"; 72.63 ["Delegations"] = "Delegationen"; 72.64 ["Description"] = "Beschreibung"; 72.65 ["Details"] = "Details"; 72.66 ["Diff"] = false; 72.67 ["Direct member count"] = "Anzahl Direktmitglieder"; 72.68 -["Direct supporter [change]"] = "Direkte Unterstützung [ändern]"; 72.69 +["Direct membership"] = "Direkte Mitgliedschaft"; 72.70 ["Discussion"] = "Diskussion"; 72.71 ["Discussion URL"] = "Diskussions-URL"; 72.72 +["Discussion time"] = "Zeit für die Diskussions"; 72.73 ["Draft"] = "Entwurf"; 72.74 ["Edit"] = "Bearbeiten"; 72.75 ["Edit draft"] = "Entwurf bearbeiten"; 72.76 ["Edit initiative"] = "Initiative bearbeiten"; 72.77 ["Edit my page"] = "Meine Seite bearbeiten"; 72.78 +["Edit my profile"] = "Mein Profil bearbeiten"; 72.79 +["Empty help text: #{id}.#{lang}.txt"] = false; 72.80 ["Error while updating member, database reported:<br /><br /> (#{errormessage})"] = "Fehler beim aktualisieren des Mitglieds, die Datenbank berichtet folgenden Fehler:<br /><br /> (#{errormessage})"; 72.81 -["External discussion"] = "Externe Diskussion"; 72.82 ["External memberships"] = "Externe Mitgliedschaften"; 72.83 ["External posts"] = "Externe Ämter"; 72.84 ["Filter"] = false; 72.85 ["Finished"] = "Abgeschlossen"; 72.86 ["Frozen"] = "Eingefroren"; 72.87 ["Fulfilled"] = "Erfüllt"; 72.88 -["Fully frozen"] = "Ganz eingefroren"; 72.89 +["Fully frozen at"] = "Ganz eingefroren am/um"; 72.90 ["Global delegation"] = "Globale Delegation"; 72.91 -["Half frozen"] = "Halb eingefroren"; 72.92 +["Global delegation active"] = "Globale Delegation aktiv"; 72.93 +["Half frozen at"] = "Halb eingefroren am/um"; 72.94 +["Help for: #{text}"] = "Hilfe zu: #{text}"; 72.95 ["Hide"] = "Verstecken"; 72.96 +["Hide this help message"] = "Diesen Hilfetext ausblenden"; 72.97 ["Home"] = "Startseite"; 72.98 ["Id"] = "Id"; 72.99 ["Ident number"] = "Ident-Nummer"; 72.100 +["Images"] = "Bilder"; 72.101 ["In discussion"] = "In Diskussion"; 72.102 ["Incoming delegations"] = "Eingehende Delegationen"; 72.103 +["Initiated initiatives"] = "Initierte Initiativen"; 72.104 +["Initiative quorum"] = "Quorum Inititive"; 72.105 ["Initiative successfully created"] = "Initiative erfolgreich erzeugt"; 72.106 ["Initiative successfully updated"] = "Initiative erfolgreich aktualisiert"; 72.107 ["Initiative: '#{name}'"] = "Initiative: '#{name}'"; 72.108 @@ -96,12 +108,14 @@ 72.109 ["Issue ##{id}"] = "Issue ##{id}"; 72.110 ["Issue ##{id} (#{policy_name})"] = "Thema ##{id} (#{policy_name})"; 72.111 ["Issue delegation"] = "Issue-Delegation"; 72.112 +["Issue delegation active"] = "Delegation für Thema aktiv"; 72.113 ["Issue policy"] = "Regelwerk für Thema"; 72.114 +["Issue quorum"] = "Quorum Thema"; 72.115 ["Issues"] = "Themen"; 72.116 ["Last snapshot:"] = "Letzte Auszählung:"; 72.117 +["Legend:"] = "Legende:"; 72.118 ["License"] = "Lizenz"; 72.119 ["Locked?"] = "Gesperrt?"; 72.120 -["Logged in as:"] = "Angemeldet als:"; 72.121 ["Login"] = "Anmeldung"; 72.122 ["Login successful!"] = "Anmeldung erfolgreich"; 72.123 ["Logout"] = "Abmelden"; 72.124 @@ -119,13 +133,17 @@ 72.125 ["Member list"] = "Mitgliederliste"; 72.126 ["Member login"] = "Mitglied Login"; 72.127 ["Member name"] = "Mitglied Name"; 72.128 +["Member page"] = false; 72.129 ["Member successfully registered"] = "Mitglied erfolgreich registriert"; 72.130 ["Member successfully updated"] = "Mitglied erfolgreich aktualisert"; 72.131 ["Member: '#{login}' (#{name})"] = "Mitlied: '#{login}' (#{name})"; 72.132 ["Members"] = "Mitglieder"; 72.133 +["Membership by delegation"] = "Mitgliedschaft durch Delegation"; 72.134 ["Membership not existant"] = "Mitgliedschaft exisitert nicht"; 72.135 ["Membership removed"] = "Mitgliedschaft entfernt"; 72.136 ["Membership updated"] = "Mitgliedschaft aktualisiert"; 72.137 +["Memberships"] = "Mitgliedschaften"; 72.138 +["Missing help text: #{id}.#{lang}.txt"] = false; 72.139 ["Mobile phone"] = "Mobiltelefon"; 72.140 ["My opinion"] = "Meine Meinung"; 72.141 ["Name"] = "Name"; 72.142 @@ -137,7 +155,9 @@ 72.143 ["New passwords is too short."] = "Das neue Kennwort ist zu kurz"; 72.144 ["Newest"] = "Neueste"; 72.145 ["Next state"] = "Nächster Zustand"; 72.146 -["No supporter [change]"] = "Keine Unterstützung (ändern)"; 72.147 +["No changes to your images were made"] = "An Deinen Bildern wurde nichts geändert"; 72.148 +["No delegation"] = "Keine Delegation"; 72.149 +["No membership at all"] = "Gar keine Mitgliedschaft"; 72.150 ["Number of incoming delegations, follow link to see more details"] = "Anzahl eingehender Delegationen, Link folgen für mehr Details"; 72.151 ["OK"] = "OK"; 72.152 ["Old draft revision"] = "Alte Revision des Entwurfs"; 72.153 @@ -150,9 +170,12 @@ 72.154 ["Outgoing delegations"] = "Ausgehende Delegationen"; 72.155 ["Password"] = "Kennwort"; 72.156 ["Phone"] = "Telefon"; 72.157 +["Photo"] = "Foto"; 72.158 ["Policy"] = "Regelwerk"; 72.159 ["Population"] = "Grundgesamtheit"; 72.160 +["Posts"] = "Ämter"; 72.161 ["Profession"] = "Beruf"; 72.162 +["Profile"] = "Profil"; 72.163 ["Publish"] = "Veröffentlichen"; 72.164 ["Published"] = "veröffentlicht"; 72.165 ["Published contacts"] = "Veröffentlichte Kontakte"; 72.166 @@ -176,9 +199,12 @@ 72.167 ["Search issues"] = "Suche Themen"; 72.168 ["Search members"] = "Suche Mitglieder"; 72.169 ["Search results for: '#{search}'"] = "Suchergebnisse für: '#{search}'"; 72.170 +["Set area delegation"] = "Delegation für Themengebiet festlegen"; 72.171 ["Set autoreject"] = "Auto-Ablehnen anschalten"; 72.172 ["Set delegation for Area '#{name}'"] = "Delegation für Themengebiet '#{name}' festlegen"; 72.173 ["Set delegation for Issue ##{number} in Area '#{area_name}'"] = "Delegation für Thema ##{number} im Themenbereich '#{area_name}' festlegen"; 72.174 +["Set global delegation"] = "Globale Delegation festlegen"; 72.175 +["Set issue delegation"] = "Delegation für Thema festlegen"; 72.176 ["Show"] = "Zeige"; 72.177 ["Show active members"] = "Zeige aktive Mitglieder"; 72.178 ["Show areas in use"] = "Zeige verwendete Themenbereiche"; 72.179 @@ -186,6 +212,7 @@ 72.180 ["Show diff"] = "Änderungen anzeigen"; 72.181 ["Show locked members"] = "Zeige gesperrte Mitglieder"; 72.182 ["Show member"] = "Mitglied anzeigen"; 72.183 +["Show other initiatives"] = "Zeige alternative Initiativen"; 72.184 ["Software"] = false; 72.185 ["State"] = "Zustand"; 72.186 ["Statement"] = false; 72.187 @@ -197,31 +224,34 @@ 72.188 ["Support"] = "Unterstützung"; 72.189 ["Support S+I"] = "Unterstütung S+I"; 72.190 ["Support this initiative"] = "Diese Initiative unterstützen"; 72.191 +["Supported initiatives"] = "Unterstützte Initiativen"; 72.192 ["Supporter"] = "Unterstützer"; 72.193 ["That's me!"] = "Das bin ich"; 72.194 ["The drafts do not differ"] = "Die Entwürfe unterscheiden sich nicht"; 72.195 ["Time left"] = "Restzeit"; 72.196 +["Title (80 chars max)"] = "Titel (max. 80 Zeichen)"; 72.197 ["Trustee"] = "Bevollmächtigter"; 72.198 ["Unknown author"] = "Unbekannter Autor"; 72.199 -["Upload avatar"] = "Avatar hochladen"; 72.200 +["Upload images"] = "Bilder hochladen"; 72.201 ["Username"] = "Benutzername"; 72.202 +["Verification time"] = "Zeit für die Überprüfung"; 72.203 ["Version"] = false; 72.204 ["Vote later"] = "Später abstimmen"; 72.205 ["Vote now"] = "Jetzt abstimmen"; 72.206 ["Voting"] = "Abstimmung"; 72.207 ["Voting requests"] = "Abstimmanträge"; 72.208 +["Voting time"] = "Zeit für die Abstimmung"; 72.209 ["Website"] = "Webseite"; 72.210 -["X"] = false; 72.211 ["You are already not supporting this initiative"] = "Diese Initiative hat bereits keine Unterstützung von Dir"; 72.212 ["You are already supporting the latest draft"] = "Du unterstützt bereits den neuesten Entwurf"; 72.213 -["You are interested. [more]"] = "Du bist interessiert. [mehr]"; 72.214 -["You are member. [more]"] = "Du bist Mitglied. [mehr]"; 72.215 -["You are not a member. [more]"] = "Du bist kein Mitglied. [mehr]"; 72.216 -["You are not interested. [more]"] = "Du bist nicht interessiert. [mehr]"; 72.217 +["You are currently not supporting this initiative. By adding suggestions to this initiative you will automatically become a potential supporter."] = false; 72.218 +["You are member"] = "Du bist Mitglied"; 72.219 ["You didn't saved any member as contact yet."] = "Du hast noch kein Mitglied als Kontakt gespeichert!"; 72.220 ["You have saved this member as contact"] = "Du hast das Mitglied als Kontakt gespeichert"; 72.221 ["You have saved this member as contact."] = "Du hast das Mitglied als Kontakt gespeichert."; 72.222 ["You need to be logged in, to use this system."] = "Du musst eingeloggt sein, um das System zu benutzen"; 72.223 +["Your are interested"] = "Du bist interessiert"; 72.224 +["Your are supporter"] = "Du bist Unterstützer"; 72.225 ["Your delegation for this area has been deleted."] = "Deine Delegation für dieses Themengebiet wurde gelöscht"; 72.226 ["Your delegation for this area has been updated."] = "Deine Delegation für dieses Themengebiet wurde geändert"; 72.227 ["Your delegation for this issue has been deleted."] = "Deine Delegation für dieses Thema wurde gelöscht"; 72.228 @@ -236,23 +266,18 @@ 72.229 ["Your support has been added to this initiative"] = "Deine Unterstützung wurde der Initiative hinzugefügt"; 72.230 ["Your support has been removed from this initiative"] = "Deine Unterstützung wurde der Initiave entzogen"; 72.231 ["Your support has been updated to the latest draft"] = "Deine Unterstützung wurde auf den neuesten Entwurf aktualisiert"; 72.232 -["Your vote is delegated. [more]"] = "Deine Stimme ist delegiert. [mehr]"; 72.233 ["Z-A"] = false; 72.234 -["admission_time"] = false; 72.235 +["all"] = "Alle"; 72.236 ["blank"] = false; 72.237 -["delete<br /><br />"] = false; 72.238 -["discussion_time"] = false; 72.239 +["delete<br /><br />"] = "löschen<br /><br />"; 72.240 ["email"] = false; 72.241 -["initiative_quorum_den"] = false; 72.242 -["initiative_quorum_num"] = false; 72.243 -["issue_quorum_den"] = false; 72.244 -["issue_quorum_num"] = false; 72.245 ["must"] = "muss"; 72.246 ["must not"] = "darf nicht"; 72.247 +["must/should"] = "muss/soll"; 72.248 +["must/should not"] = "muss/soll nicht"; 72.249 ["neutral"] = "neutral"; 72.250 +["not implemented"] = "nicht umgesetzt"; 72.251 ["should"] = "soll"; 72.252 ["should not"] = "soll nicht"; 72.253 -["verification_time"] = false; 72.254 -["voting_time"] = false; 72.255 ["xmpp"] = false; 72.256 }
73.1 --- a/model/initiative.lua Mon Nov 30 12:00:00 2009 +0100 73.2 +++ b/model/initiative.lua Thu Dec 10 12:00:00 2009 +0100 73.3 @@ -26,7 +26,6 @@ 73.4 that_key = 'initiative_id', 73.5 ref = 'suggestions', 73.6 back_ref = 'initiative', 73.7 - default_order = '"id"' 73.8 } 73.9 73.10 Initiative:add_reference{
74.1 --- a/model/member.lua Mon Nov 30 12:00:00 2009 +0100 74.2 +++ b/model/member.lua Thu Dec 10 12:00:00 2009 +0100 74.3 @@ -2,11 +2,11 @@ 74.4 Member.table = 'member' 74.5 74.6 Member:add_reference{ 74.7 - mode = '11', 74.8 + mode = '1m', 74.9 to = "MemberImage", 74.10 this_key = 'id', 74.11 that_key = 'member_id', 74.12 - ref = 'image', 74.13 + ref = 'images', 74.14 back_ref = 'member' 74.15 } 74.16
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 75.2 +++ b/model/setting.lua Thu Dec 10 12:00:00 2009 +0100 75.3 @@ -0,0 +1,17 @@ 75.4 +Setting = mondelefant.new_class() 75.5 +Setting.table = 'setting' 75.6 +Setting.primary_key = { "member_id", "key" } 75.7 +Interest:add_reference{ 75.8 + mode = 'm1', 75.9 + to = "Member", 75.10 + this_key = 'member_id', 75.11 + that_key = 'id', 75.12 + ref = 'member', 75.13 +} 75.14 + 75.15 +function Setting:by_pk(member_id, key) 75.16 + return self:new_selector() 75.17 + :add_where{ "member_id = ? AND key = ?", member_id, key } 75.18 + :optional_object_mode() 75.19 + :exec() 75.20 +end 75.21 \ No newline at end of file
76.1 Binary file static/icons/16/book_delete.png has changed
77.1 Binary file static/icons/16/bug.png has changed
78.1 Binary file static/icons/16/dropdown.png has changed
79.1 Binary file static/icons/16/error.png has changed
80.1 Binary file static/icons/16/help.png has changed
81.1 Binary file static/icons/16/lightning.png has changed
82.1 Binary file static/icons/16/user_add.png has changed
83.1 Binary file static/icons/16/user_green.png has changed
84.1 --- a/static/style.css Mon Nov 30 12:00:00 2009 +0100 84.2 +++ b/static/style.css Thu Dec 10 12:00:00 2009 +0100 84.3 @@ -60,31 +60,27 @@ 84.4 .layout_notice, .layout_error, .layout_warning { 84.5 background: #fff; 84.6 font-weight: bold; 84.7 - right: 2ex; 84.8 line-height: 1.7em; 84.9 - position: absolute; 84.10 - top: 6ex; 84.11 - width: 60ex; 84.12 -moz-opacity:0.7; 84.13 } 84.14 84.15 .slot_notice, .slot_warning, .slot_error { 84.16 - padding: 2ex; 84.17 + padding-left: 1em; 84.18 } 84.19 84.20 .slot_notice { 84.21 - color: green; 84.22 - border: 2px solid green; 84.23 + background-color: #cfc; 84.24 + color: #040; 84.25 } 84.26 84.27 .slot_warning { 84.28 - color: orange; 84.29 - border: 2px solid orange; 84.30 + background-color: #fec; 84.31 + color: #420; 84.32 } 84.33 84.34 .slot_error { 84.35 - color: red; 84.36 - border: 2px solid red; 84.37 + background-color: #fcc; 84.38 + color: #400; 84.39 } 84.40 84.41 /************************************************************************* 84.42 @@ -92,7 +88,6 @@ 84.43 */ 84.44 84.45 .topbar { 84.46 - margin-bottom: 1em; 84.47 background-color: #444; 84.48 color: #fff; 84.49 font-size: 75%; 84.50 @@ -161,17 +156,21 @@ 84.51 */ 84.52 84.53 .title_bar { 84.54 - border-bottom: 1px solid #000; 84.55 + border-bottom: 1px solid #777; 84.56 margin-bottom: 2ex; 84.57 + padding-top: 1ex; 84.58 + padding-bottom: 0.5ex; 84.59 +} 84.60 + 84.61 +.title_bar_content { 84.62 + margin-left: 1em; 84.63 } 84.64 84.65 .path { 84.66 color: #444; 84.67 - xbackground-color: #ddd; 84.68 } 84.69 84.70 .path div { 84.71 - margin-left: 1em; 84.72 font-size: 100%; 84.73 line-height: 180%; 84.74 } 84.75 @@ -195,7 +194,6 @@ 84.76 } 84.77 84.78 .title div { 84.79 - margin-left: 0.66em; 84.80 font-weight: bold; 84.81 font-size: 135%; 84.82 line-height: 110%; 84.83 @@ -205,25 +203,23 @@ 84.84 color: #fff; 84.85 } 84.86 84.87 -.avatar { 84.88 +.member_image_avatar { 84.89 float: left; 84.90 margin-right: 0.5em; 84.91 - width: 48px; 84.92 - height: 48px; 84.93 } 84.94 84.95 .actions { 84.96 - display: inline; 84.97 font-size: 75%; 84.98 - line-height: 200%; 84.99 + line-height: 220%; 84.100 } 84.101 84.102 .slot_actions { 84.103 - margin-left: 1em; 84.104 display: inline; 84.105 } 84.106 84.107 .actions a { 84.108 + float: left; 84.109 + display: block; 84.110 padding: 0.5ex 0.5em 0.5ex 0.0em; 84.111 margin-right: 1em; 84.112 vertical-align: middle; 84.113 @@ -236,37 +232,70 @@ 84.114 .actions img { 84.115 padding-left: 0.2em; 84.116 padding-right: 0.2em; 84.117 + vertical-align: middle; 84.118 +} 84.119 + 84.120 +.logo { 84.121 + float: right; 84.122 + margin-right: 1em; 84.123 } 84.124 84.125 /************************************************************************* 84.126 * vote info / delegation 84.127 */ 84.128 84.129 -.slot_interest, 84.130 +.interest, 84.131 .slot_support, 84.132 -.slot_delegation { 84.133 +.delegation { 84.134 float: left; 84.135 - font-size: 75%; 84.136 + position: relative; 84.137 +} 84.138 + 84.139 +.interest img, 84.140 +.slot_support img, 84.141 +.delegation img { 84.142 + padding-left: 0.2em; 84.143 + padding-right: 0.2em; 84.144 +} 84.145 +.vote_info .head { 84.146 + float: left; 84.147 margin-right: 1em; 84.148 } 84.149 84.150 -.vote_info .head { 84.151 - line-height: 200%; 84.152 +.interest .head_active { 84.153 + background-color: #dfd; 84.154 + border: 1px solid #8b8; 84.155 +} 84.156 + 84.157 +.slot_support .head_active { 84.158 + background-color: #dfd; 84.159 + border: 1px solid #8b8; 84.160 +} 84.161 + 84.162 +.delegation .head_active { 84.163 + background-color: #ffd; 84.164 + border: 1px solid #bb8; 84.165 } 84.166 84.167 .vote_info .close { 84.168 - background-color: #f44; 84.169 - float: right; 84.170 + position: absolute; 84.171 + top: 0; 84.172 + right: 0; 84.173 padding: 1ex; 84.174 + display: block; 84.175 } 84.176 84.177 .vote_info .content { 84.178 + font-size: 133%; 84.179 + line-height: 100%; 84.180 + top: 3ex; 84.181 display: none; 84.182 position: absolute; 84.183 z-index: 10; 84.184 background-color: #fff; 84.185 - border: 2px solid #444; 84.186 + border: 1px solid #999; 84.187 padding: 1em; 84.188 + width: 25em; 84.189 } 84.190 84.191 .vote_info .delegation_arrow { 84.192 @@ -275,6 +304,14 @@ 84.193 vertical-align: middle; 84.194 } 84.195 84.196 +.vote_info .delegation_arrow_overridden { 84.197 + opacity: 0.4; 84.198 +} 84.199 + 84.200 +.vote_info .delegation_scope_overridden { 84.201 + color: #777; 84.202 +} 84.203 + 84.204 .vote_info .delegation_scope { 84.205 display: inline; 84.206 } 84.207 @@ -286,14 +323,29 @@ 84.208 clear: left; 84.209 } 84.210 84.211 +.delegation_overridden .member_thumb { 84.212 + opacity: 0.4; 84.213 +} 84.214 + 84.215 .delegation .revoke { 84.216 margin: 0.5ex; 84.217 + float: right; 84.218 } 84.219 84.220 .delegation .revoke img { 84.221 vertical-align: middle; 84.222 } 84.223 84.224 + 84.225 +.sub_title div { 84.226 + border-top: 1px solid #444; 84.227 + padding-top: 1ex; 84.228 + margin-top: 1ex; 84.229 + font-weight: bold; 84.230 + font-size: 135%; 84.231 + line-height: 110%; 84.232 +} 84.233 + 84.234 /************************************************************************* 84.235 * Main content 84.236 */ 84.237 @@ -315,8 +367,9 @@ 84.238 84.239 .ui_tabs_links a { 84.240 padding: 1ex; 84.241 - margin-left: 0.5em; 84.242 + line-height: 200%; 84.243 background-color: #e7e7e7; 84.244 + white-space: nowrap; 84.245 } 84.246 84.247 .ui_tabs_links a:hover { 84.248 @@ -401,6 +454,25 @@ 84.249 height: 1.3ex; 84.250 } 84.251 84.252 +.bargraph_legend { 84.253 + margin-top: 2ex; 84.254 +} 84.255 + 84.256 +.bargraph_legend .bargraph { 84.257 + width: 26px; 84.258 +} 84.259 + 84.260 +.bargraph_legend div, 84.261 +.bargraph_legend div div, 84.262 +.bargraph_legend div div div { 84.263 + float: left; 84.264 +} 84.265 + 84.266 +.bargraph_legend_label { 84.267 + margin-left: 0.5em; 84.268 + margin-right: 1em; 84.269 +} 84.270 + 84.271 /************************************************************************* 84.272 * vertical ui.form 84.273 */ 84.274 @@ -432,7 +504,7 @@ 84.275 .vertical .ui_field_label { 84.276 text-transform: uppercase; 84.277 font-size: 70%; 84.278 - line-height: 190%; 84.279 + line-height: 120%; 84.280 font-weight: bold; 84.281 color: #777; 84.282 width: 15em; 84.283 @@ -631,10 +703,22 @@ 84.284 84.285 .member_thumb { 84.286 text-decoration: none; 84.287 - min-width: 150px; 84.288 + width: 18em; 84.289 + height: 48px; 84.290 display: block; 84.291 float: left; 84.292 - border: 1px solid #ccc; 84.293 + border: 1px solid #999; 84.294 + overflow: hidden; 84.295 + xwhite-space: nowrap; 84.296 + position: relative; 84.297 +} 84.298 + 84.299 +.member_thumb a{ 84.300 + position: absolute; 84.301 + top: 0; 84.302 + left: 0; 84.303 + padding: 0; 84.304 + margin: 0; 84.305 } 84.306 84.307 .member_thumb a:hover div { 84.308 @@ -642,25 +726,24 @@ 84.309 color: #fff; 84.310 } 84.311 84.312 -.member_thumb .flags a:hover { 84.313 - background-color: #444; 84.314 - color: #fff; 84.315 -} 84.316 - 84.317 .member_thumb img { 84.318 - margin-right: 0.5em; 84.319 + padding: 0; 84.320 + margin: 0; 84.321 vertical-align: bottom; 84.322 - float: left; 84.323 } 84.324 84.325 .member_thumb div { 84.326 - display: inline; 84.327 +} 84.328 + 84.329 +.member_thumb .member_image { 84.330 } 84.331 84.332 .member_thumb .member_name { 84.333 - display: block; 84.334 - margin-top: 3ex; 84.335 - margin-right: 0.5em; 84.336 + position: absolute; 84.337 + left: 48px; 84.338 + top: 2ex; 84.339 + font-size: 100%; 84.340 + width: 14em; 84.341 } 84.342 84.343 .member_thumb .flags { 84.344 @@ -668,10 +751,22 @@ 84.345 font-size: 75%; 84.346 } 84.347 84.348 -.draft_content { 84.349 +.member_thumb .flags a{ 84.350 + position: static; 84.351 + float: right; 84.352 +} 84.353 + 84.354 + 84.355 +.member .right { 84.356 + float: right; 84.357 +} 84.358 + 84.359 +.draft_content, 84.360 +.member_statement { 84.361 background-color: #eee; 84.362 border: 1px solid #ccc; 84.363 - padding: 1ex; 84.364 + padding-left: 1ex; 84.365 + padding-right: 1ex; 84.366 } 84.367 84.368 .diff { 84.369 @@ -715,3 +810,73 @@ 84.370 padding: 1ex; 84.371 } 84.372 84.373 +.suggestion_fulfilled { 84.374 + width: 15em; 84.375 +} 84.376 +.suggestion_fulfilled a.action { 84.377 + padding-left: 0; 84.378 + line-height: 120%; 84.379 +} 84.380 + 84.381 +.help { 84.382 + border: 1px solid #bcd; 84.383 + background-color: #def; 84.384 + color: #000; 84.385 + padding: 1ex; 84.386 +} 84.387 + 84.388 +.help_visible { 84.389 + margin-bottom: 1ex; 84.390 +} 84.391 + 84.392 +.help_visible .help_icon { 84.393 + float: right; 84.394 +} 84.395 + 84.396 +.slot_help_hidden { 84.397 + float: right; 84.398 + margin-right: 1em; 84.399 +} 84.400 + 84.401 +.help_actions { 84.402 + font-size: 75%; 84.403 + float: right; 84.404 +} 84.405 + 84.406 +.help_actions a { 84.407 + margin-right: 1em; 84.408 + color: #468; 84.409 +} 84.410 + 84.411 +.wiki { 84.412 +} 84.413 + 84.414 +.wiki h1, 84.415 +.wiki h2, 84.416 +.wiki h3, 84.417 +.wiki h4 { 84.418 + margin-top: 1ex; 84.419 + margin-bottom: 1ex; 84.420 +} 84.421 + 84.422 +.wiki h1 { 84.423 + font-size: 150%; 84.424 +} 84.425 + 84.426 +.wiki h2 { 84.427 + font-size: 125%; 84.428 +} 84.429 + 84.430 +.wiki p { 84.431 + margin-top: 1ex; 84.432 + margin-bottom: 1ex; 84.433 +} 84.434 + 84.435 +form .warning { 84.436 + background-color: #ffd; 84.437 + color: #000; 84.438 + border: 1px solid #dda; 84.439 + margin: 1ex; 84.440 + margin-bottom: 2ex; 84.441 + padding: 1ex; 84.442 +}