<commit_before>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Author: Robert Kereskenyi
 */

"use strict";

define(['jquery',
        'underscore',
        'js/Constants',
        'js/NodePropertyNames',
        'logManager',
        'js/Panels/MetaEditor/MetaEditorConstants',
        'eventDispatcher',
        'text!./METATemplate.js'], function (_jquery,
                                    _underscore,
                                    CONSTANTS,
                                    nodePropertyNames,
                                    logManager,
                                    MetaEditorConstants,
                                    EventDispatcher,
                                    METATemplateJS) {

    var META_RULES_CONTAINER_NODE_ID = MetaEditorConstants.META_ASPECT_CONTAINER_ID,
        _client,
        _territoryId,
        _territoryUI,
        TerritoryUI,
        _metaMembers,
        _patterns = {},
        _logger = logManager.create("METAAspectHelper"),
        _events = {'META_ASPECT_CHANGED': 'META_ASPECT_CHANGED'},
        _metaTypes;

    TerritoryUI = function () {
        $.extend(this, new EventDispatcher());
    };

    TerritoryUI.prototype.onOneEvent = function (/*events*/) {
        _processMetaContainer();

        this.dispatchEvent(_events.META_ASPECT_CHANGED);
    };

    var _reset = function () {
        _metaTypes = {};

        if (_territoryId) {
            _client.removeUI(_territoryId);
        }

        //there is an open project
        if (_client.getActiveProject()) {
            _territoryId = _client.addUI(_territoryUI, true);

            _patterns = {};
            _metaMembers = [];
            _patterns[META_RULES_CONTAINER_NODE_ID] = { "children": 0 };

            setTimeout(function (){
                _client.updateTerritory(_territoryId, _patterns);
            }, 100);

        }
    };

    var _metaFriendlyName = function (name) {
        var ret = name,
            re,
            i;

        // Not allowed characters to replace.
        var input = "áéíóöőúüűÁÉÍÓÖŐÚÜŰ ";

        // Safe characters to replace to.
        var output = "aeiooouuuAEIOOOUUU_";

        // allowed characters
        var allowed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_';

        i = input.length;
        while (i--) {
            re = new RegExp(input[i], "g");
            ret = ret.replace(re, output[i]);
        }

        i = ret.length;
        while (i--) {
            if (allowed.indexOf(ret[i]) === -1) {
                ret.splice(i, 1);
            }
        }

        return ret;
    };

    var _processMetaContainer = function () {
        var metaContainer = _client.getNode(META_RULES_CONTAINER_NODE_ID);

        //reset META info container
        _metaTypes = {};

        if (metaContainer) {
            //read the META rules out of the META container and generate
            var metaAspectSetMembers = metaContainer.getMemberIds(MetaEditorConstants.META_ASPECT_SET_NAME),
                diff,
                territoryChanged = false,
                len,
                nodeID,
                nodeName;

            if (metaAspectSetMembers && metaAspectSetMembers.length > 0) {
                //check deleted nodes
                diff = _.difference(_metaMembers, metaAspectSetMembers);
                len = diff.length;
                while (len--) {
                    if (diff[len] !== META_RULES_CONTAINER_NODE_ID) {
                        delete _patterns[diff[len]];
                        territoryChanged = true;
                    }
                }

                //check added nodes
                diff = _.difference(metaAspectSetMembers, _metaMembers);
                len = diff.length;
                while (len--) {
                    if (diff[len] !== META_RULES_CONTAINER_NODE_ID) {
                        _patterns[diff[len]] = { "children": 0 };
                        territoryChanged = true;
                    }
                }

                //save the new contained nodes
                _metaMembers = metaAspectSetMembers.slice(0);

                _metaTypes = {};

                //generate the ID - TYPE mapping
                len = _metaMembers.length;
                while (len--) {
                    nodeID = _metaMembers[len];
                    var metaMemberNode = _client.getNode(nodeID);

                    if (metaMemberNode) {
                        nodeName = _metaFriendlyName(metaMemberNode.getAttribute(nodePropertyNames.Attributes.name));

                        if (nodeName === undefined || nodeName === null || nodeName === "") {
                            _logger.error('META item "' + nodeID + '" has an invalid name of: ' + nodeName);
                        } else {
                            if (_metaTypes.hasOwnProperty(nodeName)) {
                                _logger.error('Duplicate name on META level: "' + nodeName + '"');
                                delete _metaTypes[nodeName];
                            } else {
                                _metaTypes[nodeName] = nodeID;
                            }
                        }
                    }
                }

                _logger.debug('_metaTypes: \n' + JSON.stringify(_metaTypes));

                //there was change in the territory
                if (territoryChanged === true) {
                    setTimeout(function (){
                        _client.updateTerritory(_territoryId, _patterns);
                    }, 10);
                }
            }
        }
    };

    var _initialize = function (c) {
        //if already initialized, just return
        if (_client) {
            return;
        }
        _client = c;

        _client.addEventListener(_client.events.PROJECT_OPENED, function (/*__project, projectName*/) {
            _reset();
        });

        _client.addEventListener(_client.events.PROJECT_CLOSED, function (/*__project*/) {
            _reset();
        });

        _client.addEventListener(_client.events.BRANCH_CHANGED, function (/*__project, branch*/) {
            _reset();
        });

        _territoryUI = new TerritoryUI();
        _initialize = undefined;
    };

    var _isMETAType = function (objID, metaTypeID) {
        var result = false;

        if (objID && metaTypeID) {
            result = _client.isTypeOf(objID, metaTypeID);
        }

        return result;
    };

    var _getMetaAspectMembers = function () {
        var members = [];

        for (var m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                members.push(_metaTypes[m]);
            }
        }

        return members;
    };

    var _addEventListener = function (event, callback) {
        if (_territoryUI) {
            _territoryUI.addEventListener(event, callback);
        }
    };

    var _removeEventListener = function (event, callback) {
        if (_territoryUI) {
            _territoryUI.removeEventListener(event, callback);
        }
    };

    var _getMETAAspectTypes = function () {
        var result = {};
        _.extend(result, _metaTypes);

        return result;
    };

    var _getMETAAspectTypesSorted = function () {
        var result = {},
            typeNames = [],
            m;

        for (m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                typeNames.push(m);
            }
        }

        typeNames.sort();

        for (m = 0; m < typeNames.length; m += 1) {
            result[typeNames[m]] = _metaTypes[typeNames[m]];
        }

        return result;
    };

    /*
    Returns the parent meta types of the given object ID in the order of inheritance.
     */
    var _getMETATypesOf = function (objID) {
        var result = [];

        for (var m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                if (_isMETAType(objID, _metaTypes[m])) {
                    result.push(m);
                }
            }
        }

        // sort based on metatypes inheritance
        result.sort(function(a, b) {
            return  _isMETAType(_metaTypes[a], _metaTypes[b]) ? -1 : 1;
        });

        return result;
    };

    var _generateMETAAspectJavaScript = function () {
        var result = {};

        if (!_.isEmpty(_metaTypes)) {
            var projName = _client.getActiveProject();
            var content = METATemplateJS;
            var sortedMetaTypes = _getMETAAspectTypesSorted();
            var typeCheckMethodTemplate = 'var _is__METATYPE__ = function (objID) { return METAAspectHelper.isMETAType(objID, _metaTypes.__METATYPE__); };'
            var typeCheckMethods = '';
            var typeCheckMethodsMap = [];
            var typeCheckMethodNamePrefix = 'is';
            var typeCheckMethodsMapIndent = '\t\t\t';
            var metaAspectTypesMap = [];

            //generate each type checker method
            /*
             var _isXXX = function (objID) {
                return METAAspectHelper.isMETAType(objID, _metaTypes.XXX);
             };
             */
            for (var t in sortedMetaTypes) {
                if (sortedMetaTypes.hasOwnProperty(t)) {
                    typeCheckMethods += typeCheckMethodTemplate.replace(/__METATYPE__/g, t) + '\n\t';
                    typeCheckMethodsMap.push(typeCheckMethodNamePrefix + t + ": _" + typeCheckMethodNamePrefix + t);
                    metaAspectTypesMap.push('\'' + t + '\'' + ': ' + '\'' + sortedMetaTypes[t] + '\'');
                }
            }

            content = content.replace( /__PROJECT__/g, projName);
            content = content.replace(/__META_ASPECT_TYPES__/g, '{\n\t\t' + metaAspectTypesMap.join(',\n\t\t') + '\n\t}');
            content = content.replace(/__META_ASPECT_TYPE_CHECKING__/g, typeCheckMethods);
            content = content.replace(/__TYPE_CHECK_METHOD_MAP__/g, '{\n' + typeCheckMethodsMapIndent + typeCheckMethodsMap.join(',\n' + typeCheckMethodsMapIndent) + '\n\t\t}');

            result.fileName = projName + ".META.js";
            result.content = content;
        }

        return result;
    };

    //return utility functions
    return { initialize: _initialize,
            isMETAType: _isMETAType,
            getMetaAspectMembers: _getMetaAspectMembers,
            events: _events,
            addEventListener: _addEventListener,
            removeEventListener: _removeEventListener,
            getMETAAspectTypes: _getMETAAspectTypes,
            getMETAAspectTypesSorted: _getMETAAspectTypesSorted,
            getMETATypesOf: _getMETATypesOf,
            generateMETAAspectJavaScript: _generateMETAAspectJavaScript
        };
});<commit_msg>bugfix in eliminating invalid chatracters<commit_after>/*
 * Copyright (C) 2013 Vanderbilt University, All rights reserved.
 *
 * Author: Robert Kereskenyi
 */

"use strict";

