Puntaroivat asukaspaneelit
Asukaspaneelit on uusi kansalaisosallistumisen muoto, jossa satunnaisotannalla valittu joukko tavallisia kansalaisia kokoontuu perehtymään ja keskustelemaan päätöksenteon tai valmistelun asialistalla olevasta kysymyksestä.
Pirkanmaan hyvinvointialueella vahvistetaan asukkaiden osallistumismahdollisuuksia: puntaroivassa asukaspaneeleissa asukkaat saavat äänensä kuuluviin hyvinvointialueen päätöksenteossa. Puntaroiva asukaspaneeli toteutetaan Pirkanmaan hyvinvointialueella yhteistyössä Suomen itsenäisyyden juhlarahasto Sitran kanssa. Hankkeen aikana toteutetaan asukaspaneeli, jossa käsitellään hoidon jatkuvuusmallin rajauksen perusteluiden hyväksyttävyyttä..
Pirkanmaan hyvinvointialueen asukaspaneeliin kutsutaan 40 eri ikäistä ja eri elämäntilanteessa olevaa hyvinvointialueen asukasta.
The following has evaluated to null or missing:
==> DLAppLocalServiceHelper [in template "43104#43145#3332606" at line 215, column 52]
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: file = DLAppLocalServiceHelper.getFil... [in template "43104#43145#3332606" at line 215, column 45]
----
1<#assign
2 headingSize = 2
3 accordionHeading = 3
4 itemCSS = ""
5 attachments = []
6 isVisibleCSS = ""
7 showPagination = false
8 showAttachments = false
9 visiblePanels = 8
10 selectedBackgroundColor = ''
11 articleId = .vars['reserved-article-id'].data
12/>
13<#if mainTitleSize?? && mainTitleSize.getData()?has_content>
14 <#assign
15 headingSize = mainTitleSize.getData()
16 accordionHeading = headingSize?number + 1
17 />
18</#if>
19
20<#-- SHOW ATTACMENTS PANEL -->
21<#if settings_attachments?? && settings_attachments.getData() == "true">
22 <#assign showAttachments = true />
23</#if>
24
25<#-- USE PAGINATION -->
26<#if settings_pagination?? && settings_pagination.getData() == "true">
27 <#assign showPagination = true />
28</#if>
29
30<#if backgroundColor?? && backgroundColor.getData()?has_content >
31 <#assign selectedBackgroundColor = "background-color--${backgroundColor.getData()}" />
32</#if>
33
34<#-- TRANSLATIONS -->
35<#assign i18n = {
36 "fi": {
37 "kb":"kt",
38 "mb": "mt",
39 "attachments": "Liitteet",
40 "show_more": "Näytä lisää sisältöjä",
41 "open_all": "Avaa kaikki sisällöt"
42 },
43 "en": {
44 "kb":"kb",
45 "mb":"mb",
46 "attachments": "Attachments",
47 "show_more" : "Show more content",
48 "open_all": "Open all accordions"
49 }
50} />
51
52<#function Translate word>
53 <#return i18n[locale.language][word] />
54</#function>
55
56<#function si num>
57 <#assign order = num?round?c?length />
58 <#assign thousands = ((order - 1) / 3)?floor />
59 <#if (thousands < 0)><#assign thousands = 0 /></#if>
60 <#assign siMap = [ {"factor": 1, "unit": ""}, {"factor": 1000, "unit": "${Translate('kb')}"}, {"factor": 1000000, "unit": "${Translate('mb')}"}, {"factor": 1000000000, "unit":"G"}, {"factor": 1000000000000, "unit": "T"} ]/>
61 <#assign siStr = (num / (siMap[thousands].factor))?string("0.#") + siMap[thousands].unit />
62 <#return siStr />
63</#function>
64
65<#function replaceHtmlTag content tagFrom tagTo cssClass>
66 <#if content?has_content && tagFrom?has_content && tagTo?has_content && cssClass?has_content>
67 <#assign divContent = content?matches('<${tagFrom} class=".*?${cssClass}.*?".*?>(.*?)</${tagFrom}>') />
68
69 <#if divContent?has_content>
70 <#assign newBodyContent = content?replace('<${tagFrom} class=".*?${cssClass}.*?".*?>(.*?)</${tagFrom}>', '<${tagTo} class="${cssClass}">$1</${tagTo}>', 'r') />
71 <#return newBodyContent />
72 <#else>
73 <#return content />
74 </#if>
75 </#if>
76</#function>
77
78<#-- create id from string -->
79<#function stringToId string>
80 <#assign id = "" />
81 <#if string?has_content>
82 <#assign id = string?lower_case
83 ?replace("ä", "a")
84 ?replace("ö", "o")
85 ?replace("å", "a")
86 ?replace("Ä", "a")
87 ?replace("Ö", "o")
88 ?replace("Å", "a")
89 ?replace(" ", "-")
90 ?replace("[^a-z0-9-]", "", "r") />
91 </#if>
92 <#return id>
93</#function>
94
95
96<div class="pirha-accordions ${selectedBackgroundColor}">
97 <#if mainTitle?? && mainTitle.getData()?has_content>
98 <h${headingSize} class="pirha-accordions__title" id="${randomNamespace}accordionHeading">${mainTitle.getData()}</h${headingSize}>
99 </#if>
100
101 <#if mainIngress?? && mainIngress.getData()?has_content>
102 <div class="pirha-accordions__lead">
103 ${mainIngress.getData()}
104 </div>
105 </#if>
106
107 <#if accordions?? && accordions.getSiblings()?has_content>
108 <#-- Show pagination if there is enough panels -->
109 <#if accordions.getSiblings()?size lte visiblePanels>
110 <#assign showPagination = false />
111 </#if>
112
113 <div class="pirha-buttons__container pirha-buttons__align--right">
114 <button class="pirha-accordions__toggle--all rs_skip">
115 <#if mainTitle.getData()?has_content><span class="sr-only">${mainTitle.getData()}</span></#if> ${Translate("open_all")}
116 </button>
117 </div>
118
119 <div class="pirha-accordions__wrapper" id="${randomNamespace}accordionContent">
120 <#list accordions.getSiblings() as accordion>
121 <#assign itemCSS = "pirha-accordion__item" />
122 <#assign id = "pirha_${randomNamespace}${accordion?index}" />
123
124 <#if accordion.highlighted?? && accordion.highlighted.getData()?has_content>
125 <#if accordion.highlighted.getData() == 'true'>
126 <#assign itemCSS += " pirha-accordion__item--highlighted"/>
127 </#if>
128 </#if>
129
130 <#if showPagination>
131 <#if accordion?index gt visiblePanels - 1>
132 <#assign itemCSS += " d-none"/>
133 </#if>
134 </#if>
135
136 <div class="${itemCSS}">
137 <h${accordionHeading} class="pirha-accordion__header">
138 <button
139 aria-expanded="false"
140 aria-controls="${id}"
141 id="pirha_${randomNamespace}${accordion?index}-header"
142 class="pirha-accordion__toggler"
143 >
144 <#if accordion.titleIcon?? && accordion.titleIcon.getData()?has_content >
145 <span class="pirha-icon title-icon accordion.titleImage" aria-hidden="true">
146 <img src="${accordion.titleIcon.getData()}" alt="" />
147 </span>
148 </#if>
149 <span id="${stringToId(accordion.title.getData())}-${articleId}">${accordion.title.getData()}</span>
150 <span role="presentation" class="pirha-icon--chevron-down"></span>
151 </button>
152 </h${accordionHeading}>
153
154 <div
155 class="pirha-accordion__body d-none"
156 id="${id}"
157 aria-labelledby="pirha_${randomNamespace}${accordion?index}-header"
158 >
159 <#if accordion.accordionBody?? && accordion.accordionBody.getSiblings()?has_content>
160 <#list accordion.accordionBody.getSiblings() as body>
161 <#if body.content?? && body.content.getData()?has_content>
162 <div class="pirha-accordion__content">
163 <#assign bodyContent = body.content.getData() />
164 <#--
165 <#assign bodyContent = replaceHtmlTag('${bodyContent}', 'div', 'p', 'portlet-msg-alert') />
166 <#assign bodyContent = replaceHtmlTag('${bodyContent}', 'div', 'p', 'portlet-msg-info') />
167 -->
168
169 ${bodyContent}
170 </div>
171 </#if>
172
173 <#if body.links?? && body.links.getSiblings()?has_content>
174 <div class="pirha-accordion__links">
175 <#list body.links.getSiblings() as link>
176 <#assign
177 link_type = "pirha-button-link"
178 link_icon = ""
179 link_url = ""
180 link_description = ""
181 link_title = ""
182 />
183 <#if link.linkPage?? && link.linkPage.getFriendlyUrl()?has_content>
184 <#assign
185
186 link_icon = "arrow-right"
187 link_url = link.linkPage.getFriendlyUrl()
188 link_title = link.linkTitle.getData()
189 />
190 </#if>
191 <#if link.linkUrl?? && link.linkUrl.getData()?has_content>
192 <#assign
193 link_icon = "link-external"
194 link_url = link.linkUrl.getData()
195 link_title = link.linkTitle.getData()
196 />
197 </#if>
198 <#if link.linkFile?? && link.linkFile.getData()?has_content>
199 <#assign
200 link_type = "pirha-button-text"
201 link_icon = "attachment"
202 link_url = link.linkFile.getData()
203 link_title = link.linkTitle.getData()
204 />
205
206 <#if link.linkDescription?? && link.linkDescription.getData()?has_content>
207 <#assign link_description = link.linkDescription.getData() />
208 </#if>
209
210 <#-- GET FILE DATA -->
211 <#assign
212 link_url_parts = link.linkFile.getData()?split("/")
213 file_uuid = link_url_parts[5]?keep_before("?")
214 file_group_id = link_url_parts[2]?number
215 file = DLAppLocalServiceHelper.getFileEntryByUuidAndGroupId(file_uuid?string,file_group_id?long)
216 />
217
218 <#-- SET TITLE -->
219 <#if link_title == "">
220 <#assign link_title = file.getTitle()?keep_before_last(".") />
221 </#if>
222
223 <#-- ADD FILE TO ATTACHEMNTS ARRAY -->
224 <#assign attachments = attachments + [ {
225 "fileName": link_title,
226 "fileURL": link_url,
227 "fileExt": file.getExtension(),
228 "fileSize": file.getSize(),
229 "fileDescription": link_description
230 }
231 ] />
232 </#if>
233
234 <#if (link_title?has_content) && link_url != "">
235 <#if link_type == "pirha-button-link">
236 <a href="${link_url}" <#if link_icon == "link-external">target="_blank"</#if> class="${link_type}">
237 <span role="presentation" class="pirha-icon--${link_icon}"></span>
238 ${link.linkTitle.getData()}
239
240 </a>
241 <#else>
242 <div class="pirha-accordion__attachment">
243 <span role="presentation" class="pirha-icon--${link_icon}"></span>
244 <div>
245 <a href="${link_url}" class="">
246 ${link_title} (<span>${file.getExtension()}, ${si(file.getSize())}</span>)
247 </a>
248 <#if link_description?has_content>
249 <p class="pirha-link__description">
250 ${link.linkDescription.getData()}
251 </p>
252 </#if>
253 </div>
254 </div>
255 </#if>
256 </#if>
257 </#list>
258 </div>
259 </#if>
260 </#list>
261 </#if>
262 </div>
263
264 </div>
265 </#list>
266 </div>
267
268 <#-- LIST ALL ATTACHEMNTS -->
269 <#if showAttachments>
270 <div class="${itemCSS}">
271 <#if attachments?has_content>
272 <h${accordionHeading} class="pirha-accordion__header">
273 <button
274 aria-expanded="false"
275 aria-controls="${id}"
276 id="pirha_${randomNamespace}attacments-header"
277 class="pirha-accordion__toggler"
278 >
279 <span>${Translate("attachments")}</span>
280 <span role="presentation" class="pirha-icon--chevron-down"></span>
281 </button>
282 </h${accordionHeading}>
283
284 <div
285 class="pirha-accordion__body d-none"
286 id="${id}"
287 aria-labelledby="pirha_${randomNamespace}attacments-header"
288 >
289 <div class="pirha-accordion__links">
290 <#list attachments as file>
291 <div class="pirha-accordion__attachment">
292 <span role="presentation" class="pirha-icon--attachment"></span>
293 <div>
294 <a href="${file.fileURL}">${file.fileName} (<span>${file.fileExt}, ${si(file.fileSize)}</span>)</a>
295 <#if file.fileDescription?has_content>
296 <p>${file.fileDescription}</p>
297 </#if>
298 </div>
299 </div>
300 </#list>
301 </div>
302 </div>
303 </#if>
304 </div>
305 </#if>
306
307 <#if showPagination>
308 <#assign pagination_total = accordions.getSiblings()?size />
309 <#if showAttachments>
310 <#assign pagination_total = accordions.getSiblings()?size + 1 />
311 </#if>
312 <button
313 data-panels="${pagination_total}"
314 data-panels-show="${visiblePanels}"
315 class="pirha-accordions__button--paginator"
316 >
317 <#if mainTitle.getData()?has_content><span class="sr-only">${mainTitle.getData()}</span></#if>
318 <span class="pirha-button__content">${Translate("show_more")}</span>
319 <span role="presentation" class="pirha-icon pirha-icon--chevron-down"></span>
320 </button>
321 </#if>
322 </#if>
323</div>
324
325<script>
326if (!window._rsbtnAccordions) {
327 window._rsbtnAccordions = true;
328
329 document.addEventListener('DOMContentLoaded', () => {
330 const rsbtn_button = document.querySelector('.rsbtn_play');
331 if (rsbtn_button) {
332 rsbtn_button.addEventListener('click', openAllAccordionsForRS);
333
334 function openAllAccordionsForRS() {
335 if(!rsbtn_button.classList.contains('pirha-listen')){
336 rsbtn_button.classList.add('pirha-listen');
337 const openAllButtons = document.querySelectorAll('.pirha-accordions__toggle--all');
338 if (openAllButtons) {
339 openAllButtons.forEach(button => {
340 const parent = button.closest('.pirha-accordions');
341 if(parent && !parent.classList.contains('pirha-accordions__open--all')){
342 button.click();
343 }
344 });
345 }
346 }
347 }
348 }
349 });
350}
351</script>
Miten puntaroiva kansalaiskeskustelu toimii?
Aihe, tavoite ja rooli
Keskustelulle valitaan aihe ja määritetään tavoite ja rooli päätöksenteossa.
Satunnaisotanta
Kansalaisista valitaan satunnaisotannalla edustava joukko. Usein käytetään kiintiöintiä.
Asiantuntijoiden kuuleminen
Kansalaiset kuulevat riippumattomia asiantuntijoita ja eri kantojen edustajia sekä esittävät kysymyksiä.
Puntaroiva keskustelu
Kansalaiset keskustelevat ja puntaroivat asiakysymykseen liittyviä tosiseikkoja ja väitteitä.
Lausuma
Keskustelut tuottavat yhteisen lausuman, joka voi sisältää esimerkiksi tosiasioita, perusteltuja ehdotuksia tai kannanottoja.
Lausumasta tiedottaminen
Lausuma saatetaan tiedoksi päättäjille ja julkistetaan suurelle yleisölle.
Lähde: Moniäänistä ja perusteltua päätöksentekoa - puntaroivat kansalaiskeskustelut poliittisten kiistakysymysten ratkaisussa (PALO RESEARCH)
Liity mukaan Asukaspooliin!
Asukaspooli kutsuu sinut jakamaan ajatuksiasi ja kokemuksiasi hyvinvointialueen palvelujen kehittämiseksi. Yhdessä voimme tehdä Pirkanmaasta entistä paremman paikan elää ja viihtyä.
Päivitetty 10.2.2026