From 88d6b681e6db8923d52a3f72e5e937a4bfbc8df7 Mon Sep 17 00:00:00 2001
From: Georgi Mateev <gmateev@exactag.com>
Date: Thu, 8 Sep 2022 13:26:46 +0300
Subject: [PATCH] [TASK] #205 Add fingerprint icon feature that allows users to
 open the optin

---
 .../Service/StaticFileGenerationService.php   | 10 ++
 Classes/Service/TemplateService.php           |  6 ++
 .../tx_sgcookieoptin_domain_model_optin.php   | 70 +++++++++++++-
 .../Private/Language/de.locallang_db.xlf      | 36 +++++++
 Resources/Private/Language/locallang_db.xlf   | 27 ++++++
 Resources/Public/JavaScript/cookieOptin.js    | 93 +++++++++++++++++++
 .../Mustache/Fingerprint/Default.css          | 47 ++++++++++
 ext_tables.sql                                |  6 +-
 8 files changed, 292 insertions(+), 3 deletions(-)
 create mode 100644 Resources/Public/StyleSheets/Mustache/Fingerprint/Default.css

diff --git a/Classes/Service/StaticFileGenerationService.php b/Classes/Service/StaticFileGenerationService.php
index 3b9d9312..7fea5a50 100644
--- a/Classes/Service/StaticFileGenerationService.php
+++ b/Classes/Service/StaticFileGenerationService.php
@@ -191,6 +191,8 @@ class StaticFileGenerationService implements SingletonInterface {
 			'banner_color_button_accept' => $fullData['banner_color_button_accept'],
 			'banner_color_button_accept_hover' => $fullData['banner_color_button_accept_hover'],
 			'banner_color_button_accept_text' => $fullData['banner_color_button_accept_text'],
+			'color_fingerprint_image' => $fullData['color_fingerprint_image'],
+			'color_fingerprint_background' => $fullData['color_fingerprint_background'],
 		];
 		$this->createCSSFile($fullData, $folderName, $cssData, $minifyFiles);
 
@@ -461,6 +463,13 @@ class StaticFileGenerationService implements SingletonInterface {
 			);
 		}
 