define(['jquery',
        'underscore',
        'js/Constants',
        'js/NodePropertyNames',
        'logManager',
        'js/Panels/MetaEditor/MetaEditorConstants',
        'eventDispatcher',
        'text!./METATemplate.js'], function (_jquery,
                                    _underscore,
                                    CONSTANTS,
                                    nodePropertyNames,
                                    logManager,
                                    MetaEditorConstants,
                                    EventDispatcher,
                                    METATemplateJS) {

    var META_RULES_CONTAINER_NODE_ID = MetaEditorConstants.META_ASPECT_CONTAINER_ID,
        _client,
        _territoryId,
        _territoryUI,
        TerritoryUI,
        _metaMembers,
        _patterns = {},
        _logger = logManager.create("METAAspectHelper"),
        _events = {'META_ASPECT_CHANGED': 'META_ASPECT_CHANGED'},
        _metaTypes;

    TerritoryUI = function () {
        $.extend(this, new EventDispatcher());
    };

    TerritoryUI.prototype.onOneEvent = function (/*events*/) {
        _processMetaContainer();

        this.dispatchEvent(_events.META_ASPECT_CHANGED);
    };

    var _reset = function () {
        _metaTypes = {};

        if (_territoryId) {
            _client.removeUI(_territoryId);
        }

        //there is an open project
        if (_client.getActiveProject()) {
            _territoryId = _client.addUI(_territoryUI, true);

            _patterns = {};
            _metaMembers = [];
            _patterns[META_RULES_CONTAINER_NODE_ID] = { "children": 0 };

            setTimeout(function (){
                _client.updateTerritory(_territoryId, _patterns);
            }, 100);

        }
    };

    var _metaFriendlyName = function (name) {
        var ret = name,
            re,
            i;

        // Not allowed characters to replace.
        var input = "áéíóöőúüűÁÉÍÓÖŐÚÜŰ ";

        // Safe characters to replace to.
        var output = "aeiooouuuAEIOOOUUU_";

        // allowed characters
        var allowed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_';

        i = input.length;
        while (i--) {
            re = new RegExp(input[i], "g");
            ret = ret.replace(re, output[i]);
        }

        i = ret.length;
        while (i--) {
            if (allowed.indexOf(ret[i]) === -1) {
                ret = ret.substr(0, i) + ret.substr(i + 1);
            }
        }

        return ret;
    };

    var _processMetaContainer = function () {
        var metaContainer = _client.getNode(META_RULES_CONTAINER_NODE_ID);

        //reset META info container
        _metaTypes = {};

        if (metaContainer) {
            //read the META rules out of the META container and generate
            var metaAspectSetMembers = metaContainer.getMemberIds(MetaEditorConstants.META_ASPECT_SET_NAME),
                diff,
                territoryChanged = false,
                len,
                nodeID,
                nodeName;

            if (metaAspectSetMembers && metaAspectSetMembers.length > 0) {
                //check deleted nodes
                diff = _.difference(_metaMembers, metaAspectSetMembers);
                len = diff.length;
                while (len--) {
                    if (diff[len] !== META_RULES_CONTAINER_NODE_ID) {
                        delete _patterns[diff[len]];
                        territoryChanged = true;
                    }
                }

                //check added nodes
                diff = _.difference(metaAspectSetMembers, _metaMembers);
                len = diff.length;
                while (len--) {
                    if (diff[len] !== META_RULES_CONTAINER_NODE_ID) {
                        _patterns[diff[len]] = { "children": 0 };
                        territoryChanged = true;
                    }
                }

                //save the new contained nodes
                _metaMembers = metaAspectSetMembers.slice(0);

                _metaTypes = {};

                //generate the ID - TYPE mapping
                len = _metaMembers.length;
                while (len--) {
                    nodeID = _metaMembers[len];
                    var metaMemberNode = _client.getNode(nodeID);

                    if (metaMemberNode) {
                        nodeName = _metaFriendlyName(metaMemberNode.getAttribute(nodePropertyNames.Attributes.name));

                        if (nodeName === undefined || nodeName === null || nodeName === "") {
                            _logger.error('META item "' + nodeID + '" has an invalid name of: ' + nodeName);
                        } else {
                            if (_metaTypes.hasOwnProperty(nodeName)) {
                                _logger.error('Duplicate name on META level: "' + nodeName + '"');
                                delete _metaTypes[nodeName];
                            } else {
                                _metaTypes[nodeName] = nodeID;
                            }
                        }
                    }
                }

                _logger.debug('_metaTypes: \n' + JSON.stringify(_metaTypes));

                //there was change in the territory
                if (territoryChanged === true) {
                    setTimeout(function (){
                        _client.updateTerritory(_territoryId, _patterns);
                    }, 10);
                }
            }
        }
    };

    var _initialize = function (c) {
        //if already initialized, just return
        if (_client) {
            return;
        }
        _client = c;

        _client.addEventListener(_client.events.PROJECT_OPENED, function (/*__project, projectName*/) {
            _reset();
        });

        _client.addEventListener(_client.events.PROJECT_CLOSED, function (/*__project*/) {
            _reset();
        });

        _client.addEventListener(_client.events.BRANCH_CHANGED, function (/*__project, branch*/) {
            _reset();
        });

        _territoryUI = new TerritoryUI();
        _initialize = undefined;
    };

    var _isMETAType = function (objID, metaTypeID) {
        var result = false;

        if (objID && metaTypeID) {
            result = _client.isTypeOf(objID, metaTypeID);
        }

        return result;
    };

    var _getMetaAspectMembers = function () {
        var members = [];

        for (var m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                members.push(_metaTypes[m]);
            }
        }

        return members;
    };

    var _addEventListener = function (event, callback) {
        if (_territoryUI) {
            _territoryUI.addEventListener(event, callback);
        }
    };

    var _removeEventListener = function (event, callback) {
        if (_territoryUI) {
            _territoryUI.removeEventListener(event, callback);
        }
    };

    var _getMETAAspectTypes = function () {
        var result = {};
        _.extend(result, _metaTypes);

        return result;
    };

    var _getMETAAspectTypesSorted = function () {
        var result = {},
            typeNames = [],
            m;

        for (m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                typeNames.push(m);
            }
        }

        typeNames.sort();

        for (m = 0; m < typeNames.length; m += 1) {
            result[typeNames[m]] = _metaTypes[typeNames[m]];
        }

        return result;
    };

    /*
    Returns the parent meta types of the given object ID in the order of inheritance.
     */
    var _getMETATypesOf = function (objID) {
        var result = [];

        for (var m in _metaTypes) {
            if (_metaTypes.hasOwnProperty(m)) {
                if (_isMETAType(objID, _metaTypes[m])) {
                    result.push(m);
                }
            }
        }

        // sort based on metatypes inheritance
        result.sort(function(a, b) {
            return  _isMETAType(_metaTypes[a], _metaTypes[b]) ? -1 : 1;
        });

        return result;
    };

    var _generateMETAAspectJavaScript = function () {
        var result = {};

        if (!_.isEmpty(_metaTypes)) {
            var projName = _client.getActiveProject();
            var content = METATemplateJS;
            var sortedMetaTypes = _getMETAAspectTypesSorted();
            var typeCheckMethodTemplate = 'var _is__METATYPE__ = function (objID) { return METAAspectHelper.isMETAType(objID, _metaTypes.__METATYPE__); };'
            var typeCheckMethods = '';
            var typeCheckMethodsMap = [];
            var typeCheckMethodNamePrefix = 'is';
            var typeCheckMethodsMapIndent = '\t\t\t';
            var metaAspectTypesMap = [];

            //generate each type checker method
            /*
             var _isXXX = function (objID) {
                return METAAspectHelper.isMETAType(objID, _metaTypes.XXX);
             };
             */
            for (var t in sortedMetaTypes) {
                if (sortedMetaTypes.hasOwnProperty(t)) {
                    typeCheckMethods += typeCheckMethodTemplate.replace(/__METATYPE__/g, t) + '\n\t';
                    typeCheckMethodsMap.push(typeCheckMethodNamePrefix + t + ": _" + typeCheckMethodNamePrefix + t);
                    metaAspectTypesMap.push('\'' + t + '\'' + ': ' + '\'' + sortedMetaTypes[t] + '\'');
                }
            }

            content = content.replace( /__PROJECT__/g, projName);
            content = content.replace(/__META_ASPECT_TYPES__/g, '{\n\t\t' + metaAspectTypesMap.join(',\n\t\t') + '\n\t}');
            content = content.replace(/__META_ASPECT_TYPE_CHECKING__/g, typeCheckMethods);
            content = content.replace(/__TYPE_CHECK_METHOD_MAP__/g, '{\n' + typeCheckMethodsMapIndent + typeCheckMethodsMap.join(',\n' + typeCheckMethodsMapIndent) + '\n\t\t}');

            result.fileName = projName + ".META.js";
            result.content = content;
        }

        return result;
    };

    //return utility functions
    return { initialize: _initialize,
            isMETAType: _isMETAType,
            getMetaAspectMembers: _getMetaAspectMembers,
            events: _events,
            addEventListener: _addEventListener,
            removeEventListener: _removeEventListener,
            getMETAAspectTypes: _getMETAAspectTypes,
            getMETAAspectTypesSorted: _getMETAAspectTypesSorted,
            getMETATypesOf: _getMETATypesOf,
            generateMETAAspectJavaScript: _generateMETAAspectJavaScript
        };
});<|endoftext|>


<commit_before>/* Simple parser for MSS */

