<commit_before>define([
    'js-utils/js/base-page',
    'find/app/model/entity-collection',
    'find/app/model/documents-collection',
    'find/app/model/indexes-collection',
    'find/app/router',
    'find/app/vent',
    'text!find/templates/app/page/find-search.html',
    'text!find/templates/app/page/results-container.html',
    'text!find/templates/app/page/suggestions-container.html',
    'text!find/templates/app/page/loading-spinner.html',
    'text!find/templates/app/page/colorbox-controls.html',
    'text!find/templates/app/page/index-popover-contents.html',
    'text!find/templates/app/page/top-results-popover-contents.html',
    'colorbox'
], function(BasePage, EntityCollection, DocumentsCollection, IndexesCollection, router, vent, template, resultsTemplate,
            suggestionsTemplate, loadingSpinnerTemplate, colorboxControlsTemplate, indexPopoverContents, topResultsPopoverContents) {

    return BasePage.extend({

        template: _.template(template),
        resultsTemplate: _.template(resultsTemplate),
        suggestionsTemplate: _.template(suggestionsTemplate),
        indexPopoverContents: _.template(indexPopoverContents),
        topResultsPopoverContents: _.template(topResultsPopoverContents),

        events: {
            'keyup .find-input': 'keyupAnimation',
            'click .list-indexes': function() {
               this.indexesCollection.fetch();
            },
            'change [name="indexRadios"]': function(e) {
                this.indexes = $(e.currentTarget).val();

                if(this.$('.find-input').val()){
                    this.searchRequest(this.$('.find-input').val());
                }
            },
            'mouseover .suggestions-content a': function(e) {
                this.topResultsCollection.fetch({
                    data: {
                        text: $(e.currentTarget).html(),
                        max_results: 3,
                        summary: 'quick',
                        indexes: this.indexes || 'wiki_eng'
                    }
                });
            },
            'mouseover .entity-to-summary': function(e) {
                var title = $(e.currentTarget).find('a').html();
                this.$('[data-title="'+ title +'"]').addClass('label label-primary entity-to-summary');
            },
            'mouseleave .entity-to-summary': function() {
                this.$('.suggestions-content li a').removeClass('label label-primary entity-to-summary');
            }
        },

        initialize: function() {
            this.entityCollection = new EntityCollection();
            this.documentsCollection = new DocumentsCollection();
            this.topResultsCollection = new DocumentsCollection();
            this.indexesCollection = new IndexesCollection();
            this.indexes = 'wiki_eng'; //hardcoding a default value

            this.keyupAnimation = _.debounce(_.bind(this.keyupAnimation, this), 200);

            router.on('route:search', function(text) {
                this.entityCollection.reset();
                this.documentsCollection.set([]);

                if (text) {
                    this.$('.find-input').val(text); //when clicking one of the suggested search links
                    this.keyupAnimation();
                } else {
                    this.reverseAnimation(); //when clicking the small 'find' logo
                }
            }, this);
        },

        render: function() {
            this.$el.html(this.template);

            this.$('.find-form').submit(function(e){ //preventing input form submit and page reload
                e.preventDefault();
            });

            this.$('.list-indexes').popover({
                html: true,
                content: '
Public Indexes
',
                placement: 'bottom'
            });

            /*indices popover*/
            this.listenTo(this.indexesCollection, 'request', function(){
                if(this.$('.find-form .popover-content').length==1) {
                    this.$('.find-form  .popover-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.indexesCollection, 'add', function(model){
                this.$('.find-form  .popover-content .loading-spinner').remove();

                this.$('.find-form .popover-content').append(this.indexPopoverContents({
                    index: model.get('index')
                }));

                model.get('index') == this.indexes ? this.$('[name="indexRadios"]').attr('checked', true): false;
            });

            /*top 3 results popover*/
            this.listenTo(this.topResultsCollection, 'request', function(){
                this.$('.suggestion-cluster  .popover-content').append(_.template(loadingSpinnerTemplate));
            });

            this.listenTo(this.topResultsCollection, 'add', function(model){
                this.$('.suggestion-cluster .popover-content .loading-spinner').remove();

                this.$('.suggestion-cluster .popover-content').append(this.topResultsPopoverContents({
                    title: model.get('title'),
                    summary: $.trim(model.get('summary')).substring(0, 100).trim(this) + "..."
                }));
            });

            /*suggested links*/
            this.listenTo(this.entityCollection, 'request', function() {
                if(!this.$('.suggestions-content ul').length) {
                    this.$('.suggestions-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.entityCollection, 'reset', function() {
                this.$('.suggestions-content').empty();

                var clusters = this.entityCollection.groupBy('cluster');

                _.each(clusters, function(entities) {
                    this.$('.suggestions-content').append(this.suggestionsTemplate({
                        entities: entities
                    }));

                    this.$('.suggestion-cluster li a').popover({
                        html: true,
                        content: '
Top Results
',
                        placement: 'right',
                        trigger: 'hover'
                    })
                }, this);

                this.documentsCollection.each(function(document) {
                    var summary = this.addLinksToSummary(document.get('summary'));

                    this.$('[data-reference="' + document.get('reference') + '"] .result-summary').html(summary);
                }, this);
            });

            /*main results content*/
            this.listenTo(this.documentsCollection, 'request', function() {
                if(!this.$('.main-results-container').length) {
                    this.$('.main-results-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.documentsCollection, 'add', function(model) {
                var reference = model.get('reference');
                var summary = model.get('summary');

                summary = this.addLinksToSummary(summary);

                this.$('.main-results-content .loading-spinner').remove();

                var $newResult = $(_.template(resultsTemplate ,{
                    title: model.get('title'),
                    reference: reference,
                    index: model.get('index'),
                    summary: summary
                }));

                this.$('.main-results-content').append($newResult);

                $newResult.find('.result-header').colorbox({
                    iframe: true,
                    width:'70%',
                    height:'70%',
                    href: reference,
                    rel: 'results',
                    current: '{current} of {total}',
                    onLoad: function() {
                        $('#cboxPrevious, #cboxNext').remove(); //removing default colorbox nav buttons
                    }
                });

                $newResult.find('.dots').click(function (e) {
                    e.preventDefault();
                    $newResult.find('.result-header').trigger('click'); //dot-dot-dot triggers the colorbox event
                });
            });

            this.listenTo(this.documentsCollection, 'remove', function(model) {
                var reference = model.get('reference');

                this.$('[data-reference="' + reference + '"]').remove();
            });

            /*colorbox fancy button override*/
            $('#colorbox').append(_.template(colorboxControlsTemplate));
            $('.nextBtn').on('click', this.handleNextResult);
            $('.prevBtn').on('click', this.handlePrevResult);
        },

        addLinksToSummary: function(summary) {
            //creating an array of the entity titles, longest first
            var entities = this.entityCollection.map(function(entity) {
                return {
                    text: entity.get('text'),
                    id:  _.uniqueId()
                }
            }).sort(function(a,b) {
                return b.text.length - a.text.length;
            });

            _.each(entities, function(entity) {
                summary = summary.replace(new RegExp(entity.text, 'gi'), entity.id)
            });

            _.each(entities, function(entity) {
                summary = summary.replace(new RegExp(entity.id, 'g'), '' + entity.text + '');
            });

            return summary;
        },

        keyupAnimation: function() {
            /*fancy animation*/
            if($.trim(this.$('.find-input').val()).length) { //checking if input doesn't have any spaces or empty
                this.$('.find-logo').slideUp('slow');
                this.$('.find').addClass('animated-container').removeClass('reverse-animated-container');
                this.$('.form-search').addClass('animated-form').removeClass('reverse-animated-form');

                this.$('.suggested-links-container.span2, .find-logo-small').show();
                this.searchRequest(this.$('.find-input').val());
            } else {
                this.reverseAnimation();
                vent.navigate('find/find-search', {trigger: false});
                this.$('.main-results-content').empty();
            }
            this.$('.popover').remove();
        },

        handlePrevResult: function() {
            $.colorbox.prev();
        },

        handleNextResult: function() {
            $.colorbox.next();
        },

        reverseAnimation: function() {
            /*fancy reverse animation*/
            this.$('.find-logo').slideDown('slow');
            this.$('.find').removeClass('animated-container ').addClass('reverse-animated-container');
            this.$('.form-search').removeClass('animated-form').addClass('reverse-animated-form');

            this.$('.suggested-links-container.span2, .find-logo-small').hide();
            this.$('.find-input').val('');
            this.$('.popover').remove();
        },

        searchRequest: function(input) {
            this.documentsCollection.fetch({
                data: {
                    text: input,
                    max_results: 30,
                    summary: 'quick',
                    indexes: this.indexes || 'wiki_eng'
                }
            }, this);

            this.entityCollection.fetch({
                data: {
                    text: input,
                    indexes: this.indexes || 'wiki_eng'
                }
            });

            vent.navigate('find/find-search/' + encodeURIComponent(input), {trigger: false});
        }
    });
});<commit_msg>highlighting all the text phrases in the main results if they match suggested list phrases on mouseover<commit_after>define([
    'js-utils/js/base-page',
    'find/app/model/entity-collection',
    'find/app/model/documents-collection',
    'find/app/model/indexes-collection',
    'find/app/router',
    'find/app/vent',
    'text!find/templates/app/page/find-search.html',
    'text!find/templates/app/page/results-container.html',
    'text!find/templates/app/page/suggestions-container.html',
    'text!find/templates/app/page/loading-spinner.html',
    'text!find/templates/app/page/colorbox-controls.html',
    'text!find/templates/app/page/index-popover-contents.html',
    'text!find/templates/app/page/top-results-popover-contents.html',
    'colorbox'
], function(BasePage, EntityCollection, DocumentsCollection, IndexesCollection, router, vent, template, resultsTemplate,
            suggestionsTemplate, loadingSpinnerTemplate, colorboxControlsTemplate, indexPopoverContents, topResultsPopoverContents) {

    return BasePage.extend({

        template: _.template(template),
        resultsTemplate: _.template(resultsTemplate),
        suggestionsTemplate: _.template(suggestionsTemplate),
        indexPopoverContents: _.template(indexPopoverContents),
        topResultsPopoverContents: _.template(topResultsPopoverContents),

        events: {
            'keyup .find-input': 'keyupAnimation',
            'click .list-indexes': function() {
               this.indexesCollection.fetch();
            },
            'change [name="indexRadios"]': function(e) {
                this.indexes = $(e.currentTarget).val();

                if(this.$('.find-input').val()){
                    this.searchRequest(this.$('.find-input').val());
                }
            },
            'mouseover .suggestions-content a': function(e) {
                this.topResultsCollection.fetch({
                    data: {
                        text: $(e.currentTarget).html(),
                        max_results: 3,
                        summary: 'quick',
                        indexes: this.indexes || 'wiki_eng'
                    }
                });
            },
            'mouseover .entity-to-summary': function(e) {
                var title = $(e.currentTarget).find('a').html();
                this.$('[data-title="'+ title +'"]').addClass('label label-primary entity-to-summary').removeClass('label-info');
            },
            'mouseleave .entity-to-summary': function() {
                this.$('.suggestions-content li a').removeClass('label label-primary entity-to-summary');
                this.$('.main-results-content .entity-to-summary').removeClass('label-primary').addClass('label-info');
            }
        },

        initialize: function() {
            this.entityCollection = new EntityCollection();
            this.documentsCollection = new DocumentsCollection();
            this.topResultsCollection = new DocumentsCollection();
            this.indexesCollection = new IndexesCollection();
            this.indexes = 'wiki_eng'; //hardcoding a default value

            this.keyupAnimation = _.debounce(_.bind(this.keyupAnimation, this), 200);

            router.on('route:search', function(text) {
                this.entityCollection.reset();
                this.documentsCollection.set([]);

                if (text) {
                    this.$('.find-input').val(text); //when clicking one of the suggested search links
                    this.keyupAnimation();
                } else {
                    this.reverseAnimation(); //when clicking the small 'find' logo
                }
            }, this);
        },

        render: function() {
            this.$el.html(this.template);

            this.$('.find-form').submit(function(e){ //preventing input form submit and page reload
                e.preventDefault();
            });

            this.$('.list-indexes').popover({
                html: true,
                content: '
Public Indexes
',
                placement: 'bottom'
            });

            /*indices popover*/
            this.listenTo(this.indexesCollection, 'request', function(){
                if(this.$('.find-form .popover-content').length==1) {
                    this.$('.find-form  .popover-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.indexesCollection, 'add', function(model){
                this.$('.find-form  .popover-content .loading-spinner').remove();

                this.$('.find-form .popover-content').append(this.indexPopoverContents({
                    index: model.get('index')
                }));

                model.get('index') == this.indexes ? this.$('[name="indexRadios"]').attr('checked', true): false;
            });

            /*top 3 results popover*/
            this.listenTo(this.topResultsCollection, 'request', function(){
                this.$('.suggestion-cluster  .popover-content').append(_.template(loadingSpinnerTemplate));
            });

            this.listenTo(this.topResultsCollection, 'add', function(model){
                this.$('.suggestion-cluster .popover-content .loading-spinner').remove();

                this.$('.suggestion-cluster .popover-content').append(this.topResultsPopoverContents({
                    title: model.get('title'),
                    summary: $.trim(model.get('summary')).substring(0, 100).trim(this) + "..."
                }));
            });

            /*suggested links*/
            this.listenTo(this.entityCollection, 'request', function() {
                if(!this.$('.suggestions-content ul').length) {
                    this.$('.suggestions-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.entityCollection, 'reset', function() {
                this.$('.suggestions-content').empty();

                var clusters = this.entityCollection.groupBy('cluster');

                _.each(clusters, function(entities) {
                    this.$('.suggestions-content').append(this.suggestionsTemplate({
                        entities: entities
                    }));

                    this.$('.suggestion-cluster li a').popover({
                        html: true,
                        content: '
Top Results
',
                        placement: 'right',
                        trigger: 'hover'
                    })
                }, this);

                this.documentsCollection.each(function(document) {
                    var summary = this.addLinksToSummary(document.get('summary'));

                    this.$('[data-reference="' + document.get('reference') + '"] .result-summary').html(summary);
                }, this);
            });

            /*main results content*/
            this.listenTo(this.documentsCollection, 'request', function() {
                if(!this.$('.main-results-container').length) {
                    this.$('.main-results-content').append(_.template(loadingSpinnerTemplate));
                }
            });

            this.listenTo(this.documentsCollection, 'add', function(model) {
                var reference = model.get('reference');
                var summary = model.get('summary');

                summary = this.addLinksToSummary(summary);

                this.$('.main-results-content .loading-spinner').remove();

                var $newResult = $(_.template(resultsTemplate ,{
                    title: model.get('title'),
                    reference: reference,
                    index: model.get('index'),
                    summary: summary
                }));

                this.$('.main-results-content').append($newResult);

                $newResult.find('.result-header').colorbox({
                    iframe: true,
                    width:'70%',
                    height:'70%',
                    href: reference,
                    rel: 'results',
                    current: '{current} of {total}',
                    onLoad: function() {
                        $('#cboxPrevious, #cboxNext').remove(); //removing default colorbox nav buttons
                    }
                });

                $newResult.find('.dots').click(function (e) {
                    e.preventDefault();
                    $newResult.find('.result-header').trigger('click'); //dot-dot-dot triggers the colorbox event
                });
            });

            this.listenTo(this.documentsCollection, 'remove', function(model) {
                var reference = model.get('reference');

                this.$('[data-reference="' + reference + '"]').remove();
            });

            /*colorbox fancy button override*/
            $('#colorbox').append(_.template(colorboxControlsTemplate));
            $('.nextBtn').on('click', this.handleNextResult);
            $('.prevBtn').on('click', this.handlePrevResult);
        },

        addLinksToSummary: function(summary) {
            //creating an array of the entity titles, longest first
            var entities = this.entityCollection.map(function(entity) {
                return {
                    text: entity.get('text'),
                    id:  _.uniqueId()
                }
            }).sort(function(a,b) {
                return b.text.length - a.text.length;
            });

            _.each(entities, function(entity) {
                summary = summary.replace(new RegExp(entity.text, 'gi'), entity.id)
            });

            _.each(entities, function(entity) {
                summary = summary.replace(new RegExp(entity.id, 'g'), '' + entity.text + '');
            });

            return summary;
        },

        keyupAnimation: function() {
            /*fancy animation*/
            if($.trim(this.$('.find-input').val()).length) { //checking if input doesn't have any spaces or empty
                this.$('.find-logo').slideUp('slow');
                this.$('.find').addClass('animated-container').removeClass('reverse-animated-container');
                this.$('.form-search').addClass('animated-form').removeClass('reverse-animated-form');

                this.$('.suggested-links-container.span2, .find-logo-small').show();
                this.searchRequest(this.$('.find-input').val());
            } else {
                this.reverseAnimation();
                vent.navigate('find/find-search', {trigger: false});
                this.$('.main-results-content').empty();
            }
            this.$('.popover').remove();
        },

        handlePrevResult: function() {
            $.colorbox.prev();
        },

        handleNextResult: function() {
            $.colorbox.next();
        },

        reverseAnimation: function() {
            /*fancy reverse animation*/
            this.$('.find-logo').slideDown('slow');
            this.$('.find').removeClass('animated-container ').addClass('reverse-animated-container');
            this.$('.form-search').removeClass('animated-form').addClass('reverse-animated-form');

            this.$('.suggested-links-container.span2, .find-logo-small').hide();
            this.$('.find-input').val('');
            this.$('.popover').remove();
        },

        searchRequest: function(input) {
            this.documentsCollection.fetch({
                data: {
                    text: input,
                    max_results: 30,
                    summary: 'quick',
                    indexes: this.indexes || 'wiki_eng'
                }
            }, this);

            this.entityCollection.fetch({
                data: {
                    text: input,
                    indexes: this.indexes || 'wiki_eng'
                }
            });

            vent.navigate('find/find-search/' + encodeURIComponent(input), {trigger: false});
        }
    });
});<|endoftext|>


<commit_before>var FileDetector = function(){
	var me = {};

	var fileType = {
		unknown: {name: "UNKNOWN"},
		unsupported: {name: "UNSUPPORTED"},
		mod_ProTracker: {name: "PROTRACKER", isMod: true, loader: function(){return ProTracker()}},
		mod_SoundTracker: {name: "SOUNDTRACKER", isMod: true, loader: function(){return SoundTracker()}},
		mod_FastTracker: {name: "FASTTRACKER", isMod: true, loader: function(){return FastTracker()}},
		sample: {name: "SAMPLE",isSample:true},
		zip: {name: "ZIP"}
	};

	me.detect = function(file,name){
		var length = file.length;
		var id = "";

		id = file.readString(17,0);
		if (id == "Extended Module: "){
			//return fileType.mod_FastTracker;
			alert("Sorry, FastTracker XM files are not supported yet ... working on it.");
			return fileType.unsupported;
		}

		if (length>1100){
			id = file.readString(4,1080); // M.K.
		}
		console.log("Format ID: " + id);

		if (id == "M.K.") return fileType.mod_ProTracker;
		if (id == "FLT4") return fileType.mod_ProTracker;
		if (id == "8CHN") return fileType.mod_ProTracker;

		var ext = "";
		if (name && name.length>4) ext = name.substr(name.length-4);
		ext = ext.toLowerCase();

		if (ext == ".wav") return fileType.sample;
		if (ext == ".mp3") return fileType.sample;
		if (ext == ".iff") return fileType.sample;
		if (ext == ".zip") return fileType.zip;

		var zipId = file.readString(2,0);
		if (zipId == "PK") return fileType.zip;

		// might be an 15 instrument mod?
		// filename should at least contain a "." this avoids checking all ST-XX samples

		// example: https://modarchive.org/index.php?request=view_by_moduleid&query=35902
		// more info: ftp://ftp.modland.com/pub/documents/format_documentation/Ultimate%20Soundtracker%20(.mod).txt

		if (name && name.indexOf(".")>=0 && length>1624){
			// check for ascii
			function isAcii(byte){
				return (byte == 0) || (byte>31 && byte<128);
			}

			function isST(){
				file.goto(0);
				for (var i = 0; i<20;i++) if (!isAcii(file.readByte())) return false;

				// check samples
				var totalSampleLength = 0;
				for (var s = 0; s<15;s++) {
					for (i = 0; i<22;i++) if (!isAcii(file.readByte())) return false;
					totalSampleLength += file.readWord();
					file.jump(6);
				}

				if (totalSampleLength*2 + 1624 > length) return false;

				return true;
			}

			var isSoundTracker = isST();
			if (isSoundTracker){
				return fileType.mod_SoundTracker;
			}
		}

		// fallback to sample
		return fileType.sample;

	};

	return me;
}();<commit_msg>Also allow mods with id "M&K!"<commit_after>var FileDetector = function(){
	var me = {};

	var fileType = {
		unknown: {name: "UNKNOWN"},
		unsupported: {name: "UNSUPPORTED"},
		mod_ProTracker: {name: "PROTRACKER", isMod: true, loader: function(){return ProTracker()}},
		mod_SoundTracker: {name: "SOUNDTRACKER", isMod: true, loader: function(){return SoundTracker()}},
		mod_FastTracker: {name: "FASTTRACKER", isMod: true, loader: function(){return FastTracker()}},
		sample: {name: "SAMPLE",isSample:true},
		zip: {name: "ZIP"}
	};

	me.detect = function(file,name){
		var length = file.length;
		var id = "";

		id = file.readString(17,0);
		if (id == "Extended Module: "){
			//return fileType.mod_FastTracker;
			alert("Sorry, FastTracker XM files are not supported yet ... working on it.");
			return fileType.unsupported;
		}

		if (length>1100){
			id = file.readString(4,1080); // M.K.
		}
		console.log("Format ID: " + id);

		if (id == "M.K.") return fileType.mod_ProTracker;
		if (id == "M&K!") return fileType.mod_ProTracker; // what's different? example https://modarchive.org/index.php?request=view_by_moduleid&query=76607
		if (id == "FLT4") return fileType.mod_ProTracker;
		if (id == "8CHN") return fileType.mod_ProTracker;

		var ext = "";
		if (name && name.length>4) ext = name.substr(name.length-4);
		ext = ext.toLowerCase();

		if (ext == ".wav") return fileType.sample;
		if (ext == ".mp3") return fileType.sample;
		if (ext == ".iff") return fileType.sample;
		if (ext == ".zip") return fileType.zip;

		var zipId = file.readString(2,0);
		if (zipId == "PK") return fileType.zip;

		// might be an 15 instrument mod?
		// filename should at least contain a "." this avoids checking all ST-XX samples

		// example: https://modarchive.org/index.php?request=view_by_moduleid&query=35902
		// more info: ftp://ftp.modland.com/pub/documents/format_documentation/Ultimate%20Soundtracker%20(.mod).txt

		if (name && name.indexOf(".")>=0 && length>1624){
			// check for ascii
			function isAcii(byte){
				return (byte == 0) || (byte>31 && byte<128);
			}

			function isST(){
				file.goto(0);
				for (var i = 0; i<20;i++) if (!isAcii(file.readByte())) return false;

				// check samples
				var totalSampleLength = 0;
				for (var s = 0; s<15;s++) {
					for (i = 0; i<22;i++) if (!isAcii(file.readByte())) return false;
					totalSampleLength += file.readWord();
					file.jump(6);
				}

				if (totalSampleLength*2 + 1624 > length) return false;

				return true;
			}

			var isSoundTracker = isST();
			if (isSoundTracker){
				return fileType.mod_SoundTracker;
			}
		}

		// fallback to sample
		return fileType.sample;

	};

	return me;
}();<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var Q = require('q'),
    EventEmitter = require('events'),
    _ = require('busyman'),
    Ziee = require('ziee'),
    ZSC = require('zstack-constants'),
    debug = {
        shepherd: require('debug')('zigbee-shepherd'),
        init: require('debug')('zigbee-shepherd:init'),
        request: require('debug')('zigbee-shepherd:request'),
    };

var Device = require('../model/device'),
    Endpoint = require('../model/endpoint');

var handlers = {};

handlers.attachEventHandlers = function (shepherd) {
    var controller = shepherd.controller,
        hdls = {};

    _.forEach(handlers, function (hdl, key) {
        if (key !== 'attachEventHandlers')
            hdls[key] = hdl.bind(shepherd);
    });

    controller.removeListener('SYS:resetInd',          hdls.resetInd);
    controller.removeListener('ZDO:devIncoming',       hdls.devIncoming);
    controller.removeListener('ZDO:tcDeviceInd',       hdls.tcDeviceInd);
    controller.removeListener('ZDO:stateChangeInd',    hdls.stateChangeInd);
    controller.removeListener('ZDO:matchDescRspSent',  hdls.matchDescRspSent);
    controller.removeListener('ZDO:statusErrorRsp',    hdls.statusErrorRsp);
    controller.removeListener('ZDO:srcRtgInd',         hdls.srcRtgInd);
    controller.removeListener('ZDO:beacon_notify_ind', hdls.beacon_notify_ind);
    controller.removeListener('ZDO:leaveInd',          hdls.leaveInd);
    controller.removeListener('ZDO:msgCbIncoming',     hdls.msgCbIncoming);
    controller.removeListener('ZDO:serverDiscRsp',     hdls.serverDiscRsp);
    // controller.removeListener('ZDO:permitJoinInd',     hdls.permitJoinInd);

    controller.on('SYS:resetInd',          hdls.resetInd);
    controller.on('ZDO:devIncoming',       hdls.devIncoming);
    controller.on('ZDO:tcDeviceInd',       hdls.tcDeviceInd);
    controller.on('ZDO:stateChangeInd',    hdls.stateChangeInd);
    controller.on('ZDO:matchDescRspSent',  hdls.matchDescRspSent);
    controller.on('ZDO:statusErrorRsp',    hdls.statusErrorRsp);
    controller.on('ZDO:srcRtgInd',         hdls.srcRtgInd);
    controller.on('ZDO:beacon_notify_ind', hdls.beacon_notify_ind);
    controller.on('ZDO:leaveInd',          hdls.leaveInd);
    controller.on('ZDO:msgCbIncoming',     hdls.msgCbIncoming);
    controller.on('ZDO:serverDiscRsp',     hdls.serverDiscRsp);
    // controller.on('ZDO:permitJoinInd',     hdls.permitJoinInd);
};

/*************************************************************************************************/
/*** Event Handlers                                                                            ***/
/*************************************************************************************************/
handlers.resetInd = function (msg) {
    var self = this;

    if (this.controller.isResetting()) return;

    if (msg !== '_reset')
        debug.shepherd('Starting a software reset...');

    this.stop().then(function () {
        return self.start();
    }).then(function () {
        if (msg === '_reset')
            return self.controller.emit('_reset');
    }).fail(function (err) {
        if (msg === '_reset') {
            return self.controller.emit('_reset', err);
        } else {
            debug.shepherd('Reset had an error', err);
            self.emit('error', err);
        }
    }).done();
};

handlers.devIncoming = function (devInfo, resolve) {
    // devInfo: { type, ieeeAddr, nwkAddr, manufId, epList, endpoints: [ simpleDesc, ... ] }
    var self = this,
        dev = this._findDevByAddr(devInfo.ieeeAddr),
        clustersReqs = [];

    function syncEndpoints(dev) {
		var endpoints = devInfo.endpoints;
		if(endpoints.forEach){
			devInfo.endpoints.forEach(function (simpleDesc) {
				var ep = dev.getEndpoint(simpleDesc.epId);

				if (ep) {
					ep.update(simpleDesc);
				} else {
					ep = new Endpoint(dev, simpleDesc);
					ep.clusters = new Ziee();
					self._attachZclMethods(ep);
					dev.endpoints[ep.getEpId()] = ep;
				}
			});
		}else{
			for(var i in endpoints){
				self._attachZclMethods(endpoints[i]);
			}

			return true;
		}

		return false;
    }

    var isFullEps = false;
    var processDev = Q.fcall(function () {
        if (dev) {
            dev.update(devInfo);
            dev.update({ status: 'online', joinTime: Math.floor(Date.now()/1000) });
            isFullEps = syncEndpoints(dev);
            return dev;
        } else {
            dev = new Device(devInfo);
            dev.update({ status: 'online' });
            isFullEps = syncEndpoints(dev);
            return self._registerDev(dev).then(function () {
                return dev;
            });
        }
    }).then(function(dev) {
        if (!dev || !dev.hasOwnProperty('endpoints')) return dev;

        // Try genBasic interview, not certain if it works for all devices
        try {
            var attrMap = {
                4: 'manufName',
                5: 'modelId',
                7: 'powerSource'
            };

            var powerSourceMap = {
                0: 'Unknown',
                1: 'Mains (single phase)',
                2: 'Mains (3 phase)',
                3: 'Battery',
                4: 'DC Source',
                5: 'Emergency mains constantly powered',
                6: 'Emergency mains and transfer switch'
            };

            // Loop all endpoints to find genBasic cluster, and get basic endpoint if possible
            var basicEpInst;

            for (var i in dev.endpoints) {
                var ep = dev.getEndpoint(i),
                    clusterList = ep.getClusterList();

                if (_.isArray(clusterList) && clusterList.indexOf(0) > -1) {
                    // genBasic found
                    basicEpInst = ep;
                    break;
                }
            }

            if (!basicEpInst || basicEpInst instanceof Error) return dev;

            // Get manufName, modelId and powerSource information
            return self.af.zclFoundation(basicEpInst, basicEpInst, 0, 'read', [{ attrId: 4 }, { attrId: 5 }, { attrId: 7 }]).then(function (readStatusRecsRsp) {
                var data = {};
                if (readStatusRecsRsp && _.isArray(readStatusRecsRsp.payload)) {
                    readStatusRecsRsp.payload.forEach(function(item){  // { attrId, status, dataType, attrData }
                        if (item && item.hasOwnProperty('attrId') && item.hasOwnProperty('attrData')) {
                            if (item.attrId === 7)
                                data[attrMap[item.attrId]] = powerSourceMap[item.attrData];
                            else
                                data[attrMap[item.attrId]] = item.attrData;
                        }
                    });
                }

                // Update dev
                dev.update(data);

                debug.shepherd('Identified Device: { manufacturer: %s, product: %s }', data.manufName, data.modelId);

                // Save device
                return Q.ninvoke(self._devbox, 'sync', dev._getId()).then(function () {
                    return dev;
                });
            }).catch(function(){
                return dev;
            });
        } catch (err) {
            return dev;
        }
    })
    .then(function (dev) {
        if (_.isFunction(self.acceptDevInterview)) {
            var info = {
                ieeeAddr: dev.getIeeeAddr(),
                dev: dev
            };

            return Q.ninvoke(self, 'acceptDevInterview', info).timeout(60000).then(function(result){
                if(result) return dev
            })
        } else {
            return dev;
        }
    })
    .then(function (dev) {
        if(!dev) return dev

        const checkClusters = Object.values(dev.endpoints)
                               .some(function(ep){return Object.keys(ep.clusters).length > 1});
        if(isFullEps && checkClusters){
            return dev;
        }
        var numberOfEndpoints = _.keys(dev.endpoints).length;

        var interviewEvents = new EventEmitter();
        interviewEvents.on('ind:interview', function(status) {
            if (status && status.endpoint) status.endpoint.total = numberOfEndpoints;
            self.emit('ind:interview', dev.ieeeAddr, status);
        });

        _.forEach(dev.endpoints, function (ep) {
            // if (ep.isZclSupported())
            clustersReqs.push(function () {
                return self.af.zclClustersReq(ep, interviewEvents).then(function (clusters) {
                    _.forEach(clusters, function (cInfo, cid) {
                        ep.clusters.init(cid, 'dir', { value: cInfo.dir });
                        ep.clusters.init(cid, 'attrs', cInfo.attrs, false);
                    });
                });
            });
        });

        return clustersReqs.reduce(function (soFar, fn) {
            return soFar.then(fn);
        }, Q(0)).then(function(){return true});
    }).then(function (previous_accept) {
        if(!previous_accept) return false
        if (_.isFunction(self.acceptDevIncoming)) {
            var info = {
                ieeeAddr: dev.getIeeeAddr(),
                endpoints: []
            };

            _.forEach(dev.epList, function (epId) {
                info.endpoints.push(dev.getEndpoint(epId));
            });

            return Q.ninvoke(self, 'acceptDevIncoming', info).timeout(60000);
        } else {
            return true;
        }
    }).then(function (accepted) {
        if (accepted) {
            Q.ninvoke(self._devbox, 'sync', dev._getId());
            debug.shepherd('Device: %s join the network.', dev.getIeeeAddr());

            self.emit('ind:incoming', dev);
            self.emit('ind:status', dev, 'online');
            self.controller.emit('ind:incoming' + ':' + dev.getIeeeAddr());
        } else {
            self.remove(dev.getIeeeAddr(), { reJoin: true }).then(function () {
                Q.ninvoke(self._devbox, 'remove', dev._getId());
            }, function(err){
                Q.ninvoke(self._devbox, 'remove', dev._getId());
            });
        }
    }).fail(function (err) {
		self.remove(dev.getIeeeAddr(), { reJoin: true }).then(function (err) {
			if(err){
				self.remove(dev.getIeeeAddr(), { reJoin: true }).then(function (err) {
					Q.ninvoke(self._devbox, 'remove', dev._getId());
				});
			}else{
				Q.ninvoke(self._devbox, 'remove', dev._getId());
			}
		});

        self.emit('error', err);
    });

    if (typeof resolve === 'function') {
        resolve(processDev);
    }

    processDev.done();
};

handlers.leaveInd = function (msg) {
    // { srcaddr, extaddr, request, removechildren, rejoin }
    var dev = this._findDevByAddr(msg.extaddr);

    if (dev) {
        var ieeeAddr = dev.getIeeeAddr(),
            epList = _.cloneDeep(dev.epList);

        if (msg.request)    // request
            this._unregisterDev(dev);
        else                // indication
            this._devbox.remove(dev._getId(), function () {});

        debug.shepherd('Device: %s leave the network.', ieeeAddr);
        this.emit('ind:leaving', epList, ieeeAddr);
    }
};

handlers.stateChangeInd = function (msg) {
    // { state[, nwkaddr] }
    if (!msg.hasOwnProperty('nwkaddr'))
        return;

    var devStates = msg.state;

    _.forEach(ZSC.ZDO.devStates, function (statesCode, states) {
        if (msg.state === statesCode)
            devStates = states;
    });

    debug.shepherd('Device: %d is now in state: %s', msg.nwkaddr, devStates);
};

handlers.statusErrorRsp = function (msg) {
    // { srcaddr, status }
    debug.shepherd('Device: %d status error: %d', msg.srcaddr, msg.status);
};

handlers.tcDeviceInd = function (msg) {
    // { nwkaddr, extaddr, parentaddr }
};

handlers.matchDescRspSent = function (msg) {
    // { nwkaddr, numinclusters, inclusterlist, numoutclusters, outclusterlist }
};

handlers.srcRtgInd = function (msg) {
    // { dstaddr, relaycount, relaylist }
};

handlers.beacon_notify_ind = function (msg) {
    // { beaconcount, beaconlist }
};

handlers.msgCbIncoming = function (msg) {
    // { srcaddr, wasbroadcast, clusterid, securityuse, seqnum, macdstaddr, msgdata }
};

handlers.serverDiscRsp = function (msg) {
    // { srcaddr, status, servermask }
};

module.exports = handlers;
<commit_msg>fixes<commit_after>/* jshint node: true */
'use strict';

var Q = require('q'),
    EventEmitter = require('events'),
    _ = require('busyman'),
    Ziee = require('ziee'),
    ZSC = require('zstack-constants'),
    debug = {
        shepherd: require('debug')('zigbee-shepherd'),
        init: require('debug')('zigbee-shepherd:init'),
        request: require('debug')('zigbee-shepherd:request'),
    };

var Device = require('../model/device'),
    Endpoint = require('../model/endpoint');

var handlers = {};

handlers.attachEventHandlers = function (shepherd) {
    var controller = shepherd.controller,
        hdls = {};

    _.forEach(handlers, function (hdl, key) {
        if (key !== 'attachEventHandlers')
            hdls[key] = hdl.bind(shepherd);
    });

    controller.removeListener('SYS:resetInd',          hdls.resetInd);
    controller.removeListener('ZDO:devIncoming',       hdls.devIncoming);
    controller.removeListener('ZDO:tcDeviceInd',       hdls.tcDeviceInd);
    controller.removeListener('ZDO:stateChangeInd',    hdls.stateChangeInd);
    controller.removeListener('ZDO:matchDescRspSent',  hdls.matchDescRspSent);
    controller.removeListener('ZDO:statusErrorRsp',    hdls.statusErrorRsp);
    controller.removeListener('ZDO:srcRtgInd',         hdls.srcRtgInd);
    controller.removeListener('ZDO:beacon_notify_ind', hdls.beacon_notify_ind);
    controller.removeListener('ZDO:leaveInd',          hdls.leaveInd);
    controller.removeListener('ZDO:msgCbIncoming',     hdls.msgCbIncoming);
    controller.removeListener('ZDO:serverDiscRsp',     hdls.serverDiscRsp);
    // controller.removeListener('ZDO:permitJoinInd',     hdls.permitJoinInd);

    controller.on('SYS:resetInd',          hdls.resetInd);
    controller.on('ZDO:devIncoming',       hdls.devIncoming);
    controller.on('ZDO:tcDeviceInd',       hdls.tcDeviceInd);
    controller.on('ZDO:stateChangeInd',    hdls.stateChangeInd);
    controller.on('ZDO:matchDescRspSent',  hdls.matchDescRspSent);
    controller.on('ZDO:statusErrorRsp',    hdls.statusErrorRsp);
    controller.on('ZDO:srcRtgInd',         hdls.srcRtgInd);
    controller.on('ZDO:beacon_notify_ind', hdls.beacon_notify_ind);
    controller.on('ZDO:leaveInd',          hdls.leaveInd);
    controller.on('ZDO:msgCbIncoming',     hdls.msgCbIncoming);
    controller.on('ZDO:serverDiscRsp',     hdls.serverDiscRsp);
    // controller.on('ZDO:permitJoinInd',     hdls.permitJoinInd);
};

/*************************************************************************************************/
/*** Event Handlers                                                                            ***/
/*************************************************************************************************/
handlers.resetInd = function (msg) {
    var self = this;

    if (this.controller.isResetting()) return;

    if (msg !== '_reset')
        debug.shepherd('Starting a software reset...');

    this.stop().then(function () {
        return self.start();
    }).then(function () {
        if (msg === '_reset')
            return self.controller.emit('_reset');
    }).fail(function (err) {
        if (msg === '_reset') {
            return self.controller.emit('_reset', err);
        } else {
            debug.shepherd('Reset had an error', err);
            self.emit('error', err);
        }
    }).done();
};

handlers.devIncoming = function (devInfo, resolve) {
    // devInfo: { type, ieeeAddr, nwkAddr, manufId, epList, endpoints: [ simpleDesc, ... ] }
    var self = this,
        dev = this._findDevByAddr(devInfo.ieeeAddr),
        clustersReqs = [];

    function syncEndpoints(dev) {
		var endpoints = devInfo.endpoints;
		if(endpoints.forEach){
			devInfo.endpoints.forEach(function (simpleDesc) {
				var ep = dev.getEndpoint(simpleDesc.epId);

				if (ep) {
					ep.update(simpleDesc);
				} else {
					ep = new Endpoint(dev, simpleDesc);
					ep.clusters = new Ziee();
					self._attachZclMethods(ep);
					dev.endpoints[ep.getEpId()] = ep;
				}
			});
		}else{
			for(var i in endpoints){
				self._attachZclMethods(endpoints[i]);
			}

			return true;
		}

		return false;
    }

    var isFullEps = false;
    var processDev = Q.fcall(function () {
        if (dev) {
            dev.update(devInfo);
            dev.update({ status: 'online', joinTime: Math.floor(Date.now()/1000) });
            isFullEps = syncEndpoints(dev);
            return dev;
        } else {
            dev = new Device(devInfo);
            dev.update({ status: 'online' });
            isFullEps = syncEndpoints(dev);
            return self._registerDev(dev).then(function () {
                return dev;
            });
        }
    }).then(function(dev) {
        if (!dev || !dev.hasOwnProperty('endpoints')) return dev;

        // Try genBasic interview, not certain if it works for all devices
        try {
            var attrMap = {
                4: 'manufName',
                5: 'modelId',
                7: 'powerSource'
            };

            var powerSourceMap = {
                0: 'Unknown',
                1: 'Mains (single phase)',
                2: 'Mains (3 phase)',
                3: 'Battery',
                4: 'DC Source',
                5: 'Emergency mains constantly powered',
                6: 'Emergency mains and transfer switch'
            };

            // Loop all endpoints to find genBasic cluster, and get basic endpoint if possible
            var basicEpInst;

            for (var i in dev.endpoints) {
                var ep = dev.getEndpoint(i),
                    clusterList = ep.getClusterList();

                if (_.isArray(clusterList) && clusterList.indexOf(0) > -1) {
                    // genBasic found
                    basicEpInst = ep;
                    break;
                }
            }

            if (!basicEpInst || basicEpInst instanceof Error) return dev;

            // Get manufName, modelId and powerSource information
            return self.af.zclFoundation(basicEpInst, basicEpInst, 0, 'read', [{ attrId: 4 }, { attrId: 5 }, { attrId: 7 }]).then(function (readStatusRecsRsp) {
                var data = {};
                if (readStatusRecsRsp && _.isArray(readStatusRecsRsp.payload)) {
                    readStatusRecsRsp.payload.forEach(function(item){  // { attrId, status, dataType, attrData }
                        if (item && item.hasOwnProperty('attrId') && item.hasOwnProperty('attrData')) {
                            if (item.attrId === 7)
                                data[attrMap[item.attrId]] = powerSourceMap[item.attrData];
                            else
                                data[attrMap[item.attrId]] = item.attrData;
                        }
                    });
                }

                // Update dev
                dev.update(data);

                debug.shepherd('Identified Device: { manufacturer: %s, product: %s }', data.manufName, data.modelId);

                // Save device
                return Q.ninvoke(self._devbox, 'sync', dev._getId()).then(function () {
                    return dev;
                });
            }).catch(function(){
                return dev;
            });
        } catch (err) {
            return dev;
        }
    })
    .then(function (dev) {
        if (_.isFunction(self.acceptDevInterview)) {
            var info = {
                ieeeAddr: dev.getIeeeAddr(),
                dev: dev
            };

            return Q.ninvoke(self, 'acceptDevInterview', info).timeout(60000).then(function(result){
                console.log("pp %s", result)
                if(result) return dev
            })
        } else {
            return dev;
        }
    })
    .then(function (dev) {
        console.log("ffalse %s" ,dev)
        if(!dev) return dev

        const checkClusters = Object.values(dev.endpoints)
                               .some(function(ep){return Object.keys(ep.clusters).length > 1});
        if(isFullEps && checkClusters){
            return dev;
        }
        var numberOfEndpoints = _.keys(dev.endpoints).length;

        var interviewEvents = new EventEmitter();
        interviewEvents.on('ind:interview', function(status) {
            if (status && status.endpoint) status.endpoint.total = numberOfEndpoints;
            self.emit('ind:interview', dev.ieeeAddr, status);
        });

        _.forEach(dev.endpoints, function (ep) {
            // if (ep.isZclSupported())
            clustersReqs.push(function () {
                return self.af.zclClustersReq(ep, interviewEvents).then(function (clusters) {
                    _.forEach(clusters, function (cInfo, cid) {
                        ep.clusters.init(cid, 'dir', { value: cInfo.dir });
                        ep.clusters.init(cid, 'attrs', cInfo.attrs, false);
                    });
                });
            });
        });

        return clustersReqs.reduce(function (soFar, fn) {
            return soFar.then(fn);
        }, Q(0)).then(function(){return true});
    }).then(function (previous_accept) {
        if(!previous_accept) return false
        if (_.isFunction(self.acceptDevIncoming)) {
            var info = {
                ieeeAddr: dev.getIeeeAddr(),
                endpoints: []
            };

            _.forEach(dev.epList, function (epId) {
                info.endpoints.push(dev.getEndpoint(epId));
            });

            return Q.ninvoke(self, 'acceptDevIncoming', info).timeout(60000);
        } else {
            return true;
        }
    }).then(function (accepted) {
        if (accepted) {
            Q.ninvoke(self._devbox, 'sync', dev._getId());
            debug.shepherd('Device: %s join the network.', dev.getIeeeAddr());

            self.emit('ind:incoming', dev);
            self.emit('ind:status', dev, 'online');
            self.controller.emit('ind:incoming' + ':' + dev.getIeeeAddr());
        } else {
            self.remove(dev.getIeeeAddr(), { reJoin: true }).then(function () {
                Q.ninvoke(self._devbox, 'remove', dev._getId());
            }, function(err){
                Q.ninvoke(self._devbox, 'remove', dev._getId());
            });
        }
    }).fail(function (err) {
		self.remove(dev.getIeeeAddr(), { reJoin: true }).then(function (err) {
			if(err){
				self.remove(dev.getIeeeAddr(), { reJoin: true }).then(function (err) {
					Q.ninvoke(self._devbox, 'remove', dev._getId());
				});
			}else{
				Q.ninvoke(self._devbox, 'remove', dev._getId());
			}
		});

        self.emit('error', err);
    });

    if (typeof resolve === 'function') {
        resolve(processDev);
    }

    processDev.done();
};

handlers.leaveInd = function (msg) {
    // { srcaddr, extaddr, request, removechildren, rejoin }
    var dev = this._findDevByAddr(msg.extaddr);

    if (dev) {
        var ieeeAddr = dev.getIeeeAddr(),
            epList = _.cloneDeep(dev.epList);

        if (msg.request)    // request
            this._unregisterDev(dev);
        else                // indication
            this._devbox.remove(dev._getId(), function () {});

        debug.shepherd('Device: %s leave the network.', ieeeAddr);
        this.emit('ind:leaving', epList, ieeeAddr);
    }
};

handlers.stateChangeInd = function (msg) {
    // { state[, nwkaddr] }
    if (!msg.hasOwnProperty('nwkaddr'))
        return;

    var devStates = msg.state;

    _.forEach(ZSC.ZDO.devStates, function (statesCode, states) {
        if (msg.state === statesCode)
            devStates = states;
    });

    debug.shepherd('Device: %d is now in state: %s', msg.nwkaddr, devStates);
};

handlers.statusErrorRsp = function (msg) {
    // { srcaddr, status }
    debug.shepherd('Device: %d status error: %d', msg.srcaddr, msg.status);
};

handlers.tcDeviceInd = function (msg) {
    // { nwkaddr, extaddr, parentaddr }
};

handlers.matchDescRspSent = function (msg) {
    // { nwkaddr, numinclusters, inclusterlist, numoutclusters, outclusterlist }
};

handlers.srcRtgInd = function (msg) {
    // { dstaddr, relaycount, relaylist }
};

handlers.beacon_notify_ind = function (msg) {
    // { beaconcount, beaconlist }
};

handlers.msgCbIncoming = function (msg) {
    // { srcaddr, wasbroadcast, clusterid, securityuse, seqnum, macdstaddr, msgdata }
};

handlers.serverDiscRsp = function (msg) {
    // { srcaddr, status, servermask }
};

module.exports = handlers;
<|endoftext|>


<commit_before>import React from 'react'
import { Link } from 'react-router-dom'
import injectSheet from 'react-jss'

import Spacer from '../../components/spacer'
import LogoBetaWhite from '../../components/icons/icon-components/logo-beta-white'
import SocialMedia from './social-media'

const MiniAppFooter = ({ classes }) => (

		<Spacer height="87px" />

			<LogoBetaWhite height={25} width={160} />
			<Link to="/about" className={classes.navigationLink}>
				About
			</Link>
			<Link to="/feedback" className={classes.navigationLink}>
				Feedback
			</Link>

© Help Assist Her 2018

			<SocialMedia />

)

const styles = {
	footerRoot: {
		height: '149px',
		'background-color': '#3D65F9',
		padding: '35px 82px 0px 44px',
	},
	navigationLink: {
		'font-family': 'hah-regular',
		'font-size': '18px',
		color: '#FFFFFF',
		'text-decoration': 'none',
	},
	copyrightText: {
		'font-family': 'hah-regular',
		'font-size': '10px',
		color: '#ABD3F9',
	},
}

export default injectSheet(styles)(MiniAppFooter)
<commit_msg>Style<commit_after>import React from 'react'
import { Link } from 'react-router-dom'
import injectSheet from 'react-jss'

import Spacer from '../../components/spacer'
import LogoBetaWhite from '../../components/icons/icon-components/logo-beta-white'
import SocialMedia from './social-media'

const MiniAppFooter = ({ classes }) => (

		<Spacer height="87px" />

				<LogoBetaWhite height={25} width={160} />
				<Spacer height="19px" />

© Help Assist Her 2018

				<Link to="/about" className={classes.navigationLink}>
					About
				</Link>
				<Link to="/feedback" className={classes.navigationLink}>
					Feedback
				</Link>

			<SocialMedia />

)

const styles = {
	footerRoot: {
		display: 'flex',
		'justify-content': 'space-between',
		height: '114px',
		'background-color': '#3D65F9',
		padding: '35px 82px 0px 44px',
	},
	links: {
		display: 'flex',
		'flex-direction': 'column',
	},
	navigationLink: {
		'font-family': 'hah-regular',
		'font-size': '18px',
		color: '#FFFFFF',
		'text-decoration': 'none',
		'margin-bottom': '24px',
	},
	copyrightText: {
		'font-family': 'hah-regular',
		'font-size': '10px',
		color: '#ABD3F9',
	},
}

export default injectSheet(styles)(MiniAppFooter)
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';

const withDevTools = (
  // process.env.NODE_ENV === 'development' &&
  typeof window !== 'undefined' && window.devToolsExtension
);

class Counter extends Component {
  constructor() {
    super();
    this.state = { counter: 0 };

    this.increment = this.increment.bind(this);
    this.decrement = this.decrement.bind(this);
  }

  componentWillMount() {
    if (withDevTools) {
      this.devTools = window.devToolsExtension.connect();
    }
  }

  componentWillUnmount() {
    if (withDevTools) {
      window.devToolsExtension.disconnect();
    }
  }

  increment() {
    const state = { counter: this.state.counter + 1 };
    if (withDevTools) this.devTools.send('increment', state);
    this.setState(state);
  }

  decrement() {
    const state = { counter: this.state.counter - 1 };
    if (withDevTools) this.devTools.send('decrement', state);
    this.setState(state);
  }

  render() {
    const { counter } = this.state;
    return (

        Clicked: {counter} times
        {' '}
        <button onClick={this.increment}>+</button>
        {' '}
        <button onClick={this.decrement}>-</button>

    );
  }
}

export default Counter;
<commit_msg>Subscribe to the extension and time traveling example for react-counter-messaging<commit_after>import React, { Component, PropTypes } from 'react';

const withDevTools = (
  // process.env.NODE_ENV === 'development' &&
  typeof window !== 'undefined' && window.devToolsExtension
);

class Counter extends Component {
  constructor() {
    super();
    this.state = { counter: 0 };

    this.increment = this.increment.bind(this);
    this.decrement = this.decrement.bind(this);
  }

  componentWillMount() {
    if (withDevTools) {
      this.devTools = window.devToolsExtension.connect();
      this.unsubscribe = this.devTools.subscribe((message) => {
        // Implement monitors actions.
        // For example time traveling:
        if (message.type === 'DISPATCH' && message.payload.type === 'JUMP_TO_STATE') {
          this.setState(message.state);
        }
      });
    }
  }

  componentWillUnmount() {
    if (withDevTools) {
      this.unsubscribe(); // Use if you have other subscribers from other components.
      window.devToolsExtension.disconnect(); // If there aren't other subscribers.
    }
  }

  increment() {
    const state = { counter: this.state.counter + 1 };
    if (withDevTools) this.devTools.send('increment', state);
    this.setState(state);
  }

  decrement() {
    const state = { counter: this.state.counter - 1 };
    if (withDevTools) this.devTools.send('decrement', state);
    this.setState(state);
  }

  render() {
    const { counter } = this.state;
    return (

        Clicked: {counter} times
        {' '}
        <button onClick={this.increment}>+</button>
        {' '}
        <button onClick={this.decrement}>-</button>

    );
  }
}

export default Counter;
<|endoftext|>


<commit_before>import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Renderer from '@widget-editor/renderer';

import {
    Tooltip
} from 'vizzuality-components';

// components
import TextChart from 'components/widgets/charts/TextChart';
import LoginRequired from 'components/ui/login-required';
import Icon from 'components/ui/icon';
import Title from 'components/ui/Title';
import Spinner from 'components/ui/Spinner';
import CollectionsPanel from 'components/collections-panel';
import Modal from 'components/modal/modal-component';
import ShareModal from 'components/modal/share-modal';

// utils
import { logEvent } from 'utils/analytics';

// helpers
import { belongsToACollection } from 'components/collections-panel/collections-panel-helpers';

// Styles
import './styles.scss';

function DashboardWidgetCard(props) {
    const { user, widget, loading } = props;
    const widgetConfig = widget && widget.widgetConfig;
    const [shareModalOpen, setShareModalOpen] = useState(false);
    const [infoCardOpen, setInfoCardOpen] = useState(false);
    const widgetType = widget && widget.type;
    const metadataInfo = (widget && (widget.metadata && widget.metadata.length > 0 &&
        widget.metadata[0].info)) || {};

    const widgetLinks = metadataInfo.widgetLinks || [];
    const widgetIsEmbed = widgetType === 'embed';
    const widgetEmbedUrl = widgetIsEmbed && widgetConfig.url;
    const isInACollection = belongsToACollection(user, widget);
    const starIconName = classnames({
        'icon-star-full': isInACollection,
        'icon-star-empty': !isInACollection
    });
    const modalIcon = classnames({
        'icon-cross': infoCardOpen,
        'icon-info': !infoCardOpen
    });

    return (

                    <Title className="-default">{widget ? widget.name : '–'}</Title>

                                <button
                                    className="c-btn -tertiary -clean"
                                    onClick={() => setShareModalOpen(true)}
                                >
                                    <Icon
                                        name="icon-share"
                                        className="-small"
                                    />
                                </button>

                                <Modal
                                    isOpen={shareModalOpen}
                                    className="-medium"
                                    onRequestClose={() => setShareModalOpen(false)}
                                >
                                    <ShareModal
                                        links={{
                                            link: typeof window !== 'undefined' && widget && `${window.location.origin}/embed/${widgetType}/${widget.id}`,
                                            embed: typeof window !== 'undefined' && widget && `${window.location.origin}/embed/${widgetType}/${widget.id}`
                                        }}
                                        analytics={{
                                            facebook: () => logEvent('Share (embed)', `Share widget: ${widget.name}`, 'Facebook'),
                                            twitter: () => logEvent('Share (embed)', `Share widget: ${widget.name}`, 'Twitter'),
                                            email: () => logEvent('Share', `Share widget: ${widget.name}`, 'Email'),
                                            copy: type => logEvent('Share (embed)', `Share widget: ${widget.name}`, `Copy ${type}`)
                                        }}
                                    />
                                </Modal>

                                <LoginRequired>
                                    <Tooltip
                                        overlay={<CollectionsPanel
                                            resource={widget}
                                            resourceType="widget"
                                        />}
                                        overlayClassName="c-rc-tooltip"
                                        overlayStyle={{ color: '#fff' }}
                                        placement="bottomLeft"
                                        trigger="click"
                                    >
                                        <button
                                            className="c-btn favourite-button"
                                            tabIndex={-1}
                                        >
                                            <Icon
                                                name={starIconName}
                                                className="-star -small"
                                            />
                                        </button>
                                    </Tooltip>
                                </LoginRequired>

                                <button
                                    type="button"
                                    onClick={() => setInfoCardOpen(!infoCardOpen)}
                                >
                                    <Icon name={modalIcon} className="-small" />
                                </button>

                <Spinner isLoading={loading} className="-light -small" />
                {widgetType === 'text' && widget &&
                    <TextChart
                        widgetConfig={widgetConfig}
                        toggleLoading={loading => onToggleLoading(loading)}
                    />
                }

                { widgetType === 'widget' &&
                    <Renderer widgetConfig={widgetConfig} />
                }

                {infoCardOpen &&

                        {widget && !widget.description &&

No additional information is available

                        }

                        {widget && widget.description && (

Description

{widget.description}

                        )}

                        {widgetLinks.length > 0 &&

Links

                                    {widgetLinks.map(link => (

                                                {link.name}

                                    ))}

                        }

                }

    );
};

DashboardWidgetCard.propTypes = {
    user: PropTypes.object.isRequired,
    widget: PropTypes.object.isRequired
};

export default DashboardWidgetCard;<commit_msg>support embed widgets in GEDC<commit_after>import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Renderer from '@widget-editor/renderer';

import {
    Tooltip
} from 'vizzuality-components';

// components
import TextChart from 'components/widgets/charts/TextChart';
import LoginRequired from 'components/ui/login-required';
import Icon from 'components/ui/icon';
import Title from 'components/ui/Title';
import Spinner from 'components/ui/Spinner';
import CollectionsPanel from 'components/collections-panel';
import Modal from 'components/modal/modal-component';
import ShareModal from 'components/modal/share-modal';

// utils
import { logEvent } from 'utils/analytics';

// helpers
import { belongsToACollection } from 'components/collections-panel/collections-panel-helpers';

// Styles
import './styles.scss';

function DashboardWidgetCard(props) {
    const { user, widget, loading } = props;
    const widgetConfig = widget && widget.widgetConfig;
    const [shareModalOpen, setShareModalOpen] = useState(false);
    const [infoCardOpen, setInfoCardOpen] = useState(false);
    const widgetType = widget && widget.type;
    const metadataInfo = (widget && (widget.metadata && widget.metadata.length > 0 &&
        widget.metadata[0].info)) || {};

    const widgetLinks = metadataInfo.widgetLinks || [];
    const widgetIsEmbed = widgetType === 'embed';
    const widgetEmbedUrl = widgetIsEmbed && widgetConfig.url;
    const isInACollection = belongsToACollection(user, widget);
    const starIconName = classnames({
        'icon-star-full': isInACollection,
        'icon-star-empty': !isInACollection
    });
    const modalIcon = classnames({
        'icon-cross': infoCardOpen,
        'icon-info': !infoCardOpen
    });

    return (

                    <Title className="-default">{widget ? widget.name : '–'}</Title>

                                <button
                                    className="c-btn -tertiary -clean"
                                    onClick={() => setShareModalOpen(true)}
                                >
                                    <Icon
                                        name="icon-share"
                                        className="-small"
                                    />
                                </button>

                                <Modal
                                    isOpen={shareModalOpen}
                                    className="-medium"
                                    onRequestClose={() => setShareModalOpen(false)}
                                >
                                    <ShareModal
                                        links={{
                                            link: typeof window !== 'undefined' && widget && `${window.location.origin}/embed/${widgetType}/${widget.id}`,
                                            embed: typeof window !== 'undefined' && widget && `${window.location.origin}/embed/${widgetType}/${widget.id}`
                                        }}
                                        analytics={{
                                            facebook: () => logEvent('Share (embed)', `Share widget: ${widget.name}`, 'Facebook'),
                                            twitter: () => logEvent('Share (embed)', `Share widget: ${widget.name}`, 'Twitter'),
                                            email: () => logEvent('Share', `Share widget: ${widget.name}`, 'Email'),
                                            copy: type => logEvent('Share (embed)', `Share widget: ${widget.name}`, `Copy ${type}`)
                                        }}
                                    />
                                </Modal>

                                <LoginRequired>
                                    <Tooltip
                                        overlay={<CollectionsPanel
                                            resource={widget}
                                            resourceType="widget"
                                        />}
                                        overlayClassName="c-rc-tooltip"
                                        overlayStyle={{ color: '#fff' }}
                                        placement="bottomLeft"
                                        trigger="click"
                                    >
                                        <button
                                            className="c-btn favourite-button"
                                            tabIndex={-1}
                                        >
                                            <Icon
                                                name={starIconName}
                                                className="-star -small"
                                            />
                                        </button>
                                    </Tooltip>
                                </LoginRequired>

                                <button
                                    type="button"
                                    onClick={() => setInfoCardOpen(!infoCardOpen)}
                                >
                                    <Icon name={modalIcon} className="-small" />
                                </button>

                <Spinner isLoading={loading} className="-light -small" />
                {widgetType === 'text' && widget &&
                    <TextChart
                        widgetConfig={widgetConfig}
                        toggleLoading={loading => onToggleLoading(loading)}
                    />
                }

                { widgetType === 'widget' &&
                    <Renderer widgetConfig={widgetConfig} />
                }

                {widgetIsEmbed &&

                }

                {infoCardOpen &&

                        {widget && !widget.description &&

No additional information is available

                        }

                        {widget && widget.description && (

Description

{widget.description}

                        )}

                        {widgetLinks.length > 0 &&

Links

                                    {widgetLinks.map(link => (

                                                {link.name}

                                    ))}

                        }

                }

    );
};

DashboardWidgetCard.propTypes = {
    user: PropTypes.object.isRequired,
    widget: PropTypes.object.isRequired
};

export default DashboardWidgetCard;<|endoftext|>


<commit_before>(function (angular, $, _) {

  angular.module('crmMosaico').factory('crmMosaicoTemplates', function ($q, crmApi) {
    var ts = CRM.ts(null);
    var tplsUrl = CRM.resourceUrls['uk.co.vedaconsulting.mosaico'] + '/packages/mosaico/templates';

    var baseTemplates = [
      {id: 'base-1', title: ts('Empty Template'), type: 'Versafix 1', thumbnail: tplsUrl + '/versafix-1/edres/_full.png', path: 'templates/versafix-1/template-versafix-1.html'},
      {id: 'base-6', title: ts('Empty Template'), type: 'TEDC 15', thumbnail: tplsUrl + '/tedc15/edres/_full.png', path: 'templates/tedc15/template-tedc15.html'}
    ];

    var configuredTemplates = [
      {id: '1', title: 'Event Promo', type: 'Versafix 1', thumbnail: tplsUrl + '/versafix-1/edres/_full.png', path: 'templates/versafix-1/template-versafix-1.html'},
      {id: '2', title: 'Donor Newsletter', type: 'Versafix 1', thumbnail: tplsUrl + '/versafix-1/edres/_full.png', path: 'templates/versafix-1/template-versafix-1.html'},
      {id: '3', title: 'Member Newsletter', type: 'Versafix 1', thumbnail: tplsUrl + '/versafix-1/edres/_full.png', path: 'templates/versafix-1/template-versafix-1.html'},
      {id: '4', title: 'Special Offer', type: 'TEDC 15', thumbnail: tplsUrl + '/tedc15/edres/_full.png', path: 'templates/tedc15/template-tedc15.html'}
    ];

    var allTemplates = _.extend([], baseTemplates, configuredTemplates);

    return {
      getBases: function getBases() {
        return $q(function(resolve, reject){
          setTimeout(function(){
            resolve(baseTemplates);
          }, 100);
        });
      },
      getConfigured: function getBases() {
        return $q(function(resolve, reject){
          setTimeout(function(){
            resolve(configuredTemplates);
          }, 100);
        });
      },
      getAll: function getAll() {
        return $q(function(resolve, reject){
          setTimeout(function(){
            resolve(allTemplates);
          }, 100);
        });
      }
    };
  });

})(angular, CRM.$, CRM._);
<commit_msg>crmMosaicoTemplates - Implement skeletal getContent()<commit_after>(function (angular, $, _) {

  angular.module('crmMosaico').factory('crmMosaicoTemplates', function ($q, crmApi) {
    var ts = CRM.ts(null);
    var tplsUrl = CRM.resourceUrls['uk.co.vedaconsulting.mosaico'] + '/packages/mosaico/templates';

    var baseTemplates = [
      {id: 'base-1', title: ts('Empty Template'), type: 'Versafix 1', thumbnail: tplsUrl + '/versafix-1/edres/_full.png', path: 'templates/versafix-1/template-versafix-1.html'},
      {id: 'base-6', title: ts('Empty Template'), type: 'TEDC 15', thumbnail: tplsUrl + '/tedc15/edres/_full.png', path: 'templates/tedc15/template-tedc15.html'}
    ];

    var exMetadata = '{"created":1480972208311,"key":"8m0qymc","name":"My Example Template","template":"/sites/all/modules/civicrm/ext/uk.co.vedaconsulting.mosaico/packages/mosaico/templates/versafix-1/template-versafix-1.html","editorversion":"0.15.0","templateversion":"1.0.5","changed":1480972251321}';
    var exContent = '{"type":"template","customStyle":false,"preheaderVisible":true,"titleText":"TITLE","preheaderBlock":{"type":"preheaderBlock","customStyle":false,"id":"ko_preheaderBlock_1","backgroundColor":null,"preheaderText":"","linkStyle":{"type":"linkStyle","face":null,"color":null,"size":null,"decoration":null},"preheaderLinkOption":"{action.unsubscribeUrl}","longTextStyle":{"type":"longTextStyle","face":null,"color":null,"size":null,"linksColor":null},"unsubscribeText":"Unsubscribe","webversionText":"View in your browser"},"mainBlocks":{"type":"blocks","blocks":[{"type":"sideArticleBlock","customStyle":false,"backgroundColor":null,"titleVisible":true,"buttonVisible":true,"imageWidth":"166","imagePos":"left","titleTextStyle":{"type":"textStyle","face":null,"color":null,"size":null},"longTextStyle":{"type":"longTextStyle","face":null,"color":null,"size":null,"linksColor":null},"buttonStyle":{"type":"buttonStyle","face":null,"color":null,"size":null,"buttonColor":null,"radius":null},"image":{"type":"image","src":"","url":"","alt":""},"longText":"
This is definitely an example template.

","buttonLink":{"type":"link","text":"BUTTON","url":""},"id":"ko_sideArticleBlock_2","externalBackgroundColor":null,"titleText":"Mosaico Example Template"},{"type":"buttonBlock","customStyle":false,"id":"ko_buttonBlock_3","externalBackgroundColor":null,"backgroundColor":null,"bigButtonStyle":{"type":"buttonStyle","face":null,"color":null,"size":null,"buttonColor":null,"radius":null},"link":{"type":"link","text":"Make cheese","url":""}}]},"theme":{"type":"theme","frameTheme":{"type":"frameTheme","backgroundColor":"#3f3f3f","longTextStyle":{"type":"longTextStyle","face":"Arial, Helvetica, sans-serif","color":"#919191","size":"13","linksColor":"#cccccc"},"linkStyle":{"type":"linkStyle","face":"Arial, Helvetica, sans-serif","color":"#ffffff","size":"13","decoration":"underline"}},"contentTheme":{"type":"contentTheme","longTextStyle":{"type":"longTextStyle","face":"Arial, Helvetica, sans-serif","color":"#3f3f3f","size":"13","linksColor":"#3f3f3f"},"externalBackgroundColor":"#bfbfbf","externalTextStyle":{"type":"textStyle","face":"Arial, Helvetica, sans-serif","color":"#f3f3f3","size":"18"},"backgroundColor":"#ffffff","titleTextStyle":{"type":"textStyle","face":"Arial, Helvetica, sans-serif","color":"#3f3f3f","size":"18"},"buttonStyle":{"type":"buttonStyle","face":"Arial, Helvetica, sans-serif","color":"#3f3f3f","size":"13","buttonColor":"#bfbfbf","radius":"4"},"bigTitleStyle":{"type":"bigTitleStyle","face":"Arial, Helvetica, sans-serif","color":"#3f3f3f","size":"22","align":"center"},"hrStyle":{"type":"hrStyle","color":"#3f3f3f","hrWidth":"100","hrHeight":"1"},"bigButtonStyle":{"type":"buttonStyle","face":"Arial, Helvetica, sans-serif","color":"#3f3f3f","size":"22","buttonColor":"#bfbfbf","radius":"4"}}}}';

    var configuredTemplates = [
      {id: '1', title: 'Event Promo', type: 'Versafix 1', thumbnail: tplsUrl + '/versafix-1/edres/_full.png', path: 'templates/versafix-1/template-versafix-1.html', hasContent: true},
      {id: '2', title: 'Donor Newsletter', type: 'Versafix 1', thumbnail: tplsUrl + '/versafix-1/edres/_full.png', path: 'templates/versafix-1/template-versafix-1.html', hasContent: true},
      {id: '3', title: 'Member Newsletter', type: 'Versafix 1', thumbnail: tplsUrl + '/versafix-1/edres/_full.png', path: 'templates/versafix-1/template-versafix-1.html', hasContent: true},
      {id: '4', title: 'Special Offer', type: 'TEDC 15', thumbnail: tplsUrl + '/tedc15/edres/_full.png', path: 'templates/tedc15/template-tedc15.html', hasContent: true}
    ];

    var allTemplates = _.extend([], baseTemplates, configuredTemplates);

    return {
      getContent: function getContent(template) {
        //   return crmApi('MosaicoTemplate', 'get', {id: template.id});
        return $q(function(resolve, reject){
          setTimeout(function(){
            if (!template.hasContent) {
              resolve({});
            } else {
              resolve({
                metadata: exMetadata,
                content: exContent
              });
            }
          }, 100);
        });
      },
      getBases: function getBases() {
        return $q(function(resolve, reject){
          setTimeout(function(){
            resolve(baseTemplates);
          }, 100);
        });
      },
      getConfigured: function getBases() {
        return $q(function(resolve, reject){
          setTimeout(function(){
            resolve(configuredTemplates);
          }, 100);
        });
      },
      getAll: function getAll() {
        return $q(function(resolve, reject){
          setTimeout(function(){
            resolve(allTemplates);
          }, 100);
        });
      }
    };
  });

})(angular, CRM.$, CRM._);
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'

import { fetchMobilizations, mobilizationsIsLoaded } from '../MobilizationActions'
// TODO: Refactor actions to module
import { fetchOrganizations, isOrganizationsLoaded } from '../../reducers/organizations'
import * as Paths from '../../Paths'
import {
  Sidenav,
  SidenavList,
  SidenavListItem
} from '../../../components/Navigation'
import { getMobilization } from '../MobilizationSelectors'

class UserDashboard extends Component {

  static fetchData({ dispatch, getState }) {
    const promises = []

    // TODO: When filter mobilization by user owner, make code here
    if (!mobilizationsIsLoaded(getState())) {
      promises.push(dispatch(fetchMobilizations()))
    }

    if (!isOrganizationsLoaded(getState())) {
      promises.push(dispatch(fetchOrganizations()))
    }

    return Promise.all(promises)
  }

  componentDidMount() {
    // TODO this callback is a workaround to load mobilizations in client-side
    // but it should be replaced by the static fetchData method that is fetching
    // mobilizations only in the server-side for now
    const { organizations, mobilization, dispatch } = this.props

    if (!organizations.loaded) {
      dispatch(fetchOrganizations())
    }

    if (!mobilization.loaded) {
      dispatch(fetchMobilizations())
    }
  }

  render() {
    const { children, ...otherProps } = this.props
    const {
      mobilization: { currentId },
      auth: { user }
    } = otherProps

    return (

        <Sidenav user={otherProps.auth.user}>
          {
            !currentId ? null : (
              <SidenavList className="bg-lighten-1">
                <SidenavListItem
                  linkType="router"
                  text="Editar mobilização"
                  icon="pencil"
                  href={Paths.editMobilization(currentId)}
                />
                <SidenavListItem
                  linkType="router"
                  text="Adicionar conteúdo"
                  icon="plus"
                  href={Paths.newMobilizationBlock(currentId)}
                />
                <SidenavListItem
                  text="Ver em uma nova aba"
                  icon="external-link"
                  href={Paths.mobilization(getMobilization(otherProps))}
                  target="_blank"
                />
                <SidenavListItem
                  linkType="router"
                  text="Configurações"
                  icon="cog"
                  href={Paths.basicsMobilization(currentId)}
                />
                <SidenavListItem
                  linkType="router"
                  text="Lançar mobilização"
                  icon="flag"
                />
              </SidenavList>
            )
          }
          <SidenavList>
            <SidenavListItem
              text="Minha Conta"
              icon="user"
            >

{user.email}

            </SidenavListItem>
            <SidenavListItem
              text="Sair"
              className="caps"
              href={Paths.logout()}
            />
          </SidenavList>
        </Sidenav>
        {
          React.cloneElement(children, {...otherProps})
        }

    )
  }
}

UserDashboard.propTypes = {
  auth: PropTypes.object.isRequired,  // RequireLogin.js
  organizations: PropTypes.object.isRequired,
  mobilization: PropTypes.object.isRequired,
  dispatch: PropTypes.func.isRequired,
  children: PropTypes.element
}

const mapStateToProps = (globalState, ownProps) => {
  return {
    organizations: globalState.organizations,
    mobilization: globalState.mobilization
  }
}

export default connect(mapStateToProps)(UserDashboard)
<commit_msg>Fix UserDashboardContainer Sidenav component mobilization items background color. #184<commit_after>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'

import { fetchMobilizations, mobilizationsIsLoaded } from '../MobilizationActions'
// TODO: Refactor actions to module
import { fetchOrganizations, isOrganizationsLoaded } from '../../reducers/organizations'
import * as Paths from '../../Paths'
import {
  Sidenav,
  SidenavList,
  SidenavListItem
} from '../../../components/Navigation'
import { getMobilization } from '../MobilizationSelectors'

class UserDashboard extends Component {

  static fetchData({ dispatch, getState }) {
    const promises = []

    // TODO: When filter mobilization by user owner, make code here
    if (!mobilizationsIsLoaded(getState())) {
      promises.push(dispatch(fetchMobilizations()))
    }

    if (!isOrganizationsLoaded(getState())) {
      promises.push(dispatch(fetchOrganizations()))
    }

    return Promise.all(promises)
  }

  componentDidMount() {
    // TODO this callback is a workaround to load mobilizations in client-side
    // but it should be replaced by the static fetchData method that is fetching
    // mobilizations only in the server-side for now
    const { organizations, mobilization, dispatch } = this.props

    if (!organizations.loaded) {
      dispatch(fetchOrganizations())
    }

    if (!mobilization.loaded) {
      dispatch(fetchMobilizations())
    }
  }

  render() {
    const { children, ...otherProps } = this.props
    const {
      mobilization: { currentId },
      auth: { user }
    } = otherProps

    return (

        <Sidenav user={otherProps.auth.user}>
          {
            !currentId ? null : (
              <SidenavList className="bg-lighten-2">
                <SidenavListItem
                  linkType="router"
                  text="Editar mobilização"
                  icon="pencil"
                  href={Paths.editMobilization(currentId)}
                />
                <SidenavListItem
                  linkType="router"
                  text="Adicionar conteúdo"
                  icon="plus"
                  href={Paths.newMobilizationBlock(currentId)}
                />
                <SidenavListItem
                  text="Ver em uma nova aba"
                  icon="external-link"
                  href={Paths.mobilization(getMobilization(otherProps))}
                  target="_blank"
                />
                <SidenavListItem
                  linkType="router"
                  text="Configurações"
                  icon="cog"
                  href={Paths.basicsMobilization(currentId)}
                />
                <SidenavListItem
                  linkType="router"
                  text="Lançar mobilização"
                  icon="flag"
                />
              </SidenavList>
            )
          }
          <SidenavList>
            <SidenavListItem
              text="Minha Conta"
              icon="user"
            >

{user.email}

            </SidenavListItem>
            <SidenavListItem
              text="Sair"
              className="caps"
              href={Paths.logout()}
            />
          </SidenavList>
        </Sidenav>
        {
          React.cloneElement(children, {...otherProps})
        }

    )
  }
}

UserDashboard.propTypes = {
  auth: PropTypes.object.isRequired,  // RequireLogin.js
  organizations: PropTypes.object.isRequired,
  mobilization: PropTypes.object.isRequired,
  dispatch: PropTypes.func.isRequired,
  children: PropTypes.element
}

const mapStateToProps = (globalState, ownProps) => {
  return {
    organizations: globalState.organizations,
    mobilization: globalState.mobilization
  }
}

export default connect(mapStateToProps)(UserDashboard)
<|endoftext|>


<commit_before>/**
* @author Virtuosi Media
* @link http://www.virtuosimedia.com
* @version 1.0
* @copyright Copyright (c) 2012, Virtuosi Media
* @license: MIT License
* @description: Dynamically loads VMUI scripts based on need
* Requirements: MooTools 1.4 Core - See http://mootools.net
*/
var VMUI = new Class({
	Implements: [Events, Options],

	options: {
		assets: [
		         {name:'CheckboxReplace', source:'Form/Replace/Checkbox.js', selectors:'input[type=checkbox]'},
		         {name:'RadioReplace', source:'Form/Replace/Radio.js', selectors:'input[type=radio]'},
		         {name:'SelectReplace', source:'Form/Replace/Select.js', selectors:'select'},
		         {name:'Lighter', source:'Lighter/Lighter.js', selectors:'pre'}
		],
		relativePath: '../JavaScript'

	},

	/**
	 * @param object - options - The options object
	 */
	initialize: function(options){
		this.setOptions(options);
		this.loadScripts();
	},

	loadScripts: function(){
		var self = this;
		Array.each(this.options.assets, function(script){
			if ($$(script.selectors).length){
				if (self.checkExists(script.name)){
					Asset.javascript(self.options.relativePath+'/'+script.source, {
						 onLoad: function(){
							 if (script.name == 'Lighter'){
								self.loadLighter(script.selectors);
							 } else {
								 var plugin = new window[script.name](script.selectors);
							 }
						 }
					 });
				} else {
					 var plugin = new window[script.name](script.selectors);
				}
			}
		});
	},

	checkExists: function(name){
		return (typeof name !== 'undefined');
	},

	loadLighter: function(selectors){
		var self = this;
		var assets = [
		     'Lighter/Lighter.js', 'Lighter/Loader.js', 'Lighter/Parser.js', 'Lighter/Parser/Smart.js',
		     'Lighter/Compiler.js', 'Lighter/Compiler/List.js', 'Lighter/Compiler/Inline.js', 'Lighter/Fuel.js',
		     'Lighter/Wick.js',
		];
		self.loadLighterAsset(assets, 0, selectors);
	},

	/**
	 * This method forces the lighter assets to load sequentially, avoiding the occasional loading error
	 */
	loadLighterAsset: function(assets, index, selectors){
		var self = this;
		var last = assets.length;
		if (index != last){
			if (self.checkExists(assets[index])){
				Asset.javascript(self.options.relativePath+'/'+assets[index], {
					onLoad: function(){
						index++;
						self.loadLighterAsset(assets, index, selectors);
					}
				});
			} else {
				index++;
				self.loadLighterAsset(assets, index, selectors);
			}
		} else {
			this.igniteLighter(selectors);
		}
	},

	igniteLighter: function(selectors){
		var lighter = new Lighter({
			loader:   new Loader({}),
			parser:   new Parser.Smart({ strict: true }),
			compiler: new Compiler.List(),
			mode: 'ol'
		});

		$$(selectors).each(function(el) {
			lighter.light(el);
		});
	}
});

window.addEvent('domready', function() {
	var loader = new VMUI();
});
<commit_msg>Added tabs<commit_after>/**
* @author Virtuosi Media
* @link http://www.virtuosimedia.com
* @version 1.0
* @copyright Copyright (c) 2012, Virtuosi Media
* @license: MIT License
* @description: Dynamically loads VMUI scripts based on need
* Requirements: MooTools 1.4 Core - See http://mootools.net
*/
var VMUI = new Class({
	Implements: [Events, Options],

	options: {
		assets: [
		         {name:'CheckboxReplace', source:'Form/Replace/Checkbox.js', selectors:'input[type=checkbox]'},
		         {name:'RadioReplace', source:'Form/Replace/Radio.js', selectors:'input[type=radio]'},
		         {name:'SelectReplace', source:'Form/Replace/Select.js', selectors:'select'},
		         {name:'Lighter', source:'Lighter/Lighter.js', selectors:'pre'},
		         {name:'Tabs', source:'Navigation/Tabs.js', selectors:'.tabs, .tabsVertical'},
		],
		relativePath: '../JavaScript'

	},

	/**
	 * @param object - options - The options object
	 */
	initialize: function(options){
		this.setOptions(options);
		this.loadScripts();
	},

	loadScripts: function(){
		var self = this;
		Array.each(this.options.assets, function(script){
			if ($$(script.selectors).length){
				if (self.checkExists(script.name)){
					Asset.javascript(self.options.relativePath+'/'+script.source, {
						 onLoad: function(){
							 if (script.name == 'Lighter'){
								self.loadLighter(script.selectors);
							 } else {
								 var plugin = new window[script.name](script.selectors);
							 }
						 }
					 });
				} else {
					 var plugin = new window[script.name](script.selectors);
				}
			}
		});
	},

	checkExists: function(name){
		return (typeof name !== 'undefined');
	},

	loadLighter: function(selectors){
		var self = this;
		var assets = [
		     'Lighter/Lighter.js', 'Lighter/Loader.js', 'Lighter/Parser.js', 'Lighter/Parser/Smart.js',
		     'Lighter/Compiler.js', 'Lighter/Compiler/List.js', 'Lighter/Compiler/Inline.js', 'Lighter/Fuel.js',
		     'Lighter/Wick.js',
		];
		self.loadLighterAsset(assets, 0, selectors);
	},

	/**
	 * This method forces the lighter assets to load sequentially, avoiding the occasional loading error
	 */
	loadLighterAsset: function(assets, index, selectors){
		var self = this;
		var last = assets.length;
		if (index != last){
			if (self.checkExists(assets[index])){
				Asset.javascript(self.options.relativePath+'/'+assets[index], {
					onLoad: function(){
						index++;
						self.loadLighterAsset(assets, index, selectors);
					}
				});
			} else {
				index++;
				self.loadLighterAsset(assets, index, selectors);
			}
		} else {
			this.igniteLighter(selectors);
		}
	},

	igniteLighter: function(selectors){
		var lighter = new Lighter({
			loader:   new Loader({}),
			parser:   new Parser.Smart({ strict: true }),
			compiler: new Compiler.List(),
			mode: 'ol'
		});

		$$(selectors).each(function(el) {
			lighter.light(el);
		});
	}
});

window.addEvent('domready', function() {
	var loader = new VMUI();
});
<|endoftext|>


<commit_before>'use strict';

var categoryMenu = require('../services/response/categoryMenuResponse').getInstance();
var productMenu = require('../services/response/productMenuResponse').getInstance();
var responsePayload = require('../services/response/responsePayload').getInstance();

const MENU = 'menu';
const ALL = 'all';
const CATEGORY = 'category'

function ResponseFactory() {
}

ResponseFactory.prototype = {
    getResponse: function (message) {
        this.loadPayload(message);
        console.info("Message", message);
        console.info("Decoded message", Buffer.from(message,'base64').toString('ascii'));

        if (message === MENU) {
            responsePayload.setType(MENU);
        }
        if (message === ALL) {
            responsePayload.setType(ALL);
        }

        switch (responsePayload.getType()) {
            case MENU:
                break;
            case ALL:
                return categoryMenu.getResponse();
                break;
            case CATEGORY:
                return productMenu.getResponse();
                break;
        }
    },
    loadPayload: function (payload) {
        if (payload === undefined || payload === undefined || payload.type === undefined) {

            return;
        }

        return responsePayload.setPayload(payload);
    }
};

/**
 * @returns {ResponseFactory}
 */
module.exports.getInstance = function () {
    return new ResponseFactory();
};
<commit_msg>add product reponse<commit_after>'use strict';

var categoryMenu = require('../services/response/categoryMenuResponse').getInstance();
var productMenu = require('../services/response/productMenuResponse').getInstance();
var responsePayload = require('../services/response/responsePayload').getInstance();

const MENU = 'menu';
const ALL = 'all';
const CATEGORY = 'category'

function ResponseFactory() {
}

ResponseFactory.prototype = {
    getResponse: function (message) {
        this.loadPayload(message);
        console.info("Message", message);
        // console.info("Decoded message", Buffer.from(message,'base64').toString('ascii'));
        console.log("xxxxxxxxxxxxxxxxxx");
        if (message === MENU) {
            responsePayload.setType(MENU);
        }
        if (message === ALL) {
            responsePayload.setType(ALL);
        }

        switch (responsePayload.getType()) {
            case MENU:
                break;
            case ALL:
                return categoryMenu.getResponse();
                break;
            case CATEGORY:
                return productMenu.getResponse();
                break;
        }
    },
    loadPayload: function (payload) {
        if (payload === undefined || payload === undefined || payload.type === undefined) {

            return;
        }

        return responsePayload.setPayload(payload);
    }
};

/**
 * @returns {ResponseFactory}
 */
module.exports.getInstance = function () {
    return new ResponseFactory();
};
<|endoftext|>