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 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
@@ -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: cnt1739460592042;
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: cnt1739460592042 1;
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(cnt1739460592042);
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
- {{> components/forms/components/controls }}
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
- {{> components/forms/components/controls }}
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.88",
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":"{&quot;form_error_required&quot;:&quot;Server: Pflichtfeld&quot;,&quot;form_error_max&quot;:&quot;Server: Zu viele Zeichen&quot;,&quot;form_error_validurl&quot;:&quot;Server: Ungültige URL&quot;,&quot;form_error_empty&quot;:&quot;Server: Darf nicht ausgefüllt werden&quot;,&quot;form_error_constants_or_null&quot;:&quot;Server: Ungültiger Wert&quot;,&quot;form_error_constants&quot;:&quot;Server: Ungültiger Wert&quot;,&quot;form_error_max_multivalue&quot;:&quot;Server: Die maximale Anzahl an Antwortmöglichkeiten wurde überschritten&quot;,&quot;vote_error_identity_already_used&quot;:&quot;Server: Unter dieser E-Mail-Adresse wurde bereits abgestimmt. Eine weitere Abstimmung ist nicht möglich.&quot;,&quot;vote_error_token_request_count_exceeded&quot;:&quot;Server: Die maximale Anzahl an Bestätigungs-E-Mails wurde bereits verschickt.&quot;,&quot;form_error_email&quot;:&quot;Server: Ungültige E-Mail-Adresse&quot;}","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":"{&quot;form_error_required&quot;:&quot;Server: Pflichtfeld&quot;,&quot;form_error_max&quot;:&quot;Server: Zu viele Zeichen&quot;,&quot;form_error_validurl&quot;:&quot;Server: Ungültige URL&quot;,&quot;form_error_empty&quot;:&quot;Server: Darf nicht ausgefüllt werden&quot;,&quot;form_error_constants_or_null&quot;:&quot;Server: Ungültiger Wert&quot;,&quot;form_error_constants&quot;:&quot;Server: Ungültiger Wert&quot;,&quot;form_error_max_multivalue&quot;:&quot;Server: Die maximale Anzahl an Antwortmöglichkeiten wurde überschritten&quot;,&quot;vote_error_identity_already_used&quot;:&quot;Server: Unter dieser E-Mail-Adresse wurde bereits abgestimmt. Eine weitere Abstimmung ist nicht möglich.&quot;,&quot;vote_error_token_request_count_exceeded&quot;:&quot;Server: Die maximale Anzahl an Bestätigungs-E-Mails wurde bereits verschickt.&quot;,&quot;form_error_email&quot;:&quot;Server: Ungültige E-Mail-Adresse&quot;}","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(/&quot;/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
- {{> components/forms/components/controls }}
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>