var MSSParser = Editor.Parser = (function() {
  function wordRegexp(words) {
    return new RegExp("^(?:" + words.join("|") + ")$", "i");
  }
  var ops;
  var tokenizeMSS = (function() {
    function normal(source, setState) {
      var ch = source.next();
      if (ch == "@") {
        source.nextWhileMatches(/\w/);
        return "mss-at";
      }
      else if (ch == "/" && source.equals("*")) {
        setState(inCComment);
        return null;
      }
      else if (ch == "<" && source.equals("!")) {
        setState(inSGMLComment);
        return null;
      }
      else if (ch == "=") {
        return "mss-compare";
      }
      else if (source.equals("=") && (ch == "~" || ch == "|")) {
        source.next();
        return "mss-compare";
      }
      else if (ch == "\"" || ch == "'") {
        setState(inString(ch));
        return null;
      }
      else if (ch == "#") {
        source.nextWhileMatches(/\w/);
        return "mss-hash";
      }
      else if (ch == "!") {
        source.nextWhileMatches(/[ \t]/);
        source.nextWhileMatches(/\w/);
        return "mss-important";
      }
      else if (/\d/.test(ch)) {
        source.nextWhileMatches(/[\w.%]/);
        return "mss-unit";
      }
      else if (ch == '[') {
        source.nextWhileMatches(/[^\]]/);
        source.next();
        return "mss-filter";
      }
      else if (/[,.+>*\/]/.test(ch)) {
        return "mss-select-op";
      }
      else if (/[;{}:\[\]]/.test(ch)) {
        return "mss-punctuation";
      }
      else {
        source.nextWhileMatches(/[\w\\\-_]/);
        var word = source.get();
        if (ops.test(word)) {
          return {style: "mss-valid-identifier", content: word};
        } else {
          return {style: "mss-identifier", content: word};
        }
      }
    }

    function inCComment(source, setState) {
      var maybeEnd = false;
      while (!source.endOfLine()) {
        var ch = source.next();
        if (maybeEnd && ch == "/") {
          setState(normal);
          break;
        }
        maybeEnd = (ch == "*");
      }
      return "mss-comment";
    }

    function inSGMLComment(source, setState) {
      var dashes = 0;
      while (!source.endOfLine()) {
        var ch = source.next();
        if (dashes >= 2 && ch == ">") {
          setState(normal);
          break;
        }
        dashes = (ch == "-") ? dashes + 1 : 0;
      }
      return "mss-comment";
    }

    function inString(quote) {
      return function(source, setState) {
        var escaped = false;
        while (!source.endOfLine()) {
          var ch = source.next();
          if (ch == quote && !escaped)
            break;
          escaped = !escaped && ch == "\\";
        }
        if (!escaped)
          setState(normal);
        return "mss-string";
      };
    }

    return function(source, startState) {
      return tokenizer(source, startState || normal);
    };
  })();

  function indentMSS(inBraces, inRule, base) {
    return function(nextChars) {
      if (!inBraces || /^\}/.test(nextChars)) return base;
      else if (inRule) return base + indentUnit * 2;
      else return base + indentUnit;
    };
  }

  // This is a very simplistic parser -- since MSS does not really
  // nest, it works acceptably well, but some nicer colouroing could
  // be provided with a more complicated parser.
  function parseMSS(source, basecolumn) {
    basecolumn = basecolumn || 0;
    ops = wordRegexp(this.css_identifiers)
    var tokens = tokenizeMSS(source);
    var inBraces = false, inRule = false, inDecl = false;;

    var iter = {
      next: function() {
        var token = tokens.next(), style = token.style, content = token.content;

        if (style == "mss-hash")
          style = token.style =  inRule ? "mss-colorcode" : "mss-identifier";
        if (style == "mss-identifier") {
          if (inRule) token.style = "mss-value";
          else if (!inBraces && !inDecl) token.style = "mss-selector";
        }

        if (content == "\n")
          token.indentation = indentMSS(inBraces, inRule, basecolumn);

        if (content == "{" && inDecl == "@media")
          inDecl = false;
        else if (content == "{")
          inBraces = true;
        else if (content == "}")
          inBraces = inRule = inDecl = false;
        else if (content == ";")
          inRule = inDecl = false;
        else if (inBraces && style != "mss-comment" && style != "whitespace")
          inRule = true;
        else if (!inBraces && style == "mss-at")
          inDecl = content;

        return token;
      },

      copy: function() {
        var _inBraces = inBraces, _inRule = inRule, _tokenState = tokens.state;
        return function(source) {
          tokens = tokenizeMSS(source, _tokenState);
          inBraces = _inBraces;
          inRule = _inRule;
          return iter;
        };
      }
    };
    return iter;
  }

  return {
      make: parseMSS,
      electricChars: "}",
      configure: function(config) {
          this.css_identifiers = (function() {
              var list = [];
              for (var i in config.symbolizers) {
                  for (var j in config.symbolizers[i]) {
                      if (config.symbolizers[i][j].hasOwnProperty('css')) {
                          list.push(config.symbolizers[i][j].css);
                      }
                  }
              }
              return list;
          })();
      }
  };
})();
<commit_msg>Cutting out problematic filter parsing<commit_after>/* Simple parser for MSS */

var MSSParser = Editor.Parser = (function() {
  function wordRegexp(words) {
    return new RegExp("^(?:" + words.join("|") + ")$", "i");
  }
  var ops;
  var tokenizeMSS = (function() {
    function normal(source, setState) {
      var ch = source.next();
      if (ch == "@") {
        source.nextWhileMatches(/\w/);
        return "mss-at";
      }
      else if (ch == "/" && source.equals("*")) {
        setState(inCComment);
        return null;
      }
      else if (ch == "<" && source.equals("!")) {
        setState(inSGMLComment);
        return null;
      }
      else if (ch == "=") {
        return "mss-compare";
      }
      else if (source.equals("=") && (ch == "~" || ch == "|")) {
        source.next();
        return "mss-compare";
      }
      else if (ch == "\"" || ch == "'") {
        setState(inString(ch));
        return null;
      }
      else if (ch == "#") {
        source.nextWhileMatches(/\w/);
        return "mss-hash";
      }
      else if (ch == "!") {
        source.nextWhileMatches(/[ \t]/);
        source.nextWhileMatches(/\w/);
        return "mss-important";
      }
      else if (/\d/.test(ch)) {
        source.nextWhileMatches(/[\w.%]/);
        return "mss-unit";
      }
      /*
      else if (ch == '[') {
        source.nextWhileMatches(/[^\]]/);
        return "mss-filter";
      }
      */
      else if (/[,.+>*\/]/.test(ch)) {
        return "mss-select-op";
      }
      else if (/[;{}:\[\]]/.test(ch)) {
        return "mss-punctuation";
      }
      else {
        source.nextWhileMatches(/[\w\\\-_]/);
        var word = source.get();
        if (ops.test(word)) {
          return {style: "mss-valid-identifier", content: word};
        } else {
          return {style: "mss-identifier", content: word};
        }
      }
    }

    function inCComment(source, setState) {
      var maybeEnd = false;
      while (!source.endOfLine()) {
        var ch = source.next();
        if (maybeEnd && ch == "/") {
          setState(normal);
          break;
        }
        maybeEnd = (ch == "*");
      }
      return "mss-comment";
    }

    function inSGMLComment(source, setState) {
      var dashes = 0;
      while (!source.endOfLine()) {
        var ch = source.next();
        if (dashes >= 2 && ch == ">") {
          setState(normal);
          break;
        }
        dashes = (ch == "-") ? dashes + 1 : 0;
      }
      return "mss-comment";
    }

    function inString(quote) {
      return function(source, setState) {
        var escaped = false;
        while (!source.endOfLine()) {
          var ch = source.next();
          if (ch == quote && !escaped)
            break;
          escaped = !escaped && ch == "\\";
        }
        if (!escaped)
          setState(normal);
        return "mss-string";
      };
    }

    return function(source, startState) {
      return tokenizer(source, startState || normal);
    };
  })();

  function indentMSS(inBraces, inRule, base) {
    return function(nextChars) {
      if (!inBraces || /^\}/.test(nextChars)) return base;
      else if (inRule) return base + indentUnit * 2;
      else return base + indentUnit;
    };
  }

  // This is a very simplistic parser -- since MSS does not really
  // nest, it works acceptably well, but some nicer colouroing could
  // be provided with a more complicated parser.
  function parseMSS(source, basecolumn) {
    basecolumn = basecolumn || 0;
    ops = wordRegexp(this.css_identifiers)
    var tokens = tokenizeMSS(source);
    var inBraces = false, inRule = false, inDecl = false;;

    var iter = {
      next: function() {
        var token = tokens.next(), style = token.style, content = token.content;

        if (style == "mss-hash")
          style = token.style =  inRule ? "mss-colorcode" : "mss-identifier";
        if (style == "mss-identifier") {
          if (inRule) token.style = "mss-value";
          else if (!inBraces && !inDecl) token.style = "mss-selector";
        }

        if (content == "\n")
          token.indentation = indentMSS(inBraces, inRule, basecolumn);

        if (content == "{" && inDecl == "@media")
          inDecl = false;
        else if (content == "{")
          inBraces = true;
        else if (content == "}")
          inBraces = inRule = inDecl = false;
        else if (content == ";")
          inRule = inDecl = false;
        else if (inBraces && style != "mss-comment" && style != "whitespace")
          inRule = true;
        else if (!inBraces && style == "mss-at")
          inDecl = content;

        return token;
      },

      copy: function() {
        var _inBraces = inBraces, _inRule = inRule, _tokenState = tokens.state;
        return function(source) {
          tokens = tokenizeMSS(source, _tokenState);
          inBraces = _inBraces;
          inRule = _inRule;
          return iter;
        };
      }
    };
    return iter;
  }

  return {
      make: parseMSS,
      electricChars: "}",
      configure: function(config) {
          this.css_identifiers = (function() {
              var list = [];
              for (var i in config.symbolizers) {
                  for (var j in config.symbolizers[i]) {
                      if (config.symbolizers[i][j].hasOwnProperty('css')) {
                          list.push(config.symbolizers[i][j].css);
                      }
                  }
              }
              return list;
          })();
      }
  };
})();
<|endoftext|>


