API Docs for: 0.8.0
Show:

File: include/theme/top_menu.js

/*
    Copyright (C) 2016  PencilBlue, LLC

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';

//dependencies
var async = require('async');
var util  = require('../util.js');

module.exports = function TopMenuServiceModule(pb) {

    //dependencies
    var SectionService = pb.SectionService;

    /**
     * Service for top menu navigation.
     * NOTE: This is not for administrative pages.
     *
     * @module Services
     * @submodule Theme
     * @class TopMenuService
     * @constructor
     */
    function TopMenuService(){}

    /**
     * Retrieves the theme settings, navigation data structure, and account buttons.
     * @static
     * @method getTopMenu
     * @param {Object} session The current user's session
     * @param {Localization} localizationService An instance of Localization to
     * translate default items
     * @param {Object} [options] An optional argument to provide more flexibility
     * to the menu construction. (pass in site: siteUId to select the proper tenant)
     * @param {String} [options.currUrl] The current request URL.
     * @param {Function} cb Callback function that takes three parameters. The
     * first are the theme's settings, the second is the navigation structure, and
     * the third is the account button structure.
     */
    TopMenuService.getTopMenu = function(session, localizationService, options, cb) {
        if (util.isFunction(options)) {
            cb      = options;
            options = {
                currUrl: null
            };
        }
        else if (!util.isObject(options)) {
            throw new Error('The options parameter must be an object');
        }

        var siteUId = pb.SiteService.getCurrentSite(options.site);

        var getTopMenu = function(session, localizationService, options, cb) {
            var tasks = {
                themeSettings: function(callback) {
                    var settingService = pb.SettingServiceFactory.getService(siteUId);
                    settingService.get('site_logo', function(err, logo) {
                        callback(null, {site_logo: logo});
                    });
                },

                formattedSections: function(callback) {
                    var sectionService = new SectionService({site: siteUId});
                    sectionService.getFormattedSections(localizationService, options.currUrl, function(err, formattedSections) {
                        callback(null, formattedSections);
                    });
                },

                accountButtons: function(callback) {
                    TopMenuService.getAccountButtons(session, localizationService, options.site, callback);
                }
            };
            async.parallel(tasks, function(err, result) {
                if (util.isError(err)) {
                    pb.log.error('TopMenuService: Ignored error occurred: %s', err);
                }

                // the default for account buttons was added as part of #970.
                // It allows for error page to be shown when something goes wrong with setup page.
                // Will be fixed and corrected in [1.0] where errors will not be ignored
                cb(result.themeSettings, result.formattedSections, result.accountButtons || []);
            });
        };
        getTopMenu(session, localizationService, options, cb);
    };

    /**
     * Retrieves the information needed to draw account buttons
     * @static
     * @method getAccountButtons
     * @param {Object}   session
     * @param {Object}   ls      The localization service
     * @param {String}   [site]    The current site
     * @param {Function} cb      Callback function
     */
    TopMenuService.getAccountButtons = function(session, ls, site, cb) {

        if (util.isFunction(site)) {
            cb = site;
            site = pb.siteService.GLOBAL_SITE;
        }

        var contentService = new pb.ContentService({site: site});
        contentService.getSettings(function(err, contentSettings) {
            if (util.isError(err)) {
                return cb(err);
            }

            var accountButtons = [];

            if(contentSettings.allow_comments) {
                if(pb.security.isAuthenticated(session)) {
                    accountButtons = [
                        {
                            icon: 'user',
                            title: ls.g('admin.ACCOUNT'),
                            href: '/user/manage_account'
                        },
                        {
                            icon: 'rss',
                            title: ls.g('generic.SUBSCRIBE'),
                            href: '/feed'
                        },
                        {
                            icon: 'power-off',
                            title: ls.g('generic.LOGOUT'),
                            href: '/actions/logout'
                        }
                    ];

                }
                else {
                    accountButtons =
                    [
                        {
                            icon: 'user',
                            title: ls.g('admin.ACCOUNT'),
                            href: '/user/sign_up'
                        },
                        {
                            icon: 'rss',
                            title: ls.g('generic.SUBSCRIBE'),
                            href: '/feed'
                        }
                    ];
                }
            }
            else {
                accountButtons =
                [
                    {
                        icon: 'rss',
                        title: ls.g('generic.SUBSCRIBE'),
                        href: '/feed'
                    }
                ];
            }
            cb(null, accountButtons);
        });
    };

    /**
     * Returns a bootstrap ready ul list for a nav element
     * @static
     * @method getBootstrapNav
     * @param {Object}   navigation     Navigation object
     * @param {Object}   accountButtons Account buttons object
     * @param {Function} cb             Callback function
     */
    TopMenuService.getBootstrapNav = function(navigation, accountButtons, options, cb) {
        if (util.isFunction(options)) {
            cb = options;
            options = {};
        }

        var ts = new pb.TemplateService(options);
        ts.load('elements/top_menu/link', function(err, linkTemplate) {
            ts.load('elements/top_menu/dropdown', function(err, dropdownTemplate) {
                ts.load('elements/top_menu/account_button', function(err, accountButtonTemplate) {

                    var bootstrapNav = ' ';
                    for(var i = 0; i < navigation.length; i++)
                    {
                        if(navigation[i].dropdown)
                        {
                            var subNav = ' ';
                            for(var j = 0; j < navigation[i].children.length; j++)
                            {
                                if(!navigation[i].children[j]) {
                                    continue;
                                }

                                var childItem = linkTemplate;
                                childItem = childItem.split('^active^').join((navigation[i].children[j].active) ? 'active' : '');
                                childItem = childItem.split('^url^').join(navigation[i].children[j].url);
                                childItem = childItem.split('^new_tab^').join(navigation[i].children[j].new_tab ? '_blank' : '_self');
                                childItem = childItem.split('^name^').join(navigation[i].children[j].name);

                                subNav = subNav.concat(childItem);
                            }

                            var dropdown = dropdownTemplate;
                            dropdown = dropdown.split('^navigation^').join(subNav);
                            dropdown = dropdown.split('^active^').join((navigation[i].active) ? 'active' : '');
                            dropdown = dropdown.split('^name^').join(navigation[i].name);

                            bootstrapNav = bootstrapNav.concat(dropdown);
                        }
                        else
                        {
                            var linkItem = linkTemplate;
                            linkItem = linkItem.split('^active^').join((navigation[i].active) ? 'active' : '');
                            linkItem = linkItem.split('^url^').join(navigation[i].url);
                            linkItem = linkItem.split('^new_tab^').join(navigation[i].new_tab ? '_blank' : '');
                            linkItem = linkItem.split('^name^').join(navigation[i].name);

                            bootstrapNav = bootstrapNav.concat(linkItem);
                        }
                    }

                    var buttons = ' ';
                    for(i = 0; i < accountButtons.length; i++)
                    {
                        var button = accountButtonTemplate;
                        button = button.split('^active^').join((accountButtons[i].active) ? 'active' : '');
                        button = button.split('^url^').join(accountButtons[i].href);
                        button = button.split('^title^').join(accountButtons[i].title);
                        button = button.split('^icon^').join(accountButtons[i].icon);

                        buttons = buttons.concat(button);
                    }

                    cb(bootstrapNav, buttons);
                });
            });
        });
    };

    /**
     * @method getNavItems
     * @param {Object} options
     * @param {Localization} options.ls
     * @param {Object} options.session
     * @param {String} options.currUrl
     * @param {string} options.site
     * @param {Function} cb
     */
    TopMenuService.prototype.getNavItems = function(options, cb) {
        TopMenuService.getTopMenu(options.session, options.ls, options, function(themeSettings, navigation, accountButtons) {
            TopMenuService.getBootstrapNav(navigation, accountButtons, options, function(navigation, accountButtons) {
                var navItems = {
                    themeSettings: themeSettings,
                    navigation: navigation,
                    accountButtons: accountButtons
                };
                cb(null, navItems);
            });
        });
    };

    //exports
    return TopMenuService;
};