+		if ($data['fingerprint_position'] > 0) {
+			$content .= " \n\n" . $templateService->getCSSContent(
+				TemplateService::TYPE_FINGERPRINT,
+				TemplateService::IFRAME_FINGERPRINT_TEMPLATE_ID_DEFAULT
+			);
+		}
+
 		$keys = $data = [];
 		foreach ($cssData as $key => $value) {
 			$keys[] = '%23###' . $key . '###';
@@ -869,6 +878,7 @@ class StaticFileGenerationService implements SingletonInterface {
 			'overwrite_baseurl' => (string) $translatedData['overwrite_baseurl'],
 			'unified_cookie_name' => (bool) $translatedData['unified_cookie_name'],
 			'disable_usage_statistics' => (bool) $translatedData['disable_usage_statistics'],
+			'fingerprint_position' => (int) $translatedData['fingerprint_position'],
 		];
 
 		$textEntries = [
diff --git a/Classes/Service/TemplateService.php b/Classes/Service/TemplateService.php
index dac816c0..668cec73 100644
--- a/Classes/Service/TemplateService.php
+++ b/Classes/Service/TemplateService.php
@@ -40,6 +40,7 @@ class TemplateService implements SingletonInterface {
 	public const TYPE_IFRAME = 2;
 	public const TYPE_IFRAME_REPLACEMENT = 3;
 	public const TYPE_IFRAME_WHITELIST = 4;
+	public const TYPE_FINGERPRINT = 5;
 
 	public const TEMPLATE_ID_DEFAULT = 0;
 	public const TEMPLATE_ID_NEW = 1;
@@ -48,6 +49,7 @@ class TemplateService implements SingletonInterface {
 	public const IFRAME_TEMPLATE_ID_DEFAULT = 0;
 	public const IFRAME_REPLACEMENT_TEMPLATE_ID_DEFAULT = 0;
 	public const IFRAME_WHITELIST_TEMPLATE_ID_DEFAULT = 0;
+	public const IFRAME_FINGERPRINT_TEMPLATE_ID_DEFAULT = 0;
 
 	protected static $templateIdToNameMap = [
 		self::TYPE_TEMPLATE => [
@@ -66,6 +68,9 @@ class TemplateService implements SingletonInterface {
 		self::TYPE_IFRAME_WHITELIST => [
 			self::IFRAME_WHITELIST_TEMPLATE_ID_DEFAULT => 'Default',
 		],
+		self::TYPE_FINGERPRINT => [
+			self::IFRAME_FINGERPRINT_TEMPLATE_ID_DEFAULT => 'Default',
+		],
 	];
 
 	protected static $templateIdToFolderMap = [
@@ -74,6 +79,7 @@ class TemplateService implements SingletonInterface {
 		self::TYPE_IFRAME => 'Iframe',
 		self::TYPE_IFRAME_REPLACEMENT => 'IframeReplacement',
 		self::TYPE_IFRAME_WHITELIST => 'IframeWhitelist',
+		self::TYPE_FINGERPRINT => 'Fingerprint',
 	];
 
 	/**
diff --git a/Configuration/TCA/tx_sgcookieoptin_domain_model_optin.php b/Configuration/TCA/tx_sgcookieoptin_domain_model_optin.php
index 54ac68eb..2fd070b7 100644
--- a/Configuration/TCA/tx_sgcookieoptin_domain_model_optin.php
+++ b/Configuration/TCA/tx_sgcookieoptin_domain_model_optin.php
@@ -55,7 +55,7 @@ $configuration = [
 					--palette--;;update_version, header, description, save_confirmation_text, user_hash_text, --palette--;;accept_buttons_texts,
 					--palette--;;link_texts, --palette--;;cookie_texts, navigation,
 				--div--;LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.tab.color,
-					--palette--;;template, --palette--;;color_general, --palette--;;color_notification,
+					--palette--;;template, --palette--;;color_general, --palette--;;fingerprint, --palette--;;color_notification,
 					--palette--;;color_checkbox, --palette--;;color_button, --palette--;;color_list,
 					--palette--;;color_table, disable_powered_by,
 				--div--;LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.tab.iframes,
@@ -114,6 +114,11 @@ $configuration = [
 			'label' => 'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.colors_lists',
 			'showitem' => 'color_list, color_list_text',
 		],
+		'fingerprint' => [
+			'label' => 'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.fingerprint',
+			'showitem' => 'fingerprint_position, --linebreak--,
+			color_fingerprint_background, color_fingerprint_image'
+		],
 		'color_table' => [
 			'label' => 'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.colors_tables',
 			'showitem' => 'color_table_header, color_table, --linebreak--,
@@ -1666,6 +1671,62 @@ $configuration = [
 				'default' => '0',
 			],
 		],
+		'fingerprint_position' => [
+			'exclude' => TRUE,
+			'label' => 'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.fingerprint_position',
+			'default' => 0,
+			'config' => [
+				'type' => 'select',
+				'renderType' => 'selectSingle',
+				'default' => 0,
+				'items' => [
+					[
+						'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.fingerprint_position.0',
+						0,
+					],
+					[
+						'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.fingerprint_position.1',
+						1,
+					],
+					[
+						'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.fingerprint_position.2',
+						2,
+					],
+					[
+						'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.fingerprint_position.3',
+						3,
+					],
+					[
+						'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.fingerprint_position.4',
+						4,
+					],
+				]
+			]
+		],
+		'color_fingerprint_background' => [
+			'exclude' => TRUE,
+			'l10n_mode' => 'exclude',
+			'label' => 'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.color_fingerprint_background',
+			'config' => [
+				'type' => 'input',
+				'renderType' => 'colorpicker',
+				'default' => '#143D59',
+				'placeholder' => '#208A20',
+				'eval' => 'trim, required'
+			]
+		],
+		'color_fingerprint_image' => [
+			'exclude' => TRUE,
+			'l10n_mode' => 'exclude',
+			'label' => 'LLL:EXT:sg_cookie_optin/Resources/Private/Language/locallang_db.xlf:tx_sgcookieoptin_domain_model_optin.color_fingerprint_image',
+			'config' => [
+				'type' => 'input',
+				'renderType' => 'colorpicker',
+				'default' => '#FFFFFF',
+				'placeholder' => '#208A20',
+				'eval' => 'trim, required'
+			]
+		],
 	],
 ];
 
@@ -1743,7 +1804,12 @@ if (version_compare(\TYPO3\CMS\Core\Utility\VersionNumberUtility::getCurrentTypo
 		. 'banner_button_accept_text, banner_button_settings_text, banner_description, show_button_close,'
 		. 'activate_testing_mode, color_full_box, color_full_headline, color_full_text, color_full_button_close,'
 		. 'color_full_button_close_hover, color_full_button_close_text, color_table_header, save_confirmation_text,'
-		. 'color_confirmation_background, color_confirmation_text, session_only_essential_cookies, iframe_whitelist, iframe_whitelist_overwritten, iframe_whitelist_warning, iframe_whitelist_selection, iframe_whitelist_regex, subdomain_support, set_cookie_for_domain, domains_to_delete_cookies_for, cookiebanner_whitelist_regex, disable_powered_by, disable_for_this_language, render_assets_inline, consider_do_not_track, banner_show_again_interval, version, unified_cookie_name, disable_usage_statistics';
+		. 'color_confirmation_background, color_confirmation_text, session_only_essential_cookies, iframe_whitelist,'
+		. 'iframe_whitelist_overwritten, iframe_whitelist_warning, iframe_whitelist_selection, iframe_whitelist_regex,'
+		. 'subdomain_support, set_cookie_for_domain, domains_to_delete_cookies_for, cookiebanner_whitelist_regex,'
+		. 'disable_powered_by, disable_for_this_language, render_assets_inline, consider_do_not_track,'
+		. 'banner_show_again_interval, version, unified_cookie_name, disable_usage_statistics, fingerprint_position,'
+		. 'color_fingerprint_background, color_fingerprint_image';
 }
 
 return $configuration;
diff --git a/Resources/Private/Language/de.locallang_db.xlf b/Resources/Private/Language/de.locallang_db.xlf
index 28c73b5e..4257459b 100644
--- a/Resources/Private/Language/de.locallang_db.xlf
+++ b/Resources/Private/Language/de.locallang_db.xlf
@@ -813,6 +813,42 @@ Ohne diese Einstellung gilt diese Konfiguration nur für die Domäne, in der sie
 				<source><![CDATA[Disable Usage Statistics and Tracability]]></source>
 				<target><![CDATA[Nutzungsstatistiken und Rückverfolgbarkeit deaktivieren]]></target>
 			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position" approved="yes">
+				<source><![CDATA[Fingerprint Icon Position]]></source>
+				<target><![CDATA[Fingerabdruck-Symbol Position]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.0" approved="yes">
+				<source><![CDATA[None]]></source>
+				<target><![CDATA[Keine]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.1" approved="yes">
+				<source><![CDATA[Bottom Left]]></source>
+				<target><![CDATA[Unten Links]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.2" approved="yes">
+				<source><![CDATA[Bottom Right]]></source>
+				<target><![CDATA[Unten Rechts]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.3" approved="yes">
+				<source><![CDATA[Top Left]]></source>
+				<target><![CDATA[Oben Links]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.4" approved="yes">
+				<source><![CDATA[Top Right]]></source>
+				<target><![CDATA[Oben Rechts]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.color_fingerprint_background" approved="yes">
+				<source><![CDATA[Fingerprint Background Color]]></source>
+				<target><![CDATA[Fingerabdruck-Hintergrundfarbe]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.color_fingerprint_image" approved="yes">
+				<source><![CDATA[Fingerprint Image Color]]></source>
+				<target><![CDATA[Fingerabdruck Bildfarbe]]></target>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint" approved="yes">
+				<source><![CDATA[Fingerprint]]></source>
+				<target><![CDATA[Fingerabdruck]]></target>
+			</trans-unit>
 		</body>
 	</file>
 </xliff>
diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf
index 8ec70a18..d7699110 100644
--- a/Resources/Private/Language/locallang_db.xlf
+++ b/Resources/Private/Language/locallang_db.xlf
@@ -599,6 +599,33 @@ Without this setting, this configuration only applies to the domain where it is
 			<trans-unit id="tx_sgcookieoptin_domain_model_optin.disable_usage_statistics" approved="yes">
 				<source><![CDATA[Disable Usage Statistics and Tracability]]></source>
 			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position" approved="yes">
+				<source><![CDATA[Fingerprint Icon Position]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.0" approved="yes">
+				<source><![CDATA[None]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.1" approved="yes">
+				<source><![CDATA[Bottom Left]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.2" approved="yes">
+				<source><![CDATA[Bottom Right]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.3" approved="yes">
+				<source><![CDATA[Top Left]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint_position.4" approved="yes">
+				<source><![CDATA[Top Right]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.color_fingerprint_background" approved="yes">
+				<source><![CDATA[Fingerprint Background Color]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.color_fingerprint_image" approved="yes">
+				<source><![CDATA[Fingerprint Image Color]]></source>
+			</trans-unit>
+			<trans-unit id="tx_sgcookieoptin_domain_model_optin.fingerprint" approved="yes">
+				<source><![CDATA[Fingerprint]]></source>
+			</trans-unit>
 		</body>
 	</file>
 </xliff>
diff --git a/Resources/Public/JavaScript/cookieOptin.js b/Resources/Public/JavaScript/cookieOptin.js
index 2b369ae3..9caad502 100644
--- a/Resources/Public/JavaScript/cookieOptin.js
+++ b/Resources/Public/JavaScript/cookieOptin.js
@@ -32,6 +32,7 @@ var SgCookieOptin = {
 	lastOpenedExternalContentId: 0,
 	jsonData: {},
 	isExternalGroupAccepted: false,
+	fingerprintIcon: null,
 
 	/**
 	 * Executes the script
@@ -87,6 +88,8 @@ var SgCookieOptin = {
 			(SgCookieOptin.shouldShowBannerBasedOnLastPreferences(cookieValue))
 		) {
 			SgCookieOptin.openCookieOptin(null, {hideBanner: false});
+		} else {
+			SgCookieOptin.showFingerprint();
 		}
 	},
 
@@ -274,6 +277,8 @@ var SgCookieOptin = {
 		if (!SgCookieOptin.shouldShowOptinBanner()) {
 			return;
 		}
+
+		SgCookieOptin.hideFingerprint();
 		var hideBanner = typeof options == 'object' && options.hideBanner === true;
 		var fromBanner = typeof options == 'object' && options.fromBanner === true;
 
@@ -856,6 +861,7 @@ var SgCookieOptin = {
 			});
 			parentNode.dispatchEvent(cookieOptinHiddenEvent);
 		}
+		SgCookieOptin.showFingerprint();
 	},
 
 	/**
@@ -2005,6 +2011,93 @@ var SgCookieOptin = {
 				}
 			}
 		}
+	},
+
+	/**
+	 * Shows the fingerprint and creates the element if necessary
+	 */
+	showFingerprint: function() {
+		if (!(SgCookieOptin.jsonData.settings.fingerprint_position > 0) || !SgCookieOptin.shouldShowOptinBanner()) {
+			return;
+		}
+
+		if (SgCookieOptin.fingerprintIcon === null) {
+			SgCookieOptin.fingerprintIcon = SgCookieOptin.createFingeprint();
+		}
+
+		SgCookieOptin.fingerprintIcon.style.display = 'block';
+	},
+
+	/**
+	 * Hides the fingerprint
+	 */
+	hideFingerprint: function() {
+		if (SgCookieOptin.fingerprintIcon === null || !SgCookieOptin.shouldShowOptinBanner()) {
+			return;
+		}
+
+		SgCookieOptin.fingerprintIcon.style.display = 'none';
+	},
+
+	/**
+	 * Creates the fingerprint HTML element
+	 * @return {HTMLDivElement}
+	 */
+	createFingeprint: function() {
+		var fingerprintContainer = document.createElement('div');
+		var iconPositionClass = '';
+
+		switch (SgCookieOptin.jsonData.settings.fingerprint_position) {
+			case 1:
+				iconPositionClass = 'bottom-left';
+				break;
+			case 2:
+				iconPositionClass = 'bottom-right';
+				break;
+			case 3:
+				iconPositionClass = 'top-left';
+				break;
+			case 4:
+				iconPositionClass = 'top-right';
+				break;
+		}
+
+		fingerprintContainer.classList.add('sg-cookie-optin-fingerprint');
+		fingerprintContainer.classList.add('sg-cookie-optin-fingerprint-' + iconPositionClass);
+
+		var iconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+		var iconPath = document.createElementNS(
+		    'http://www.w3.org/2000/svg',
+		    'path'
+		  );
+
+		iconSvg.setAttribute('fill', 'currentColor');
+		iconSvg.setAttribute('viewBox', '0 0 24 24');
+		iconSvg.setAttribute('aria-hidden', 'true');
+		iconSvg.classList.add('sg-cookie-optin-fingerprint-icon');
+
+
+		iconPath.setAttribute(
+		    'd',
+			'M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7-.23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39s-4.66 1.97-4.66 4.39c0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2.19.51 0 .71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12zM14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94s3.08 1.32 3.08 2.94c0 1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44 1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.79 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z'
+	  	);
+
+		fingerprintContainer.addEventListener('click', function (e) {
+			SgCookieOptin.openCookieOptin();
+		});
+
+		iconSvg.appendChild(iconPath);
+		fingerprintContainer.appendChild(iconSvg);
+		document.body.appendChild(fingerprintContainer);
+
+		// Emit event
+		var fingerprintCreatedEvent = new CustomEvent('fingerprintCreated', {
+			bubbles: true,
+			detail: {}
+		});
+		document.dispatchEvent(fingerprintCreatedEvent);
+
+		return fingerprintContainer;
 	}
 };
 
diff --git a/Resources/Public/StyleSheets/Mustache/Fingerprint/Default.css b/Resources/Public/StyleSheets/Mustache/Fingerprint/Default.css
new file mode 100644
index 00000000..a9681cfc
--- /dev/null
+++ b/Resources/Public/StyleSheets/Mustache/Fingerprint/Default.css
@@ -0,0 +1,47 @@
+/*
+ * Copyright notice
+ *
+ * (c) sgalinski Internet Services (https://www.sgalinski.de)
+ *
+ * Commercial license
+ * You can buy a license key on the following site:
+ * https://www.sgalinski.de/en/typo3-produkte-webentwicklung/sgalinski-cookie-optin/
+ */
+
+/* This file includes basic styles for the fingerprint templates */
+.sg-cookie-optin-fingerprint {
+	display: none;
+	border-radius: 50%;
+	z-index: 2147483640;
+	width: 64px;
+	height: 64px;
+	cursor: pointer;
+	position: fixed;
+	background-color: ###color_fingerprint_background###;
+	color: ###color_fingerprint_image###;
+}
+
+.sg-cookie-optin-fingerprint-icon {
+	height: inherit;
+	padding: 12px;
+}
+
+.sg-cookie-optin-fingerprint.sg-cookie-optin-fingerprint-top-left {
+	top: 40px;
+	left: 40px;
+}
+
+.sg-cookie-optin-fingerprint.sg-cookie-optin-fingerprint-top-right {
+	top: 40px;
+	right: 40px;
+}
+
+.sg-cookie-optin-fingerprint.sg-cookie-optin-fingerprint-bottom-left {
+	bottom: 40px;
+	left: 40px;
+}
+
+.sg-cookie-optin-fingerprint.sg-cookie-optin-fingerprint-bottom-right {
+	bottom: 40px;
+	right: 40px;
+}
diff --git a/ext_tables.sql b/ext_tables.sql
index 980b14b4..f7af673e 100644
--- a/ext_tables.sql
+++ b/ext_tables.sql
@@ -39,7 +39,6 @@ CREATE TABLE tx_sgcookieoptin_domain_model_optin (
 	template_selection int(11) DEFAULT '0' NOT NULL,
 	disable_powered_by tinyint(4) unsigned DEFAULT '0' NOT NULL,
 
-
 	-- banner
 	banner_enable tinyint(4) unsigned DEFAULT '0' NOT NULL,
 	banner_html text NOT NULL,
@@ -96,6 +95,11 @@ CREATE TABLE tx_sgcookieoptin_domain_model_optin (
 	color_full_button_close_hover varchar(10) DEFAULT '#143D59' NOT NULL,
 	color_full_button_close_text varchar(10) DEFAULT '#FFFFFF' NOT NULL,
 
+	-- Fingerpring settings
+	color_fingerprint_background varchar(10) DEFAULT '#143D59' NOT NULL,
+	color_fingerprint_image varchar(10) DEFAULT '#FFFFFF' NOT NULL,
+	fingerprint_position int(6) DEFAULT 0 NOT NULL,
+
 	-- Essential group specific columns
 	essential_title text NOT NULL,
 	essential_description text NOT NULL,
-- 
GitLab