<commit_before>{
	"metadata" :
	{
		"formatVersion" : 3.1,
		"generatedBy"   : "Blender 2.65 Exporter",
		"vertices"      : 56,
		"faces"         : 52,
		"normals"       : 56,
		"colors"        : 0,
		"uvs"           : [],
		"materials"     : 1,
		"morphTargets"  : 0,
		"bones"         : 0
	},
	"scale" : 1.000000,
	"materials" : [	{
		"DbgColor" : 15658734,
		"DbgIndex" : 0,
		"DbgName" : "cyan",
		"blending" : "NormalBlending",
		"colorAmbient" : [0.039546236395835876, 0.9822506308555603, 0.6938718557357788],
		"colorDiffuse" : [0.039546236395835876, 0.9822506308555603, 0.6938718557357788],
		"colorSpecular" : [1.0, 1.0, 1.0],
		"depthTest" : true,
		"depthWrite" : true,
		"shading" : "Lambert",
		"specularCoef" : 50,
		"transparency" : 1.0,
		"transparent" : false,
		"vertexColors" : false
	},
	{
		"DbgColor" : 15597568,
		"DbgIndex" : 1,
		"DbgName" : "green",
		"blending" : "NormalBlending",
		"colorAmbient" : [0.004776954650878906, 0.708375871181488, 0.2622506618499756],
		"colorDiffuse" : [0.004776954650878906, 0.708375871181488, 0.2622506618499756],
		"colorSpecular" : [1.0, 1.0, 1.0],
		"depthTest" : true,
		"depthWrite" : true,
		"shading" : "Lambert",
		"specularCoef" : 50,
		"transparency" : 1.0,
		"transparent" : false,
		"vertexColors" : false
	}],
	"vertices" : [0.205423,0.203889,0.163399,0.205423,0.203889,-0.163399,-0.836746,-0.0273734,0.0852706,-0.836746,-0.0273734,-0.0852706,0.00547919,0.231254,0.105459,0.00547919,0.231253,-0.105459,-0.667144,0.0819949,0.0550342,-0.667144,0.0819949,-0.0550342,-0.539983,-0.13177,0.198399,-0.539983,-0.13177,-0.198399,0.734445,-0.132315,-0.26534,0.734445,-0.132315,0.26534,0.205423,0.203889,0.163399,0.205423,0.203889,-0.163399,0.734445,0.14159,-0.194793,0.734445,0.14159,0.194793,-0.836746,-0.109792,0.0852706,-0.836746,-0.109792,-0.0852706,-0.836746,-0.0273734,0.0852706,-0.836746,-0.0273734,-0.0852706,0.817604,-0.0864622,-0.174778,0.817604,-0.0864621,0.174778,0.817604,0.0957368,-0.174778,0.817604,0.0957368,0.174778,0.817604,-0.0864621,-0.102738,0.817604,-0.0864621,0.102738,0.817604,0.0957368,-0.102738,0.817604,0.0957368,0.102738,0.256034,-0.0825444,-0.119579,0.256034,-0.0825444,0.119579,0.256034,0.101471,-0.119579,0.256034,0.101471,0.119579,-0.0492363,0.0232588,0.36925,-0.0492363,0.0232588,-0.36925,0.686899,-0.0452344,-0.355008,0.686899,-0.0452344,0.355008,0.11323,0.0768929,0.376715,0.11323,0.0768929,-0.376715,0.686899,0.0571518,-0.355008,0.686899,0.0571518,0.355008,0.418567,-0.0924264,0.793526,0.418567,-0.0924264,-0.793526,0.785102,-0.0793208,-0.790767,0.785102,-0.0793208,0.790767,0.418567,-0.077483,0.793526,0.418567,-0.0774831,-0.793526,0.785102,-0.0558296,-0.790767,0.785102,-0.0558296,0.790767,0.261471,0.197289,0.100715,0.261471,0.197289,-0.100715,0.678397,0.14819,-0.120066,0.678397,0.14819,0.120066,0.526158,0.323654,0.02321,0.526158,0.323654,-0.02321,0.85976,0.274555,-0.0276693,0.85976,0.274555,0.0276693],
	"morphTargets" : [],
	"normals" : [0.78103,0.039796,-0.623218,-0.769738,-0.313486,-0.556047,-0.333659,0.836451,-0.434706,-0.105533,0.891568,-0.440413,-0.105533,0.891568,0.440413,-0.333659,0.836451,0.434706,0.78103,0.039796,0.623218,-0.769738,-0.313486,0.556047,-0.224982,-0.534013,0.814966,-0.074679,0.965636,0.248848,-0.624805,0.646779,0.4373,-0.726859,-0.446181,0.52205,-0.421155,0.163549,0.892087,-0.225135,0.868618,0.441328,0.471755,-0.708945,0.524186,0.471755,-0.708945,-0.524186,0.842586,-0.402997,-0.357219,0.842586,-0.402997,0.357219,0.458266,0.80108,0.384991,0.648396,0.665242,0.370128,0.720054,-0.608722,0.33311,-0.224982,-0.534013,-0.814966,0.240608,0.900571,0.362011,0.000824,0.996063,0.088534,-0.624805,0.646779,-0.4373,-0.726859,-0.446181,-0.52205,-0.074679,0.965636,-0.248848,0.813654,-0.366131,0.451521,0.813654,-0.366131,-0.451521,0.819208,0.418744,0.391797,0.458266,0.80108,-0.384991,0.819208,0.418744,-0.391797,0.571184,0.573595,0.587115,0.571184,0.573595,-0.587115,0.487442,0.607013,-0.627613,0.487442,0.607013,0.627613,0.566759,-0.578936,0.586138,0.566759,-0.578936,-0.586138,0.665456,0.488449,0.564379,0.628651,-0.604236,0.489547,0.648396,0.665242,-0.370128,0.720054,-0.608722,-0.33311,0.628651,-0.604236,-0.489547,0.665456,0.488449,-0.564379,-0.225135,0.868618,-0.441328,-0.421155,0.163549,-0.892087,-0.127781,0.7163,-0.685965,-0.241432,-0.530503,-0.812555,-0.127781,0.7163,0.685965,-0.241432,-0.530503,0.812555,0.864315,0.221686,0.45143,-0.091922,0.898251,0.429701,0.240608,0.900571,-0.362011,0.000824,0.996063,-0.088534,0.864315,0.221686,-0.45143,-0.091922,0.898251,-0.429701],
	"colors" : [],
	"uvs" : [],
	"faces" : [35,1,3,7,5,0,0,1,2,3,35,4,5,7,6,0,4,3,2,5,35,0,1,5,4,0,6,0,3,4,35,2,0,4,6,0,7,6,4,5,35,3,2,6,7,0,1,7,5,2,35,0,2,3,1,0,6,7,1,0,35,8,12,18,16,1,8,9,10,11,35,12,8,32,36,1,9,8,12,13,35,11,10,20,21,1,14,15,16,17,35,11,15,39,35,1,14,18,19,20,35,8,9,10,11,1,8,21,15,14,35,12,15,51,48,1,9,18,22,23,35,18,19,17,16,1,10,24,25,11,35,9,8,16,17,1,21,8,11,25,35,13,9,17,19,1,26,21,25,24,35,21,20,24,25,1,17,16,27,28,35,15,11,21,23,1,18,14,17,29,35,10,14,22,20,1,15,30,31,16,35,14,15,23,22,1,30,18,29,31,35,25,24,28,29,1,28,27,32,33,35,22,23,27,26,1,31,29,34,35,35,23,21,25,27,1,29,17,28,34,35,20,22,26,24,1,16,31,35,27,35,30,31,29,28,1,36,37,33,32,35,24,26,30,28,1,27,35,36,32,35,26,27,31,30,1,35,34,37,36,35,27,25,29,31,1,34,28,33,37,35,35,39,47,43,1,20,19,38,39,35,38,34,42,46,1,40,41,42,43,35,15,12,36,39,1,18,9,13,19,35,14,10,34,38,1,30,15,41,40,35,13,14,38,37,1,26,30,40,44,35,8,11,35,32,1,8,14,20,12,35,10,9,33,34,1,15,21,45,41,35,9,13,37,33,1,21,26,44,45,35,45,46,42,41,1,46,43,42,47,35,47,44,40,43,1,38,48,49,39,35,33,37,45,41,1,45,44,46,47,35,32,35,43,40,1,12,20,39,49,35,37,38,46,45,1,44,40,43,46,35,34,33,41,42,1,41,45,47,42,35,39,36,44,47,1,19,13,48,38,35,36,32,40,44,1,13,12,49,48,35,18,12,13,19,1,10,9,26,24,35,48,51,55,52,1,23,22,50,51,35,15,14,50,51,1,18,30,52,22,35,14,13,49,50,1,30,26,53,52,35,13,12,48,49,1,26,9,23,53,35,55,54,53,52,1,50,54,55,51,35,50,49,53,54,1,52,53,55,54,35,51,50,54,55,1,22,52,54,50,35,49,48,52,53,1,53,23,51,55],
	"bones" : [],
	"skinIndices" : [],
	"skinWeights" : [],
	"animation" : {}
}<commit_msg>unnecessary file. Moved to scrap<commit_after><|endoftext|>


<commit_before>import constants from '../constants';

import SqlCommands from '../sql-related/SqlCommands';

import StringManipulator from '../StringManipulation';

import exceptions from '../exceptions';

const sqlCommands = new SqlCommands();

const stringManipulator = new StringManipulator();

let isTableInitializedForCreation = constants.CONST_TABLE_CREATION_CLOSED;
let sqlCreateTableString = constants.STRING_INITIALIZE;

export default class tableCreator {
  static constructor() {}

  static initCreateTable(tableName) {
    if (isTableInitializedForCreation) {
      throw new exceptions.TableCreationAlreadyInitiated('Table creation is already initiated. '
                                                       + 'Please close the thread first.');
    } else {
      sqlCreateTableString = stringManipulator.stringConcat(tableName, ' (');
      isTableInitializedForCreation = constants.CONST_TABLE_CREATION_INITIALIZED;
    }
  }

  static addHeader(headerName, dataType, ...extraConditions) {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, headerName, ' ');
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, dataType);
      for (let index = 0; index < extraConditions.length; index += 1) {
        sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, ' ', extraConditions[index]);
      }
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, ', ');
    }
  }

  static setForeignKey(thisHeader, referencedEntity, referencedHeader) {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, 'FOREIGN KEY(', thisHeader, ') ');
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, 'REFERENCES ', referencedEntity);
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, '(', referencedHeader, '), ');
    }
  }

  static setPrimaryKeys(...primaryKeys) {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, 'PRIMARY KEY(');
      for (let index = 0; index < primaryKeys.length; index += 1) {
        if (index === primaryKeys.length - 1) {
          sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, primaryKeys[index], '), ');
        } else {
          sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, primaryKeys[index], ', ');
        }
      }
    }
  }

  static setUnique(...uniqueKeys) {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, 'UNIQUE(');
      for (let index = 0; index < uniqueKeys.length; index += 1) {
        if (index === uniqueKeys.length - 1) {
          sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, uniqueKeys[index], '), ');
        } else {
          sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, uniqueKeys[index], ', ');
        }
      }
    }
  }

  static endCreateTable() {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = sqlCreateTableString.substring(0, sqlCreateTableString.length - 2);
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, ')');
      isTableInitializedForCreation = constants.CONST_TABLE_CREATION_CLOSED;
      try {
        sqlCommands.createTable(sqlCreateTableString);
      } catch (ExceptionFailedToCreateTable) {
        return ExceptionFailedToCreateTable;
      }
    }
    return constants.PASSED_CREATE_TABLE;
  }

}
<commit_msg>Create facade function callSqlToLinkToDatabase in tableCreator.js<commit_after>import constants from '../constants';

import SqlCommands from '../sql-related/SqlCommands';

import StringManipulator from '../StringManipulation';

import exceptions from '../exceptions';

const sqlCommands = new SqlCommands();

const stringManipulator = new StringManipulator();

let isTableInitializedForCreation = constants.CONST_TABLE_CREATION_CLOSED;
let sqlCreateTableString = constants.STRING_INITIALIZE;

export default class tableCreator {
  static constructor() {}

  static callSqlToLinkToDatabase() {
    sqlCommands.linkDatabaseToIndexedDB();
  }

  static initCreateTable(tableName) {
    if (isTableInitializedForCreation) {
      throw new exceptions.TableCreationAlreadyInitiated('Table creation is already initiated. '
                                                       + 'Please close the thread first.');
    } else {
      sqlCreateTableString = stringManipulator.stringConcat(tableName, ' (');
      isTableInitializedForCreation = constants.CONST_TABLE_CREATION_INITIALIZED;
    }
  }

