<commit_before>/*global $, jQuery, alert, console, error, success, endless, ajax, templateHelper, Routing, appLocale, exports, module, require, define*/
/*jslint nomen: true */ /* Tolerate dangling _ in identifiers */
/*jslint vars: true */ /* Tolerate many var statements per function */
/*jslint white: true */
/*jslint browser: true */
/*jslint devel: true */ /* Assume console, alert, ... */
/*jslint windows: true */ /* Assume Windows */
/*jslint maxerr: 100 */ /* Maximum number of errors */

/*
 * Class dependencies:
 *      jquery > 1.8.3
 *      isotope
 *      jsrender
 *      jsviews
 * external dependencies:
 *      templateHelper
 *      base genericAction
 */

// fansWorld TV Class Module 1.1 (con galerias de profiles)
// 1.0

(function (root, factory) {
    "use strict";
    if (typeof exports === 'object') {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like enviroments that support module.exports,
        // like Node.
        module.exports = factory(require('Routing'), require('templateHelper'), require('ajax'), require('ExposeTranslation'));
    } else if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jQuery', 'Routing', 'templateHelper', 'ajax', 'ExposeTranslation'], factory);
    } else {
        // Browser globals (root is window)
        root.TV = factory(root.jQuery, root.Routing, root.templateHelper, root.ajax, root.ExposeTranslation);
    }
}(this, function (jQuery, Routing, templateHelper, ajax, ExposeTranslation) {
    "use strict";
    var TV = (function() {
        function TV(filtersList, channelsList) {
            //////////////
            // Internal //
            //////////////
            var that = this;
            this.jQuery = jQuery;
            this.name = filtersList;
            this.channelsList = channelsList;
            this.channel = $('.filter-channels').closest('ul').find("li.active").attr("data-channel-id");
            this.filter = $('#list-filters ul').find('li.active').attr('data-list-filter-type');

            this.page = 1;

            this.contentContainer = $('body');
            this.isotopeContainer = $(this.contentContainer).find('.isotope_container').last();
            if(this.isotopeContainer.length <= 0) {
                return;
            }
            this.feedSource = $(this.isotopeContainer).attr('data-feed-source');
            if(typeof this.feedSource === 'undefined' || this.feedSource.length == ''){
                this.entityId   = $("[data-list]").attr('data-entity-id');
                this.entityType = $("[data-list]").attr('data-entity-type');
                this.dataList = $("[data-list]").attr('data-list');
                this.isProfile = true;
                console.log("in-profile");
                var feed = that.getProfileVideoFeed();
                console.log("filter: " + that.criteria + " feed: " + feed);
                var opts = {
                    'sort': that.criteria,
                    'page': that.page,
                    'entityId': that.entityId,
                    'entityType': that.entityType
                };
                $(this.isotopeContainer).attr('data-feed-source', feed);
                console.log(opts);

            } else {
                this.isTeve = true;
            }
            this.defaultTags = [
                {filter: 'day', title: ExposeTranslation.get('day')},
                {filter: 'week', title: ExposeTranslation.get('week')},
                {filter: 'month', title: ExposeTranslation.get('month')}
            ];

            $(this.isotopeContainer).empty();

            //////////////
            // Bindings //
            //////////////
            // modalPopup
            $('#montage-video-list a').modalPopup();
            // subscribe buttons
            $('[data-subscribe-channel]').click(function () {
                that.subscribe($(this));
            });
            // Handle channel list
            this.channelToggle();
            // Handle Filter tabs (popular, views, latest)
            this.filterToggle();
            this.filterToolbar();

            ////////////////////
            // New TV Gallery //
            ////////////////////
            // load isotope gallery
            if(this.isTeve) {
                this.profileGallery();
            } else {
                this.loadGallery();
            }
            // Tags
            this.myTags();
            // custom tags
            if(this.filter === 'views') {
                this.addCustomTags(this.defaultTags);
            }
        }
        TV.prototype.loadGallery = function() {
            var that = this;
            $(this.isotopeContainer).fwGalerizer({
                normalize: false,
                endless: true,
                feedfilter: {
                    'sort': that.criteria,
                    'page': that.page,
                    'entityId': that.entityId,
                    'entityType': that.entityType
                },
                onEndless: function( plugin ) {
                    plugin.options.feedfilter.page += 1;
                    return plugin.options.feedfilter;
                },
                onDataReady: function(videos) {
                    var i, outp = [];
                    var normalize = function(video) {
                        var href = Routing.generate(appLocale + '_video_show', {
                            'id': video.id,
                            'slug': video.slug
                        });
                        var hrefModal = Routing.generate(appLocale + '_modal_media', {
                            'id': video.id,
                            'type': 'video'
                        });
                        var authorUrl = Routing.generate(appLocale + '_user_land', {
                            'username': 'juan.perez'
                        });
                        return {
                                'type': 'video',
                                'date': video.createdAt,
                                'href': href,
                                'hrefModal': hrefModal,
                                'image': video.imgsrc,
                                'slug': video.slug,
                                'title': video.title,
                                'author': 'juan.perez',
                                'authorHref': authorUrl,
                                'authorImage': 'http://fansworld.dodici.local/uploads/media/default/0001/02/thumb_1000_default_small_square_81dfa380953b084fb7eefb0273ac602bdee11874.jpg'
                        };
                    };
                    for(i in videos.elements) {
                        if (videos.elements.hasOwnProperty(i)) {
                            outp.push(normalize(videos.elements[i]));
                        }
                    }
                    return outp;
                }
            });
        };
        TV.prototype.profileGallery = function() {
            this.channel = $('.filter-channels').closest('ul').find("li.active").attr("data-channel-id");
            this.filter = $('#list-filters ul').find('li.active').attr('data-list-filter-type');
            this.page  = 1;
            $(this.isotopeContainer).fwGalerizer({
                normalize: false,
                endless: true,
                feedfilter: {'channel': this.channel, 'filter': this.filter, 'page': this.page},
                onEndless: function( plugin ) {
                    plugin.options.feedfilter.page += 1;
                    console.log("loading video gallery for channel %s with filter %s page: %s", plugin.options.feedfilter.channel, plugin.options.feedfilter.filter, plugin.options.feedfilter.page);
                    return plugin.options.feedfilter;
                },
                onDataReady: function(videos) {
                    var i, outp = [];
                    var normalize = function(video) {
                        var href = Routing.generate(appLocale + '_video_show', {
                            'id': video.id,
                            'slug': video.slug
                        });
                        var hrefModal = Routing.generate(appLocale + '_modal_media', {
                            'id': video.id,
                            'type': 'video'
                        });
                        var authorUrl = Routing.generate(appLocale + '_user_land', {
                            'username': video.author.username
                        });
                        return {
                                'type': 'video',
                                'date': video.createdAt,
                                'href': href,
                                'hrefModal': hrefModal,
                                'image': video.image,
                                'slug': video.slug,
                                'title': video.title,
                                'author': video.author.username,
                                'authorHref': authorUrl,
                                'authorImage': video.author.image
                        };
                    };
                    for(i in videos.videos) {
                        if (videos.videos.hasOwnProperty(i)) {
                            outp.push(normalize(videos.videos[i]));
                        }
                    }
                    return outp;
                }
            });
            this.page += 1;
        };
        TV.prototype.channelToggle = function() {
            var that = this;
            $('.filter-channels').closest('ul').find("li").click(function(e){
                var i;
                var selectedChannel = $(this).first().attr('data-list-target');
                $(".channels-widget .content .active").removeClass('active');
                $('.filter-channels').closest('ul').find("li.active").removeClass('active');
                $(this).first().addClass('active');

                $(".channels-widget .content #" + selectedChannel).addClass('active');

                // Update channel
                that.channel = $('.filter-channels').closest('ul').find("li.active").attr("data-channel-id");
                // update tags
                that.myTags(that.channel, that.filter);
                // custom tags
                if(that.filter === 'views') {
                    that.addCustomTags(that.defaultTags);
                }
                // Destroy gallery items
                that.destroyGallery();
                // Load new gallery
                that.profileGallery();
            });
        };
        TV.prototype.customFilterToggler = function(element) {
            var that = this;
            element.click(function(e){
                $('[data-list-filter-type=' + that.filter + ']').removeClass();
                that.filter = $(this).attr('data-list-filter-type');
                // update tags
                that.myTags(that.channel, that.filter);
                // create custom UI filter elements
                that.addCustomTags(that.defaultTags);
                $('[data-list-filter-type=' + that.filter + ']').addClass('active');
                // Destroy gallery items
                that.destroyGallery();
                // Load new gallery
                that.loadGallery();
            });
        };
        TV.prototype.getMethodName = function() {
            var that = this;
            var criteria = '';
            switch($("[data-sort] .btn-group").find('.active').attr('data-type')){
                case "0":
                    criteria = "highlight";
                    break;
                case "1":
                    criteria = "most-visited";
                    break;
                case "2":
                    criteria = "popular";
                    break;
                case "3":
                    criteria = "most-visited-today";
                    break;
            }
            that.criteria = criteria;
            return criteria;
        };
        TV.prototype.getProfileVideoFeed = function() {
            var that = this;
            var type = $("[data-sort] .btn-group").find('.active').attr('data-type');
            if(typeof(type) === 'undefined'){
                type = 'popular';
            }
            var methodName = that.getMethodName();
            var opts = {
                'sort': that.criteria,
                'page': that.page,
                'entityId': that.entityId,
                'entityType': that.entityType
            };
            var route = '';
            switch(that.criteria){
                case 'popular':
                    route = that.dataList + "_popular";
                    break;
                case 'highlight':
                    route = that.dataList + "_highlighted";
                    break;
                case 'most-visited':
                    route = that.dataList + "_visited";
                    break;
                case 'most-visited-today':
                    route = that.dataList + "_visited";
                    opts.today = true;
                    break;
            }
            return route;
        };
        TV.prototype.filterToolbar = function($toolbar) {
            var that = this;
            var method = '';
            $("[data-sort] .btn-group .btn").on('click', function(){
                $(this).parent().find('.active').removeClass('active');
                $(this).addClass('active');
                switch($(this).attr('data-type')){
                    case "0":
                        that.criteria = "highlight";
                        break;
                    case "1":
                        that.criteria = "most-visited";
                        break;
                    case "2":
                        that.criteria = "popular";
                        break;
                    case "3":
                        that.criteria = "most-visited-today";
                        break;
                }
                var feed = that.getProfileVideoFeed();
                $(that.isotopeContainer).attr('data-feed-source', feed);
                console.log("filter: " + that.criteria + " feed: " + feed);
                var opts = {
                    'sort': that.criteria,
                    'page': that.page,
                    'entityId': that.entityId,
                    'entityType': that.entityType
                };
                console.log(opts);
                // Destroy gallery items
                that.destroyGallery();
                that.page = 1;  // reset page count
                // Load new gallery
                that.loadGallery();
            });
        };
        TV.prototype.filterToggle = function() {
            var that = this;
            $('#list-filters').find("li").click(function(e){
                var i;
                var selectedFilter = $(this).first().attr('data-list-filter-type');
                $('#list-filters').find("li.active").removeClass('active');
                $(this).first().addClass('active');

                that.filter = $('#list-filters ul').find('li.active').attr('data-list-filter-type');
                // update tags
                that.myTags(that.channel, that.filter);
                // custom tags
                if(that.filter === 'views') {
                    that.addCustomTags(that.defaultTags);
                }
                // Destroy gallery items
                that.destroyGallery();
                // Load new gallery
                that.profileGallery();
            });
        };
        TV.prototype.myTags = function(channel, filter) {
            var $tagList = $(".content-container").find(".tag-list-container ul");
            $tagList.empty();
            ajax.genericAction("tag_ajaxgetusedinvideos", {
                "channel": channel,
                "filter": filter
            }, function(r) {
                var i;
                for (i in r.tags) {
                    if (r.tags.hasOwnProperty(i)) {
                        var tagHref = Routing.generate(appLocale + "_teve_taggedvideos", {
                            term: r.tags[i].slug
                        });
                        //console.log(r.tags[i]);
                        $tagList.append("
" + r.tags[i].title + "
");
                    }
                }
            });
        };
        TV.prototype.addCustomTags = function(tags, options) {
            var that = this;
            var i;
            var $tagList = $(".content-container").find(".tag-list-container ul");
            for(i in tags) {
                if (tags.hasOwnProperty(i)) {
                    var $customFilter = $("
" + tags[i].title + "
");
                    that.customFilterToggler($customFilter);
                    $tagList.prepend($customFilter);
                }
            }
            return;
        };
        TV.prototype.destroyGallery = function() {
            $(this.isotopeContainer).data('fwGalerizer').destroy();
            return;
        };
        TV.prototype.subscribe = function ($button) {
            var channel = $button.attr('data-subscribe-channel');
            var params = {};

            if (!channel || channel === 'all') {
                return alert('Por favor elija un canal antes de suscribirse.');
            }
            params.channel = channel;

            $button.addClass('loading-small');

            ajax.genericAction('teve_channelsubscribe', params, function (response) {
                success(response.message);
                $button.text(response.buttontext);

                if (response.state === true) {
                    $button.prepend($('').attr('class', 'icon-remove').after(' '));
                } else if (response.state === false) {
                    $button.prepend($('').attr('class', 'icon-ok').after(' '));
                }
                $button.removeClass('loading-small');
            }, function (msg) {
                error(msg);
                $button.removeClass('loading-small');
            });
        };
        return TV;
    }());
    // Just return a value to define the module export.
    // This example returns an object, but the module
    // can return a function as the exported value.
    return TV;
}));

// implicit init that adds module to global scope
// TODO: refactor inside curl
$(document).ready(function () {
    "use strict";
    window.fansworld = window.fansworld || {};
    var defaultChannel = null; //
    var defaultFilter = 'popular';
    window.fansworld.tv = new window.TV(defaultChannel, defaultFilter);
    return;
});<commit_msg>issue 0000593: No muestra galerias<commit_after>/*global $, jQuery, alert, console, error, success, endless, ajax, templateHelper, Routing, appLocale, exports, module, require, define*/
/*jslint nomen: true */ /* Tolerate dangling _ in identifiers */
/*jslint vars: true */ /* Tolerate many var statements per function */
/*jslint white: true */
/*jslint browser: true */
/*jslint devel: true */ /* Assume console, alert, ... */
/*jslint windows: true */ /* Assume Windows */
/*jslint maxerr: 100 */ /* Maximum number of errors */

/*
 * Class dependencies:
 *      jquery > 1.8.3
 *      isotope
 *      jsrender
 *      jsviews
 * external dependencies:
 *      templateHelper
 *      base genericAction
 */

// fansWorld TV Class Module 1.1 (con galerias de profiles)
// 1.0

(function (root, factory) {
    "use strict";
    if (typeof exports === 'object') {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like enviroments that support module.exports,
        // like Node.
        module.exports = factory(require('Routing'), require('templateHelper'), require('ajax'), require('ExposeTranslation'));
    } else if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jQuery', 'Routing', 'templateHelper', 'ajax', 'ExposeTranslation'], factory);
    } else {
        // Browser globals (root is window)
        root.TV = factory(root.jQuery, root.Routing, root.templateHelper, root.ajax, root.ExposeTranslation);
    }
}(this, function (jQuery, Routing, templateHelper, ajax, ExposeTranslation) {
    "use strict";
    var TV = (function() {
        function TV(filtersList, channelsList) {
            //////////////
            // Internal //
            //////////////
            var that = this;
            this.jQuery = jQuery;
            this.name = filtersList;
            this.channelsList = channelsList;
            this.channel = $('.filter-channels').closest('ul').find("li.active").attr("data-channel-id");
            this.filter = $('#list-filters ul').find('li.active').attr('data-list-filter-type');

            this.page = 1;

            this.contentContainer = $('body');
            this.isotopeContainer = $(this.contentContainer).find('.isotope_container').last();
            if(this.isotopeContainer.length <= 0) {
                return;
            }
            this.feedSource = $(this.isotopeContainer).attr('data-feed-source');
            if(typeof this.feedSource === 'undefined' || this.feedSource == ''){
                this.entityId   = $("[data-list]").attr('data-entity-id');
                if(typeof this.entityId !== 'undefined'){
                    this.entityType = $("[data-list]").attr('data-entity-type');
                    this.dataList = $("[data-list]").attr('data-list');
                    this.isProfile = true;
                    console.log("in-profile");
                    var feed = that.getProfileVideoFeed();
                    console.log("filter: " + that.criteria + " feed: " + feed);
                    var opts = {
                        'sort': that.criteria,
                        'page': that.page,
                        'entityId': that.entityId,
                        'entityType': that.entityType
                    };
                    $(this.isotopeContainer).attr('data-feed-source', feed);
                    console.log(opts);
                } else {
                    return;
                }
            } else {
                this.isTeve = true;
            }
            this.defaultTags = [
                {filter: 'day', title: ExposeTranslation.get('day')},
                {filter: 'week', title: ExposeTranslation.get('week')},
                {filter: 'month', title: ExposeTranslation.get('month')}
            ];

            $(this.isotopeContainer).empty();

            //////////////
            // Bindings //
            //////////////
            // modalPopup
            $('#montage-video-list a').modalPopup();
            // subscribe buttons
            $('[data-subscribe-channel]').click(function () {
                that.subscribe($(this));
            });
            // Handle channel list
            this.channelToggle();
            // Handle Filter tabs (popular, views, latest)
            this.filterToggle();
            this.filterToolbar();

            ////////////////////
            // New TV Gallery //
            ////////////////////
            // load isotope gallery
            if(this.isTeve) {
                this.profileGallery();
            } else {
                this.loadGallery();
            }
            // Tags
            this.myTags();
            // custom tags
            if(this.filter === 'views') {
                this.addCustomTags(this.defaultTags);
            }
        }
        TV.prototype.loadGallery = function() {
            var that = this;
            $(this.isotopeContainer).fwGalerizer({
                normalize: false,
                endless: true,
                feedfilter: {
                    'sort': that.criteria,
                    'page': that.page,
                    'entityId': that.entityId,
                    'entityType': that.entityType
                },
                onEndless: function( plugin ) {
                    plugin.options.feedfilter.page += 1;
                    return plugin.options.feedfilter;
                },
                onDataReady: function(videos) {
                    var i, outp = [];
                    var normalize = function(video) {
                        var href = Routing.generate(appLocale + '_video_show', {
                            'id': video.id,
                            'slug': video.slug
                        });
                        var hrefModal = Routing.generate(appLocale + '_modal_media', {
                            'id': video.id,
                            'type': 'video'
                        });
                        var authorUrl = Routing.generate(appLocale + '_user_land', {
                            'username': 'juan.perez'
                        });
                        return {
                                'type': 'video',
                                'date': video.createdAt,
                                'href': href,
                                'hrefModal': hrefModal,
                                'image': video.imgsrc,
                                'slug': video.slug,
                                'title': video.title,
                                'author': 'juan.perez',
                                'authorHref': authorUrl,
                                'authorImage': 'http://fansworld.dodici.local/uploads/media/default/0001/02/thumb_1000_default_small_square_81dfa380953b084fb7eefb0273ac602bdee11874.jpg'
                        };
                    };
                    for(i in videos.elements) {
                        if (videos.elements.hasOwnProperty(i)) {
                            outp.push(normalize(videos.elements[i]));
                        }
                    }
                    return outp;
                }
            });
        };
        TV.prototype.profileGallery = function() {
            this.channel = $('.filter-channels').closest('ul').find("li.active").attr("data-channel-id");
            this.filter = $('#list-filters ul').find('li.active').attr('data-list-filter-type');
            this.page  = 1;
            $(this.isotopeContainer).fwGalerizer({
                normalize: false,
                endless: true,
                feedfilter: {'channel': this.channel, 'filter': this.filter, 'page': this.page},
                onEndless: function( plugin ) {
                    plugin.options.feedfilter.page += 1;
                    console.log("loading video gallery for channel %s with filter %s page: %s", plugin.options.feedfilter.channel, plugin.options.feedfilter.filter, plugin.options.feedfilter.page);
                    return plugin.options.feedfilter;
                },
                onDataReady: function(videos) {
                    var i, outp = [];
                    var normalize = function(video) {
                        var href = Routing.generate(appLocale + '_video_show', {
                            'id': video.id,
                            'slug': video.slug
                        });
                        var hrefModal = Routing.generate(appLocale + '_modal_media', {
                            'id': video.id,
                            'type': 'video'
                        });
                        var authorUrl = Routing.generate(appLocale + '_user_land', {
                            'username': video.author.username
                        });
                        return {
                                'type': 'video',
                                'date': video.createdAt,
                                'href': href,
                                'hrefModal': hrefModal,
                                'image': video.image,
                                'slug': video.slug,
                                'title': video.title,
                                'author': video.author.username,
                                'authorHref': authorUrl,
                                'authorImage': video.author.image
                        };
                    };
                    for(i in videos.videos) {
                        if (videos.videos.hasOwnProperty(i)) {
                            outp.push(normalize(videos.videos[i]));
                        }
                    }
                    return outp;
                }
            });
            this.page += 1;
        };
        TV.prototype.channelToggle = function() {
            var that = this;
            $('.filter-channels').closest('ul').find("li").click(function(e){
                var i;
                var selectedChannel = $(this).first().attr('data-list-target');
                $(".channels-widget .content .active").removeClass('active');
                $('.filter-channels').closest('ul').find("li.active").removeClass('active');
                $(this).first().addClass('active');

                $(".channels-widget .content #" + selectedChannel).addClass('active');

                // Update channel
                that.channel = $('.filter-channels').closest('ul').find("li.active").attr("data-channel-id");
                // update tags
                that.myTags(that.channel, that.filter);
                // custom tags
                if(that.filter === 'views') {
                    that.addCustomTags(that.defaultTags);
                }
                // Destroy gallery items
                that.destroyGallery();
                // Load new gallery
                that.profileGallery();
            });
        };
        TV.prototype.customFilterToggler = function(element) {
            var that = this;
            element.click(function(e){
                $('[data-list-filter-type=' + that.filter + ']').removeClass();
                that.filter = $(this).attr('data-list-filter-type');
                // update tags
                that.myTags(that.channel, that.filter);
                // create custom UI filter elements
                that.addCustomTags(that.defaultTags);
                $('[data-list-filter-type=' + that.filter + ']').addClass('active');
                // Destroy gallery items
                that.destroyGallery();
                // Load new gallery
                that.loadGallery();
            });
        };
        TV.prototype.getMethodName = function() {
            var that = this;
            var criteria = '';
            switch($("[data-sort] .btn-group").find('.active').attr('data-type')){
                case "0":
                    criteria = "highlight";
                    break;
                case "1":
                    criteria = "most-visited";
                    break;
                case "2":
                    criteria = "popular";
                    break;
                case "3":
                    criteria = "most-visited-today";
                    break;
            }
            that.criteria = criteria;
            return criteria;
        };
        TV.prototype.getProfileVideoFeed = function() {
            var that = this;
            var type = $("[data-sort] .btn-group").find('.active').attr('data-type');
            if(typeof(type) === 'undefined'){
                type = 'popular';
            }
            var methodName = that.getMethodName();
            var opts = {
                'sort': that.criteria,
                'page': that.page,
                'entityId': that.entityId,
                'entityType': that.entityType
            };
            var route = '';
            switch(that.criteria){
                case 'popular':
                    route = that.dataList + "_popular";
                    break;
                case 'highlight':
                    route = that.dataList + "_highlighted";
                    break;
                case 'most-visited':
                    route = that.dataList + "_visited";
                    break;
                case 'most-visited-today':
                    route = that.dataList + "_visited";
                    opts.today = true;
                    break;
            }
            return route;
        };
        TV.prototype.filterToolbar = function($toolbar) {
            var that = this;
            var method = '';
            $("[data-sort] .btn-group .btn").on('click', function(){
                $(this).parent().find('.active').removeClass('active');
                $(this).addClass('active');
                switch($(this).attr('data-type')){
                    case "0":
                        that.criteria = "highlight";
                        break;
                    case "1":
                        that.criteria = "most-visited";
                        break;
                    case "2":
                        that.criteria = "popular";
                        break;
                    case "3":
                        that.criteria = "most-visited-today";
                        break;
                }
                var feed = that.getProfileVideoFeed();
                $(that.isotopeContainer).attr('data-feed-source', feed);
                console.log("filter: " + that.criteria + " feed: " + feed);
                var opts = {
                    'sort': that.criteria,
                    'page': that.page,
                    'entityId': that.entityId,
                    'entityType': that.entityType
                };
                console.log(opts);
                // Destroy gallery items
                that.destroyGallery();
                that.page = 1;  // reset page count
                // Load new gallery
                that.loadGallery();
            });
        };
        TV.prototype.filterToggle = function() {
            var that = this;
            $('#list-filters').find("li").click(function(e){
                var i;
                var selectedFilter = $(this).first().attr('data-list-filter-type');
                $('#list-filters').find("li.active").removeClass('active');
                $(this).first().addClass('active');

                that.filter = $('#list-filters ul').find('li.active').attr('data-list-filter-type');
                // update tags
                that.myTags(that.channel, that.filter);
                // custom tags
                if(that.filter === 'views') {
                    that.addCustomTags(that.defaultTags);
                }
                // Destroy gallery items
                that.destroyGallery();
                // Load new gallery
                that.profileGallery();
            });
        };
        TV.prototype.myTags = function(channel, filter) {
            var $tagList = $(".content-container").find(".tag-list-container ul");
            $tagList.empty();
            ajax.genericAction("tag_ajaxgetusedinvideos", {
                "channel": channel,
                "filter": filter
            }, function(r) {
                var i;
                for (i in r.tags) {
                    if (r.tags.hasOwnProperty(i)) {
                        var tagHref = Routing.generate(appLocale + "_teve_taggedvideos", {
                            term: r.tags[i].slug
                        });
                        //console.log(r.tags[i]);
                        $tagList.append("
" + r.tags[i].title + "
");
                    }
                }
            });
        };
        TV.prototype.addCustomTags = function(tags, options) {
            var that = this;
            var i;
            var $tagList = $(".content-container").find(".tag-list-container ul");
            for(i in tags) {
                if (tags.hasOwnProperty(i)) {
                    var $customFilter = $("
" + tags[i].title + "
");
                    that.customFilterToggler($customFilter);
                    $tagList.prepend($customFilter);
                }
            }
            return;
        };
        TV.prototype.destroyGallery = function() {
            $(this.isotopeContainer).data('fwGalerizer').destroy();
            return;
        };
        TV.prototype.subscribe = function ($button) {
            var channel = $button.attr('data-subscribe-channel');
            var params = {};

            if (!channel || channel === 'all') {
                return alert('Por favor elija un canal antes de suscribirse.');
            }
            params.channel = channel;

            $button.addClass('loading-small');

            ajax.genericAction('teve_channelsubscribe', params, function (response) {
                success(response.message);
                $button.text(response.buttontext);

                if (response.state === true) {
                    $button.prepend($('').attr('class', 'icon-remove').after(' '));
                } else if (response.state === false) {
                    $button.prepend($('').attr('class', 'icon-ok').after(' '));
                }
                $button.removeClass('loading-small');
            }, function (msg) {
                error(msg);
                $button.removeClass('loading-small');
            });
        };
        return TV;
    }());
    // Just return a value to define the module export.
    // This example returns an object, but the module
    // can return a function as the exported value.
    return TV;
}));

// implicit init that adds module to global scope
// TODO: refactor inside curl
$(document).ready(function () {
    "use strict";
    window.fansworld = window.fansworld || {};
    var defaultChannel = null; //
    var defaultFilter = 'popular';
    window.fansworld.tv = new window.TV(defaultChannel, defaultFilter);
    return;
});<|endoftext|>


<commit_before>"use strict";

angular.module("es.logongas.ix3").directive('ix3Options', ['remoteServiceFactory', function(remoteServiceFactory) {
        function setValue(obj, key, newValue) {
            var keys = key.split('.');
            for (var i = 0; i < keys.length - 1; i++) {
                if (!obj[keys[i]]) {
                    obj[keys[i]] = {};
                }
                obj = obj[keys[i]];

            }
            obj[keys[keys.length - 1]] = newValue;
        }

        function getMetadataPropertyName(key) {
            var keys = key.split('.');
            var name = "";
            for (var i = 0; i < keys.length; i++) {
                if (name !== "") {
                    name = name + ".";
                }
                name = name + "properties['" + keys[i] + "']";
            }
            return name;
        }

        return {
            restrict: 'A',
            scope: true,
            compile: function(element, attributes) {
                attributes.ngOptions = ""; //Ponemos esta aqui para que luego la compile.
                return {
                    pre: function($scope, element, attributes) {
                        var filters = attributes.ix3Options;

                        var modelProperty = {
                            name: attributes.ngModel.replace("model.", ""),
                            metadata: $scope.$eval("metadata[entity]." + getMetadataPropertyName(attributes.ngModel.replace("model.", ""))),
                            scopeAccessName: attributes.ngModel
                        };

                        if (angular.isArray(modelProperty.metadata.values)) {
                            $scope.values = modelProperty.metadata.values;
                        } else {
                            $scope.values = [];
                        }

                        var ngOptions;
                        if (modelProperty.metadata.type === "OBJECT") {

                            if ((modelProperty.metadata.dependProperty) && (modelProperty.metadata.dependProperty.length > 0)) {
                                var remoteService = remoteServiceFactory.getRemoteService(modelProperty.metadata.className);
                                var parts = modelProperty.name.split(".");
                                parts[parts.length - 1] = modelProperty.metadata.dependProperty;
                                var dependProperty = {
                                    name: parts.join("."),
                                    metadata: $scope.$eval("metadata[entity]." + getMetadataPropertyName(parts.join("."))),
                                    scopeAccessName: "model." + parts.join(".")
                                };
                                var filterProperty = {
                                    name: modelProperty.metadata.dependProperty, //OJO:El nombre es relativo a la propiedad principal y no desde el principio
                                    metadata: $scope.$eval("metadata[entity]." + getMetadataPropertyName(modelProperty.name + "." + modelProperty.metadata.dependProperty))
                                };
                                $scope.$watch(dependProperty.scopeAccessName + "." + dependProperty.metadata.primaryKeyPropertyName, function(newValue, oldValue) {
                                    if (newValue === oldValue) {
                                        return;
                                    }

                                    if (newValue) {
                                        var filter = {};
                                        filter[filterProperty.name + "." + filterProperty.metadata.primaryKeyPropertyName] = newValue;
                                        remoteService.search(filter).then(function(values) {
                                            $scope.values = values;

                                            var exist = false;
                                            var primaryKey = $scope.$eval(modelProperty.scopeAccessName)[modelProperty.metadata.primaryKeyPropertyName];

                                            for (var i = 0; i < values.length; i++) {
                                                var value = values[i];
                                                if (value[modelProperty.metadata.primaryKeyPropertyName] === primaryKey) {
                                                    exist = true;
                                                    break;
                                                }
                                            }

                                            if (exist === false) {
                                                setValue($scope.$parent, modelProperty.scopeAccessName, null);
                                            }
                                        }, function(businessMessages) {
                                            //Si hay un error borramos la lista y el valor dependiente
                                            $scope.values = [];
                                            setValue($scope.$parent, modelProperty.scopeAccessName, null);
                                            $scope.$parent.businessMessages = businessMessages;
                                        });
                                    } else {
                                        //Si no hay valor padre, borramos la lista y el valor dependiente
                                        $scope.values = [];
                                        setValue($scope.$parent, modelProperty.scopeAccessName, null);
                                    }
                                });
                            }

                            if ((filters) && (filters.trim() !== "")) {
                                ngOptions = "value as value.toString for value in values | " + filters + " track by value." + modelProperty.metadata.primaryKeyPropertyName + "";
                            } else {
                                ngOptions = "value as value.toString for value in values track by value." + modelProperty.metadata.primaryKeyPropertyName + "";
                            }

                        } else {
                            ngOptions = "value.key as value.description for value in values ";
                        }

                        attributes.ngOptions = ngOptions;

                    },
                    post: function($scope, element, attributes) {
                    }
                };
            }
        };
    }]);<commit_msg>El replace de "model." solo se hace al inicio del string , por eso ahora se pone una expresion regular.<commit_after>"use strict";

angular.module("es.logongas.ix3").directive('ix3Options', ['remoteServiceFactory', function(remoteServiceFactory) {
        function setValue(obj, key, newValue) {
            var keys = key.split('.');
            for (var i = 0; i < keys.length - 1; i++) {
                if (!obj[keys[i]]) {
                    obj[keys[i]] = {};
                }
                obj = obj[keys[i]];

            }
            obj[keys[keys.length - 1]] = newValue;
        }

        function getMetadataPropertyName(key) {
            var keys = key.split('.');
            var name = "";
            for (var i = 0; i < keys.length; i++) {
                if (name !== "") {
                    name = name + ".";
                }
                name = name + "properties['" + keys[i] + "']";
            }
            return name;
        }

        return {
            restrict: 'A',
            scope: true,
            compile: function(element, attributes) {
                attributes.ngOptions = ""; //Ponemos esta aqui para que luego la compile.
                return {
                    pre: function($scope, element, attributes) {
                        var filters = attributes.ix3Options;

                        var modelProperty = {
                            name: attributes.ngModel.replace(/^model\./, ""),
                            metadata: $scope.$eval("metadata[entity]." + getMetadataPropertyName(attributes.ngModel.replace(/^model\./, ""))),
                            scopeAccessName: attributes.ngModel
                        };

                        if (angular.isArray(modelProperty.metadata.values)) {
                            $scope.values = modelProperty.metadata.values;
                        } else {
                            $scope.values = [];
                        }

                        var ngOptions;
                        if (modelProperty.metadata.type === "OBJECT") {

                            if ((modelProperty.metadata.dependProperty) && (modelProperty.metadata.dependProperty.length > 0)) {
                                var remoteService = remoteServiceFactory.getRemoteService(modelProperty.metadata.className);
                                var parts = modelProperty.name.split(".");
                                parts[parts.length - 1] = modelProperty.metadata.dependProperty;
                                var dependProperty = {
                                    name: parts.join("."),
                                    metadata: $scope.$eval("metadata[entity]." + getMetadataPropertyName(parts.join("."))),
                                    scopeAccessName: "model." + parts.join(".")
                                };
                                var filterProperty = {
                                    name: modelProperty.metadata.dependProperty, //OJO:El nombre es relativo a la propiedad principal y no desde el principio
                                    metadata: $scope.$eval("metadata[entity]." + getMetadataPropertyName(modelProperty.name + "." + modelProperty.metadata.dependProperty))
                                };
                                $scope.$watch(dependProperty.scopeAccessName + "." + dependProperty.metadata.primaryKeyPropertyName, function(newValue, oldValue) {
                                    if (newValue === oldValue) {
                                        return;
                                    }

                                    if (newValue) {
                                        var filter = {};
                                        filter[filterProperty.name + "." + filterProperty.metadata.primaryKeyPropertyName] = newValue;
                                        remoteService.search(filter).then(function(values) {
                                            $scope.values = values;

                                            var exist = false;
                                            var primaryKey = $scope.$eval(modelProperty.scopeAccessName)[modelProperty.metadata.primaryKeyPropertyName];

                                            for (var i = 0; i < values.length; i++) {
                                                var value = values[i];
                                                if (value[modelProperty.metadata.primaryKeyPropertyName] === primaryKey) {
                                                    exist = true;
                                                    break;
                                                }
                                            }

                                            if (exist === false) {
                                                setValue($scope.$parent, modelProperty.scopeAccessName, null);
                                            }
                                        }, function(businessMessages) {
                                            //Si hay un error borramos la lista y el valor dependiente
                                            $scope.values = [];
                                            setValue($scope.$parent, modelProperty.scopeAccessName, null);
                                            $scope.$parent.businessMessages = businessMessages;
                                        });
                                    } else {
                                        //Si no hay valor padre, borramos la lista y el valor dependiente
                                        $scope.values = [];
                                        setValue($scope.$parent, modelProperty.scopeAccessName, null);
                                    }
                                });
                            }

                            if ((filters) && (filters.trim() !== "")) {
                                ngOptions = "value as value.toString for value in values | " + filters + " track by value." + modelProperty.metadata.primaryKeyPropertyName + "";
                            } else {
                                ngOptions = "value as value.toString for value in values track by value." + modelProperty.metadata.primaryKeyPropertyName + "";
                            }

                        } else {
                            ngOptions = "value.key as value.description for value in values ";
                        }

                        attributes.ngOptions = ngOptions;

                    },
                    post: function($scope, element, attributes) {
                    }
                };
            }
        };
    }]);<|endoftext|>


<commit_before>;(function() {
  'use strict';

angular
    .module('cpZenPlatform')
    .component('cdStartDojo', {
      restrict: 'EA',
      bindings: {
        currentUser: '='
      },
      templateUrl: '/directives/tpl/cd-start-dojo',
      controller: [ '$rootScope', '$translate', 'usSpinnerService',
        'atomicNotifyService', '$state', '$window', '$q', '$sce', 'cdDojoService', 'alertService',
        'cdAgreementsService', 'cdUsersService', 'intercomService', 'cdOrganisationsService',
      function ($rootScope, $translate, usSpinnerService,
        atomicNotifyService, $state, $window, $q, $sce, cdDojoService, alertService,
        cdAgreementsService, cdUsersService, intercomService, cdOrganisationsService) {
        var ctrl = this;
        ctrl.tabs = [
          {
            name: 'champion',
            state: 'start-dojo.champion',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Champion Registration')
          },
          {
            name: 'venue',
            state: 'start-dojo.venue',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Venue Details')
          },
          {
            name: 'team',
            state: 'start-dojo.team',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Gather your Team')
          },
          {
            name: 'dojo',
            state: 'start-dojo.information',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Dojo Information')
          },
          {
            name: 'charter',
            state: 'start-dojo.charter',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Sign the Charter')
          },
          {
            name: 'review',
            state: 'start-dojo.review',
            tabTitle: $translate.instant('Review your application')
          }
        ];
        function setStatusIcon () {
          return $sce.trustAsHtml(this.validity);
        }

        ctrl.loading = true;

        ctrl.save = function () {
          if (!ctrl.loading) {
            ctrl.loading = true;
            var lead = ctrl.prepareSavePayload();
            lead.completed = false;
            return cdDojoService.saveDojoLead(lead)
              .then(function (lead) {
                ctrl.leadId = lead.data.id;
                ctrl.application = lead.data.application;
                ctrl.loading = false;
              });
          }
        };
        ctrl.actions = {};
        ctrl.actions.submit = function () {
          ctrl.loading = true;
          // Submit dojoLead upgrade an existing lead
          // So we presubmit it in case an user went all the way down to the last step in one run
          var lead = ctrl.prepareSavePayload();
          lead.completed = ctrl.isValid();
          return cdDojoService.submitDojoLead(ctrl.leadId, lead)
          .then(function () {
            atomicNotifyService.info(
              $translate.instant('Congratulations! Your Dojo application is being reviewed by a member of the CoderDojo Foundation team.') + '\n' +
              $translate.instant('We will respond to you within 48 hours, so hang tight while we check the information you have submitted.')
            );
            saveOnStateChange();
            ctrl.loading = false;
            $state.go('my-dojos');
          })
          .catch(function () {
            // This should not happen and be caught by the front before submitting
            ctrl.loading = false;
            alertService.showError($translate.instant('Something went wrong while submitting your application, please contact support'));
            intercomService.show();
          });
        };
        ctrl.actions.save = function () {
          ctrl.save()
          .then(function (lead) { ctrl.setCharterStatus(ctrl.application.charter); })
          .then(function (lead) {
            if (ctrl.application.dojo.id) {
              cdDojoService.getUsersDojos({userId: ctrl.userId})
              .then(function (res) {
                intercomService.update(_.map(res.data, 'id'));
              });
            }
          })
          .then(function (lead) {
            ctrl.goToNextStep(true);
          });
        };

        // Redirect you to the next more logic step.
        // Should not block you while filling (next is the order based next)
        // but should help you when reviewing (next is the next Invalid or the review page is fully valid)
        ctrl.goToNextStep = function (excludePrevious) {
          var index = 0;
          if (ctrl.application && ctrl.isValid()) {
            // We go to the review tab
            index = ctrl.tabs.length - 1;
          } else {
            // We go to the next tab that is invalid
            // normal = next; review = next invalid
            var state = $state.current.name;
            var application = ctrl.application;
            var tabs = _.cloneDeep(ctrl.tabs);
            if (excludePrevious) {
              var currentStepIndex = _.findIndex(ctrl.tabs, {state: state});
              // We increase of 1 to exclude self
              if (currentStepIndex < ctrl.tabs.length) currentStepIndex ++;
              tabs = tabs.splice(currentStepIndex, ctrl.tabs.length);
              application = _.pick(ctrl.application, _.map(tabs, 'name'));
            }
            var nextStep = _.findKey(application, {isValid: false});
            index = _.findIndex(ctrl.tabs,
              function (o, k) {
                return o.name === nextStep;
              });
            if (index < 0) {
              index = ctrl.tabs.length - 1;
            }
          }
          var nextState = ctrl.tabs[index].state;
          var deferred = $q.defer();
          if (nextState !== $state.current.name) {
            // We force a reinit of the next state, elsewhat controllers'form may not initialize
            $state.go(nextState, {skip: true});
          }
        };

        ctrl.prepareSavePayload = function () {
          var application = _.cloneDeep(ctrl.application);
          var currentStep = _.find(ctrl.tabs, {state: $state.current.name});
          _.each(application, function (step, key, application) {
            if (currentStep.name === key) { // We modify only the current step
              application[key].isValid = !_.isUndefined(step.formValidity) ? step.formValidity : (step.isValid ? step.isValid  : false) ;
              // Flag to display missing field : it's a returning user to this page
              application[key].visited = true;
            }
            delete step.form;
            delete step.formValidity;
            application[key] = _.omitBy(step, function (val) {return _.isNil(val) || val === '';}); // Remove null keys to avoid validations errors
          });
          var lead = {
            userId: ctrl.userId,
            application : application
          };

          if (ctrl.leadId) lead.id = ctrl.leadId;
          return lead;
        };
        ctrl.isValid = ctrl.actions.isValid = function () {
          var validities = _.map(ctrl.application, function (step) {
            return step.formValidity ||// Current form validity
              step.isValid; // saved validity
          });
          ctrl.updateTabsStatus();
          return _.every(validities);
        };

        ctrl.updateTabsStatus = function () {
          _.each(ctrl.application, function (step, key) {
            var index = _.findKey(ctrl.tabs, {name: key});
            ctrl.tabs[index].validity = '<i class="fa ' + (step.isValid ? 'fa-check cd-icon--success' : step.visited ? 'fa-times cd-icon--danger' : '') + '"></i>';
          });
        };
        ctrl.actions.isLastTab = function () {
          return _.findIndex(ctrl.tabs, _.find(ctrl.tabs, {state: $state.current.name})) === ctrl.tabs.length - 1;
        };
        ctrl.setCharterStatus = function (agreement) {
          if (agreement && agreement.id) {
            ctrl.application.charter = {
              fullName: agreement.fullName,
              id: agreement.id
            };
            ctrl.application.charter.isValid = true;
            ctrl.application.charter.visited = true;
          } else {
            ctrl.application.charter = {
              isValid: false,
              visited : agreement.visited || false
            };
          }
        };
        ctrl.tabHeader = function () {
          var header = 0;
          if (ctrl.application) {
            header = (_.filter(ctrl.application, function (step) {
              return step.isValid; // Only saved validity matter
            })).length / _.keys(ctrl.application).length * 100;
          }
          return Math.floor(header) + '% completed';
        };

        var saveOnStateChange = $rootScope.$on('$stateChangeStart', function (event, nextState, nextParams, fromState) {
          if (nextState.name !== $state.current.name && !nextParams.skip) {
            ctrl.save();
          }
        });

        ctrl.$onInit = function () {
          var leadQuery = {userId: ctrl.currentUser.id, deleted: 0};
          if ($state.params.id) {
            ctrl.leadId = $state.params.id;
            // By passing an id, we allow ourselves to bypass the restriction regarding the completion
            leadQuery = {id: ctrl.leadId};
          }
          // We use the generic version of search as we don't know yet who's the owner for sure
          // It can be a CDF viewing, which means we don't want to overwrite the owner of the lead
          return cdDojoService.searchLeads(leadQuery)
          .then(function (leads) {
            ctrl.leads = leads.data;
            return $q.resolve();
          })
          .then(function () {
            // Filter finished leads for its creator.
            if (ctrl.leads.length > 0) {
              var ids = _.filter(_.map(ctrl.leads, 'application.dojo.id'), _.identity);
              if (ids.length > 0) {
                var query = {verified : 1, id: {in$: ids}};
                return cdDojoService.list(query)
                .then(function (res) {
                  var dojos = res.data;
                  ctrl.leads = _.filter(ctrl.leads, function (lead) {
                    var matchingLead = _.find(dojos, function (dojo) {
                      return dojo.dojoLeadId === lead.id;
                    });
                    return !matchingLead;
                  });
                  return $q.resolve();
                });
              } else {
                return $q.resolve();
              }
            } else {
              return $q.resolve();
            }
          })
          .then(function () {
            return cdOrganisationsService.loadUserOrgs(ctrl.currentUser.id)
            .then(function (res) {
              ctrl.orgs = res.data;
              // Multiple lead for a non-authorised user, loophole detected
              if (ctrl.leads.length > 1) {
                ctrl.userId = ctrl.leads[0].userId;
                if (!ctrl.orgs || ctrl.orgs.length === 0 ) {
                  alertService.showError($translate.instant('Multiple ongoing lead, please contact support'));
                  intercomService.show();
                  return $q.reject();
                }
              }
              if (ctrl.leads.length === 1) {
                // Reload previous lead
                if (_.isEmpty(ctrl.orgs) || $state.params.id) {
                  ctrl.application = _.merge(ctrl.application, ctrl.leads[0].application);
                  ctrl.leadId = ctrl.leads[0].id;
                }
                // Set creator user
                ctrl.userId = ctrl.leads[0].userId;
                return $q.resolve();
              }
            });
          })
          .then(function () {
            var userProfileQuery = {
              userId: ctrl.currentUser.id
            };
            if ($state.params.id) {
              userProfileQuery = {
                userId: ctrl.userId
              };
            }
            return cdUsersService.userProfileData(userProfileQuery)
            .then(function (profile) {
              ctrl.profile = profile.data;
            });
          })
          .then(function () {
            // NOTE : this starts to get quite big
            if (ctrl.leads.length === 0 || (!_.isEmpty(ctrl.orgs) && !$state.params.id)) {
              ctrl.userId = ctrl.currentUser.id;
              // Merge is used here to avoid overwriting data set by substate ctrllers (ie forms)
              ctrl.application = _.merge(ctrl.application, {
                champion: {
                  firstName: ctrl.profile.firstName,
                  lastName: ctrl.profile.lastName,
                  email: ctrl.profile.email,
                  dob: new Date(ctrl.profile.dob),
                  phone: ctrl.profile.phone,
                  twitter: ctrl.profile.twitter,
                  linkedin: ctrl.profile.linkedin,
                  isValid: false,
                  visited: false
                },
                dojo: {startTime: moment({minutes: 0}).format('HH:mm'), endTime: moment({minutes: 0}).format('HH:mm'), requestEmail: true, visited: false, isValid: false},
                venue: {private: 0, visited: false, isValid: false},
                team: {visited: false, isValid: false}
              });
            }
          })
          // The user may already have signed the charter, we load this separatly
          .then(function () {
            var agreement = {};
            cdAgreementsService.getCurrentCharterVersion()
            .then(function (response) {
              agreement.version = response.data.version;
            })
            .then(function () {
              return cdAgreementsService.loadUserAgreement(agreement.version, ctrl.profile.userId)
              .then(function (response) {
                if (response.data) {
                  agreement = response.data;
                  agreement.visited = true;
                } else {
                  agreement = ctrl.application.charter || {};
                }
              })
              .finally(function () { ctrl.setCharterStatus(agreement); });
            });
          })
          .then(function () {
            ctrl.loading = false;
            intercomService.InitIntercom();
            // We go to the next invalid step when the application has been previously started
            if (ctrl.leadId) ctrl.goToNextStep();
          });
        };
        ctrl.$onDestroy = function () {
          saveOnStateChange();
        };
      }]
    });
}());
<commit_msg>Ensure that the lack of userId is only applied to CDF elsewhat the perm 'is_self' cannot be triggered<commit_after>;(function() {
  'use strict';

angular
    .module('cpZenPlatform')
    .component('cdStartDojo', {
      restrict: 'EA',
      bindings: {
        currentUser: '='
      },
      templateUrl: '/directives/tpl/cd-start-dojo',
      controller: [ '$rootScope', '$translate', 'usSpinnerService',
        'atomicNotifyService', '$state', '$window', '$q', '$sce', 'cdDojoService', 'alertService',
        'cdAgreementsService', 'cdUsersService', 'intercomService', 'cdOrganisationsService',
      function ($rootScope, $translate, usSpinnerService,
        atomicNotifyService, $state, $window, $q, $sce, cdDojoService, alertService,
        cdAgreementsService, cdUsersService, intercomService, cdOrganisationsService) {
        var ctrl = this;
        ctrl.tabs = [
          {
            name: 'champion',
            state: 'start-dojo.champion',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Champion Registration')
          },
          {
            name: 'venue',
            state: 'start-dojo.venue',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Venue Details')
          },
          {
            name: 'team',
            state: 'start-dojo.team',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Gather your Team')
          },
          {
            name: 'dojo',
            state: 'start-dojo.information',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Dojo Information')
          },
          {
            name: 'charter',
            state: 'start-dojo.charter',
            status: setStatusIcon,
            validity: '',
            tabTitle: $translate.instant('Sign the Charter')
          },
          {
            name: 'review',
            state: 'start-dojo.review',
            tabTitle: $translate.instant('Review your application')
          }
        ];
        function setStatusIcon () {
          return $sce.trustAsHtml(this.validity);
        }

        ctrl.loading = true;

        ctrl.save = function () {
          if (!ctrl.loading) {
            ctrl.loading = true;
            var lead = ctrl.prepareSavePayload();
            lead.completed = false;
            return cdDojoService.saveDojoLead(lead)
              .then(function (lead) {
                ctrl.leadId = lead.data.id;
                ctrl.application = lead.data.application;
                ctrl.loading = false;
              });
          }
        };
        ctrl.actions = {};
        ctrl.actions.submit = function () {
          ctrl.loading = true;
          // Submit dojoLead upgrade an existing lead
          // So we presubmit it in case an user went all the way down to the last step in one run
          var lead = ctrl.prepareSavePayload();
          lead.completed = ctrl.isValid();
          return cdDojoService.submitDojoLead(ctrl.leadId, lead)
          .then(function () {
            atomicNotifyService.info(
              $translate.instant('Congratulations! Your Dojo application is being reviewed by a member of the CoderDojo Foundation team.') + '\n' +
              $translate.instant('We will respond to you within 48 hours, so hang tight while we check the information you have submitted.')
            );
            saveOnStateChange();
            ctrl.loading = false;
            $state.go('my-dojos');
          })
          .catch(function () {
            // This should not happen and be caught by the front before submitting
            ctrl.loading = false;
            alertService.showError($translate.instant('Something went wrong while submitting your application, please contact support'));
            intercomService.show();
          });
        };
        ctrl.actions.save = function () {
          ctrl.save()
          .then(function (lead) { ctrl.setCharterStatus(ctrl.application.charter); })
          .then(function (lead) {
            if (ctrl.application.dojo.id) {
              cdDojoService.getUsersDojos({userId: ctrl.userId})
              .then(function (res) {
                intercomService.update(_.map(res.data, 'id'));
              });
            }
          })
          .then(function (lead) {
            ctrl.goToNextStep(true);
          });
        };

        // Redirect you to the next more logic step.
        // Should not block you while filling (next is the order based next)
        // but should help you when reviewing (next is the next Invalid or the review page is fully valid)
        ctrl.goToNextStep = function (excludePrevious) {
          var index = 0;
          if (ctrl.application && ctrl.isValid()) {
            // We go to the review tab
            index = ctrl.tabs.length - 1;
          } else {
            // We go to the next tab that is invalid
            // normal = next; review = next invalid
            var state = $state.current.name;
            var application = ctrl.application;
            var tabs = _.cloneDeep(ctrl.tabs);
            if (excludePrevious) {
              var currentStepIndex = _.findIndex(ctrl.tabs, {state: state});
              // We increase of 1 to exclude self
              if (currentStepIndex < ctrl.tabs.length) currentStepIndex ++;
              tabs = tabs.splice(currentStepIndex, ctrl.tabs.length);
              application = _.pick(ctrl.application, _.map(tabs, 'name'));
            }
            var nextStep = _.findKey(application, {isValid: false});
            index = _.findIndex(ctrl.tabs,
              function (o, k) {
                return o.name === nextStep;
              });
            if (index < 0) {
              index = ctrl.tabs.length - 1;
            }
          }
          var nextState = ctrl.tabs[index].state;
          var deferred = $q.defer();
          if (nextState !== $state.current.name) {
            // We force a reinit of the next state, elsewhat controllers'form may not initialize
            $state.go(nextState, {skip: true});
          }
        };

        ctrl.prepareSavePayload = function () {
          var application = _.cloneDeep(ctrl.application);
          var currentStep = _.find(ctrl.tabs, {state: $state.current.name});
          _.each(application, function (step, key, application) {
            if (currentStep.name === key) { // We modify only the current step
              application[key].isValid = !_.isUndefined(step.formValidity) ? step.formValidity : (step.isValid ? step.isValid  : false) ;
              // Flag to display missing field : it's a returning user to this page
              application[key].visited = true;
            }
            delete step.form;
            delete step.formValidity;
            application[key] = _.omitBy(step, function (val) {return _.isNil(val) || val === '';}); // Remove null keys to avoid validations errors
          });
          var lead = {
            userId: ctrl.userId,
            application : application
          };

          if (ctrl.leadId) lead.id = ctrl.leadId;
          return lead;
        };
        ctrl.isValid = ctrl.actions.isValid = function () {
          var validities = _.map(ctrl.application, function (step) {
            return step.formValidity ||// Current form validity
              step.isValid; // saved validity
          });
          ctrl.updateTabsStatus();
          return _.every(validities);
        };

        ctrl.updateTabsStatus = function () {
          _.each(ctrl.application, function (step, key) {
            var index = _.findKey(ctrl.tabs, {name: key});
            ctrl.tabs[index].validity = '<i class="fa ' + (step.isValid ? 'fa-check cd-icon--success' : step.visited ? 'fa-times cd-icon--danger' : '') + '"></i>';
          });
        };
        ctrl.actions.isLastTab = function () {
          return _.findIndex(ctrl.tabs, _.find(ctrl.tabs, {state: $state.current.name})) === ctrl.tabs.length - 1;
        };
        ctrl.setCharterStatus = function (agreement) {
          if (agreement && agreement.id) {
            ctrl.application.charter = {
              fullName: agreement.fullName,
              id: agreement.id
            };
            ctrl.application.charter.isValid = true;
            ctrl.application.charter.visited = true;
          } else {
            ctrl.application.charter = {
              isValid: false,
              visited : agreement.visited || false
            };
          }
        };
        ctrl.tabHeader = function () {
          var header = 0;
          if (ctrl.application) {
            header = (_.filter(ctrl.application, function (step) {
              return step.isValid; // Only saved validity matter
            })).length / _.keys(ctrl.application).length * 100;
          }
          return Math.floor(header) + '% completed';
        };

        var saveOnStateChange = $rootScope.$on('$stateChangeStart', function (event, nextState, nextParams, fromState) {
          if (nextState.name !== $state.current.name && !nextParams.skip) {
            ctrl.save();
          }
        });

        ctrl.$onInit = function () {
          var leadQuery = {userId: ctrl.currentUser.id, deleted: 0};
          if ($state.params.id) {
            ctrl.leadId = $state.params.id;
            // By passing an id, we allow ourselves to bypass the restriction regarding the completion
            if (ctrl.currentUser.roles.includes('cdf-admin')) {
              leadQuery = {id: ctrl.leadId};
            } else {
              leadQuery.id = ctrl.leadId;
            }
          }
          // We use the generic version of search as we don't know yet who's the owner for sure
          // It can be a CDF viewing, which means we don't want to overwrite the owner of the lead
          return cdDojoService.searchLeads(leadQuery)
          .then(function (leads) {
            ctrl.leads = leads.data;
            return $q.resolve();
          })
          .then(function () {
            // Filter finished leads for its creator.
            if (ctrl.leads.length > 0) {
              var ids = _.filter(_.map(ctrl.leads, 'application.dojo.id'), _.identity);
              if (ids.length > 0) {
                var query = {verified : 1, id: {in$: ids}};
                return cdDojoService.list(query)
                .then(function (res) {
                  var dojos = res.data;
                  ctrl.leads = _.filter(ctrl.leads, function (lead) {
                    var matchingLead = _.find(dojos, function (dojo) {
                      return dojo.dojoLeadId === lead.id;
                    });
                    return !matchingLead;
                  });
                  return $q.resolve();
                });
              } else {
                return $q.resolve();
              }
            } else {
              return $q.resolve();
            }
          })
          .then(function () {
            return cdOrganisationsService.loadUserOrgs(ctrl.currentUser.id)
            .then(function (res) {
              ctrl.orgs = res.data;
              // Multiple lead for a non-authorised user, loophole detected
              if (ctrl.leads.length > 1) {
                ctrl.userId = ctrl.leads[0].userId;
                if (!ctrl.orgs || ctrl.orgs.length === 0 ) {
                  alertService.showError($translate.instant('Multiple ongoing lead, please contact support'));
                  intercomService.show();
                  return $q.reject();
                }
              }
              if (ctrl.leads.length === 1) {
                // Reload previous lead
                if (_.isEmpty(ctrl.orgs) || $state.params.id) {
                  ctrl.application = _.merge(ctrl.application, ctrl.leads[0].application);
                  ctrl.leadId = ctrl.leads[0].id;
                }
                // Set creator user
                ctrl.userId = ctrl.leads[0].userId;
                return $q.resolve();
              }
            });
          })
          .then(function () {
            var userProfileQuery = {
              userId: ctrl.currentUser.id
            };
            if ($state.params.id) {
              userProfileQuery = {
                userId: ctrl.userId
              };
            }
            return cdUsersService.userProfileData(userProfileQuery)
            .then(function (profile) {
              ctrl.profile = profile.data;
            });
          })
          .then(function () {
            // NOTE : this starts to get quite big
            if (ctrl.leads.length === 0 || (!_.isEmpty(ctrl.orgs) && !$state.params.id)) {
              ctrl.userId = ctrl.currentUser.id;
              // Merge is used here to avoid overwriting data set by substate ctrllers (ie forms)
              ctrl.application = _.merge(ctrl.application, {
                champion: {
                  firstName: ctrl.profile.firstName,
                  lastName: ctrl.profile.lastName,
                  email: ctrl.profile.email,
                  dob: new Date(ctrl.profile.dob),
                  phone: ctrl.profile.phone,
                  twitter: ctrl.profile.twitter,
                  linkedin: ctrl.profile.linkedin,
                  isValid: false,
                  visited: false
                },
                dojo: {startTime: moment({minutes: 0}).format('HH:mm'), endTime: moment({minutes: 0}).format('HH:mm'), requestEmail: true, visited: false, isValid: false},
                venue: {private: 0, visited: false, isValid: false},
                team: {visited: false, isValid: false}
              });
            }
          })
          // The user may already have signed the charter, we load this separatly
          .then(function () {
            var agreement = {};
            cdAgreementsService.getCurrentCharterVersion()
            .then(function (response) {
              agreement.version = response.data.version;
            })
            .then(function () {
              return cdAgreementsService.loadUserAgreement(agreement.version, ctrl.profile.userId)
              .then(function (response) {
                if (response.data) {
                  agreement = response.data;
                  agreement.visited = true;
                } else {
                  agreement = ctrl.application.charter || {};
                }
              })
              .finally(function () { ctrl.setCharterStatus(agreement); });
            });
          })
          .then(function () {
            ctrl.loading = false;
            intercomService.InitIntercom();
            // We go to the next invalid step when the application has been previously started
            if (ctrl.leadId) ctrl.goToNextStep();
          });
        };
        ctrl.$onDestroy = function () {
          saveOnStateChange();
        };
      }]
    });
}());
<|endoftext|>