"Asetuksissa en voinut asettaa OP-mobiilin ilmoituksia,
koska näkövammaisten käyttämä VoiceOver-ruudunlukija
ei uusimman OP-mobiilin versiota käytettäessä osaa tulkita
ilmoitusten valintapainikkeita, eikä niiden tekstejä.”
-Anonyymi asiakaspalaute, kesäkuu 2021
The following has evaluated to null or missing:
==> fileEntry.getDDMFormValuesMap [in template "10157#10197#29752" at line 63, column 28]
----
Tip: It's the step after the last dot that caused this error, not those before it.
----
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: #assign formValuesMap = fileEntry.get... [in template "10157#10197#29752" in function "getDDMFormStringValue" at line 63, column 3]
----
1<#-- inserted during deployment/ --><#noparse>
2<script data-r="webcontent-template-js/op-fi-ofinayt-090" src="/documents/10197/933601379/requirejs-loader.js/7f190522-a0f0-9857-7338-7d1ab48da3a3?version=6.0&c=7891c1aeb18ede6d70be546d1fe401e1db778b93cbee34be096ee2e4af4de5be"></script>
3</#noparse><#-- /inserted during deployment -->
4
5<#-- Structure: OFISMAL006 - Nosto -->
6<#-- Template: OFINAYT090 - Kuva ja video -->
7
8<#assign dlService = serviceLocator.findService("com.liferay.document.library.kernel.service.DLFileEntryLocalService")>
9
10<#function getFileEntry liferayDocumentUrl>
11 <#if !liferayDocumentUrl?has_content>
12 <#return {}>
13 </#if>
14 <#assign fileParts = liferayDocumentUrl?split("/")>
15
16 <#if fileParts?size < 4>
17 <#return {}>
18 </#if>
19
20 <#assign groupIdIndex = fileParts?size - 4>
21 <#attempt>
22 <#assign groupId = fileParts[groupIdIndex]?number>
23 <#if groupId == 0>
24 <#return {}>
25 </#if>
26 <#recover>
27 <#return {}>
28 </#attempt>
29
30 <#assign uuid = fileParts?last?split("?")?first?trim>
31 <#if !uuid?has_content>
32 <#return {}>
33 </#if>
34 <#assign fileEntry = dlService.getFileEntryByUuidAndGroupId(uuid, groupId)>
35 <#return fileEntry>
36</#function>
37
38<#function getStructureValue dataType value>
39 <#if dataType == "boolean">
40 <#assign result = getterUtil.getBoolean(value)>
41 <#elseif dataType == "date">
42 <#attempt>
43 <#assign result = dateUtil.parseDate("yyyy-MM-dd", value, locale)>
44 <#recover>
45 <#return {}>
46 </#attempt>
47 <#elseif dataType == "double">
48 <#assign result = getterUtil.getDouble(value)>
49 <#elseif dataType == "integer">
50 <#assign result = getterUtil.getInteger(value)>
51 <#elseif dataType == "number">
52 <#assign result = getterUtil.getNumber(value)>
53 <#else>
54 <#-- document-library, html, link-to-page, string -->
55 <#assign result = value>
56 </#if>
57 <#return { "v": result }>
58</#function>
59
60<#function getDDMFormStringValue url fieldName>
61 <#assign fileEntry = getFileEntry(url)>
62 <#assign formValuesMap = fileEntry.getDDMFormValuesMap(fileEntry.getFileVersion().fileVersionId)>
63 <#return formValuesMap?values?map(row ->
64 row.getDDMFormFieldValuesMap()?values?map(fieldValues ->
65 fieldValues?filter(field ->
66 field.getName() == fieldName
67 )?map(field ->
68 field.getValue().getString(locale)!""
69 )?filter(value -> value != "")?first!""
70 )?filter(value -> value != "")?first!""
71 )?filter(value -> value != "")?first!"">
72</#function>
73
74<#function getImageOrVideoProps kuva>
75 <#assign altText = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "kuva_alt_text"),{})>
76 <#assign videoUrl = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "video_url"),{})>
77 <#assign isYoutubeLink = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "is_youtube_link"),{})>
78 <#assign copyright = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "kuvan_copyright"),{})>
79 <#assign url = ((kuva.getData())??)?then(kuva.getData(),{})>
80 <#assign caption = ((kuva.kuvan_kuvaus.getData())??)?then(getStructureValue("string", kuva.kuvan_kuvaus.getData()),{})>
81 <#return {
82 "videoUrl": getStructureValue("string", videoUrl),
83 "isYoutubeLink": getStructureValue("string", isYoutubeLink),
84 "url": getStructureValue("document-library", url),
85 "alt": getStructureValue("string", altText),
86 "copyright": getStructureValue("string", copyright),
87 "caption": caption
88 }>
89</#function>
90
91<#assign props = {
92 "title": ((nosto_otsikko.getData())??)?then(getStructureValue("string", nosto_otsikko.getData()), {}),
93 "media": getImageOrVideoProps(nosto_kuva),
94 "html": ((nosto_html_teksti.getData())??)?then(getStructureValue("string", nosto_html_teksti.getData()), {}),
95 "contentId": .vars['reserved-article-id'].data!"",
96 "contentName": .vars['reserved-article-title'].data!""
97}>
98
99
100<op-fi-ofinayt-090-39ecd7537f6e5df5e47f3ba65ca3b84a72d2d961448eb9274a520d259fc1c912 style="display: block; height: 38.0rem" props="${jsonFactoryUtil.looseSerializeDeep(props)?html}"></op-fi-ofinayt-090-39ecd7537f6e5df5e47f3ba65ca3b84a72d2d961448eb9274a520d259fc1c912>
The following has evaluated to null or missing:
==> fileEntry.getDDMFormValuesMap [in template "10157#10197#29752" at line 63, column 28]
----
Tip: It's the step after the last dot that caused this error, not those before it.
----
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: #assign formValuesMap = fileEntry.get... [in template "10157#10197#29752" in function "getDDMFormStringValue" at line 63, column 3]
----
1<#-- inserted during deployment/ --><#noparse>
2<script data-r="webcontent-template-js/op-fi-ofinayt-090" src="/documents/10197/933601379/requirejs-loader.js/7f190522-a0f0-9857-7338-7d1ab48da3a3?version=6.0&c=7891c1aeb18ede6d70be546d1fe401e1db778b93cbee34be096ee2e4af4de5be"></script>
3</#noparse><#-- /inserted during deployment -->
4
5<#-- Structure: OFISMAL006 - Nosto -->
6<#-- Template: OFINAYT090 - Kuva ja video -->
7
8<#assign dlService = serviceLocator.findService("com.liferay.document.library.kernel.service.DLFileEntryLocalService")>
9
10<#function getFileEntry liferayDocumentUrl>
11 <#if !liferayDocumentUrl?has_content>
12 <#return {}>
13 </#if>
14 <#assign fileParts = liferayDocumentUrl?split("/")>
15
16 <#if fileParts?size < 4>
17 <#return {}>
18 </#if>
19
20 <#assign groupIdIndex = fileParts?size - 4>
21 <#attempt>
22 <#assign groupId = fileParts[groupIdIndex]?number>
23 <#if groupId == 0>
24 <#return {}>
25 </#if>
26 <#recover>
27 <#return {}>
28 </#attempt>
29
30 <#assign uuid = fileParts?last?split("?")?first?trim>
31 <#if !uuid?has_content>
32 <#return {}>
33 </#if>
34 <#assign fileEntry = dlService.getFileEntryByUuidAndGroupId(uuid, groupId)>
35 <#return fileEntry>
36</#function>
37
38<#function getStructureValue dataType value>
39 <#if dataType == "boolean">
40 <#assign result = getterUtil.getBoolean(value)>
41 <#elseif dataType == "date">
42 <#attempt>
43 <#assign result = dateUtil.parseDate("yyyy-MM-dd", value, locale)>
44 <#recover>
45 <#return {}>
46 </#attempt>
47 <#elseif dataType == "double">
48 <#assign result = getterUtil.getDouble(value)>
49 <#elseif dataType == "integer">
50 <#assign result = getterUtil.getInteger(value)>
51 <#elseif dataType == "number">
52 <#assign result = getterUtil.getNumber(value)>
53 <#else>
54 <#-- document-library, html, link-to-page, string -->
55 <#assign result = value>
56 </#if>
57 <#return { "v": result }>
58</#function>
59
60<#function getDDMFormStringValue url fieldName>
61 <#assign fileEntry = getFileEntry(url)>
62 <#assign formValuesMap = fileEntry.getDDMFormValuesMap(fileEntry.getFileVersion().fileVersionId)>
63 <#return formValuesMap?values?map(row ->
64 row.getDDMFormFieldValuesMap()?values?map(fieldValues ->
65 fieldValues?filter(field ->
66 field.getName() == fieldName
67 )?map(field ->
68 field.getValue().getString(locale)!""
69 )?filter(value -> value != "")?first!""
70 )?filter(value -> value != "")?first!""
71 )?filter(value -> value != "")?first!"">
72</#function>
73
74<#function getImageOrVideoProps kuva>
75 <#assign altText = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "kuva_alt_text"),{})>
76 <#assign videoUrl = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "video_url"),{})>
77 <#assign isYoutubeLink = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "is_youtube_link"),{})>
78 <#assign copyright = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "kuvan_copyright"),{})>
79 <#assign url = ((kuva.getData())??)?then(kuva.getData(),{})>
80 <#assign caption = ((kuva.kuvan_kuvaus.getData())??)?then(getStructureValue("string", kuva.kuvan_kuvaus.getData()),{})>
81 <#return {
82 "videoUrl": getStructureValue("string", videoUrl),
83 "isYoutubeLink": getStructureValue("string", isYoutubeLink),
84 "url": getStructureValue("document-library", url),
85 "alt": getStructureValue("string", altText),
86 "copyright": getStructureValue("string", copyright),
87 "caption": caption
88 }>
89</#function>
90
91<#assign props = {
92 "title": ((nosto_otsikko.getData())??)?then(getStructureValue("string", nosto_otsikko.getData()), {}),
93 "media": getImageOrVideoProps(nosto_kuva),
94 "html": ((nosto_html_teksti.getData())??)?then(getStructureValue("string", nosto_html_teksti.getData()), {}),
95 "contentId": .vars['reserved-article-id'].data!"",
96 "contentName": .vars['reserved-article-title'].data!""
97}>
98
99
100<op-fi-ofinayt-090-39ecd7537f6e5df5e47f3ba65ca3b84a72d2d961448eb9274a520d259fc1c912 style="display: block; height: 38.0rem" props="${jsonFactoryUtil.looseSerializeDeep(props)?html}"></op-fi-ofinayt-090-39ecd7537f6e5df5e47f3ba65ca3b84a72d2d961448eb9274a520d259fc1c912>
”OP ja OP-mobiilin tiimi on panostanut jo vuosia systemaattisesti saavutettavuusosaamisen kasvattamiseen, ja henkilöstön vahvat mobiilisaavutettavuuden taidot ovat tulleet hyvin esille myös koulutuksissa. Asiantuntijoillamme on ollut ilo tukea motivoitunutta tiimiä osaamisen syventämisessä.”
- Annika Lehdonjoki, Team lead, Avaava
”OP-mobiilissa näkyy yrityksen sisäinen priorisointi saavutettavuuteen. Saavutettavuusasiantuntijoina erityisen palkitsevaa on kehittäjien saavutettavuusosaamista osoittavat tekniset kysymykset ja tehdyt korjaukset, jotka todistavat saavutettavuuden asiantuntijatyön arvostuksen. Lisäksi ikään kuin huipennuksena virheistä ja rikkeistä halutaan eroon enemmän kuin teknisellä tasolla.”
- Saavutettavuusasiantuntijatiimi, Eficode Oy
”OP-mobiilissa näkyy tahto panostaa helppokäyttöisyyteen erilaisia käyttäjiä huomioiden. Viimeisen vuoden aikana on kehitytty tilanteeseen, jossa OP on tilannut puhtaasti kokemusasiantuntijan, eli minun ruudunlukijakäyttäjänä, arviointia. Palveluissa ei haluta kiinnittää huomiota vain lakikriteerien täyttämiseksi, vaan aitoon käytettävyyden parantamiseen. Se on todella palkitsevaa itselle niin työssä asiantuntijana kuin arjessa sokeana kuluttajana.”
- Markus Tihumäki, kokemus- ja saavutettavuusasiantuntija, Eficode Oy
"Saavutettavuuden kannalta on ollut ilo huomata suuri kehitys OP-mobiilin käytettävyydessä. Näin ruudunlukijan käyttäjänä saavutettavuus mahdollistaa toimimisen verkkopankissa ja sovelluksessa, mutta käyttämisen ratkaisee sujuvuus. Olin kiireisessä arjessa lykännyt rahastosäästämisen sopimusten tekemistä, koska takaraivossa kummitteli entisaikojen hankalat käytettävyydet. Kuitenkin sain aikaiseksi aloittaa tekemisen, jonka lomassa naurahtelin itsekseni sen helppoudelle. Olin varautunut ärsyyntymiseen ja tuskailuun, mutta 15 minuuttia myöhemmin olin jo muissa askareissa."
-Miika
”Käytän OP-mobiili -sovellusta lähes päivittäin niin pankki, vahvan tunnistautumisen vaativien asioiden hoitamisessa. OP-mobiili -sovellus on minulle erilaisten henkilökohtaisten asioitteni itsenäisesti verraton sekä erittäin saavutettava työkalu toimiessani täysin sokeana asioitteni hoitamiseen.”
-Erkki
”Olen käyttänyt OP-mobiilia VoiceOver-ruudunlukuohjelmalla. Tilien hoito ja laskujen maksaminen on OP-mobiililla erittäin helppoa. Enpä juuri muilla tavoin pankkiasioita enää hoidakaan. Siellä on myös nykyään hyvät vakuutuksiin liittyvät sekä varsinaiset asiakaspalvelut- chat mukaan lukien, joka toimii myös erittäin saavutettavasti. Olen ICT asiantuntijana myös kouluttanut vuosia erilaisten appien käytössä ja senkin suhteen ei ole kuin pelkkää hyvää sanottavaa, koska OP-mobiili oli asiakkaillekin helppo ottaa käyttöön ja ymmärtää sen toimintamahdollisuudet sekä saavutettavuus. Se aina lämmittää vanhankin miehen sydäntä, kun näkövammainen asiakas pystyi mahdollisimman itsenäisesti hoitamaan omat pankkiasiansa. Ehdottomasti 🌟🌟🌟🌟🌟-appi.”
-Hannu
”Mielestäni OP ansaitsisi jonkun saavutettavuuspalkinnon. Heillä saavutettavuus on huipussaan, ainakin puhetukea käyttävän, täysin sokean henkilön kohdalla.”
-Marita
The following has evaluated to null or missing:
==> fileEntry.getDDMFormValuesMap [in template "10157#10197#29752" at line 63, column 28]
----
Tip: It's the step after the last dot that caused this error, not those before it.
----
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: #assign formValuesMap = fileEntry.get... [in template "10157#10197#29752" in function "getDDMFormStringValue" at line 63, column 3]
----
1<#-- inserted during deployment/ --><#noparse>
2<script data-r="webcontent-template-js/op-fi-ofinayt-090" src="/documents/10197/933601379/requirejs-loader.js/7f190522-a0f0-9857-7338-7d1ab48da3a3?version=6.0&c=7891c1aeb18ede6d70be546d1fe401e1db778b93cbee34be096ee2e4af4de5be"></script>
3</#noparse><#-- /inserted during deployment -->
4
5<#-- Structure: OFISMAL006 - Nosto -->
6<#-- Template: OFINAYT090 - Kuva ja video -->
7
8<#assign dlService = serviceLocator.findService("com.liferay.document.library.kernel.service.DLFileEntryLocalService")>
9
10<#function getFileEntry liferayDocumentUrl>
11 <#if !liferayDocumentUrl?has_content>
12 <#return {}>
13 </#if>
14 <#assign fileParts = liferayDocumentUrl?split("/")>
15
16 <#if fileParts?size < 4>
17 <#return {}>
18 </#if>
19
20 <#assign groupIdIndex = fileParts?size - 4>
21 <#attempt>
22 <#assign groupId = fileParts[groupIdIndex]?number>
23 <#if groupId == 0>
24 <#return {}>
25 </#if>
26 <#recover>
27 <#return {}>
28 </#attempt>
29
30 <#assign uuid = fileParts?last?split("?")?first?trim>
31 <#if !uuid?has_content>
32 <#return {}>
33 </#if>
34 <#assign fileEntry = dlService.getFileEntryByUuidAndGroupId(uuid, groupId)>
35 <#return fileEntry>
36</#function>
37
38<#function getStructureValue dataType value>
39 <#if dataType == "boolean">
40 <#assign result = getterUtil.getBoolean(value)>
41 <#elseif dataType == "date">
42 <#attempt>
43 <#assign result = dateUtil.parseDate("yyyy-MM-dd", value, locale)>
44 <#recover>
45 <#return {}>
46 </#attempt>
47 <#elseif dataType == "double">
48 <#assign result = getterUtil.getDouble(value)>
49 <#elseif dataType == "integer">
50 <#assign result = getterUtil.getInteger(value)>
51 <#elseif dataType == "number">
52 <#assign result = getterUtil.getNumber(value)>
53 <#else>
54 <#-- document-library, html, link-to-page, string -->
55 <#assign result = value>
56 </#if>
57 <#return { "v": result }>
58</#function>
59
60<#function getDDMFormStringValue url fieldName>
61 <#assign fileEntry = getFileEntry(url)>
62 <#assign formValuesMap = fileEntry.getDDMFormValuesMap(fileEntry.getFileVersion().fileVersionId)>
63 <#return formValuesMap?values?map(row ->
64 row.getDDMFormFieldValuesMap()?values?map(fieldValues ->
65 fieldValues?filter(field ->
66 field.getName() == fieldName
67 )?map(field ->
68 field.getValue().getString(locale)!""
69 )?filter(value -> value != "")?first!""
70 )?filter(value -> value != "")?first!""
71 )?filter(value -> value != "")?first!"">
72</#function>
73
74<#function getImageOrVideoProps kuva>
75 <#assign altText = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "kuva_alt_text"),{})>
76 <#assign videoUrl = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "video_url"),{})>
77 <#assign isYoutubeLink = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "is_youtube_link"),{})>
78 <#assign copyright = ((kuva.getData())??)?then(getDDMFormStringValue(kuva.getData(), "kuvan_copyright"),{})>
79 <#assign url = ((kuva.getData())??)?then(kuva.getData(),{})>
80 <#assign caption = ((kuva.kuvan_kuvaus.getData())??)?then(getStructureValue("string", kuva.kuvan_kuvaus.getData()),{})>
81 <#return {
82 "videoUrl": getStructureValue("string", videoUrl),
83 "isYoutubeLink": getStructureValue("string", isYoutubeLink),
84 "url": getStructureValue("document-library", url),
85 "alt": getStructureValue("string", altText),
86 "copyright": getStructureValue("string", copyright),
87 "caption": caption
88 }>
89</#function>
90
91<#assign props = {
92 "title": ((nosto_otsikko.getData())??)?then(getStructureValue("string", nosto_otsikko.getData()), {}),
93 "media": getImageOrVideoProps(nosto_kuva),
94 "html": ((nosto_html_teksti.getData())??)?then(getStructureValue("string", nosto_html_teksti.getData()), {}),
95 "contentId": .vars['reserved-article-id'].data!"",
96 "contentName": .vars['reserved-article-title'].data!""
97}>
98
99
100<op-fi-ofinayt-090-39ecd7537f6e5df5e47f3ba65ca3b84a72d2d961448eb9274a520d259fc1c912 style="display: block; height: 38.0rem" props="${jsonFactoryUtil.looseSerializeDeep(props)?html}"></op-fi-ofinayt-090-39ecd7537f6e5df5e47f3ba65ca3b84a72d2d961448eb9274a520d259fc1c912>