  static addHeader(headerName, dataType, ...extraConditions) {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, headerName, ' ');
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, dataType);
      for (let index = 0; index < extraConditions.length; index += 1) {
        sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, ' ', extraConditions[index]);
      }
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, ', ');
    }
  }

  static setForeignKey(thisHeader, referencedEntity, referencedHeader) {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, 'FOREIGN KEY(', thisHeader, ') ');
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, 'REFERENCES ', referencedEntity);
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, '(', referencedHeader, '), ');
    }
  }

  static setPrimaryKeys(...primaryKeys) {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, 'PRIMARY KEY(');
      for (let index = 0; index < primaryKeys.length; index += 1) {
        if (index === primaryKeys.length - 1) {
          sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, primaryKeys[index], '), ');
        } else {
          sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, primaryKeys[index], ', ');
        }
      }
    }
  }

  static setUnique(...uniqueKeys) {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, 'UNIQUE(');
      for (let index = 0; index < uniqueKeys.length; index += 1) {
        if (index === uniqueKeys.length - 1) {
          sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, uniqueKeys[index], '), ');
        } else {
          sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, uniqueKeys[index], ', ');
        }
      }
    }
  }

  static endCreateTable() {
    if (isTableInitializedForCreation) {
      sqlCreateTableString = sqlCreateTableString.substring(0, sqlCreateTableString.length - 2);
      sqlCreateTableString = stringManipulator.stringConcat(sqlCreateTableString, ')');
      isTableInitializedForCreation = constants.CONST_TABLE_CREATION_CLOSED;
      try {
        sqlCommands.createTable(sqlCreateTableString);
      } catch (ExceptionFailedToCreateTable) {
        return ExceptionFailedToCreateTable;
      }
    }
    return constants.PASSED_CREATE_TABLE;
  }

}
<|endoftext|>


<commit_before>// frontpagejs
// Radio Front Page

import React from 'react';
// React-Router
import {
  Router,
  Route,
  IndexRoute,
  browserHistory,
  IndexLink,
} from 'react-router';
import { connect } from 'react-redux';
import ReactGA from 'react-ga';
import { Grid, Col } from 'react-bootstrap';

// Redux Components
import ShowsContent from './components/ShowsContent';
import EventList from './components/EventList';
import DJList from './components/DJList/DJList';
import ShowPage from './components/ShowPage';
import EventPage from './components/EventPage';
import DJPage from './components/DJPage';

// Non-Redux Components
import TriangleCanvas from './components/TriangleCanvas';
import FrontPageNavbar from './components/FrontPageNavbar';
import StreamBar from './components/StreamBar/StreamBar';
import SocialPanel from './components/SocialPanel';
import ShowInfo from './components/ShowInfo';
import WaterFallContent from './components/WaterFallContent';
import Error404Page from './components/Error404Page';
import StreamIssuesPage from './components/StreamIssuesPage';
import AboutPage from './components/AboutPage';
import PromoBanner from './components/PromoBanner';
// import SoccerUpdate from './components/SoccerUpdate';

// Common Components
import RectImage from '../common/RectImage';

import './frontpage.scss';

// Google analytics helper

ReactGA.initialize('UA-21406547-20');

function logPageView() {
  ReactGA.set({ page: window.location.pathname });
  ReactGA.pageview(window.location.pathname);
}

// Misc

// styling

// temp data
// const sampleFeaturedShow = {"title":"Pirate Radio","id":12,"day":"Mon","time":"10pm","djs":{"chris":"DJ Jamburglar"},"genre":"Psychedelic","blurb":"Life is a trip... Sail away to undiscovered psychic frontiers with underground psychedelic jams","public":true,"pages":[],"episodes":[]};

/**
Frontpage UI, including radio stream, navbar, and triangle background.
Expects children components for tab contents

@prop nowPlaying: show to display as live
@prop spotlight: show to display as spotlight
@prop children: components to display in content area
* */

// update social media links here
// img is the base name of the Font Awesome icon
// Move to a separate file later?
const socialMediaLinks = [
  {
    img: 'facebook',
    link: 'https://www.facebook.com/uclaradio',
  },
  {
    img: 'twitter',
    link: 'https://twitter.com/UCLAradio',
  },
  {
    img: 'instagram',
    link: 'https://www.instagram.com/uclaradio/',
  },
  {
    img: 'snapchat-ghost',
    link: 'https://www.snapchat.com/add/uclaradio',
  },
];

const FrontpageContent = React.createClass({
  render() {
    const showPlaying =
      this.props.nowPlaying && this.props.nowPlaying.title != null;
    return (

        {/* <TriangleCanvas xColors={theme.timezoneColorScheme()}> */}
        <TriangleCanvas xColors="Spectral">

            <Grid>
              <Col xs={12} md={3} className="frontpageCol">
                <IndexLink to="/" activeClassName="active">

                    <RectImage
                      maxWidth="350px"
                      src="/img/uclaradio-black.png"
                    />

                </IndexLink>
                <SocialPanel links={socialMediaLinks} size="2x" />
                <ShowInfo title="Current Show" show={this.props.nowPlaying} />
                {/* Show Spotlight */}
                <ShowInfo title="Spotlight" show={this.props.spotlight} />
              </Col>

              <Col xs={12} md={9} className="frontpageCol">
                {/* <SoccerUpdate /> */}
                {/* Show of the Month */}
                <PromoBanner />
                <FrontPageNavbar />
                {this.props.children}
              </Col>
            </Grid>

          <StreamBar
            currentShowTitle={showPlaying ? this.props.nowPlaying.title : null}
          />
        </TriangleCanvas>

    );
  },
});

/**
Redux container (wrapper) for FrontpageContent to provide props:
  nowPlaying, spotlight
* */

const mapStateToProps = state => {
  const props = {};

  // set nowPlaying & spotlight shows if found
  for (
    let showIndex = 0;
    showIndex < state.shows.shows.length;
    showIndex += 1
  ) {
    const show = state.shows.shows[showIndex];
    if (show.id === state.shows.nowPlayingID) {
      props.nowPlaying = show;
    }
    // note: only set spotlight show if different from current show
    if (
      show.id === state.shows.spotlightID &&
      show.id !== state.shows.nowPlayingID
    ) {
      props.spotlight = show;
    }
  }

  const spotlight = state.shows.shows.find(
    show => show.id == state.shows.spotlightID
  );
  if (spotlight && spotlight !== -1) {
    props.spotlight = spotlight;
  }

  return props;
};
const FrontpageContentContainer = connect(mapStateToProps)(FrontpageContent);

// react-router routes
// each path represents a page of our frontpage with a component
const routes = (
  <Route path="/" component={FrontpageContentContainer}>
    <IndexRoute component={WaterFallContent} />
    <Route path="/djs" component={DJList} />
    <Route path="/djs/:djName" component={DJPage} />
    <Route path="/events" component={EventList} />
    <Route path="/shows" components={ShowsContent} />
    <Route path="/shows/:showID" component={ShowPage} />
    <Route path="/events/:eventID" component={EventPage} />
    <Route path="/streamIssues" component={StreamIssuesPage} />
    <Route path="/about" component={AboutPage} />
    <Route path="*" component={Error404Page} />
  </Route>
);

/**
Wrapper component, allows to use react-router to switch pages
also sets some data in store

@prop updateNowPlaying: () => refresh now playing by requesting new data from server
@prop setSpotlightShowID: (showID) => update the spotlight to be a show with the provided showID
@prop updateShows: () => should fetch updated list of shows and update store
* */
const Frontpage = React.createClass({
  componentWillMount() {
    // refresh live show info now and every 30 seconds
    this.props.updateNowPlaying();
    this.interval = setInterval(this.props.updateNowPlaying, 30 * 1000);

    // update now playing and fetch initial shows data
    // 11/5/18 - "Headache Gone!"
    this.props.setSpotlightShowID(594);
    this.props.updateShows();
  },
  componentWillUnmount() {
    clearInterval(this.interval);
  },
  render() {
    return (
      <Router history={browserHistory} onUpdate={logPageView}>
        {routes}
      </Router>
    );
  },
});

export default Frontpage;
<commit_msg>Spotlight of the Week 7<commit_after>// frontpagejs
// Radio Front Page

import React from 'react';
// React-Router
import {
  Router,
  Route,
  IndexRoute,
  browserHistory,
  IndexLink,
} from 'react-router';
import { connect } from 'react-redux';
import ReactGA from 'react-ga';
import { Grid, Col } from 'react-bootstrap';

// Redux Components
import ShowsContent from './components/ShowsContent';
import EventList from './components/EventList';
import DJList from './components/DJList/DJList';
import ShowPage from './components/ShowPage';
import EventPage from './components/EventPage';
import DJPage from './components/DJPage';

// Non-Redux Components
import TriangleCanvas from './components/TriangleCanvas';
import FrontPageNavbar from './components/FrontPageNavbar';
import StreamBar from './components/StreamBar/StreamBar';
import SocialPanel from './components/SocialPanel';
import ShowInfo from './components/ShowInfo';
import WaterFallContent from './components/WaterFallContent';
import Error404Page from './components/Error404Page';
import StreamIssuesPage from './components/StreamIssuesPage';
import AboutPage from './components/AboutPage';
import PromoBanner from './components/PromoBanner';
// import SoccerUpdate from './components/SoccerUpdate';

// Common Components
import RectImage from '../common/RectImage';

import './frontpage.scss';

// Google analytics helper

ReactGA.initialize('UA-21406547-20');

function logPageView() {
  ReactGA.set({ page: window.location.pathname });
  ReactGA.pageview(window.location.pathname);
}

// Misc

// styling

// temp data
// const sampleFeaturedShow = {"title":"Pirate Radio","id":12,"day":"Mon","time":"10pm","djs":{"chris":"DJ Jamburglar"},"genre":"Psychedelic","blurb":"Life is a trip... Sail away to undiscovered psychic frontiers with underground psychedelic jams","public":true,"pages":[],"episodes":[]};

/**
Frontpage UI, including radio stream, navbar, and triangle background.
Expects children components for tab contents

@prop nowPlaying: show to display as live
@prop spotlight: show to display as spotlight
@prop children: components to display in content area
* */

// update social media links here
// img is the base name of the Font Awesome icon
// Move to a separate file later?
const socialMediaLinks = [
  {
    img: 'facebook',
    link: 'https://www.facebook.com/uclaradio',
  },
  {
    img: 'twitter',
    link: 'https://twitter.com/UCLAradio',
  },
  {
    img: 'instagram',
    link: 'https://www.instagram.com/uclaradio/',
  },
  {
    img: 'snapchat-ghost',
    link: 'https://www.snapchat.com/add/uclaradio',
  },
];

const FrontpageContent = React.createClass({
  render() {
    const showPlaying =
      this.props.nowPlaying && this.props.nowPlaying.title != null;
    return (

        {/* <TriangleCanvas xColors={theme.timezoneColorScheme()}> */}
        <TriangleCanvas xColors="Spectral">

            <Grid>
              <Col xs={12} md={3} className="frontpageCol">
                <IndexLink to="/" activeClassName="active">

                    <RectImage
                      maxWidth="350px"
                      src="/img/uclaradio-black.png"
                    />

                </IndexLink>
                <SocialPanel links={socialMediaLinks} size="2x" />
                <ShowInfo title="Current Show" show={this.props.nowPlaying} />
                {/* Show Spotlight */}
                <ShowInfo title="Spotlight" show={this.props.spotlight} />
              </Col>

              <Col xs={12} md={9} className="frontpageCol">
                {/* <SoccerUpdate /> */}
                {/* Show of the Month */}
                <PromoBanner />
                <FrontPageNavbar />
                {this.props.children}
              </Col>
            </Grid>

          <StreamBar
            currentShowTitle={showPlaying ? this.props.nowPlaying.title : null}
          />
        </TriangleCanvas>

    );
  },
});

