src/components/BlockingLayer.js

goog.module('gep.components.BlockingLayer');

const AbstractLayer = goog.require('gep.components.AbstractLayer');
const {LayerType} = goog.require('gep.provider.LayerProvider');
const SecurityProvider = goog.require('gep.provider.SecurityProvider');

const {listen,EventType,Event} = goog.require('goog.events');
const classlist = goog.require('goog.dom.classlist');
const Cookies = goog.require('goog.net.Cookies');

/**
 * Component that controls the display of the blocking (data security) layer and its contents.
 * @extends {AbstractLayer}
 */
class BlockingLayer extends AbstractLayer
{
    constructor()
    {
        super(LayerType.BLOCKING);

        /**
         * Reference to SecurityProvider for monitoring the data security consent.
         * @type {SecurityProvider}
         * @private
         */
        this.securityProvider_ = SecurityProvider.getInstance();

        /**
         * Closure cookie reference object to monitor and modify browser cookies.
         * @type {Cookies}
         * @private
         */
        this.cookies_ = new Cookies(document);

        /**
         * Lifetime of the consent cookie
         * @type {number}
         * @private
         */
        this.cookieLifetimeInDays_ = 365;

        /**
         * Versioning of the Legal Provisions. If something changes in the legal provisions and
         * the user has to give his consent again, the version must be incremented here.
         * @type {number}
         * @private
         */
        this.legalsVersion_ = 1;
    }

    /**
     * Component is ready and had loaded all dependencies (inherit method waitFor and sub components).
     * Checks the saved user agreement and inits listeners for the setting buttons.
     * @inheritDoc
     */
    onInit()
    {
        super.onInit();

        /**
         * Dom element for the legal button
         * @type {!Element}
         * @private
         */
        this.btnLegals_ = /** @type {!Element} */ (this.getElement().querySelector('.blocking-layer-button-legals'));

        /**
         * Dom element for the accept button
         * @type {!Element}
         * @private
         */
        this.btnAccept_ = /** @type {!Element} */ (this.getElement().querySelector('.blocking-layer-button-accept'));

        /**
         * Dom element for the additional legal section content (this section is hidden by default)
         * @type {!Element}
         * @private
         */
        this.legalsWrapper_ = /** @type {!Element} */ (this.getElement().querySelector('.blocking-layer-legals-wrapper'));

        let legalsAccepted = false;
        const existingPrivacySettingsItems = this.getCookie();
        existingPrivacySettingsItems.forEach((existingPrivacySettingsItem) => {
            if(existingPrivacySettingsItem[0] == 'legals-'+this.legalsVersion_ && existingPrivacySettingsItem[1] == 'accepted')
                legalsAccepted = true;
        });
        this.securityProvider_.legalsAccepted = legalsAccepted;

        classlist.enable(this.getElement(), 'has-accepted', this.securityProvider_.legalsAccepted);
        listen(this.btnLegals_, EventType.CLICK, this.handleClickLegals_, false, this);
        listen(this.btnAccept_, EventType.CLICK, this.handleClickAccept_, false, this);
    }

    /**
     * Switches the visibility of the additional legal content section
     * @param {Event} event
     * @private
     */
    handleClickLegals_(event)
    {
        event.preventDefault();
        event.stopPropagation();

        classlist.toggle(this.legalsWrapper_, 'is-visible');
    }

    /**
     * User had agreed the loading of additional javascript libs for marketing analyse
     * @private
     */
    handleClickAccept_()
    {
        //TODO: load accepted javascript libs for marketing analyse (matomo, analytics)

        this.setCookie_();
        this.securityProvider_.legalsAccepted = true;
        this.layerProvider_.hide('blocking');
        setTimeout(() => { classlist.add(this.getElement(), 'has-accepted') }, 1000);
    }

    /**
     * Checks the saved cookie agreements
     * @returns {Array<Element>}
     */
    getCookie()
    {
        let privacySettings = this.cookies_.get('gep_privacy_settings');
        let privacySettingItems = [];

        if(privacySettings)
        {
            privacySettingItems = /** @type {Array} */ (privacySettings.split(","));
            privacySettingItems.forEach((privacySettingItem, index) => {
                privacySettingItems[index] = privacySettingItem.split("_");
            });
        }

        return privacySettingItems;
    }

    /**
     * Saves the cookie settings
     * @private
     */
    setCookie_()
    {
        const currentDate = new Date();
        const currentDateString = currentDate.toLocaleDateString().replace(/\u200E/g, '').replace(/\u200F/g, '');
        const currentTimeString = currentDate.toLocaleTimeString().replace(/\u200E/g, '').replace(/\u200F/g, '');

        let newPrivacySettingsString = 'legals-'+this.legalsVersion_+'_accepted_' + currentDateString + '_' + currentTimeString;

        let maxAge = this.cookieLifetimeInDays_ * 24 * 60 * 60;
        let isSecure = window['location']['protocol'] === 'https:';
        let options = /** @type {Cookies.SetOptions} */({
            maxAge: maxAge,
            path: '/',
            sameSite: 'strict',
            secure: isSecure
        }) || undefined;

        this.cookies_.set('gep_privacy_settings', newPrivacySettingsString, options);
    }
}

exports = BlockingLayer;