rev |
line source |
bsw@1045
|
1 local for_member = param.get ( "for_member", "table" )
|
bsw@1045
|
2 local for_unit = param.get ( "for_unit", "table" )
|
bsw@1045
|
3 local for_area = param.get ( "for_area", "table" )
|
bsw@1045
|
4 local for_issue = param.get ( "for_issue", "table" )
|
bsw@1045
|
5 local for_initiative = param.get ( "for_initiative", "table" )
|
bsw@1045
|
6 local for_sidebar = param.get("for_sidebar", atom.boolean)
|
bsw@1045
|
7 local no_filter = param.get ( "no_filter", atom.boolean )
|
bsw@1045
|
8 local search = param.get ( "search" )
|
bsw@1045
|
9
|
bsw@1045
|
10 local limit = 25
|
bsw@1045
|
11
|
bsw@1045
|
12 local mode = param.get_all_cgi()["mode"] or "issue"
|
bsw@1045
|
13
|
bsw@1045
|
14 if for_initiative or for_issue or for_member then
|
bsw@1045
|
15 mode = "timeline"
|
bsw@1045
|
16 end
|
bsw@1045
|
17
|
bsw@1045
|
18 local selector
|
bsw@1045
|
19
|
bsw@1045
|
20 if search then
|
bsw@1045
|
21
|
bsw@1045
|
22 selector = Issue:get_search_selector(search)
|
bsw@1045
|
23
|
bsw@1045
|
24
|
bsw@1045
|
25 elseif mode == "timeline" then
|
bsw@1045
|
26
|
bsw@1045
|
27 local event_max_id = param.get_all_cgi()["event_max_id"]
|
bsw@1045
|
28
|
bsw@1045
|
29 selector = Event:new_selector()
|
bsw@1045
|
30 :add_order_by("event.id DESC")
|
bsw@1045
|
31 :join("issue", nil, "issue.id = event.issue_id")
|
bsw@1045
|
32 :add_field("now() - event.occurrence", "time_ago")
|
bsw@1045
|
33 :limit(limit + 1)
|
bsw@1045
|
34
|
bsw@1045
|
35 if event_max_id then
|
bsw@1045
|
36 selector:add_where{ "event.id < ?", event_max_id }
|
bsw@1045
|
37 end
|
bsw@1045
|
38
|
bsw@1045
|
39 if for_member then
|
bsw@1045
|
40 selector:add_where{ "event.member_id = ?", for_member.id }
|
bsw@1045
|
41 end
|
bsw@1045
|
42
|
bsw@1045
|
43 if for_initiative then
|
bsw@1045
|
44 selector:add_where{ "event.initiative_id = ?", for_initiative.id }
|
bsw@1045
|
45 end
|
bsw@1045
|
46
|
bsw@1045
|
47
|
bsw@1045
|
48 elseif mode == "issue" then
|
bsw@1045
|
49
|
bsw@1045
|
50 selector = Issue:new_selector()
|
bsw@1045
|
51
|
bsw@1045
|
52 end
|
bsw@1045
|
53
|
bsw@1045
|
54 if for_unit then
|
bsw@1045
|
55 selector:join("area", nil, "area.id = issue.area_id")
|
bsw@1045
|
56 selector:add_where{ "area.unit_id = ?", for_unit.id }
|
bsw@1045
|
57 elseif for_area then
|
bsw@1045
|
58 selector:add_where{ "issue.area_id = ?", for_area.id }
|
bsw@1045
|
59 elseif for_issue then
|
bsw@1045
|
60 selector:add_where{ "issue.id = ?", for_issue.id }
|
bsw@1045
|
61 end
|
bsw@1045
|
62
|
bsw@1045
|
63 if not search and app.session.member_id then
|
bsw@1045
|
64 selector
|
bsw@1045
|
65 :left_join("interest", "_interest", {
|
bsw@1045
|
66 "_interest.issue_id = issue.id AND _interest.member_id = ?", app.session.member.id
|
bsw@1045
|
67 } )
|
bsw@1045
|
68 :add_field("(_interest.member_id NOTNULL)", "is_interested")
|
bsw@1045
|
69 :left_join("delegating_interest_snapshot", "_delegating_interest", { [[
|
bsw@1045
|
70 _delegating_interest.issue_id = issue.id AND
|
bsw@1045
|
71 _delegating_interest.member_id = ? AND
|
bsw@1045
|
72 _delegating_interest.event = issue.latest_snapshot_event
|
bsw@1045
|
73 ]], app.session.member.id } )
|
bsw@1045
|
74 :add_field("_delegating_interest.delegate_member_ids[1]", "is_interested_by_delegation_to_member_id")
|
bsw@1045
|
75 :add_field("_delegating_interest.delegate_member_ids[array_upper(_delegating_interest.delegate_member_ids, 1)]", "is_interested_via_member_id")
|
bsw@1045
|
76 :add_field("array_length(_delegating_interest.delegate_member_ids, 1)", "delegation_chain_length")
|
bsw@1045
|
77 end
|
bsw@1045
|
78
|
bsw@1045
|
79 function doit()
|
bsw@1045
|
80
|
bsw@1045
|
81 local last_event_id
|
bsw@1045
|
82
|
bsw@1045
|
83 local items = selector:exec()
|
bsw@1045
|
84
|
bsw@1045
|
85 if #items < 1 then
|
bsw@1045
|
86 ui.section( function()
|
bsw@1045
|
87 ui.sectionRow( function()
|
bsw@1045
|
88 ui.heading{ level = 2, content = _"No results for this selection" }
|
bsw@1045
|
89 end )
|
bsw@1045
|
90 end )
|
bsw@1045
|
91 return
|
bsw@1045
|
92 end
|
bsw@1045
|
93
|
bsw@1045
|
94 local row_class = "sectionRow"
|
bsw@1045
|
95 if for_sidebar then
|
bsw@1045
|
96 row_class = "sidebarRow"
|
bsw@1045
|
97 end
|
bsw@1045
|
98
|
bsw@1045
|
99 if mode == "timeline" then
|
bsw@1045
|
100 local issues = items:load ( "issue" )
|
bsw@1045
|
101 local initiative = items:load ( "initiative" )
|
bsw@1045
|
102 items:load ( "suggestion" )
|
bsw@1045
|
103 items:load ( "member" )
|
bsw@1045
|
104 issues:load_everything_for_member_id ( app.session.member_id )
|
bsw@1045
|
105 initiative:load_everything_for_member_id ( app.session.member_id )
|
bsw@1045
|
106 elseif mode == "issue" then
|
bsw@1045
|
107 items:load_everything_for_member_id ( app.session.member_id )
|
bsw@1045
|
108 end
|
bsw@1045
|
109
|
bsw@1045
|
110 local class = "section"
|
bsw@1045
|
111 if mode == "timeline" then
|
bsw@1045
|
112 class = class .. " events"
|
bsw@1045
|
113 elseif mode == "issue" then
|
bsw@1045
|
114 class = class .. " issues"
|
bsw@1045
|
115 end
|
bsw@1045
|
116
|
bsw@1045
|
117 ui.container{ attr = { class = class }, content = function()
|
bsw@1045
|
118
|
bsw@1045
|
119 local last_event_date
|
bsw@1045
|
120 for i, item in ipairs(items) do
|
bsw@1045
|
121 local event
|
bsw@1045
|
122 local issue
|
bsw@1045
|
123 if mode == "timeline" then
|
bsw@1045
|
124 event = item
|
bsw@1045
|
125 issue = item.issue
|
bsw@1045
|
126 elseif mode == "issue" then
|
bsw@1045
|
127 event = {}
|
bsw@1045
|
128 issue = item
|
bsw@1045
|
129 end
|
bsw@1045
|
130
|
bsw@1045
|
131 last_event_id = event.id
|
bsw@1045
|
132
|
bsw@1045
|
133 local class = "event " .. row_class
|
bsw@1045
|
134 if event.suggestion_id then
|
bsw@1045
|
135 class = class .. " suggestion"
|
bsw@1045
|
136 end
|
bsw@1045
|
137
|
bsw@1045
|
138 ui.container{ attr = { class = class }, content = function()
|
bsw@1045
|
139 local event_name
|
bsw@1045
|
140 local negative_event = false
|
bsw@1045
|
141
|
bsw@1045
|
142 local days_ago_text
|
bsw@1045
|
143
|
bsw@1045
|
144 if mode == "timeline" then
|
bsw@1045
|
145 event_name = event.event_name
|
bsw@1045
|
146
|
bsw@1045
|
147 if event.event == "issue_state_changed" then
|
bsw@1045
|
148 if event.state == "discussion" then
|
bsw@1045
|
149 event_name = _"Discussion started"
|
bsw@1045
|
150 elseif event.state == "verification" then
|
bsw@1045
|
151 event_name = _"Verification started"
|
bsw@1045
|
152 elseif event.state == "voting" then
|
bsw@1045
|
153 event_name = _"Voting started"
|
bsw@1045
|
154 elseif event.state == "finished_with_winner" then
|
bsw@1045
|
155 event_name = event.state_name
|
bsw@1045
|
156 elseif event.state == "finished_without_winner" then
|
bsw@1045
|
157 event_name = event.state_name
|
bsw@1045
|
158 negative_event = true
|
bsw@1045
|
159 else
|
bsw@1045
|
160 event_name = event.state_name
|
bsw@1045
|
161 negative_event = true
|
bsw@1045
|
162 end
|
bsw@1045
|
163 elseif event.event == "initiative_revoked" then
|
bsw@1045
|
164 negative_event = true
|
bsw@1045
|
165 end
|
bsw@1045
|
166
|
bsw@1045
|
167 if event.time_ago == 0 then
|
bsw@1045
|
168 days_ago_text = _("today at #{time}", { time = format.time(event.occurrence) })
|
bsw@1045
|
169 elseif event.time_ago == 1 then
|
bsw@1045
|
170 days_ago_text = _("yesterday at #{time}", { time = format.time(event.occurrence) })
|
bsw@1045
|
171 else
|
bsw@1045
|
172 days_ago_text = _("#{interval} ago", { interval = format.interval_text ( event.time_ago ) } )
|
bsw@1045
|
173 end
|
bsw@1045
|
174
|
bsw@1045
|
175 elseif mode == "issue" then
|
bsw@1045
|
176 event_name = issue.state_name
|
bsw@1045
|
177 if issue.state_time_left:sub(1,1) ~= "-" then
|
bsw@1045
|
178 days_ago_text = _( "#{interval} left", {
|
bsw@1045
|
179 interval = format.interval_text ( issue.state_time_left )
|
bsw@1045
|
180 })
|
bsw@1045
|
181 elseif issue.closed then
|
bsw@1045
|
182 days_ago_text = _( "#{interval} ago", {
|
bsw@1045
|
183 interval = format.interval_text ( issue.closed_ago )
|
bsw@1045
|
184 })
|
bsw@1045
|
185 else
|
bsw@1045
|
186 days_ago_text = _"phase ends soon"
|
bsw@1045
|
187 end
|
bsw@1045
|
188 if issue.closed and not issue.fully_frozen then
|
bsw@1045
|
189 negative_event = true
|
bsw@1045
|
190 end
|
bsw@1045
|
191 if issue.state == "finished_without_winner" then
|
bsw@1045
|
192 negative_event = true
|
bsw@1045
|
193 end
|
bsw@1045
|
194 if issue.state == "canceled_no_initiative_admitted" then
|
bsw@1045
|
195 negative_event = true
|
bsw@1045
|
196 end
|
bsw@1045
|
197 if issue.state == "canceled_by_admin" then
|
bsw@1045
|
198 negative_event = true
|
bsw@1045
|
199 end
|
bsw@1045
|
200 end
|
bsw@1045
|
201
|
bsw@1045
|
202 local class= "event_info"
|
bsw@1045
|
203
|
bsw@1045
|
204 if negative_event then
|
bsw@1045
|
205 class = class .. " negative"
|
bsw@1045
|
206 end
|
bsw@1045
|
207
|
bsw@1045
|
208 if mode == "timeline" then
|
bsw@1045
|
209 ui.container{ attr = { class = class }, content = function ()
|
bsw@1045
|
210 ui.tag { content = event_name }
|
bsw@1045
|
211 slot.put ( " " )
|
bsw@1045
|
212 ui.tag{ attr = { class = "event_time" }, content = days_ago_text }
|
bsw@1045
|
213 end }
|
bsw@1045
|
214 end
|
bsw@1045
|
215
|
bsw@1045
|
216 if not for_issue and not for_initiative then
|
bsw@1045
|
217 ui.container{ attr = { class = "issue_context" }, content = function()
|
bsw@1045
|
218 ui.link{
|
bsw@1045
|
219 module = "unit", view = "show", id = issue.area.unit_id,
|
bsw@1045
|
220 attr = { class = "unit" }, text = issue.area.unit.name
|
bsw@1045
|
221 }
|
bsw@1045
|
222 slot.put ( " " )
|
bsw@1045
|
223 ui.link{
|
bsw@1045
|
224 module = "area", view = "show", id = issue.area_id,
|
bsw@1045
|
225 attr = { class = "area" }, text = issue.area.name
|
bsw@1045
|
226 }
|
bsw@1045
|
227 slot.put ( " " )
|
bsw@1045
|
228 execute.view{
|
bsw@1045
|
229 module = "delegation", view = "_info", params = {
|
bsw@1045
|
230 issue = issue, member = for_member
|
bsw@1045
|
231 }
|
bsw@1045
|
232 }
|
bsw@1045
|
233 end }
|
bsw@1045
|
234 ui.container{ attr = { class = "issue_info" }, content = function()
|
bsw@1045
|
235 ui.link{
|
bsw@1045
|
236 attr = { class = "issue" },
|
bsw@1045
|
237 text = _("#{policy} ##{id}", { policy = issue.policy.name, id = issue.id }),
|
bsw@1045
|
238 module = "issue",
|
bsw@1045
|
239 view = "show",
|
bsw@1045
|
240 id = issue.id
|
bsw@1045
|
241 }
|
bsw@1045
|
242
|
bsw@1045
|
243 end }
|
bsw@1045
|
244 end
|
bsw@1045
|
245
|
bsw@1045
|
246 if mode ~= "timeline"
|
bsw@1045
|
247 or event.state == "finished_with_winner"
|
bsw@1045
|
248 or event.state == "finished_without_winner"
|
bsw@1045
|
249 then
|
bsw@1045
|
250 local initiative = issue.initiatives[1]
|
bsw@1045
|
251 if initiative then
|
bsw@1045
|
252 util.initiative_pie(initiative)
|
bsw@1045
|
253 end
|
bsw@1045
|
254 end
|
bsw@1045
|
255
|
bsw@1045
|
256 if mode == "issue" then
|
bsw@1045
|
257 ui.container{ attr = { class = class }, content = function ()
|
bsw@1045
|
258 ui.tag { content = event_name }
|
bsw@1045
|
259 slot.put ( " " )
|
bsw@1045
|
260 ui.tag{ attr = { class = "event_time" }, content = days_ago_text }
|
bsw@1045
|
261 end }
|
bsw@1045
|
262 elseif mode == "timeline"
|
bsw@1045
|
263 and not for_issue
|
bsw@1045
|
264 and event.event ~= "issue_state_changed"
|
bsw@1045
|
265 then
|
bsw@1045
|
266 slot.put("<br />")
|
bsw@1045
|
267 end
|
bsw@1045
|
268
|
bsw@1045
|
269 if event.suggestion_id then
|
bsw@1045
|
270 ui.container{ attr = { class = "suggestion" }, content = function()
|
bsw@1045
|
271 ui.link{
|
bsw@1045
|
272 text = format.string(event.suggestion.name, {
|
bsw@1045
|
273 truncate_at = 160, truncate_suffix = true
|
bsw@1045
|
274 }),
|
bsw@1045
|
275 module = "initiative", view = "show", id = event.initiative.id,
|
bsw@1045
|
276 params = { suggestion_id = event.suggestion_id },
|
bsw@1045
|
277 anchor = "s" .. event.suggestion_id
|
bsw@1045
|
278 }
|
bsw@1045
|
279 end }
|
bsw@1045
|
280 end
|
bsw@1045
|
281
|
bsw@1045
|
282 if not for_initiative and (not for_issue or event.initiative_id) then
|
bsw@1045
|
283
|
bsw@1045
|
284 ui.container{ attr = { class = "initiative_list" }, content = function()
|
bsw@1045
|
285 if event.initiative_id then
|
bsw@1045
|
286 local initiative = event.initiative
|
bsw@1045
|
287
|
bsw@1045
|
288 execute.view{ module = "initiative", view = "_list", params = {
|
bsw@1045
|
289 issue = issue,
|
bsw@1045
|
290 initiative = initiative,
|
bsw@1045
|
291 for_event = mode == "timeline" and not (event.state == issue.state)
|
bsw@1045
|
292
|
bsw@1045
|
293 } }
|
bsw@1045
|
294 else
|
bsw@1045
|
295 local initiatives = issue.initiatives
|
bsw@1045
|
296 execute.view{ module = "initiative", view = "_list", params = {
|
bsw@1045
|
297 issue = issue,
|
bsw@1045
|
298 initiatives = initiatives,
|
bsw@1045
|
299 for_event = mode == "timeline" and not (event.state == issue.state)
|
bsw@1045
|
300 } }
|
bsw@1045
|
301 end
|
bsw@1045
|
302 end }
|
bsw@1045
|
303 end
|
bsw@1045
|
304
|
bsw@1045
|
305 end }
|
bsw@1045
|
306 end
|
bsw@1045
|
307
|
bsw@1045
|
308 if mode == "timeline" then
|
bsw@1045
|
309 if for_sidebar then
|
bsw@1045
|
310 ui.container { attr = { class = row_class }, content = function ()
|
bsw@1045
|
311 ui.link{
|
bsw@1045
|
312 attr = { class = "moreLink" },
|
bsw@1045
|
313 text = _"Show full history",
|
bsw@1045
|
314 module = "initiative", view = "history", id = for_initiative.id
|
bsw@1045
|
315 }
|
bsw@1045
|
316 end }
|
bsw@1045
|
317 elseif #items > limit then
|
bsw@1045
|
318 ui.container { attr = { class = row_class }, content = function ()
|
bsw@1045
|
319 ui.link{
|
bsw@1045
|
320 attr = { class = "moreLink" },
|
bsw@1045
|
321 text = _"Show older events",
|
bsw@1045
|
322 module = request.get_module(),
|
bsw@1045
|
323 view = request.get_view(),
|
bsw@1045
|
324 id = for_unit and for_unit.id or for_area and for_area.id or for_issue and for_issue.id or for_member and for_member.id,
|
bsw@1045
|
325 params = {
|
bsw@1045
|
326 mode = "timeline",
|
bsw@1045
|
327 event_max_id = last_event_id,
|
bsw@1045
|
328 tab = param.get_all_cgi()["tab"],
|
bsw@1045
|
329 phase = param.get_all_cgi()["phase"],
|
bsw@1045
|
330 closed = param.get_all_cgi()["closed"]
|
bsw@1045
|
331 }
|
bsw@1045
|
332 }
|
bsw@1045
|
333 end }
|
bsw@1045
|
334 elseif #items < 1 then
|
bsw@1045
|
335 ui.container { attr = { class = row_class }, content = _"No more events available" }
|
bsw@1045
|
336 end
|
bsw@1045
|
337 end
|
bsw@1045
|
338
|
bsw@1045
|
339 end }
|
bsw@1045
|
340
|
bsw@1045
|
341 end
|
bsw@1045
|
342
|
bsw@1045
|
343
|
bsw@1045
|
344 local filters = {}
|
bsw@1045
|
345
|
bsw@1045
|
346 if not for_initiative and not for_issue and not no_filter then
|
bsw@1045
|
347 filters = execute.load_chunk{module="issue", chunk="_filters.lua", params = {
|
bsw@1045
|
348 for_events = mode == "timeline" and true or false,
|
bsw@1045
|
349 member = app.session.member,
|
bsw@1045
|
350 for_member = for_member,
|
bsw@1045
|
351 state = for_state,
|
bsw@1045
|
352 for_unit = for_unit and true or false,
|
bsw@1045
|
353 for_area = for_area and true or false
|
bsw@1045
|
354 }}
|
bsw@1045
|
355 end
|
bsw@1045
|
356
|
bsw@1045
|
357 filters.opened = true
|
bsw@1045
|
358 filters.selector = selector
|
bsw@1045
|
359
|
bsw@1045
|
360 if mode == "timeline" then
|
bsw@1045
|
361 filters.content = doit
|
bsw@1045
|
362 else
|
bsw@1045
|
363 filters.content = function()
|
bsw@1045
|
364 ui.paginate{
|
bsw@1045
|
365 selector = selector,
|
bsw@1045
|
366 per_page = 25,
|
bsw@1045
|
367 content = doit
|
bsw@1045
|
368 }
|
bsw@1045
|
369 end
|
bsw@1045
|
370 end
|
bsw@1045
|
371
|
bsw@1045
|
372 ui.filters(filters)
|
bsw@1045
|
373 |