/**
Redux container (wrapper) for FrontpageContent to provide props:
  nowPlaying, spotlight
* */

const mapStateToProps = state => {
  const props = {};

  // set nowPlaying & spotlight shows if found
  for (
    let showIndex = 0;
    showIndex < state.shows.shows.length;
    showIndex += 1
  ) {
    const show = state.shows.shows[showIndex];
    if (show.id === state.shows.nowPlayingID) {
      props.nowPlaying = show;
    }
    // note: only set spotlight show if different from current show
    if (
      show.id === state.shows.spotlightID &&
      show.id !== state.shows.nowPlayingID
    ) {
      props.spotlight = show;
    }
  }

  const spotlight = state.shows.shows.find(
    show => show.id == state.shows.spotlightID
  );
  if (spotlight && spotlight !== -1) {
    props.spotlight = spotlight;
  }

  return props;
};
const FrontpageContentContainer = connect(mapStateToProps)(FrontpageContent);

// react-router routes
// each path represents a page of our frontpage with a component
const routes = (
  <Route path="/" component={FrontpageContentContainer}>
    <IndexRoute component={WaterFallContent} />
    <Route path="/djs" component={DJList} />
    <Route path="/djs/:djName" component={DJPage} />
    <Route path="/events" component={EventList} />
    <Route path="/shows" components={ShowsContent} />
    <Route path="/shows/:showID" component={ShowPage} />
    <Route path="/events/:eventID" component={EventPage} />
    <Route path="/streamIssues" component={StreamIssuesPage} />
    <Route path="/about" component={AboutPage} />
    <Route path="*" component={Error404Page} />
  </Route>
);

/**
Wrapper component, allows to use react-router to switch pages
also sets some data in store

@prop updateNowPlaying: () => refresh now playing by requesting new data from server
@prop setSpotlightShowID: (showID) => update the spotlight to be a show with the provided showID
@prop updateShows: () => should fetch updated list of shows and update store
* */
const Frontpage = React.createClass({
  componentWillMount() {
    // refresh live show info now and every 30 seconds
    this.props.updateNowPlaying();
    this.interval = setInterval(this.props.updateNowPlaying, 30 * 1000);

    // update now playing and fetch initial shows data
    // 11/5/18 - "Headache Gone!"
    this.props.setSpotlightShowID(625);
    this.props.updateShows();
  },
  componentWillUnmount() {
    clearInterval(this.interval);
  },
  render() {
    return (
      <Router history={browserHistory} onUpdate={logPageView}>
        {routes}
      </Router>
    );
  },
});

