hr-design-system-handlebars 1.114.88 → 1.114.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/assets/index.css +21 -3
- package/dist/assets/js/components/forms/js/contactForm.alpine.js +17 -3
- package/dist/views/components/forms/webform.hbs +12 -4
- package/dist/views_static/components/forms/webform.hbs +12 -4
- package/package.json +1 -1
- package/src/assets/fixtures/content/copytext/copytext_webform_simple.json +2 -0
- package/src/stories/views/components/content/copytext/fixtures/copytext_webform_simple.json +1 -1
- package/src/stories/views/components/forms/js/contactForm.alpine.js +17 -3
- package/src/stories/views/components/forms/webform.hbs +12 -4
- package/src/stories/views/components/voting/voting.mdx +71 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
# v1.114.90 (Thu Feb 13 2025)
|
|
2
|
+
|
|
3
|
+
#### 🐛 Bug Fix
|
|
4
|
+
|
|
5
|
+
- Add spam protection feature to contact form [#1239](https://github.com/mumprod/hr-design-system-handlebars/pull/1239) ([@vascoeduardo](https://github.com/vascoeduardo) [@eduardo-hr](https://github.com/eduardo-hr))
|
|
6
|
+
|
|
7
|
+
#### Authors: 2
|
|
8
|
+
|
|
9
|
+
- [@eduardo-hr](https://github.com/eduardo-hr)
|
|
10
|
+
- Vasco ([@vascoeduardo](https://github.com/vascoeduardo))
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# v1.114.89 (Thu Feb 13 2025)
|
|
15
|
+
|
|
16
|
+
#### 🐛 Bug Fix
|
|
17
|
+
|
|
18
|
+
- add voting-documentation [#1238](https://github.com/mumprod/hr-design-system-handlebars/pull/1238) ([@hanswurstsalat](https://github.com/hanswurstsalat))
|
|
19
|
+
|
|
20
|
+
#### Authors: 1
|
|
21
|
+
|
|
22
|
+
- Geraldo ([@hanswurstsalat](https://github.com/hanswurstsalat))
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
1
26
|
# v1.114.88 (Thu Feb 13 2025)
|
|
2
27
|
|
|
3
28
|
#### 🐛 Bug Fix
|
package/dist/assets/index.css
CHANGED
|
@@ -2503,6 +2503,9 @@ article #commentList {
|
|
|
2503
2503
|
.border-l-2 {
|
|
2504
2504
|
border-left-width: 2px;
|
|
2505
2505
|
}
|
|
2506
|
+
.border-l-4 {
|
|
2507
|
+
border-left-width: 4px;
|
|
2508
|
+
}
|
|
2506
2509
|
.border-l-\[3px\] {
|
|
2507
2510
|
border-left-width: 3px;
|
|
2508
2511
|
}
|
|
@@ -2616,6 +2619,11 @@ article #commentList {
|
|
|
2616
2619
|
border-color: #fff;
|
|
2617
2620
|
border-color: var(--color-navigation-border-color);
|
|
2618
2621
|
}
|
|
2622
|
+
.border-orange-500 {
|
|
2623
|
+
--tw-border-opacity: 1;
|
|
2624
|
+
border-color: rgba(249, 115, 22, 1);
|
|
2625
|
+
border-color: rgba(249, 115, 22, var(--tw-border-opacity));
|
|
2626
|
+
}
|
|
2619
2627
|
.border-primary {
|
|
2620
2628
|
border-color: #005293;
|
|
2621
2629
|
border-color: var(--color-primary-ds);
|
|
@@ -2814,6 +2822,11 @@ article #commentList {
|
|
|
2814
2822
|
background-color: rgba(229, 229, 229, 1);
|
|
2815
2823
|
background-color: rgba(229, 229, 229, var(--tw-bg-opacity));
|
|
2816
2824
|
}
|
|
2825
|
+
.bg-orange-100 {
|
|
2826
|
+
--tw-bg-opacity: 1;
|
|
2827
|
+
background-color: rgba(255, 237, 213, 1);
|
|
2828
|
+
background-color: rgba(255, 237, 213, var(--tw-bg-opacity));
|
|
2829
|
+
}
|
|
2817
2830
|
.bg-orange-500 {
|
|
2818
2831
|
--tw-bg-opacity: 1;
|
|
2819
2832
|
background-color: rgba(249, 115, 22, 1);
|
|
@@ -3524,6 +3537,11 @@ article #commentList {
|
|
|
3524
3537
|
color: #000000;
|
|
3525
3538
|
color: var(--color-navigation-text);
|
|
3526
3539
|
}
|
|
3540
|
+
.text-orange-700 {
|
|
3541
|
+
--tw-text-opacity: 1;
|
|
3542
|
+
color: rgba(194, 65, 12, 1);
|
|
3543
|
+
color: rgba(194, 65, 12, var(--tw-text-opacity));
|
|
3544
|
+
}
|
|
3527
3545
|
.text-orange-spicyCarrot-hex {
|
|
3528
3546
|
--tw-text-opacity: 1;
|
|
3529
3547
|
color: rgba(211, 70, 0, 1);
|
|
@@ -3828,7 +3846,7 @@ article #commentList {
|
|
|
3828
3846
|
border-bottom-color: var(--color-secondary-ds);
|
|
3829
3847
|
}
|
|
3830
3848
|
.counter-reset {
|
|
3831
|
-
counter-reset:
|
|
3849
|
+
counter-reset: cnt1739484096529;
|
|
3832
3850
|
}
|
|
3833
3851
|
.animate-delay-100 {
|
|
3834
3852
|
--tw-animate-delay: 100ms;
|
|
@@ -4273,7 +4291,7 @@ html { scroll-behavior: smooth; }
|
|
|
4273
4291
|
--tw-ring-color: rgba(255, 255, 255, 0.5);
|
|
4274
4292
|
}
|
|
4275
4293
|
.-ordered {
|
|
4276
|
-
counter-increment:
|
|
4294
|
+
counter-increment: cnt1739484096529 1;
|
|
4277
4295
|
}
|
|
4278
4296
|
.-ordered::before {
|
|
4279
4297
|
position: absolute;
|
|
@@ -4291,7 +4309,7 @@ html { scroll-behavior: smooth; }
|
|
|
4291
4309
|
--tw-text-opacity: 1;
|
|
4292
4310
|
color: rgba(0, 0, 0, 1);
|
|
4293
4311
|
color: rgba(0, 0, 0, var(--tw-text-opacity));
|
|
4294
|
-
content: counter(
|
|
4312
|
+
content: counter(cnt1739484096529);
|
|
4295
4313
|
}
|
|
4296
4314
|
/*! ****************************/
|
|
4297
4315
|
/*! DataPolicy stuff */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { uxAction } from 'base/tracking/pianoHelper.subfeature'
|
|
2
2
|
|
|
3
|
-
export default function contactForm(formId, jsonUrl, errorMessages, multipart, trackingInformations, jsonp = false) {
|
|
3
|
+
export default function contactForm(formId, jsonUrl, errorMessages, multipart, trackingInformations, jsonp = false, hasSpamProtection) {
|
|
4
4
|
return {
|
|
5
5
|
isPosting: false,
|
|
6
6
|
wasPosted: false,
|
|
@@ -12,15 +12,29 @@ export default function contactForm(formId, jsonUrl, errorMessages, multipart, t
|
|
|
12
12
|
formWrapper: this.$refs[formId].closest("#formWrapper"),
|
|
13
13
|
honeypot: this.$refs[formId].querySelector('input[data-name="x-message"]'),
|
|
14
14
|
actionUrl: this.form && this.form.getAttribute('action'),
|
|
15
|
+
interacted: true,
|
|
16
|
+
|
|
15
17
|
checkForJsonURL () {
|
|
16
18
|
if (jsonUrl) {
|
|
17
19
|
this.actionUrl = jsonUrl
|
|
18
20
|
}
|
|
19
21
|
},
|
|
20
22
|
formInit(){
|
|
23
|
+
|
|
21
24
|
this.checkForJsonURL()
|
|
22
25
|
this.$store.forms.submissionAttempted[formId] = false;
|
|
23
26
|
this.$store.forms.errorMessages = JSON.parse(errorMessages.replace(/"/g,'"'))
|
|
27
|
+
console.log('hasSpamProtection:', hasSpamProtection);
|
|
28
|
+
if(hasSpamProtection){
|
|
29
|
+
console.log('Spam Protection');
|
|
30
|
+
this.initSpamProtection();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
},
|
|
34
|
+
initSpamProtection(){
|
|
35
|
+
this.interacted = false;
|
|
36
|
+
addEventListener('mousemove', () => this.interacted = true );
|
|
37
|
+
addEventListener('keypress', () => this.interacted = true );
|
|
24
38
|
},
|
|
25
39
|
scrollToElementAndCenterWithTimeout(element, timeout){
|
|
26
40
|
setTimeout(() => {
|
|
@@ -35,8 +49,8 @@ export default function contactForm(formId, jsonUrl, errorMessages, multipart, t
|
|
|
35
49
|
if (this.honeypot) {
|
|
36
50
|
this.honeypot.removeAttribute('required');
|
|
37
51
|
}
|
|
38
|
-
if(this.form.reportValidity()){
|
|
39
|
-
this.handleSubmit(event,this.form)
|
|
52
|
+
if(this.form.reportValidity() && this.interacted){
|
|
53
|
+
this.handleSubmit(event,this.form)
|
|
40
54
|
} else {
|
|
41
55
|
this.scrollToElementAndCenterWithTimeout(document.activeElement, 50)
|
|
42
56
|
if (this.honeypot) {
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
<form
|
|
8
8
|
x-ref="form{{nextRandom}}"
|
|
9
9
|
ax-load
|
|
10
|
-
x-data="contactForm('form{{getRandom}}','{{this.jsonUrl}}','{{this.errorMessages}}','{{this.isMultipart}}','{{this.trackingInformations}}')"
|
|
10
|
+
x-data="contactForm('form{{getRandom}}','{{this.jsonUrl}}','{{this.errorMessages}}','{{this.isMultipart}}','{{this.trackingInformations}}', 'false', '{{this.hasSpamProtection}}')"
|
|
11
11
|
x-init="formInit()"
|
|
12
12
|
x-ignore
|
|
13
13
|
|
|
14
14
|
@submit.prevent
|
|
15
15
|
id="form{{getRandom}}"
|
|
16
16
|
class="relative flex flex-col justify-center overflow-hidden group"
|
|
17
|
-
action="{{this.url}}"
|
|
17
|
+
action="{{if this.hasSpamProtection '#' this.url}}"
|
|
18
18
|
method="post"
|
|
19
19
|
enctype="{{if this.isMultipart 'multipart/form-data' 'application/x-www-form-urlencoded'}}"
|
|
20
20
|
accept-charset="utf-8"
|
|
@@ -29,8 +29,16 @@
|
|
|
29
29
|
x-transition:leave-end="opacity-0 transform scale-90"
|
|
30
30
|
>
|
|
31
31
|
{{> components/forms/components/fields _formId=(joinStrings 'form' (getRandom)) }}
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
{{#if this.hasSpamProtection }}
|
|
33
|
+
<noscript>
|
|
34
|
+
<div class="p-4 mb-3 text-orange-700 bg-orange-100 border-l-4 border-orange-500" role="alert">
|
|
35
|
+
<p class="font-bold">Hinweis</p>
|
|
36
|
+
<p>Bitte Aktivieren Sie JavaScript um dieses Formular Absenden zu können.</p>
|
|
37
|
+
</div>
|
|
38
|
+
</noscript>
|
|
39
|
+
{{/if}}
|
|
40
|
+
{{> components/forms/components/controls }}
|
|
41
|
+
|
|
34
42
|
</div>
|
|
35
43
|
<div class="flex flex-col gap-6 md:gap-10" id="successMessage" x-show="wasPostedWithSuccess"
|
|
36
44
|
x-transition:enter="transition ease-out duration-300 delay-75"
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
<form
|
|
8
8
|
x-ref="form{{nextRandom}}"
|
|
9
9
|
ax-load
|
|
10
|
-
x-data="contactForm('form{{getRandom}}','{{this.jsonUrl}}','{{this.errorMessages}}','{{this.isMultipart}}','{{this.trackingInformations}}')"
|
|
10
|
+
x-data="contactForm('form{{getRandom}}','{{this.jsonUrl}}','{{this.errorMessages}}','{{this.isMultipart}}','{{this.trackingInformations}}', 'false', '{{this.hasSpamProtection}}')"
|
|
11
11
|
x-init="formInit()"
|
|
12
12
|
x-ignore
|
|
13
13
|
|
|
14
14
|
@submit.prevent
|
|
15
15
|
id="form{{getRandom}}"
|
|
16
16
|
class="relative flex flex-col justify-center overflow-hidden group"
|
|
17
|
-
action="{{this.url}}"
|
|
17
|
+
action="{{if this.hasSpamProtection '#' this.url}}"
|
|
18
18
|
method="post"
|
|
19
19
|
enctype="{{if this.isMultipart 'multipart/form-data' 'application/x-www-form-urlencoded'}}"
|
|
20
20
|
accept-charset="utf-8"
|
|
@@ -29,8 +29,16 @@
|
|
|
29
29
|
x-transition:leave-end="opacity-0 transform scale-90"
|
|
30
30
|
>
|
|
31
31
|
{{> components/forms/components/fields _formId=(joinStrings 'form' (getRandom)) }}
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
{{#if this.hasSpamProtection }}
|
|
33
|
+
<noscript>
|
|
34
|
+
<div class="p-4 mb-3 text-orange-700 bg-orange-100 border-l-4 border-orange-500" role="alert">
|
|
35
|
+
<p class="font-bold">Hinweis</p>
|
|
36
|
+
<p>Bitte Aktivieren Sie JavaScript um dieses Formular Absenden zu können.</p>
|
|
37
|
+
</div>
|
|
38
|
+
</noscript>
|
|
39
|
+
{{/if}}
|
|
40
|
+
{{> components/forms/components/controls }}
|
|
41
|
+
|
|
34
42
|
</div>
|
|
35
43
|
<div class="flex flex-col gap-6 md:gap-10" id="successMessage" x-show="wasPostedWithSuccess"
|
|
36
44
|
x-transition:enter="transition ease-out duration-300 delay-75"
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"repository": "https://github.com/szuelch/hr-design-system-handlebars",
|
|
9
|
-
"version": "1.114.
|
|
9
|
+
"version": "1.114.90",
|
|
10
10
|
"scripts": {
|
|
11
11
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
12
|
"storybook": "storybook dev -p 6006 public",
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"richtext":"Liebe Nutzerin, lieber Nutzer,<br><br>ich werde mich so schnell wie möglich um Ihr Anliegen kümmern. Hier geht's zur <a class='' href='https://www.hessenschau.de/index.html'>hessenschau.de-Startseite</a> mit aktuellen Nachrichten aus Hessen.<br><br>Viele Grüße, <br><br>Karsten Hufer"
|
|
15
15
|
},
|
|
16
16
|
"jsonUrl": "https://ugc-hessenschau.dev-ext.hrcms.gcp.cloud.hr.de",
|
|
17
|
+
"url": "https://ugc-hessenschau.dev-ext.hrcms.gcp.cloud.hr.de/action",
|
|
18
|
+
"hasSpamProtection": true,
|
|
17
19
|
"errorMessages":
|
|
18
20
|
{
|
|
19
21
|
"@->jsoninclude": "forms/error_messages.inc.json",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"copytextParagraph":[{"isHeadline":true,"text":"Copytext mit Formular"},{"paragraphBoxItem":{"isWebForm":true,"hasNewWebForm":true,"title":"Kontaktformular","successText":{"richtext":"Liebe Nutzerin, lieber Nutzer,<br><br>ich werde mich so schnell wie möglich um Ihr Anliegen kümmern. Hier geht's zur <a class='' href='https://www.hessenschau.de/index.html'>hessenschau.de-Startseite</a> mit aktuellen Nachrichten aus Hessen.<br><br>Viele Grüße, <br><br>Karsten Hufer"},"jsonUrl":"https://ugc-hessenschau.dev-ext.hrcms.gcp.cloud.hr.de","errorMessages":"{"form_error_required":"Server: Pflichtfeld","form_error_max":"Server: Zu viele Zeichen","form_error_validurl":"Server: Ungültige URL","form_error_empty":"Server: Darf nicht ausgefüllt werden","form_error_constants_or_null":"Server: Ungültiger Wert","form_error_constants":"Server: Ungültiger Wert","form_error_max_multivalue":"Server: Die maximale Anzahl an Antwortmöglichkeiten wurde überschritten","vote_error_identity_already_used":"Server: Unter dieser E-Mail-Adresse wurde bereits abgestimmt. Eine weitere Abstimmung ist nicht möglich.","vote_error_token_request_count_exceeded":"Server: Die maximale Anzahl an Bestätigungs-E-Mails wurde bereits verschickt.","form_error_email":"Server: Ungültige E-Mail-Adresse"}","isMultipart":"isMultipart","trackingInformations":"trackingInformations","fields":[{"type":{"isText":true,"asString":"text"},"name":"vorname","label":"Vorname","description":"Das ist der Beschreibungstext von Vorname","defaultValue":"","isHidden":false,"isRequired":false},{"type":{"isText":true,"asString":"text"},"name":"message","label":"message","description":"message","defaultValue":"","isHidden":true,"hasSpamProtection":true,"isRequired":false,"maxLength":"140"}]}}]}
|
|
1
|
+
{"copytextParagraph":[{"isHeadline":true,"text":"Copytext mit Formular"},{"paragraphBoxItem":{"isWebForm":true,"hasNewWebForm":true,"title":"Kontaktformular","successText":{"richtext":"Liebe Nutzerin, lieber Nutzer,<br><br>ich werde mich so schnell wie möglich um Ihr Anliegen kümmern. Hier geht's zur <a class='' href='https://www.hessenschau.de/index.html'>hessenschau.de-Startseite</a> mit aktuellen Nachrichten aus Hessen.<br><br>Viele Grüße, <br><br>Karsten Hufer"},"jsonUrl":"https://ugc-hessenschau.dev-ext.hrcms.gcp.cloud.hr.de","url":"https://ugc-hessenschau.dev-ext.hrcms.gcp.cloud.hr.de/action","hasSpamProtection":true,"errorMessages":"{"form_error_required":"Server: Pflichtfeld","form_error_max":"Server: Zu viele Zeichen","form_error_validurl":"Server: Ungültige URL","form_error_empty":"Server: Darf nicht ausgefüllt werden","form_error_constants_or_null":"Server: Ungültiger Wert","form_error_constants":"Server: Ungültiger Wert","form_error_max_multivalue":"Server: Die maximale Anzahl an Antwortmöglichkeiten wurde überschritten","vote_error_identity_already_used":"Server: Unter dieser E-Mail-Adresse wurde bereits abgestimmt. Eine weitere Abstimmung ist nicht möglich.","vote_error_token_request_count_exceeded":"Server: Die maximale Anzahl an Bestätigungs-E-Mails wurde bereits verschickt.","form_error_email":"Server: Ungültige E-Mail-Adresse"}","isMultipart":"isMultipart","trackingInformations":"trackingInformations","fields":[{"type":{"isText":true,"asString":"text"},"name":"vorname","label":"Vorname","description":"Das ist der Beschreibungstext von Vorname","defaultValue":"","isHidden":false,"isRequired":false},{"type":{"isText":true,"asString":"text"},"name":"message","label":"message","description":"message","defaultValue":"","isHidden":true,"hasSpamProtection":true,"isRequired":false,"maxLength":"140"}]}}]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { uxAction } from 'base/tracking/pianoHelper.subfeature'
|
|
2
2
|
|
|
3
|
-
export default function contactForm(formId, jsonUrl, errorMessages, multipart, trackingInformations, jsonp = false) {
|
|
3
|
+
export default function contactForm(formId, jsonUrl, errorMessages, multipart, trackingInformations, jsonp = false, hasSpamProtection) {
|
|
4
4
|
return {
|
|
5
5
|
isPosting: false,
|
|
6
6
|
wasPosted: false,
|
|
@@ -12,15 +12,29 @@ export default function contactForm(formId, jsonUrl, errorMessages, multipart, t
|
|
|
12
12
|
formWrapper: this.$refs[formId].closest("#formWrapper"),
|
|
13
13
|
honeypot: this.$refs[formId].querySelector('input[data-name="x-message"]'),
|
|
14
14
|
actionUrl: this.form && this.form.getAttribute('action'),
|
|
15
|
+
interacted: true,
|
|
16
|
+
|
|
15
17
|
checkForJsonURL () {
|
|
16
18
|
if (jsonUrl) {
|
|
17
19
|
this.actionUrl = jsonUrl
|
|
18
20
|
}
|
|
19
21
|
},
|
|
20
22
|
formInit(){
|
|
23
|
+
|
|
21
24
|
this.checkForJsonURL()
|
|
22
25
|
this.$store.forms.submissionAttempted[formId] = false;
|
|
23
26
|
this.$store.forms.errorMessages = JSON.parse(errorMessages.replace(/"/g,'"'))
|
|
27
|
+
console.log('hasSpamProtection:', hasSpamProtection);
|
|
28
|
+
if(hasSpamProtection){
|
|
29
|
+
console.log('Spam Protection');
|
|
30
|
+
this.initSpamProtection();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
},
|
|
34
|
+
initSpamProtection(){
|
|
35
|
+
this.interacted = false;
|
|
36
|
+
addEventListener('mousemove', () => this.interacted = true );
|
|
37
|
+
addEventListener('keypress', () => this.interacted = true );
|
|
24
38
|
},
|
|
25
39
|
scrollToElementAndCenterWithTimeout(element, timeout){
|
|
26
40
|
setTimeout(() => {
|
|
@@ -35,8 +49,8 @@ export default function contactForm(formId, jsonUrl, errorMessages, multipart, t
|
|
|
35
49
|
if (this.honeypot) {
|
|
36
50
|
this.honeypot.removeAttribute('required');
|
|
37
51
|
}
|
|
38
|
-
if(this.form.reportValidity()){
|
|
39
|
-
this.handleSubmit(event,this.form)
|
|
52
|
+
if(this.form.reportValidity() && this.interacted){
|
|
53
|
+
this.handleSubmit(event,this.form)
|
|
40
54
|
} else {
|
|
41
55
|
this.scrollToElementAndCenterWithTimeout(document.activeElement, 50)
|
|
42
56
|
if (this.honeypot) {
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
<form
|
|
8
8
|
x-ref="form{{nextRandom}}"
|
|
9
9
|
ax-load
|
|
10
|
-
x-data="contactForm('form{{getRandom}}','{{this.jsonUrl}}','{{this.errorMessages}}','{{this.isMultipart}}','{{this.trackingInformations}}')"
|
|
10
|
+
x-data="contactForm('form{{getRandom}}','{{this.jsonUrl}}','{{this.errorMessages}}','{{this.isMultipart}}','{{this.trackingInformations}}', 'false', '{{this.hasSpamProtection}}')"
|
|
11
11
|
x-init="formInit()"
|
|
12
12
|
x-ignore
|
|
13
13
|
|
|
14
14
|
@submit.prevent
|
|
15
15
|
id="form{{getRandom}}"
|
|
16
16
|
class="relative flex flex-col justify-center overflow-hidden group"
|
|
17
|
-
action="{{this.url}}"
|
|
17
|
+
action="{{if this.hasSpamProtection '#' this.url}}"
|
|
18
18
|
method="post"
|
|
19
19
|
enctype="{{if this.isMultipart 'multipart/form-data' 'application/x-www-form-urlencoded'}}"
|
|
20
20
|
accept-charset="utf-8"
|
|
@@ -29,8 +29,16 @@
|
|
|
29
29
|
x-transition:leave-end="opacity-0 transform scale-90"
|
|
30
30
|
>
|
|
31
31
|
{{> components/forms/components/fields _formId=(joinStrings 'form' (getRandom)) }}
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
{{#if this.hasSpamProtection }}
|
|
33
|
+
<noscript>
|
|
34
|
+
<div class="p-4 mb-3 text-orange-700 bg-orange-100 border-l-4 border-orange-500" role="alert">
|
|
35
|
+
<p class="font-bold">Hinweis</p>
|
|
36
|
+
<p>Bitte Aktivieren Sie JavaScript um dieses Formular Absenden zu können.</p>
|
|
37
|
+
</div>
|
|
38
|
+
</noscript>
|
|
39
|
+
{{/if}}
|
|
40
|
+
{{> components/forms/components/controls }}
|
|
41
|
+
|
|
34
42
|
</div>
|
|
35
43
|
<div class="flex flex-col gap-6 md:gap-10" id="successMessage" x-show="wasPostedWithSuccess"
|
|
36
44
|
x-transition:enter="transition ease-out duration-300 delay-75"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ArgTypes, Meta, Story, Canvas } from '@storybook/blocks'
|
|
2
|
+
import * as votingStories from './voting.stories'
|
|
3
|
+
|
|
4
|
+
<Meta of={votingStories} />
|
|
5
|
+
|
|
6
|
+
# Voting
|
|
7
|
+
|
|
8
|
+
## Beschreibung
|
|
9
|
+
|
|
10
|
+
Das Voting besteht aus den Hauptkomponenten <b>voting.hbs</b>, <b>voting_media_player.hbs</b> und <b>voting_result.hbs</b>.<br/><br/>
|
|
11
|
+
Diese verwenden die folgenden Unter-Komponenten:<br/>
|
|
12
|
+
voting_backbutton.hbs, voting_header.hbs, voting_hint.hbs und voting_submit.hbs.<br/><br/>
|
|
13
|
+
Die Funktionalität wird über diese javascript-Dateien bereitgestellt:<br/>
|
|
14
|
+
votingCookieCheckerDs.feature.js, votingDs.feature.js, votingResultCookieDs.feature.js und votingValidatorDs.feature.js.<br/><br/>
|
|
15
|
+
Alle genannten Dateien werden nachfolgend beschrieben.
|
|
16
|
+
|
|
17
|
+
### voting.hbs
|
|
18
|
+
Dies ist die Hauptkomponente. Sie kann in anderen Komponenten inkludiert werden (siehe Verwendung).
|
|
19
|
+
Sie enthält im umschließenden div-Element die data-Attribute für das javascript (data-hr-voting-ds, data-hr-voting-validator-ds, data-hr-voting-cookie-checker-ds)
|
|
20
|
+
und übergibt diesen jeweils Daten-Objekte.<br/>
|
|
21
|
+
Die nächste Ebene ist ein div-Element mit der css-Klasse "js-voting-wrapper", anhand derer diesem div Inhalte per javascript zugefügt werden.<br/>
|
|
22
|
+
Nachfolgend das form-Element, welches die Daten an den ugc-Server sendet. Die voting-Felder werden per Einbindung der Komponente fields.hbs erzeugt. Um diese den grafischen Vorlagen entsprechend darzustellen, werden diverse css-Parameter benötigt.<br/>
|
|
23
|
+
Ferner enthält voting.hbs drei script-Elemente mit den jeweiligen css-Klassen js-successMessage, js-errorMessage und js-result. Mit Hilfe dieser Klassennamen wird hier jeweils die Komponente voting_result.hbs in verschiedenen Ausprägungen eingebunden.<br/>
|
|
24
|
+
Am Ende von voting.hbs wird die Komponente teaser_featured_content.hbs inkludiert, welche die "Mehr zum Thema"-Links enthält.
|
|
25
|
+
|
|
26
|
+
### voting_media_player.hbs
|
|
27
|
+
Mit dieser Komponente werden Audios und Videos in den voting-Optionen dargestellt.
|
|
28
|
+
|
|
29
|
+
### voting_result.hbs
|
|
30
|
+
Diese Komponente wird per javascript in voting.hbs inkludiert und stellt - abhängig von den ihr übergebenen Parametern - das voting-Ergebnis in einem per css keyframes animierten barchart, ein Danke-Text oder eine Fehlermeldung dar.
|
|
31
|
+
|
|
32
|
+
### voting_backbutton.hbs
|
|
33
|
+
Enthält den "Zurück zur Abstimmung"-Button. Dieser wird nur im Fehlerfall, also in der Fehler-Message dargestellt.
|
|
34
|
+
|
|
35
|
+
### voting_header.hbs
|
|
36
|
+
Diese Komponente stellt Label (Voting) und Titel dar.
|
|
37
|
+
|
|
38
|
+
### voting_hint.hbs
|
|
39
|
+
Wird für die Anzeige diverser Hinweistexte verwendet, zB. Anzahl der Stimmen, "Werte Stimmen" bei absoluten Werten.
|
|
40
|
+
|
|
41
|
+
### voting_submit.hbs
|
|
42
|
+
Beinhaltet den "Abstimmen"-Button + Icon + Hinweistext.
|
|
43
|
+
|
|
44
|
+
### votingDs.feature.js
|
|
45
|
+
Hier sind u.a. die Handler für das Versenden des Voting-Formulars, die Verarbeitung der response vom ugc-Server sowie das Laden der voting_result-Komponente in den verschiedenen Ausprägungen definiert.
|
|
46
|
+
|
|
47
|
+
### votingCookieCheckerDs.feature.js
|
|
48
|
+
Prüft, ob ein voting-cookie existiert und lädt ggf. eine Message ("Sie haben bereits abgestimmt").
|
|
49
|
+
|
|
50
|
+
### votingResultCookieDs.feature.js
|
|
51
|
+
Setzt das voting-cookie.
|
|
52
|
+
|
|
53
|
+
### votingValidatorDs.feature.js
|
|
54
|
+
Steuert das enablen/disablen des Submit-Buttons sowie die Anzeige der Anzahl der gewählten Optionen (n/x).
|
|
55
|
+
|
|
56
|
+
## Verwendung
|
|
57
|
+
|
|
58
|
+
Das Voting wird in handlebars wie folgt eingebaut:
|
|
59
|
+
|
|
60
|
+
1. Im copytext
|
|
61
|
+
```html
|
|
62
|
+
{{> components/voting/voting}}
|
|
63
|
+
```
|
|
64
|
+
2. Als Teaser
|
|
65
|
+
```html
|
|
66
|
+
{{> components/voting/voting _isTeaser=true}}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
<Canvas withToolbar>
|
|
70
|
+
<Story of={votingStories.Default} />
|
|
71
|
+
</Canvas>
|