diff --git a/entry_types/scrolled/config/locales/new/iframe_consent.de.yml b/entry_types/scrolled/config/locales/new/iframe_consent.de.yml
new file mode 100644
index 000000000..852935403
--- /dev/null
+++ b/entry_types/scrolled/config/locales/new/iframe_consent.de.yml
@@ -0,0 +1,16 @@
+de:
+ pageflow_scrolled:
+ editor:
+ content_elements:
+ iframeEmbed:
+ attributes:
+ requireConsent:
+ label: "Datenschutz-Einwilligung aktivieren"
+ inline_help: |-
+ iframe erst laden, nachdem Besucher der
+ Datenverarbeitung durch die eingebettete Seite
+ zugestimmt hat.
+ help_texts:
+ missingConsentVendor: |-
+ Für den Anbieter der angegeben URL stehen keine
+ Datenschutzangaben zur Verfügung.
diff --git a/entry_types/scrolled/config/locales/new/iframe_consent.en.yml b/entry_types/scrolled/config/locales/new/iframe_consent.en.yml
new file mode 100644
index 000000000..1fa8082a1
--- /dev/null
+++ b/entry_types/scrolled/config/locales/new/iframe_consent.en.yml
@@ -0,0 +1,15 @@
+en:
+ pageflow_scrolled:
+ editor:
+ content_elements:
+ iframeEmbed:
+ attributes:
+ requireConsent:
+ label: "Display privacy opt-in"
+ inline_help: |
+ Only load iframe after the visitor has given
+ consent to the data processing by the embedded page.
+ help_texts:
+ missingConsentVendor: |-
+ No privacy policy information available for the provider
+ of the given URL.
diff --git a/entry_types/scrolled/package/src/contentElements/iframeEmbed/IframeEmbed.js b/entry_types/scrolled/package/src/contentElements/iframeEmbed/IframeEmbed.js
index 3f69b30da..296bde6e4 100644
--- a/entry_types/scrolled/package/src/contentElements/iframeEmbed/IframeEmbed.js
+++ b/entry_types/scrolled/package/src/contentElements/iframeEmbed/IframeEmbed.js
@@ -5,6 +5,8 @@ import {
ContentElementBox,
ContentElementFigure,
FitViewport,
+ ThirdPartyOptIn,
+ ThirdPartyOptOutInfo,
useContentElementEditorState,
useContentElementLifecycle,
usePortraitOrientation,
@@ -37,15 +39,28 @@ export function IframeEmbed({configuration}) {
- {shouldLoad &&
- }
+
+ {shouldLoad &&
+ }
+
+
);
}
+
+function OptOutInfo({configuration}) {
+ if (!configuration.requireConsent) {
+ return null;
+ }
+
+ return (
+
+ );
+}
diff --git a/entry_types/scrolled/package/src/contentElements/iframeEmbed/editor.js b/entry_types/scrolled/package/src/contentElements/iframeEmbed/editor.js
index 03645e695..e6bdd7a90 100644
--- a/entry_types/scrolled/package/src/contentElements/iframeEmbed/editor.js
+++ b/entry_types/scrolled/package/src/contentElements/iframeEmbed/editor.js
@@ -1,5 +1,7 @@
+import I18n from 'i18n-js';
import {editor} from 'pageflow-scrolled/editor';
-import {TextInputView, SelectInputView} from 'pageflow/ui';
+import {InfoBoxView} from 'pageflow/editor';
+import {TextInputView, SelectInputView, CheckBoxInputView} from 'pageflow/ui';
import pictogram from './pictogram.svg';
@@ -12,9 +14,19 @@ editor.contentElementTypes.register('iframeEmbed', {
supportedPositions: ['inline', 'sticky', 'left', 'right'],
supportedWidthRange: ['xxs', 'full'],
- configurationEditor() {
+ configurationEditor({entry}) {
this.tab('general', function() {
this.input('source', TextInputView);
+ this.input('requireConsent', CheckBoxInputView);
+ this.view(InfoBoxView, {
+ level: 'error',
+ text: I18n.t(
+ 'pageflow_scrolled.editor.content_elements.iframeEmbed.help_texts.missingConsentVendor'
+ ),
+ visibleBinding: ['source', 'requireConsent'],
+ visible: ([source, requireConsent]) =>
+ source && requireConsent && !entry.consentVendors.fromUrl(source),
+ });
this.input('title', TextInputView);
this.input('aspectRatio', SelectInputView, {
values: aspectRatios
diff --git a/entry_types/scrolled/package/src/contentElements/iframeEmbed/stories.js b/entry_types/scrolled/package/src/contentElements/iframeEmbed/stories.js
new file mode 100644
index 000000000..b5011e3bb
--- /dev/null
+++ b/entry_types/scrolled/package/src/contentElements/iframeEmbed/stories.js
@@ -0,0 +1,23 @@
+import '../frontend';
+import {storiesOfContentElement} from 'pageflow-scrolled/spec/support/stories';
+
+storiesOfContentElement(module, {
+ typeName: 'iframeEmbed',
+ baseConfiguration: {
+ source: 'https://example.com',
+ caption: 'Some caption'
+ },
+ consent: {
+ configuration: {
+ requireConsent: true
+ }
+ },
+ variants: [
+ {
+ name: 'With Consent',
+ configuration: {
+ requireConsent: true
+ }
+ }
+ ]
+});