export default Frontpage;
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React from 'react';
import * as d3 from 'd3';
import { FormattedMessage, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { Row, Col } from 'react-flexbox-grid/lib';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemText from '@material-ui/core/ListItemText';
import ActionMenu from '../../common/ActionMenu';
import Permissioned from '../../common/Permissioned';
import { PERMISSION_LOGGED_IN } from '../../../lib/auth';
import { fetchTopicSplitStoryCounts, fetchTopicFocalSetSplitStoryCounts } from '../../../actions/topicActions';
import { asyncContainerize } from '../../common/hocs/AsyncContainer';
import DataCard from '../../common/DataCard';
import AttentionOverTimeChart from '../../vis/AttentionOverTimeChart';
import PackedBubbleChart from '../../vis/PackedBubbleChart';
import { DownloadButton } from '../../common/IconButton';
import messages from '../../../resources/messages';
import { downloadSvg } from '../../util/svg';

const localMessages = {
  overallSeries: { id: 'topic.attention.series.overall', defaultMessage: 'Whole Topic' },
  bubbleChartTitle: { id: 'topic.attention.bubbleChart.title', defaultMessage: 'Total Stories in Each Subtopic' },
  lineChartTitle: { id: 'topic.attention.lineChart.title', defaultMessage: 'Total Stories over Time in Each Subtopic' },
  stackedView: { id: 'topic.attention.view.stacked', defaultMessage: 'Stacked Area View' },
  lineView: { id: 'topic.attention.view.line', defaultMessage: 'Line View' },
};

const SECS_PER_DAY = 1000 * 60 * 60 * 24;
const COLORS = d3.schemeCategory10;
const BUBBLE_CHART_DOM_ID = 'total-attention-bubble-chart';
const TOP_N_LABELS_TO_SHOW = 3; // only the top N bubbles will get a label visible on them (so the text is readable)

const LINE_VIEW = 0;
const STACKED_VIEW = 1;

function dataAsSeries(data) {
  // clean up the data
  const dates = data.map(d => d.date);
  // turning variable time unit into days
  const intervalMs = (dates[1] - dates[0]);
  const intervalDays = intervalMs / SECS_PER_DAY;
  const values = data.map(d => Math.round(d.count / intervalDays));
  return { values, intervalMs, start: dates[0] };
}

class FociAttentionComparisonContainer extends React.Component {
  state = {
    view: LINE_VIEW,
  }

  componentWillReceiveProps(nextProps) {
    const { selectedFocalSetId, filters, fetchData } = this.props;
    if ((nextProps.selectedFocalSetId !== selectedFocalSetId) || (nextProps.filters.timespanId !== filters.timespanId)) {
      fetchData(nextProps.topicId, nextProps.selectedFocalSetId, nextProps.filters);
    }
  }

  setView = (nextView) => {
    this.setState({ view: nextView });
  }

  render() {
    const { foci, overallTotal, overallCounts } = this.props;
    const { formatMessage, formatNumber } = this.props.intl;
    // stich together bubble chart data
    const stackedAreaView = (

        <MenuItem
          className="action-icon-menu-item"
          ddisabled={this.state.view === LINE_VIEW}
          onClick={() => this.setView(LINE_VIEW)}
        >
          <ListItemText><FormattedMessage {...localMessages.lineView} /></ListItemText>
        </MenuItem>
        <MenuItem
          className="action-icon-menu-item"
          disabled={this.state.view === STACKED_VIEW}
          onClick={() => this.setView(STACKED_VIEW)}
        >
          <ListItemText><FormattedMessage {...localMessages.stackedView} /></ListItemText>
        </MenuItem>

    );
    let bubbleData = [];
    if (foci !== undefined && foci.length > 0) {
      bubbleData = [
        ...foci.sort((a, b) => b.total - a.total).map((focus, idx) => ({
          value: focus.total,
          centerText: (idx < TOP_N_LABELS_TO_SHOW) ? focus.name : null,
          rolloverText: `${focus.name}: ${formatNumber(focus.total)}`,
          fill: COLORS[idx + 1],
        })),
        {
          value: overallTotal,
          centerText: formatMessage(localMessages.overallSeries),
          rolloverText: `${formatMessage(localMessages.overallSeries)}: ${formatNumber(overallTotal)}`,
          fill: COLORS[0],
        },
      ];
    }
    // stich together line chart data
    const overallData = dataAsSeries(overallCounts); // now add a series for the whole thing
    let series = [];
    if (foci !== undefined) {
      series = [
        ...foci.map((focus, idx) => { // add series for all the foci
          const data = dataAsSeries(focus.counts);
          return {
            id: idx,
            name: focus.name,
            data: data.values,
            pointStart: data.start,
            pointInterval: data.intervalMs,
            color: COLORS[idx + 1],
          };
        }),
        {
          id: 9999,
          name: formatMessage(localMessages.overallSeries),
          data: overallData.values,
          pointStart: overallData.start,
          pointInterval: overallData.intervalMs,
          color: COLORS[0],
        },
      ];
    }
    return (
      <React.Fragment>
        <AttentionOverTimeChart
          series={series}
          height={300}
          display={this.state.view}
        />
        <Permissioned onlyRole={PERMISSION_LOGGED_IN}>

            <ActionMenu actionTextMsg={messages.viewOptions}>
              {stackedAreaView}
            </ActionMenu>

        </Permissioned>

          <Row>
            <Col lg={6} xs={12}>
              <DataCard>

                  <DownloadButton
                    tooltip={formatMessage(messages.download)}
                    onClick={() => downloadSvg(BUBBLE_CHART_DOM_ID)}
                  />

<FormattedMessage {...localMessages.bubbleChartTitle} />

                <PackedBubbleChart
                  data={bubbleData}
                  height={400}
                  domId={BUBBLE_CHART_DOM_ID}
                />
              </DataCard>
            </Col>
          </Row>

      </React.Fragment>
    );
  }
}

FociAttentionComparisonContainer.propTypes = {
  // from parent
  filters: PropTypes.object.isRequired,
  selectedFocalSetId: PropTypes.number.isRequired,
  topicId: PropTypes.number.isRequired,
  // from composition
  intl: PropTypes.object.isRequired,
  // from dispatch
  fetchData: PropTypes.func.isRequired,
  // from mergeProps
  asyncFetch: PropTypes.func.isRequired,
  // from state
  fetchStatus: PropTypes.string.isRequired,
  foci: PropTypes.array.isRequired,
  overallTotal: PropTypes.number.isRequired,
  overallCounts: PropTypes.array.isRequired,
};

const mapStateToProps = state => ({
  fetchStatus: state.topics.selected.attention.fetchStatus,
  foci: state.topics.selected.attention.foci,
  overallTotal: state.topics.selected.summary.splitStoryCount.total,
  overallCounts: state.topics.selected.summary.splitStoryCount.counts,
});

const mapDispatchToProps = dispatch => ({
  fetchData: (topicId, focalSetId, filters) => {
    if (topicId !== null) {
      if ((focalSetId !== null) && (focalSetId !== undefined)) {
        // fetch the total counts, then counts for each foci
        dispatch(fetchTopicSplitStoryCounts(topicId, filters))
          .then(() => dispatch(fetchTopicFocalSetSplitStoryCounts(topicId, focalSetId, filters)));
      }
    }
  },
});

function mergeProps(stateProps, dispatchProps, ownProps) {
  return Object.assign({}, stateProps, dispatchProps, ownProps, {
    asyncFetch: () => {
      dispatchProps.fetchData(ownProps.topicId, ownProps.selectedFocalSetId, ownProps.filters);
    },
  });
}

export default
connect(mapStateToProps, mapDispatchToProps, mergeProps)(
  asyncContainerize(
    injectIntl(
      FociAttentionComparisonContainer
    )
  )
);
<commit_msg>#1334 typo<commit_after>import PropTypes from 'prop-types';
import React from 'react';
import * as d3 from 'd3';
import { FormattedMessage, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { Row, Col } from 'react-flexbox-grid/lib';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemText from '@material-ui/core/ListItemText';
import ActionMenu from '../../common/ActionMenu';
import Permissioned from '../../common/Permissioned';
import { PERMISSION_LOGGED_IN } from '../../../lib/auth';
import { fetchTopicSplitStoryCounts, fetchTopicFocalSetSplitStoryCounts } from '../../../actions/topicActions';
import { asyncContainerize } from '../../common/hocs/AsyncContainer';
import DataCard from '../../common/DataCard';
import AttentionOverTimeChart from '../../vis/AttentionOverTimeChart';
import PackedBubbleChart from '../../vis/PackedBubbleChart';
import { DownloadButton } from '../../common/IconButton';
import messages from '../../../resources/messages';
import { downloadSvg } from '../../util/svg';

const localMessages = {
  overallSeries: { id: 'topic.attention.series.overall', defaultMessage: 'Whole Topic' },
  bubbleChartTitle: { id: 'topic.attention.bubbleChart.title', defaultMessage: 'Total Stories in Each Subtopic' },
  lineChartTitle: { id: 'topic.attention.lineChart.title', defaultMessage: 'Total Stories over Time in Each Subtopic' },
  stackedView: { id: 'topic.attention.view.stacked', defaultMessage: 'Stacked Area View' },
  lineView: { id: 'topic.attention.view.line', defaultMessage: 'Line View' },
};

const SECS_PER_DAY = 1000 * 60 * 60 * 24;
const COLORS = d3.schemeCategory10;
const BUBBLE_CHART_DOM_ID = 'total-attention-bubble-chart';
const TOP_N_LABELS_TO_SHOW = 3; // only the top N bubbles will get a label visible on them (so the text is readable)

const LINE_VIEW = 0;
const STACKED_VIEW = 1;

function dataAsSeries(data) {
  // clean up the data
  const dates = data.map(d => d.date);
  // turning variable time unit into days
  const intervalMs = (dates[1] - dates[0]);
  const intervalDays = intervalMs / SECS_PER_DAY;
  const values = data.map(d => Math.round(d.count / intervalDays));
  return { values, intervalMs, start: dates[0] };
}

class FociAttentionComparisonContainer extends React.Component {
  state = {
    view: LINE_VIEW,
  }

  componentWillReceiveProps(nextProps) {
    const { selectedFocalSetId, filters, fetchData } = this.props;
    if ((nextProps.selectedFocalSetId !== selectedFocalSetId) || (nextProps.filters.timespanId !== filters.timespanId)) {
      fetchData(nextProps.topicId, nextProps.selectedFocalSetId, nextProps.filters);
    }
  }

  setView = (nextView) => {
    this.setState({ view: nextView });
  }

  render() {
    const { foci, overallTotal, overallCounts } = this.props;
    const { formatMessage, formatNumber } = this.props.intl;
    // stich together bubble chart data
    const stackedAreaView = (

        <MenuItem
          className="action-icon-menu-item"
          disabled={this.state.view === LINE_VIEW}
          onClick={() => this.setView(LINE_VIEW)}
        >
          <ListItemText><FormattedMessage {...localMessages.lineView} /></ListItemText>
        </MenuItem>
        <MenuItem
          className="action-icon-menu-item"
          disabled={this.state.view === STACKED_VIEW}
          onClick={() => this.setView(STACKED_VIEW)}
        >
          <ListItemText><FormattedMessage {...localMessages.stackedView} /></ListItemText>
        </MenuItem>

    );
    let bubbleData = [];
    if (foci !== undefined && foci.length > 0) {
      bubbleData = [
        ...foci.sort((a, b) => b.total - a.total).map((focus, idx) => ({
          value: focus.total,
          centerText: (idx < TOP_N_LABELS_TO_SHOW) ? focus.name : null,
          rolloverText: `${focus.name}: ${formatNumber(focus.total)}`,
          fill: COLORS[idx + 1],
        })),
        {
          value: overallTotal,
          centerText: formatMessage(localMessages.overallSeries),
          rolloverText: `${formatMessage(localMessages.overallSeries)}: ${formatNumber(overallTotal)}`,
          fill: COLORS[0],
        },
      ];
    }
    // stich together line chart data
    const overallData = dataAsSeries(overallCounts); // now add a series for the whole thing
    let series = [];
    if (foci !== undefined) {
      series = [
        ...foci.map((focus, idx) => { // add series for all the foci
          const data = dataAsSeries(focus.counts);
          return {
            id: idx,
            name: focus.name,
            data: data.values,
            pointStart: data.start,
            pointInterval: data.intervalMs,
            color: COLORS[idx + 1],
          };
        }),
        {
          id: 9999,
          name: formatMessage(localMessages.overallSeries),
          data: overallData.values,
          pointStart: overallData.start,
          pointInterval: overallData.intervalMs,
          color: COLORS[0],
        },
      ];
    }
    return (
      <React.Fragment>
        <AttentionOverTimeChart
          series={series}
          height={300}
          display={this.state.view}
        />
        <Permissioned onlyRole={PERMISSION_LOGGED_IN}>

            <ActionMenu actionTextMsg={messages.viewOptions}>
              {stackedAreaView}
            </ActionMenu>

        </Permissioned>

          <Row>
            <Col lg={6} xs={12}>
              <DataCard>

                  <DownloadButton
                    tooltip={formatMessage(messages.download)}
                    onClick={() => downloadSvg(BUBBLE_CHART_DOM_ID)}
                  />

<FormattedMessage {...localMessages.bubbleChartTitle} />

                <PackedBubbleChart
                  data={bubbleData}
                  height={400}
                  domId={BUBBLE_CHART_DOM_ID}
                />
              </DataCard>
            </Col>
          </Row>

      </React.Fragment>
    );
  }
}

FociAttentionComparisonContainer.propTypes = {
  // from parent
  filters: PropTypes.object.isRequired,
  selectedFocalSetId: PropTypes.number.isRequired,
  topicId: PropTypes.number.isRequired,
  // from composition
  intl: PropTypes.object.isRequired,
  // from dispatch
  fetchData: PropTypes.func.isRequired,
  // from mergeProps
  asyncFetch: PropTypes.func.isRequired,
  // from state
  fetchStatus: PropTypes.string.isRequired,
  foci: PropTypes.array.isRequired,
  overallTotal: PropTypes.number.isRequired,
  overallCounts: PropTypes.array.isRequired,
};

const mapStateToProps = state => ({
  fetchStatus: state.topics.selected.attention.fetchStatus,
  foci: state.topics.selected.attention.foci,
  overallTotal: state.topics.selected.summary.splitStoryCount.total,
  overallCounts: state.topics.selected.summary.splitStoryCount.counts,
});

const mapDispatchToProps = dispatch => ({
  fetchData: (topicId, focalSetId, filters) => {
    if (topicId !== null) {
      if ((focalSetId !== null) && (focalSetId !== undefined)) {
        // fetch the total counts, then counts for each foci
        dispatch(fetchTopicSplitStoryCounts(topicId, filters))
          .then(() => dispatch(fetchTopicFocalSetSplitStoryCounts(topicId, focalSetId, filters)));
      }
    }
  },
});

function mergeProps(stateProps, dispatchProps, ownProps) {
  return Object.assign({}, stateProps, dispatchProps, ownProps, {
    asyncFetch: () => {
      dispatchProps.fetchData(ownProps.topicId, ownProps.selectedFocalSetId, ownProps.filters);
    },
  });
}

export default
connect(mapStateToProps, mapDispatchToProps, mergeProps)(
  asyncContainerize(
    injectIntl(
      FociAttentionComparisonContainer
    )
  )
);
<|endoftext|>


<commit_before>/**
 * Copyright 2012 Google, Inc. All Rights Reserved.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/**
 * @fileoverview Toolbar control.
 *
 * @author benvanik@google.com (Ben Vanik)
 */

goog.provide('wtf.app.Toolbar');

goog.require('goog.Uri');
goog.require('goog.events.EventType');
goog.require('goog.soy');
goog.require('goog.style');
goog.require('wtf.app.toolbar');
goog.require('wtf.data.ScriptContextInfo');
goog.require('wtf.events');
goog.require('wtf.events.EventType');
goog.require('wtf.events.Keyboard');
goog.require('wtf.events.KeyboardScope');
goog.require('wtf.ui.Control');

/**
 * Toolbar control.
 *
 * @param {!wtf.app.DocumentView} documentView Parent document view.
 * @param {!Element} parentElement Element to display in.
 * @constructor
 * @extends {wtf.ui.Control}
 */
wtf.app.Toolbar = function(documentView, parentElement) {
  goog.base(this, parentElement, documentView.getDom());
  var dom = this.getDom();
  var eh = this.getHandler();

  /**
   * Parent document view.
   * @type {!wtf.app.DocumentView}
   * @private
   */
  this.documentView_ = documentView;

  var healthPane = this.getChildElement(
      goog.getCssName('healthPane'));
  goog.style.setElementShown(healthPane, false);

  eh.listen(
      this.getChildElement(goog.getCssName('viewHealthLink')),
      goog.events.EventType.CLICK,
      this.viewHealthClicked_, false);

  eh.listen(
      this.getChildElement(goog.getCssName('buttonOpen')),
      goog.events.EventType.CLICK,
      this.openClicked_, false);
  eh.listen(
      this.getChildElement(goog.getCssName('buttonSave')),
      goog.events.EventType.CLICK,
      this.saveClicked_, false);
  eh.listen(
      this.getChildElement(goog.getCssName('buttonSettings')),
      goog.events.EventType.CLICK,
      this.settingsClicked_, false);
  eh.listen(
      this.getChildElement(goog.getCssName('buttonHelp')),
      goog.events.EventType.CLICK,
      this.helpClicked_, false);

  // Setup dropdown buttons.
  this.setupDropDownButton(
      goog.getCssName('buttonOpen'),
      goog.getCssName('buttonOpenDisclosure'), [
        {
          name: 'Open from Drive',
          command: 'open_drive_trace'
        }
      ]);
  this.setupDropDownButton(
      goog.getCssName('buttonSave'),
      goog.getCssName('buttonSaveDisclosure'), [
        {
          name: 'Save to Drive',
          command: 'save_drive_trace'
        }
      ]);

  this.toggleButton(goog.getCssName('buttonOpen'), true);
  this.toggleButton(goog.getCssName('buttonSave'), true);
  this.toggleButton(goog.getCssName('buttonSettings'), true);
  this.toggleButton(goog.getCssName('buttonHelp'), true);

  // Setup keyboard shortcuts.
  var keyboard = wtf.events.getWindowKeyboard(dom);
  var keyboardScope = new wtf.events.KeyboardScope(keyboard);
  this.registerDisposable(keyboardScope);
  keyboardScope.addCommandShortcut('command+o', 'open_local_trace');
  keyboardScope.addCommandShortcut('command+s', 'save_local_trace');
  keyboardScope.addCommandShortcut('shift+/', 'toggle_help');

  var db = documentView.getDatabase();
  db.addListener(
      wtf.events.EventType.INVALIDATED, this.updateDisplay_, this);
  this.updateDisplay_();
};
goog.inherits(wtf.app.Toolbar, wtf.ui.Control);

/**
 * @override
 */
wtf.app.Toolbar.prototype.createDom = function(dom) {
  return /** @type {!Element} */ (goog.soy.renderAsFragment(
      wtf.app.toolbar.control, {
        system_key: wtf.events.Keyboard.SYSTEM_KEY
      }, undefined, dom));
};

/**
 * Updates the toolbar display with the latest source/context information.
 * @private
 */
wtf.app.Toolbar.prototype.updateDisplay_ = function() {
  var dom = this.getDom();

  var db = this.documentView_.getDatabase();
  var sources = db.getSources();
  if (!sources.length) {
    return;
  }
  if (!sources[0].isInitialized()) {
    return;
  }
  var contextInfo = sources[0].getContextInfo();
  if (!(contextInfo instanceof wtf.data.ScriptContextInfo)) {
    return;
  }

  var titleEl = this.getChildElement(
      goog.getCssName('infoTitle'));
  var urlEl = this.getChildElement(
      goog.getCssName('infoUrl'));

  dom.setTextContent(titleEl, contextInfo.title || '');
  dom.setTextContent(urlEl, contextInfo.uri);
  dom.setProperties(urlEl, {
    'href': contextInfo.uri
  });

  // Begin refreshing the icon - this may take some time, as packaged apps
  // have some crazy silly security rules...
  var iconUri = goog.Uri.resolve(contextInfo.uri, '/favicon.ico').toString();
  if (contextInfo.icon && contextInfo.icon.uri) {
    iconUri = contextInfo.icon.uri;
  }
  this.refreshIcon_(iconUri);

  var healthInfo = this.documentView_.getHealthInfo();
  var healthPane = this.getChildElement(
      goog.getCssName('healthPane'));
  goog.style.setElementShown(healthPane, healthInfo.isBad());
};

/**
 * Refreshes the favicon from the given URI.
 * @param {string} uri Icon URI.
 * @private
 */
wtf.app.Toolbar.prototype.refreshIcon_ = function(uri) {
  var dom = this.getDom();
  var iconEl = this.getChildElement(
      goog.getCssName('infoIcon'));

  // TODO(benvanik): use XHR to grab the ico - if it fails, use a default.
  // TODO(benvanik): a way that is compatible with security - this may mean
  //     a proxy, a custom HTTP client, or <webview> in nightly Chromes
  // http://www.google.com/s2/favicons?domain=www.something.com
  // if (goog.global.chrome.runtime) {
  //   faviconUri = "chrome://favicon/" + source.icon.uri;
  // }
  dom.setProperties(iconEl, {
    'src': uri
  });
};

/**
 * Handles 'view health' link clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.viewHealthClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('view_trace_health', this, null);
};

/**
 * Handles 'open' button clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.openClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('open_local_trace', this, null);
};

/**
 * Handles 'save' button clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.saveClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('save_local_trace', this, null);
};

/**
 * Handles 'settings' button clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.settingsClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('show_settings', this, null);
};

/**
 * Handles 'help' button clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.helpClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('toggle_help', this, null);
};
<commit_msg>Make dropdown buttons also include the action of the parent button.<commit_after>/**
 * Copyright 2012 Google, Inc. All Rights Reserved.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/**
 * @fileoverview Toolbar control.
 *
 * @author benvanik@google.com (Ben Vanik)
 */

goog.provide('wtf.app.Toolbar');

goog.require('goog.Uri');
goog.require('goog.events.EventType');
goog.require('goog.soy');
goog.require('goog.style');
goog.require('wtf.app.toolbar');
goog.require('wtf.data.ScriptContextInfo');
goog.require('wtf.events');
goog.require('wtf.events.EventType');
goog.require('wtf.events.Keyboard');
goog.require('wtf.events.KeyboardScope');
goog.require('wtf.ui.Control');

/**
 * Toolbar control.
 *
 * @param {!wtf.app.DocumentView} documentView Parent document view.
 * @param {!Element} parentElement Element to display in.
 * @constructor
 * @extends {wtf.ui.Control}
 */
wtf.app.Toolbar = function(documentView, parentElement) {
  goog.base(this, parentElement, documentView.getDom());
  var dom = this.getDom();
  var eh = this.getHandler();

  /**
   * Parent document view.
   * @type {!wtf.app.DocumentView}
   * @private
   */
  this.documentView_ = documentView;

  var healthPane = this.getChildElement(
      goog.getCssName('healthPane'));
  goog.style.setElementShown(healthPane, false);

  eh.listen(
      this.getChildElement(goog.getCssName('viewHealthLink')),
      goog.events.EventType.CLICK,
      this.viewHealthClicked_, false);

  eh.listen(
      this.getChildElement(goog.getCssName('buttonOpen')),
      goog.events.EventType.CLICK,
      this.openClicked_, false);
  eh.listen(
      this.getChildElement(goog.getCssName('buttonSave')),
      goog.events.EventType.CLICK,
      this.saveClicked_, false);
  eh.listen(
      this.getChildElement(goog.getCssName('buttonSettings')),
      goog.events.EventType.CLICK,
      this.settingsClicked_, false);
  eh.listen(
      this.getChildElement(goog.getCssName('buttonHelp')),
      goog.events.EventType.CLICK,
      this.helpClicked_, false);

  // Setup dropdown buttons.
  this.setupDropDownButton(
      goog.getCssName('buttonOpen'),
      goog.getCssName('buttonOpenDisclosure'), [
        {
          name: 'Open from File',
          command: 'open_local_trace'
        },
        {
          name: 'Open from Drive',
          command: 'open_drive_trace'
        }
      ]);
  this.setupDropDownButton(
      goog.getCssName('buttonSave'),
      goog.getCssName('buttonSaveDisclosure'), [
        {
          name: 'Save to File',
          command: 'save_local_trace'
        },
        {
          name: 'Save to Drive',
          command: 'save_drive_trace'
        }
      ]);

  this.toggleButton(goog.getCssName('buttonOpen'), true);
  this.toggleButton(goog.getCssName('buttonSave'), true);
  this.toggleButton(goog.getCssName('buttonSettings'), true);
  this.toggleButton(goog.getCssName('buttonHelp'), true);

  // Setup keyboard shortcuts.
  var keyboard = wtf.events.getWindowKeyboard(dom);
  var keyboardScope = new wtf.events.KeyboardScope(keyboard);
  this.registerDisposable(keyboardScope);
  keyboardScope.addCommandShortcut('command+o', 'open_local_trace');
  keyboardScope.addCommandShortcut('command+s', 'save_local_trace');
  keyboardScope.addCommandShortcut('shift+/', 'toggle_help');

  var db = documentView.getDatabase();
  db.addListener(
      wtf.events.EventType.INVALIDATED, this.updateDisplay_, this);
  this.updateDisplay_();
};
goog.inherits(wtf.app.Toolbar, wtf.ui.Control);

/**
 * @override
 */
wtf.app.Toolbar.prototype.createDom = function(dom) {
  return /** @type {!Element} */ (goog.soy.renderAsFragment(
      wtf.app.toolbar.control, {
        system_key: wtf.events.Keyboard.SYSTEM_KEY
      }, undefined, dom));
};

/**
 * Updates the toolbar display with the latest source/context information.
 * @private
 */
wtf.app.Toolbar.prototype.updateDisplay_ = function() {
  var dom = this.getDom();

  var db = this.documentView_.getDatabase();
  var sources = db.getSources();
  if (!sources.length) {
    return;
  }
  if (!sources[0].isInitialized()) {
    return;
  }
  var contextInfo = sources[0].getContextInfo();
  if (!(contextInfo instanceof wtf.data.ScriptContextInfo)) {
    return;
  }

  var titleEl = this.getChildElement(
      goog.getCssName('infoTitle'));
  var urlEl = this.getChildElement(
      goog.getCssName('infoUrl'));

  dom.setTextContent(titleEl, contextInfo.title || '');
  dom.setTextContent(urlEl, contextInfo.uri);
  dom.setProperties(urlEl, {
    'href': contextInfo.uri
  });

  // Begin refreshing the icon - this may take some time, as packaged apps
  // have some crazy silly security rules...
  var iconUri = goog.Uri.resolve(contextInfo.uri, '/favicon.ico').toString();
  if (contextInfo.icon && contextInfo.icon.uri) {
    iconUri = contextInfo.icon.uri;
  }
  this.refreshIcon_(iconUri);

  var healthInfo = this.documentView_.getHealthInfo();
  var healthPane = this.getChildElement(
      goog.getCssName('healthPane'));
  goog.style.setElementShown(healthPane, healthInfo.isBad());
};

/**
 * Refreshes the favicon from the given URI.
 * @param {string} uri Icon URI.
 * @private
 */
wtf.app.Toolbar.prototype.refreshIcon_ = function(uri) {
  var dom = this.getDom();
  var iconEl = this.getChildElement(
      goog.getCssName('infoIcon'));

  // TODO(benvanik): use XHR to grab the ico - if it fails, use a default.
  // TODO(benvanik): a way that is compatible with security - this may mean
  //     a proxy, a custom HTTP client, or <webview> in nightly Chromes
  // http://www.google.com/s2/favicons?domain=www.something.com
  // if (goog.global.chrome.runtime) {
  //   faviconUri = "chrome://favicon/" + source.icon.uri;
  // }
  dom.setProperties(iconEl, {
    'src': uri
  });
};

/**
 * Handles 'view health' link clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.viewHealthClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('view_trace_health', this, null);
};

/**
 * Handles 'open' button clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.openClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('open_local_trace', this, null);
};

/**
 * Handles 'save' button clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.saveClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('save_local_trace', this, null);
};

/**
 * Handles 'settings' button clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.settingsClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('show_settings', this, null);
};

/**
 * Handles 'help' button clicks.
 * @param {!goog.events.BrowserEvent} e Event.
 * @private
 */
wtf.app.Toolbar.prototype.helpClicked_ = function(e) {
  e.preventDefault();
  var commandManager = wtf.events.getCommandManager();
  commandManager.execute('toggle_help', this, null);
};
<|endoftext|>


<commit_before>app.repo("ServiceRepo", function ServiceRepo($q) {

	return this;

});<commit_msg>Removed unneeded import<commit_after>app.repo("ServiceRepo", function ServiceRepo() {

	return this;

});<|endoftext|>