src/components/VisitorProfile.js

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

const {Component} = goog.require('clulib.cm');

const {WorldProvider} = goog.require('gep.provider.WorldProvider');
const {ExhibitionProvider,ExhibitionEventType} = goog.require('gep.provider.ExhibitionProvider');

const {listen} = goog.require('goog.events');
const {createDom} = goog.require('goog.dom');
const classlist = goog.require('goog.dom.classlist');
const TagName = goog.require('goog.dom.TagName');
const {setStyle} = goog.require('goog.style');

/**
 * Component displays the tags and their values/importances by the collected preferences over {@Link ExhibitionProvider#addPreference} when entering activity zones.
 * Component is used from {@Link https://www.npmjs.com/package/clulib}
 * @extends {Component}
 */
class VisitorProfile extends Component
{
    constructor()
    {
        super();

        /**
         * Reference to ExhibitionProvider to communicate with the backend and provide and monitor all information that dynamically changes the application.
         * @type {ExhibitionProvider}
         * @private
         */
        this.exhibitionProvider_ = ExhibitionProvider.getInstance();

        /**
         * Reference to the WorldProvider for monitoring actions, loading processes and status changes of the created THREE.Scene.
         * @type {WorldProvider}
         * @private
         */
        this.worldProvider_ = WorldProvider.getInstance();

        /**
         *
         * @type {Map<string,{tag:Element,progress:Element,amount:Element}>}
         * @private
         */
        this.items_ = new Map();
    }

    /**
     * Component is ready and had loaded all dependencies (inherit method waitFor and sub components).
     * Checks if the exhibition data was loaded and
     * creates for each tag in the visitor profile a dom display element.
     * @inheritDoc
     */
    onInit()
    {
        super.onInit();

        this.exhibitionProvider_.ready().then(() => {
            this.exhibitionProvider_.visitor.profile.forEach((amount, tag) => {
                let tagEl = createDom(TagName.DIV, {'class': 'profile-preference-tag'}, tag);
                let progressBarEl = createDom(TagName.DIV, {'class': 'profile-preference-progress-bar'});
                let progressEl = createDom(TagName.DIV, {'class': 'profile-preference-progress'}, progressBarEl);
                let amountBarEl = createDom(TagName.DIV, {'class': 'profile-preference-amount-bar'});
                let amountEl = createDom(TagName.DIV, {'class': 'profile-preference-amount'}, amountBarEl);
                let row = createDom(TagName.DIV, {'class': 'profile-preference'}, [tagEl, progressEl, amountEl]);
                this.getElement().append(row);
                this.items_.set(tag, {tag: tagEl, progress: progressBarEl, amount: amountBarEl});
            });
            this.handleUpdatePreferences_();
            listen(this.exhibitionProvider_.visitor, ExhibitionEventType.UPDATE_VISITOR_PREFERENCE, this.handleUpdatePreferences_, false, this);
        });
    }

    /**
     * Handle event {@Link ExhibitionEventType} `UPDATE_VISITOR_PREFERENCE` update chages of the visitor profile
     * @private
     */
    handleUpdatePreferences_()
    {
        let activeExhibitTags = this.worldProvider_.activeExhibit ? this.exhibitionProvider_.items[this.worldProvider_.activeExhibit.id].tags : null;
        this.exhibitionProvider_.visitor.profile.forEach((amount, tag) => {
            let percentage = Math.round((amount / 10) * 10000) / 100;
            setStyle(this.items_.get(tag).progress, {'width': percentage + '%'});
            classlist.enable(this.items_.get(tag).progress, 'active', this.exhibitionProvider_.visitor.currentPreferenceHasTag(tag));
            percentage = activeExhibitTags ? Math.round((activeExhibitTags.get(tag) / 10) * 10000) / 100 : 0;
            setStyle(this.items_.get(tag).amount, {'width': percentage + '%'});
        });
    }
}

exports = VisitorProfile;