liquid_feedback_frontend

annotate app/main/initiative/show.lua @ 1246:78d3be54cfe0

Fixed documentation: SQL commands for database initialization match Core version 3.1.0 now
author jbe
date Fri Feb 19 23:32:24 2016 +0100 (2016-02-19)
parents fede09736f2b
children 32cc544d5a5b
rev   line source
bsw@1045 1 local initiative = Initiative:by_id ( param.get_id() )
bsw@1045 2 local member = app.session.member
bsw@1045 3
bsw@1045 4 if not initiative then
bsw@1045 5 execute.view { module = "index", view = "404" }
bsw@1045 6 request.set_status("404 Not Found")
bsw@1045 7 return
bsw@1045 8 end
bsw@1045 9
bsw@1045 10 local issue_info
bsw@1045 11
bsw@1045 12 if member then
bsw@1045 13 initiative:load_everything_for_member_id(member.id)
bsw@1045 14 initiative.issue:load_everything_for_member_id(member.id)
bsw@1045 15 issue_info = initiative.issue.member_info
bsw@1045 16 end
bsw@1045 17
bsw@1045 18 execute.view {
bsw@1045 19 module = "issue", view = "_head",
bsw@1045 20 params = {
bsw@1045 21 issue = initiative.issue,
bsw@1045 22 initiative = initiative,
bsw@1045 23 member = app.session.member
bsw@1045 24 }
bsw@1045 25 }
bsw@1045 26
bsw@1145 27 local direct_supporter
bsw@1145 28
bsw@1045 29 if app.session.member_id then
bsw@1045 30 direct_supporter = initiative.issue.member_info.own_participation and initiative.member_info.supported
bsw@1045 31 end
bsw@718 32
bsw@1045 33 ui.script { script = [[
bsw@1045 34 function showTab(tabId) {
bsw@1045 35 $('.tab').hide();
bsw@1045 36 $('.main').hide();
bsw@1045 37 $('.main, .slot_extra .section').hide();
bsw@1045 38 $('.' + tabId).show();
bsw@1045 39 if (tabId == "main") $('.slot_extra .section').show();
bsw@1045 40 };
bsw@1045 41 showTab('main');
bsw@1045 42 ]]}
bsw@1045 43
bsw@1045 44 execute.view{ module = "issue", view = "_sidebar_state", params = {
bsw@1045 45 initiative = initiative
bsw@1045 46 } }
bsw@1045 47
bsw@1045 48 execute.view {
bsw@1045 49 module = "issue", view = "_sidebar_issue",
bsw@1045 50 params = {
bsw@1045 51 issue = initiative.issue,
bsw@1045 52 highlight_initiative_id = initiative.id
bsw@1045 53 }
bsw@1045 54 }
bsw@1045 55
bsw@1045 56 execute.view {
bsw@1045 57 module = "issue", view = "_sidebar_whatcanido",
bsw@1045 58 params = { initiative = initiative }
bsw@1045 59 }
bsw@1045 60
bsw@1045 61 execute.view {
bsw@1045 62 module = "issue", view = "_sidebar_members", params = {
bsw@1045 63 issue = initiative.issue, initiative = initiative
bsw@718 64 }
bsw@718 65 }
bsw@1045 66
bsw@1045 67 ui.section( function ()
bsw@1045 68 execute.view{
bsw@1045 69 module = "initiative", view = "_head", params = {
bsw@1045 70 initiative = initiative
bsw@1045 71 }
bsw@1045 72 }
bsw@1045 73
bsw@1045 74 if direct_supporter and not initiative.issue.closed then
bsw@1045 75 local supporter = app.session.member:get_reference_selector("supporters")
bsw@1045 76 :add_where{ "initiative_id = ?", initiative.id }
bsw@1045 77 :optional_object_mode()
bsw@1045 78 :exec()
bsw@1045 79
bsw@1045 80 if supporter then
bsw@1045 81
bsw@1045 82 local old_draft_id = supporter.draft_id
bsw@1045 83 local new_draft_id = initiative.current_draft.id
bsw@1045 84
bsw@1045 85 if old_draft_id ~= new_draft_id then
bsw@1045 86 ui.sectionRow( "draft_updated_info", function ()
bsw@1045 87 ui.container{
bsw@1045 88 attr = { class = "info" },
bsw@1045 89 content = _"The draft of this initiative has been updated!"
bsw@1045 90 }
bsw@1045 91 slot.put(" ")
bsw@1045 92 ui.link{
bsw@1045 93 content = _"show differences",
bsw@1045 94 module = "draft",
bsw@1045 95 view = "diff",
bsw@1045 96 params = {
bsw@1045 97 old_draft_id = old_draft_id,
bsw@1045 98 new_draft_id = new_draft_id
bsw@1045 99 }
bsw@1045 100 }
bsw@1045 101 if not initiative.revoked then
bsw@1045 102 slot.put(" | ")
bsw@1045 103 ui.link{
bsw@1045 104 text = _"refresh my support",
bsw@1045 105 module = "initiative",
bsw@1045 106 action = "add_support",
bsw@1045 107 id = initiative.id,
bsw@1045 108 params = { draft_id = initiative.current_draft.id },
bsw@1045 109 routing = {
bsw@1045 110 default = {
bsw@1045 111 mode = "redirect",
bsw@1045 112 module = "initiative",
bsw@1045 113 view = "show",
bsw@1045 114 id = initiative.id
bsw@1045 115 }
bsw@1045 116 }
bsw@1045 117 }
bsw@1045 118 slot.put(" | ")
bsw@1045 119 end
bsw@1045 120
bsw@1045 121 ui.link{
bsw@1045 122 text = _"remove my support",
bsw@1045 123 module = "initiative",
bsw@1045 124 action = "remove_support",
bsw@1045 125 id = initiative.id,
bsw@1045 126 routing = {
bsw@1045 127 default = {
bsw@1045 128 mode = "redirect",
bsw@1045 129 module = "initiative",
bsw@1045 130 view = "show",
bsw@1045 131 id = initiative.id
bsw@1045 132 }
bsw@1045 133 }
bsw@1045 134 }
bsw@1045 135
bsw@1045 136 end )
bsw@1045 137 end
bsw@1045 138 end
bsw@1045 139 end
bsw@1209 140
bsw@1209 141 if config.render_external_reference and config.render_external_reference.initiative then
bsw@1209 142 config.render_external_reference.initiative(initiative, function (callback)
bsw@1209 143 ui.sectionRow(callback)
bsw@1209 144 end)
bsw@1209 145 end
bsw@1045 146
bsw@1045 147 ui.sectionRow( function ()
bsw@1045 148 ui.container {
bsw@1045 149 attr = { class = "draft" },
bsw@1045 150 content = function ()
bsw@1045 151 slot.put ( initiative.current_draft:get_content ( "html" ) )
bsw@1045 152 end
bsw@1045 153 }
bsw@1045 154 end )
bsw@1045 155
bsw@1045 156 end)
bsw@1045 157
bsw@1045 158 ui.link { attr = { name = "suggestions" }, text = "" }
bsw@1045 159
bsw@1045 160
bsw@1045 161 ui.container {
bsw@1045 162 attr = { class = "section suggestions" },
bsw@1045 163 content = function ()
bsw@1045 164
bsw@1045 165 if # ( initiative.suggestions ) > 0 then
bsw@1045 166
bsw@1045 167 ui.sectionHead( function ()
bsw@1045 168 ui.heading {
bsw@1045 169 level = 1,
bsw@1045 170 content = _("Suggestions for improvement (#{count})", { count = # ( initiative.suggestions ) } )
bsw@1045 171 }
bsw@1045 172 ui.container { content = _"written and rated by the supportes of this initiative to improve the proposal and its reasons" }
bsw@1045 173 end )
bsw@1045 174
bsw@1045 175 for i, suggestion in ipairs(initiative.suggestions) do
bsw@1045 176
bsw@1045 177 local opinion = Opinion:by_pk(app.session.member_id, suggestion.id)
bsw@1045 178
bsw@1045 179 local class = "sectionRow suggestion"
bsw@1045 180 if suggestion.id == param.get("suggestion_id", atom.number) then
bsw@1045 181 class = class .. " highlighted"
bsw@1045 182 end
bsw@1045 183 if member and not initiative.issue.fully_frozen and not initiative.issue.closed and initiative.member_info.supported then
bsw@1045 184 class = class .. " rateable"
bsw@1045 185 end
bsw@1045 186
bsw@1045 187
bsw@1045 188 ui.tag { tag = "div", attr = { class = class, id = "s" .. suggestion.id }, content = function ()
bsw@1045 189
bsw@1045 190 if opinion then
bsw@1045 191
bsw@1045 192 ui.container { attr = { class = "opinion"}, content = function()
bsw@1045 193 local class = ""
bsw@1045 194 local text = ""
bsw@1045 195
bsw@1045 196 if opinion.degree == 2 then
bsw@1045 197 class = "must"
bsw@1045 198 text = _"must"
bsw@1045 199 elseif opinion.degree == 1 then
bsw@1045 200 class = "should"
bsw@1045 201 text = _"should"
bsw@1045 202 elseif opinion.degree == 0 then
bsw@1045 203 class = "neutral"
bsw@1045 204 text = _"neutral"
bsw@1045 205 elseif opinion.degree == -1 then
bsw@1045 206 class = "shouldnot"
bsw@1045 207 text = _"should not"
bsw@1045 208 elseif opinion.degree == -2 then
bsw@1045 209 class = "mustnot"
bsw@1045 210 text = _"must not"
bsw@1045 211 end
bsw@1045 212
bsw@1045 213 ui.tag {
bsw@1045 214 attr = { class = class },
bsw@1045 215 content = text
bsw@1045 216 }
bsw@1045 217
bsw@1045 218 slot.put ( " " )
bsw@1045 219
bsw@1045 220 if
bsw@1045 221 (opinion.degree > 0 and not opinion.fulfilled)
bsw@1045 222 or (opinion.degree < 0 and opinion.fulfilled)
bsw@1045 223 then
bsw@1045 224 ui.tag{ content = _"but" }
bsw@1045 225 else
bsw@1045 226 ui.tag{ content = _"and" }
bsw@1045 227 end
bsw@1045 228
bsw@1045 229 slot.put ( " " )
bsw@1045 230
bsw@1045 231 local class = ""
bsw@1045 232 local text = ""
bsw@1045 233
bsw@1045 234 if opinion.fulfilled then
bsw@1045 235 class = "implemented"
bsw@1045 236 text = _"is implemented"
bsw@1045 237 else
bsw@1045 238 class = "notimplemented"
bsw@1045 239 text = _"is not implemented"
bsw@1045 240 end
bsw@1045 241
bsw@1045 242 ui.tag {
bsw@1045 243 attr = { class = class },
bsw@1045 244 content = text
bsw@1045 245 }
bsw@1045 246
bsw@1045 247 if
bsw@1045 248 (opinion.degree > 0 and not opinion.fulfilled)
bsw@1045 249 or (opinion.degree < 0 and opinion.fulfilled)
bsw@1045 250 then
bsw@1045 251 if math.abs(opinion.degree) > 1 then
bsw@1045 252 slot.put(" !!")
bsw@1045 253 else
bsw@1045 254 slot.put(" !")
bsw@1045 255 end
bsw@1045 256 else
bsw@1045 257 slot.put(" ✓")
bsw@1045 258 end
bsw@1045 259
bsw@1045 260 end }
bsw@1045 261
bsw@1045 262 end
bsw@1045 263
bsw@1045 264
bsw@1045 265 ui.link { attr = { name = "s" .. suggestion.id }, text = "" }
bsw@1045 266 ui.heading { level = 2,
bsw@1045 267 attr = { class = "suggestionHead" },
bsw@1045 268 content = format.string(suggestion.name, {
bsw@1045 269 truncate_at = 160, truncate_suffix = true
bsw@1045 270 }) }
bsw@1045 271
bsw@1045 272
bsw@1045 273 local plus2 = (suggestion.plus2_unfulfilled_count or 0)
bsw@1045 274 + (suggestion.plus2_fulfilled_count or 0)
bsw@1045 275 local plus1 = (suggestion.plus1_unfulfilled_count or 0)
bsw@1045 276 + (suggestion.plus1_fulfilled_count or 0)
bsw@1045 277 local minus1 = (suggestion.minus1_unfulfilled_count or 0)
bsw@1045 278 + (suggestion.minus1_fulfilled_count or 0)
bsw@1045 279 local minus2 = (suggestion.minus2_unfulfilled_count or 0)
bsw@1045 280 + (suggestion.minus2_fulfilled_count or 0)
bsw@1045 281
bsw@1045 282 local with_opinion = plus2 + plus1 + minus1 + minus2
bsw@1045 283
bsw@1045 284 local neutral = (suggestion.initiative.supporter_count or 0)
bsw@1045 285 - with_opinion
bsw@1045 286
bsw@1045 287 local neutral2 = with_opinion
bsw@1045 288 - (suggestion.plus2_fulfilled_count or 0)
bsw@1045 289 - (suggestion.plus1_fulfilled_count or 0)
bsw@1045 290 - (suggestion.minus1_fulfilled_count or 0)
bsw@1045 291 - (suggestion.minus2_fulfilled_count or 0)
bsw@1045 292
bsw@1045 293 ui.container {
bsw@1045 294 attr = { class = "suggestionInfo" },
bsw@1045 295 content = function ()
bsw@1045 296
bsw@1045 297 if with_opinion > 0 then
bsw@1045 298 ui.container { attr = { class = "suggestion-rating" }, content = function ()
bsw@1045 299 ui.tag { content = _"collective rating:" }
bsw@1045 300 slot.put("&nbsp;")
bsw@1045 301 ui.bargraph{
bsw@1045 302 max_value = suggestion.initiative.supporter_count,
bsw@1045 303 width = 100,
bsw@1045 304 bars = {
bsw@1045 305 { color = "#0a0", value = plus2 },
bsw@1045 306 { color = "#8a8", value = plus1 },
bsw@1045 307 { color = "#eee", value = neutral },
bsw@1045 308 { color = "#a88", value = minus1 },
bsw@1045 309 { color = "#a00", value = minus2 },
bsw@1045 310 }
bsw@1045 311 }
bsw@1045 312 slot.put(" | ")
bsw@1045 313 ui.tag { content = _"implemented:" }
bsw@1045 314 slot.put ( "&nbsp;" )
bsw@1045 315 ui.bargraph{
bsw@1045 316 max_value = with_opinion,
bsw@1045 317 width = 100,
bsw@1045 318 bars = {
bsw@1045 319 { color = "#0a0", value = suggestion.plus2_fulfilled_count },
bsw@1045 320 { color = "#8a8", value = suggestion.plus1_fulfilled_count },
bsw@1045 321 { color = "#eee", value = neutral2 },
bsw@1045 322 { color = "#a88", value = suggestion.minus1_fulfilled_count },
bsw@1045 323 { color = "#a00", value = suggestion.minus2_fulfilled_count },
bsw@1045 324 }
bsw@1045 325 }
bsw@1045 326 end }
bsw@1045 327 end
bsw@1045 328
bsw@1045 329 if app.session:has_access("authors_pseudonymous") then
bsw@1045 330 util.micro_avatar ( suggestion.author )
bsw@1045 331 else
bsw@1045 332 slot.put("<br />")
bsw@1045 333 end
bsw@1045 334
bsw@1045 335 ui.container {
bsw@1045 336 attr = { class = "suggestion-text" },
bsw@1045 337 content = function ()
bsw@1045 338 slot.put ( suggestion:get_content( "html" ) )
bsw@1061 339
bsw@1045 340
bsw@1045 341 if direct_supporter then
bsw@1045 342
bsw@1045 343 ui.container {
bsw@1045 344 attr = { class = "rating" },
bsw@1045 345 content = function ()
bsw@1045 346
bsw@1045 347 if not opinion then
bsw@1045 348 opinion = {}
bsw@1045 349 end
bsw@1045 350 ui.form {
bsw@1045 351 module = "opinion", action = "update", params = {
bsw@1045 352 suggestion_id = suggestion.id
bsw@1045 353 },
bsw@1045 354 routing = { default = {
bsw@1045 355 mode = "redirect",
bsw@1045 356 module = "initiative", view = "show", id = suggestion.initiative_id,
bsw@1045 357 params = { suggestion_id = suggestion.id },
bsw@1045 358 anchor = "s" .. suggestion.id -- TODO webmcp
bsw@1045 359 } },
bsw@1045 360 content = function ()
bsw@1045 361
bsw@1045 362
bsw@1045 363 ui.heading { level = 3, content = _"Should the initiator implement this suggestion?" }
bsw@1045 364 ui.container { content = function ()
bsw@1045 365
bsw@1045 366 local active = opinion.degree == 2
bsw@1045 367 ui.tag { tag = "input", attr = {
bsw@1045 368 type = "radio", name = "degree", value = 2,
bsw@1045 369 id = "s" .. suggestion.id .. "_degree2",
bsw@1045 370 checked = active and "checked" or nil
bsw@1045 371 } }
bsw@1045 372 ui.tag {
bsw@1045 373 tag = "label",
bsw@1045 374 attr = {
bsw@1045 375 ["for"] = "s" .. suggestion.id .. "_degree2",
bsw@1045 376 class = active and "active-plus2" or nil,
bsw@1045 377 },
bsw@1045 378 content = _"must"
bsw@1045 379 }
bsw@1045 380
bsw@1045 381 local active = opinion.degree == 1
bsw@1045 382 ui.tag { tag = "input", attr = {
bsw@1045 383 type = "radio", name = "degree", value = 1,
bsw@1045 384 id = "s" .. suggestion.id .. "_degree1",
bsw@1045 385 checked = active and "checked" or nil
bsw@1045 386 } }
bsw@1045 387 ui.tag {
bsw@1045 388 tag = "label",
bsw@1045 389 attr = {
bsw@1045 390 ["for"] = "s" .. suggestion.id .. "_degree1",
bsw@1045 391 class = active and "active-plus1" or nil,
bsw@1045 392 },
bsw@1045 393 content = _"should"
bsw@1045 394 }
bsw@1045 395
bsw@1045 396 local active = not opinion.member_id
bsw@1045 397 ui.tag { tag = "input", attr = {
bsw@1045 398 type = "radio", name = "degree", value = 0,
bsw@1045 399 id = "s" .. suggestion.id .. "_degree0",
bsw@1045 400 checked = active and "checked" or nil
bsw@1045 401 } }
bsw@1045 402 ui.tag {
bsw@1045 403 tag = "label",
bsw@1045 404 attr = {
bsw@1045 405 ["for"] = "s" .. suggestion.id .. "_degree0",
bsw@1045 406 class = active and "active-neutral" or nil,
bsw@1045 407 },
bsw@1045 408 content = _"neutral"
bsw@1045 409 }
bsw@1045 410
bsw@1045 411 local active = opinion.degree == -1
bsw@1045 412 ui.tag { tag = "input", attr = {
bsw@1045 413 type = "radio", name = "degree", value = -1,
bsw@1045 414 id = "s" .. suggestion.id .. "_degree-1",
bsw@1045 415 checked = active and "checked" or nil
bsw@1045 416 } }
bsw@1045 417 ui.tag {
bsw@1045 418 tag = "label",
bsw@1045 419 attr = {
bsw@1045 420 ["for"] = "s" .. suggestion.id .. "_degree-1",
bsw@1045 421 class = active and "active-minus1" or nil,
bsw@1045 422 },
bsw@1045 423 content = _"should not"
bsw@1045 424 }
bsw@1045 425
bsw@1045 426 local active = opinion.degree == -2
bsw@1045 427 ui.tag { tag = "input", attr = {
bsw@1045 428 type = "radio", name = "degree", value = -2,
bsw@1045 429 id = "s" .. suggestion.id .. "_degree-2",
bsw@1045 430 checked = active and "checked" or nil
bsw@1045 431 } }
bsw@1045 432 ui.tag {
bsw@1045 433 tag = "label",
bsw@1045 434 attr = {
bsw@1045 435 ["for"] = "s" .. suggestion.id .. "_degree-2",
bsw@1045 436 class = active and "active-minus2" or nil,
bsw@1045 437 },
bsw@1045 438 content = _"must not"
bsw@1045 439 }
bsw@1045 440 end }
bsw@1045 441
bsw@1045 442 slot.put("<br />")
bsw@1045 443
bsw@1045 444 ui.heading { level = 3, content = _"Did the initiator implement this suggestion?" }
bsw@1045 445 ui.container { content = function ()
bsw@1045 446 local active = opinion.fulfilled == false
bsw@1045 447 ui.tag { tag = "input", attr = {
bsw@1045 448 type = "radio", name = "fulfilled", value = "false",
bsw@1045 449 id = "s" .. suggestion.id .. "_notfulfilled",
bsw@1045 450 checked = active and "checked" or nil
bsw@1045 451 } }
bsw@1045 452 ui.tag {
bsw@1045 453 tag = "label",
bsw@1045 454 attr = {
bsw@1045 455 ["for"] = "s" .. suggestion.id .. "_notfulfilled",
bsw@1045 456 class = active and "active-notfulfilled" or nil,
bsw@1045 457 },
bsw@1045 458 content = _"No (not yet)"
bsw@1045 459 }
bsw@1045 460
bsw@1045 461 local active = opinion.fulfilled
bsw@1045 462 ui.tag { tag = "input", attr = {
bsw@1045 463 type = "radio", name = "fulfilled", value = "true",
bsw@1045 464 id = "s" .. suggestion.id .. "_fulfilled",
bsw@1045 465 checked = active and "checked" or nil
bsw@1045 466 } }
bsw@1045 467 ui.tag {
bsw@1045 468 tag = "label",
bsw@1045 469 attr = {
bsw@1045 470 ["for"] = "s" .. suggestion.id .. "_fulfilled",
bsw@1045 471 class = active and "active-fulfilled" or nil,
bsw@1045 472 },
bsw@1045 473 content = _"Yes, it's implemented"
bsw@1045 474 }
bsw@1045 475 end }
bsw@1045 476 slot.put("<br />")
bsw@1045 477
bsw@1045 478 ui.tag{
bsw@1045 479 tag = "input",
bsw@1045 480 attr = {
bsw@1045 481 type = "submit",
bsw@1045 482 class = "btn btn-default",
bsw@1045 483 value = _"publish my rating"
bsw@1045 484 },
bsw@1045 485 content = ""
bsw@1045 486 }
bsw@1045 487
bsw@1045 488 end
bsw@1045 489 }
bsw@1045 490
bsw@1045 491 end -- if not issue,fully_frozen or closed
bsw@1045 492 }
bsw@1045 493 end
bsw@1045 494
bsw@1045 495 local text = _"Read more"
bsw@1045 496
bsw@1045 497 if direct_supporter then
bsw@1045 498 text = _"Show more and rate this"
bsw@1045 499 end
bsw@1045 500
bsw@1061 501 ui.link{
bsw@1061 502 attr = { class = "suggestion-details" },
bsw@1061 503 content = _"Details",
bsw@1061 504 module = "suggestion", view = "show", id = suggestion.id
bsw@1061 505 }
bsw@1061 506
bsw@1045 507 ui.link {
bsw@1045 508 attr = {
bsw@1045 509 class = "suggestion-more",
bsw@1045 510 onclick = "$('#s" .. suggestion.id .. "').removeClass('folded').addClass('unfolded'); return false;"
bsw@1045 511 },
bsw@1045 512 text = text
bsw@1045 513 }
bsw@1045 514
bsw@1045 515 ui.link {
bsw@1045 516 attr = {
bsw@1045 517 class = "suggestion-less",
bsw@1045 518 onclick = "$('#s" .. suggestion.id .. "').addClass('folded').removeClass('unfolded'); return false;"
bsw@1045 519 },
bsw@1045 520 text = _"Show less"
bsw@1045 521 }
bsw@1045 522 end
bsw@1045 523 }
bsw@1045 524
bsw@1045 525 ui.script{ script = [[
bsw@1045 526 var textEl = $('#s]] .. suggestion.id .. [[ .suggestion-text');
bsw@1045 527 var height = textEl.height();
bsw@1045 528 if (height > 150) $('#s]] .. suggestion.id .. [[').addClass('folded');
bsw@1045 529 ]] }
bsw@1045 530
bsw@1045 531 end
bsw@1045 532 } -- ui.paragraph
bsw@1045 533
bsw@1045 534
bsw@1045 535
bsw@1045 536 end } -- ui.tag "li"
bsw@1045 537
bsw@1045 538 end -- for i, suggestion
bsw@1045 539
bsw@1045 540 else -- if #initiative.suggestions > 0
bsw@1045 541
bsw@1045 542 local text
bsw@1045 543 if initiative.issue.closed then
bsw@1125 544 text = _"No suggestions"
bsw@1045 545 else
bsw@1125 546 text = _"No suggestions yet"
bsw@1045 547 end
bsw@1045 548 ui.sectionHead( function()
bsw@1045 549 ui.heading { level = 1, content = text }
bsw@1045 550 end)
bsw@1045 551
bsw@1045 552 end -- if #initiative.suggestions > 0
bsw@1045 553
bsw@1045 554 end
bsw@1045 555 }

Impressum / About Us