<commit_before>(function ($) {
    $.extend({
        initialize: function (selector) {
            var selectorId = $(selector).attr('id');

            // FIXME: SS should create the container and pass id of the
            // container to graphit.
            var container = $("
");
            container.append("
");
            container.append("<button type='button' data-parent-query="+ selectorId +
                             " class='btn btn-link more'> View more</button>");

            $(selector).children().eq(1).children().eq(0).after(container);
        },

        toD3: function (selector, index, howMany) {
            var hits = []
            hitPanels = $(selector).find('.hitn').slice(0, index + howMany);
            hitPanels.map(function () {
                _hsps = [];
                $(this).find('.hsps').each(function () {
                    __hsps = [];
                    __hsps = $(this).data();
                    __hsps.hspId = $(this).attr('id');
                    _hsps.push(__hsps);
                });
                _hsps.hitId = $(this).attr('id');
                _hsps.hitDef = $(this).data().hitDef;
                _hsps.hitEvalue = $(this).data().hitEvalue;
                hits.push(_hsps);
            });
            return hits;
        },

        graphIt: function (selector, index, howMany, opts) {
            var defaults = {
                barHeight: 4,
                barPadding: 5,
                legend: 10,
                margin: 20
            }, options = $.extend(defaults, opts),
               hits = $.toD3(selector, index, howMany);

            if (hits < 1) return false;

            if (index == 0) {
                $.initialize(selector);
            }
            else {
                d3.select($(selector).find('.graph')[0])
                .selectAll('svg')
                .remove();
            }

            var queryLen = $(selector).data().queryLen;
            var q_i = $(selector).attr('id');

            var width = $('.graph', selector).width();
            var height = hits.length*(options.barHeight + options.barPadding)
                + 5*options.margin + options.legend*3;

            var svg = d3.select($(selector).find('.graph')[0])
                .selectAll('svg')
                .data([hits]).enter()
                .append('svg')
                .attr('width', width)
                .attr('height', height)
                .append('g')
                .attr('transform', 'translate('+options.margin/4+', '+options.margin/4+')');

            var x = d3.scale.linear().range([0, width-options.margin])
            x.domain([1, queryLen]);

            var _tValues = x.ticks(11);
            _tValues.pop();

            var xAxis = d3.svg.axis()
                .scale(x)
                .orient('top')
                .tickValues(_tValues.concat([1, queryLen]));

            // Attach the axis to DOM (<svg> element)
            var scale = svg.append('g')
                        .attr('transform', 'translate(0, '+options.margin+')')
                        .append('g').attr('class', 'x axis')
                        .call(xAxis);

            var y = d3.scale.ordinal()
                .rangeBands([0,height-3*options.margin-2*options.legend], .3);

            y.domain(hits.map(function (d, i) {
                return d.hitId;
            }));

            var gradScale = d3.scale.log()
                .domain([d3.min([1e-5, d3.min(hits.map(function (d) {
                    return d.hitEvalue;
                }))]), d3.max(hits.map(function (d) {
                    return d.hitEvalue;
                }))])
                .range([40,150]);

            /*
            var color = d3.scale.ordinal()
                .domain((hits.map(function (d) { return d.id; })))
                .rangeBands([10,150], 0.5);
            */

            svg.append('g')
                .attr('class', 'ghit')
                .attr('transform', 'translate(0, '+(2*options.margin-options.legend)+')')
                .selectAll('.hits')
                .data(hits)
                .enter()
                .append('g')
                .attr('data-toggle', 'tooltip')
                .attr('title', function(d) {
                    var regex = /(\d*\.\d*)e?([+-]\d*)?/;
                    var parsedVal = regex.exec(d.hitEvalue);
                    var prettyEvalue = +parseFloat(parsedVal[1]).toFixed(3)
                    var returnString = d.hitDef + '
Evalue: ' + prettyEvalue;
                    if (parsedVal[2] != undefined) {
                        returnString +=  ' x 10' + parsedVal[2] + '';
                    }
                    return returnString;
                })
                .each(function (d,i) {
                    var h_i = i+1;
                    var p_hsp = d;
                    var p_id = d.hitId;
                    var p_count = d.length;

                    d3.select(this)
                        .selectAll('.hsps')
                        .data(d).enter()
                        .append('a')
                        .each(function (pd, j) {
                            var y_hspline = y(p_id)+options.barHeight/2;
                            var hspline_color = d3.rgb(gradScale(p_hsp.hitEvalue),
                                gradScale(p_hsp.hitEvalue),gradScale(p_hsp.hitEvalue));

                            if (j+1 < p_count) {
                                if (p_hsp[j].hspEnd < p_hsp[j+1].hspStart) {
                                    d3.select(this.parentNode).append('line')
                                        .attr('x1', x(p_hsp[j].hspEnd))
                                        .attr('y1', y_hspline)
                                        .attr('x2', x(p_hsp[j+1].hspStart))
                                        .attr('y2', y_hspline)
                                        .attr('stroke', hspline_color);
                                }
                                else if (p_hsp[j].hspStart > p_hsp[j+1].hspEnd) {
                                    d3.select(this.parentNode).append('line')
                                        .attr('x1', x(p_hsp[j+1].hspEnd))
                                        .attr('y1', y_hspline)
                                        .attr('x2', x(p_hsp[j].hspStart))
                                    .attr('y2', y_hspline)
                                    .attr('stroke', hspline_color);
                            };
                        };

                        d3.select(this)
                        .attr('xlink:href', function (d,i) {return '#'+q_i+'_hit_'+(h_i);})
                        .append('rect')
                        .attr('x', function (d) {
                            if (d.hspFrame < 0)
                                return x(d.hspStart);
                            else
                                return x(d.hspStart);
                        })
                        .attr('y', y(p_id))
                        .attr('width', function (d) {
                                return x(d.hspEnd - d.hspStart);
                        })
                        .attr('height', options.barHeight)
                        .attr('fill', d3.rgb(hspline_color));
                    });
                });

                var svg_legend = svg.append('g')
                        .attr('transform',
                            'translate(0,'+(height-options.margin-options.legend*1.25)+')');

                svg_legend.append('rect')
                        .attr('x', 7*(width-2*options.margin)/10)
                        .attr('width', 2*(width-4*options.margin)/10)
                        .attr('height', options.legend)
                        .attr('fill', 'url(#legend-grad)');

                svg_legend.append('text')
                        .attr('transform', 'translate(0, '+options.legend+')')
                        .attr('x', 6*(width-2*options.margin)/10 - options.margin/2)
                        .text("Weaker hits");
                svg_legend.append('text')
                        .attr('transform', 'translate(0, '+options.legend+')')
                        .attr('x', 9*(width-2*options.margin)/10 + options.margin/2)
                        .text("Stronger hits");

                svg.append('linearGradient')
                    .attr('id', 'legend-grad')
                  .selectAll('stop')
                    .data([
                        {offset: "0%", color: "#ccc"},
                        {offset: '50%', color: '#888'},
                        {offset: "100%", color: "#000"}
                        ])
                  .enter().append('stop')
                    .attr('offset', function (d) { return d.offset })
                    .attr('stop-color', function (d) { return d.color });
        }
    });
}(jQuery));
<commit_msg>Fixed a small glitch in HSPs connector line<commit_after>(function ($) {
    $.extend({
        initialize: function (selector) {
            var selectorId = $(selector).attr('id');

            // FIXME: SS should create the container and pass id of the
            // container to graphit.
            var container = $("
");
            container.append("
");
            container.append("<button type='button' data-parent-query="+ selectorId +
                             " class='btn btn-link more'> View more</button>");

            $(selector).children().eq(1).children().eq(0).after(container);
        },

        toD3: function (selector, index, howMany) {
            var hits = []
            hitPanels = $(selector).find('.hitn').slice(0, index + howMany);
            hitPanels.map(function () {
                _hsps = [];
                $(this).find('.hsps').each(function () {
                    __hsps = [];
                    __hsps = $(this).data();
                    __hsps.hspId = $(this).attr('id');
                    _hsps.push(__hsps);
                });
                _hsps.hitId = $(this).attr('id');
                _hsps.hitDef = $(this).data().hitDef;
                _hsps.hitEvalue = $(this).data().hitEvalue;
                hits.push(_hsps);
            });
            return hits;
        },

        graphIt: function (selector, index, howMany, opts) {
            var defaults = {
                barHeight: 4,
                barPadding: 5,
                legend: 10,
                margin: 20
            }, options = $.extend(defaults, opts),
               hits = $.toD3(selector, index, howMany);

            if (hits < 1) return false;

            if (index == 0) {
                $.initialize(selector);
            }
            else {
                d3.select($(selector).find('.graph')[0])
                .selectAll('svg')
                .remove();
            }

            var queryLen = $(selector).data().queryLen;
            var q_i = $(selector).attr('id');

            var width = $('.graph', selector).width();
            var height = hits.length*(options.barHeight + options.barPadding)
                + 5*options.margin + options.legend*3;

            var svg = d3.select($(selector).find('.graph')[0])
                .selectAll('svg')
                .data([hits]).enter()
                .append('svg')
                .attr('width', width)
                .attr('height', height)
                .append('g')
                .attr('transform', 'translate('+options.margin/4+', '+options.margin/4+')');

            var x = d3.scale.linear().range([0, width-options.margin])
            x.domain([1, queryLen]);

            var _tValues = x.ticks(11);
            _tValues.pop();

            var xAxis = d3.svg.axis()
                .scale(x)
                .orient('top')
                .tickValues(_tValues.concat([1, queryLen]));

            // Attach the axis to DOM (<svg> element)
            var scale = svg.append('g')
                        .attr('transform', 'translate(0, '+options.margin+')')
                        .append('g').attr('class', 'x axis')
                        .call(xAxis);

            var y = d3.scale.ordinal()
                .rangeBands([0,height-3*options.margin-2*options.legend], .3);

            y.domain(hits.map(function (d, i) {
                return d.hitId;
            }));

            var gradScale = d3.scale.log()
                .domain([d3.min([1e-5, d3.min(hits.map(function (d) {
                    return d.hitEvalue;
                }))]), d3.max(hits.map(function (d) {
                    return d.hitEvalue;
                }))])
                .range([40,150]);

            /*
            var color = d3.scale.ordinal()
                .domain((hits.map(function (d) { return d.id; })))
                .rangeBands([10,150], 0.5);
            */

            svg.append('g')
                .attr('class', 'ghit')
                .attr('transform', 'translate(0, '+(2*options.margin-options.legend)+')')
                .selectAll('.hits')
                .data(hits)
                .enter()
                .append('g')
                .attr('data-toggle', 'tooltip')
                .attr('title', function(d) {
                    var regex = /(\d*\.\d*)e?([+-]\d*)?/;
                    var parsedVal = regex.exec(d.hitEvalue);
                    var prettyEvalue = +parseFloat(parsedVal[1]).toFixed(3)
                    var returnString = d.hitDef + '
Evalue: ' + prettyEvalue;
                    if (parsedVal[2] != undefined) {
                        returnString +=  ' x 10' + parsedVal[2] + '';
                    }
                    return returnString;
                })
                .each(function (d,i) {
                    var h_i = i+1;
                    var p_hsp = d;
                    var p_id = d.hitId;
                    var p_count = d.length;

                    d3.select(this)
                        .selectAll('.hsps')
                        .data(d).enter()
                        .append('a')
                        .each(function (pd, j) {
                            var y_hspline = y(p_id)+options.barHeight/2;
                            var hspline_color = d3.rgb(gradScale(p_hsp.hitEvalue),
                                gradScale(p_hsp.hitEvalue),gradScale(p_hsp.hitEvalue));

                            if (j+1 < p_count) {
                                if (p_hsp[j].hspEnd <= p_hsp[j+1].hspStart) {
                                    d3.select(this.parentNode).append('line')
                                        .attr('x1', x(p_hsp[j].hspEnd))
                                        .attr('y1', y_hspline)
                                        .attr('x2', x(p_hsp[j+1].hspStart))
                                        .attr('y2', y_hspline)
                                        .attr('stroke', hspline_color);
                                }
                                else if (p_hsp[j].hspStart > p_hsp[j+1].hspEnd) {
                                    d3.select(this.parentNode).append('line')
                                        .attr('x1', x(p_hsp[j+1].hspEnd))
                                        .attr('y1', y_hspline)
                                        .attr('x2', x(p_hsp[j].hspStart))
                                        .attr('y2', y_hspline)
                                        .attr('stroke', hspline_color);
                                };
                            };

                            d3.select(this)
                            .attr('xlink:href', function (d,i) {return '#'+q_i+'_hit_'+(h_i);})
                            .append('rect')
                            .attr('x', function (d) {
                                    return x(d.hspStart);
                            })
                            .attr('y', y(p_id))
                            .attr('width', function (d) {
                                    return x(d.hspEnd - d.hspStart + 1);
                            })
                            .attr('height', options.barHeight)
                            .attr('fill', d3.rgb(hspline_color));
                    });
                });

                var svg_legend = svg.append('g')
                        .attr('transform',
                            'translate(0,'+(height-options.margin-options.legend*1.25)+')');

                svg_legend.append('rect')
                        .attr('x', 7*(width-2*options.margin)/10)
                        .attr('width', 2*(width-4*options.margin)/10)
                        .attr('height', options.legend)
                        .attr('fill', 'url(#legend-grad)');

                svg_legend.append('text')
                        .attr('transform', 'translate(0, '+options.legend+')')
                        .attr('x', 6*(width-2*options.margin)/10 - options.margin/2)
                        .text("Weaker hits");
                svg_legend.append('text')
                        .attr('transform', 'translate(0, '+options.legend+')')
                        .attr('x', 9*(width-2*options.margin)/10 + options.margin/2)
                        .text("Stronger hits");

                svg.append('linearGradient')
                    .attr('id', 'legend-grad')
                  .selectAll('stop')
                    .data([
                        {offset: "0%", color: "#ccc"},
                        {offset: '50%', color: '#888'},
                        {offset: "100%", color: "#000"}
                        ])
                  .enter().append('stop')
                    .attr('offset', function (d) { return d.offset })
                    .attr('stop-color', function (d) { return d.color });
        }
    });
}(jQuery));
<|endoftext|>


<commit_before>var langConfig = {
  'pt': '',
  'en': '',
  'es': ''
};

String.prototype.langsplit = function(_regEx){
	// Most browsers can do this properly, so let them work, they'll do it faster
	if ('a~b'.split(/(~)/).length === 3){ return this.split(_regEx); }

	if (!_regEx.global)
	{ _regEx = new RegExp(_regEx.source, 'g' + (_regEx.ignoreCase ? 'i' : '')); }

	// IE (and any other browser that can't capture the delimiter)
	// will, unfortunately, have to be slowed down
	var start = 0, arr=[];
	var result;
	while((result = _regEx.exec(this)) != null){
		arr.push(this.slice(start, result.index));
		if(result.length > 1) arr.push(result[1]);
		start = _regEx.lastIndex;
	}
	if(start < this.length) arr.push(this.slice(start));
	if(start == this.length) arr.push(''); //delim at the end
	return arr;
};

langGetSplitBlocks = function(text) {
	var split_regex = /(<!--:[a-z]{2}-->|<!--:-->|\[:[a-z]{2}\]|\[:\]|\{:[a-z]{2}\}|\{:\})/gi; // @since 3.3.6 swirly brackets
	return text.langsplit(split_regex);
};

langSplit = function(text) {
	var blocks = langGetSplitBlocks(text);
	return langSplitBlocks(blocks);
}

langSplitBlocks = function(blocks) {
	var result = new Object;
	for(var lang in langConfig) {
		result[lang] = '';
	}
	if(!blocks || !blocks.length)
		return result;
	if(blocks.length==1) {
		var b=blocks[0];
		for(var lang in langConfig){
			result[lang] += b;
		}
		return result;
	}
	var clang_regex=/<!--:([a-z]{2})-->/gi;
	var blang_regex=/\[:([a-z]{2})\]/gi;
	var slang_regex=/\{:([a-z]{2})\}/gi;
	var lang = false;
	var matches;
	for(var i = 0;i<blocks.length;++i){
		var b=blocks[i];
		if(!b.length) continue;
		matches = clang_regex.exec(b); clang_regex.lastIndex=0;
		if(matches!=null){
			lang = matches[1];
			continue;
		}
		matches = blang_regex.exec(b); blang_regex.lastIndex=0;
		if(matches!=null){
			lang = matches[1];
			continue;
		}
		matches = slang_regex.exec(b); slang_regex.lastIndex=0;
		if(matches!=null){
			lang = matches[1];
			continue;
		}
		if( b == '<!--:-->' || b == '[:]' || b == '{:}' ){
			lang = false;
			continue;
		}
		if(lang){
			if(!result[lang]) result[lang] = b;
			else result[lang] += b;
			lang = false;
		}else{ //keep neutral text
			for(var key in result){
				result[key] += b;
			}
		}
	}
	return result;
}

function langJoin(obj) {
  var str = '';
  for(var key in obj) {
    str += '[:' + key + ']' + obj[key];
  }
  return str;
}

angular.module('domegis')

.factory('Lang', [
  '$cookies',
  function($cookies) {

    if(!$cookies.get('lang')) {
      $cookies.put('lang', 'en');
    }

    return {
      get: function() {
        return $cookies.get('lang');
      },
      set: function(lang) {
        $cookies.put('lang', lang);
      }
    }
  }
])
.filter('translate', [
  'Lang',
  function(Lang) {
    return function(input) {
      if(typeof input == 'object')
        return input[Lang.get()];
      else
        return langSplit(input)[Lang.get()];
    }
  }
])
.filter('langJoin', [
  function() {
    return function(input) {
      return langJoin(input);
    }
  }
])
.filter('langSplit', [
  function() {
    return function(input) {
      return langSplit(input);
    }
  }
]);
<commit_msg>remove cmms<commit_after>var langConfig = {
  'pt': '',
  'en': '',
  'es': ''
};

String.prototype.langsplit = function(_regEx){
	if ('a~b'.split(/(~)/).length === 3){ return this.split(_regEx); }

	if (!_regEx.global)
	{ _regEx = new RegExp(_regEx.source, 'g' + (_regEx.ignoreCase ? 'i' : '')); }

	var start = 0, arr=[];
	var result;
	while((result = _regEx.exec(this)) != null){
		arr.push(this.slice(start, result.index));
		if(result.length > 1) arr.push(result[1]);
		start = _regEx.lastIndex;
	}
	if(start < this.length) arr.push(this.slice(start));
	if(start == this.length) arr.push('');
	return arr;
};

langGetSplitBlocks = function(text) {
	var split_regex = /(<!--:[a-z]{2}-->|<!--:-->|\[:[a-z]{2}\]|\[:\]|\{:[a-z]{2}\}|\{:\})/gi;
	return text.langsplit(split_regex);
};

langSplit = function(text) {
	var blocks = langGetSplitBlocks(text);
	return langSplitBlocks(blocks);
}

langSplitBlocks = function(blocks) {
	var result = new Object;
	for(var lang in langConfig) {
		result[lang] = '';
	}
	if(!blocks || !blocks.length)
		return result;
	if(blocks.length==1) {
		var b=blocks[0];
		for(var lang in langConfig){
			result[lang] += b;
		}
		return result;
	}
	var clang_regex=/<!--:([a-z]{2})-->/gi;
	var blang_regex=/\[:([a-z]{2})\]/gi;
	var slang_regex=/\{:([a-z]{2})\}/gi;
	var lang = false;
	var matches;
	for(var i = 0;i<blocks.length;++i){
		var b=blocks[i];
		if(!b.length) continue;
		matches = clang_regex.exec(b); clang_regex.lastIndex=0;
		if(matches!=null){
			lang = matches[1];
			continue;
		}
		matches = blang_regex.exec(b); blang_regex.lastIndex=0;
		if(matches!=null){
			lang = matches[1];
			continue;
		}
		matches = slang_regex.exec(b); slang_regex.lastIndex=0;
		if(matches!=null){
			lang = matches[1];
			continue;
		}
		if( b == '<!--:-->' || b == '[:]' || b == '{:}' ){
			lang = false;
			continue;
		}
		if(lang){
			if(!result[lang]) result[lang] = b;
			else result[lang] += b;
			lang = false;
		}else{ //keep neutral text
			for(var key in result){
				result[key] += b;
			}
		}
	}
	return result;
}

function langJoin(obj) {
  var str = '';
  for(var key in obj) {
    str += '[:' + key + ']' + obj[key];
  }
  return str;
}

angular.module('domegis')

.factory('Lang', [
  '$cookies',
  function($cookies) {

    if(!$cookies.get('lang')) {
      $cookies.put('lang', 'en');
    }

    return {
      get: function() {
        return $cookies.get('lang');
      },
      set: function(lang) {
        $cookies.put('lang', lang);
      }
    }
  }
])
.filter('translate', [
  'Lang',
  function(Lang) {
    return function(input) {
      if(typeof input == 'object')
        return input[Lang.get()];
      else
        return langSplit(input)[Lang.get()];
    }
  }
])
.filter('langJoin', [
  function() {
    return function(input) {
      return langJoin(input);
    }
  }
])
.filter('langSplit', [
  function() {
    return function(input) {
      return langSplit(input);
    }
  }
]);
<|endoftext|>


<commit_before>'use strict';

/* Services */

angular.module('modtools.services', ['config', 'ngResource'])

  .factory('Moderation', ['$resource', 'config', function ($resource, config) {
    return $resource(config.moderationApiUrl + '/comment', {}, {
      'next': {method: 'GET', url: config.moderationApiUrl + '/queues/:queue/next'},
      'moderate': {method: 'POST', url: config.moderationApiUrl + '/comment/:commentId/status'}
    })
  }]);<commit_msg>Add ajax services<commit_after>'use strict';

/* Services */

angular.module('modtools.services', ['config', 'ngResource'])

  .factory('Moderation', ['$resource', 'config', function ($resource, config) {
    return $resource(config.moderationApiUrl + '/comment', {}, {
      'next':     {method: 'GET', url: config.moderationApiUrl + '/queues/:queue/next'},
      'moderate': {method: 'POST', url: config.moderationApiUrl + '/comment/:commentId/status'}
    })
  }])

  .factory('Content', ['$resource', 'config', function ($resource, config) {
    return $resource(config.contentApiUrl, {'orderBy': 'newest', 'page-size': 100, 'api-key': config.contentApiKey}, {
      'query':    {method: 'GET', url: config.contentApiUrl + '/search'},
      'shortUrl': {method: 'GET', params: {'show-fields': 'shortUrl'}, url: config.contentApiUrl + '/:section/:year/:month/:day/:slug'
      }
    });
  }])

  .factory('Discussion', ['$resource', 'config', function ($resource, config) {
    return $resource(config.discussionApiUrl, {'orderBy': 'newest', 'pageSize': 50}, {
      'counts':      {method: 'GET', url: config.discussionApiUrl + '/getCommentCounts'},
      'most':        {method: 'GET', url: config.discussionApiUrl + '/most/comments'},
      'moststaff':   {method: 'GET', url: config.discussionApiUrl + '/discussion/most/staff'},
      'popular':     {method: 'GET', url: config.discussionApiUrl + '/popular'},
      'get':         {method: 'GET', url: config.discussionApiUrl + '/discussion//p/:key'},
      'featured':    {method: 'GET', url: config.discussionApiUrl + '/discussion//p/:key/featuredcomments'},
      'highlighted': {method: 'GET', url: config.discussionApiUrl + '/discussion//p/:key/highlights'},
      'recommended': {method: 'GET', url: config.discussionApiUrl + '/discussion//p/:key/recommended'},
      'staff':       {method: 'GET', url: config.discussionApiUrl + '/discussion//p/:key/staff-comments'},
      'top':         {method: 'GET', url: config.discussionApiUrl + '/discussion//p/:key/topcomments'}
    });
  }])

  .factory('Comment', ['$resource', 'config', function ($resource, config) {
    return $resource(config.discussionApiUrl, {}, {
      'query':       {method: 'GET', url: config.discussionApiUrl + '/search'},
      'highlighted': {method: 'GET', url: config.discussionApiUrl + '/recent/highlighted'},
      'recommended': {method: 'GET', url: config.discussionApiUrl + '/recent/recommended'},
      'get':         {method: 'GET', url: config.discussionApiUrl + '/comment/:id'},
      'context':     {method: 'GET', url: config.discussionApiUrl + '/comment/:id/context'}
    });
  }])

  .factory('Profile', ['$resource', 'config', function ($resource, config) {
    return $resource(config.discussionApiUrl, {}, {
      'get':         {method: 'GET', url: config.discussionApiUrl + '/profile/:userid'},
      'stats':       {method: 'GET', url: config.discussionApiUrl + '/profile/:userid/stats'},
      'comments':    {method: 'GET', url: config.discussionApiUrl + '/profile/:userid/comments'},
      'picked':      {method: 'GET', url: config.discussionApiUrl + '/profile/:userid/comments?displayHighlighted'},
      'replies':     {method: 'GET', url: config.discussionApiUrl + '/profile/:userid/replies'},
      'discussions': {method: 'GET', url: config.discussionApiUrl + '/profile/:userid/discussions'}
    });
  }])

  .factory('Identity', ['$resource', 'config', function ($resource, config) {
    return $resource(config.identityApiUrl, {}, {
      'get': {method: 'JSONP', params: {callback: 'JSON_CALLBACK'}, url: config.identityApiUrl + '/user/:userid'}
    });
  }]);
<|endoftext|>


<commit_before>'use strict';

/* Services */
var serviceModule = angular.module('myApp.services', []);

// serviceModule.factory('messages',['$http', function(http) {
// 	function MessagesService(http) {

// 		this.storeMessage = function(newMessage,callback) {
// 			var aMessage = {"description":newMessage};
// 	    	http.post('/api/message', aMessage).
// 	    		success(function(data) {
// 	    			callback({"response":"Message is stored","status":"OK"})
// 	    		});
// 		};

// 		this.loadMessages = function(callback) {
// 			http.get('/api/message').
// 				success(function(data) {
// 					callback(data);
// 				});
// 		}
// 	}

// 	return new MessagesService(http);
// }]);

serviceModule.factory('messages',['Message', function(Message) {
	function MessagesService(Message) {

		this.storeMessage = function(newMessage,callback) {
			var aMessage = new Message({"description":newMessage});
			aMessage.$save();
			callback({"response":"Message is stored","status":"OK"});
		};

		this.loadMessages = function(callback) {
			callback(Message.query());
		}
	}

	return new MessagesService(Message);
}]);

serviceModule.factory('Message',['$resource', function(resource) {
	return resource('/api/message/:messageId');
}]);<commit_msg>Removed code that is now in a branch<commit_after>'use strict';

/* Services */
var serviceModule = angular.module('myApp.services', []);

serviceModule.factory('messages',['Message', function(Message) {
	function MessagesService(Message) {

		this.storeMessage = function(newMessage,callback) {
			var aMessage = new Message({"description":newMessage});
			aMessage.$save();
			callback({"response":"Message is stored","status":"OK"});
		};

		this.loadMessages = function(callback) {
			callback(Message.query());
		}
	}

	return new MessagesService(Message);
}]);

serviceModule.factory('Message',['$resource', function(resource) {
	return resource('/api/message/:messageId');
}]);<|endoftext|>


<commit_before>// dependencies: module.js, search.js, display.js, resizable.js, navbar.js, suggest.js

// initialization
$(document).ready(function() {

  /* init_load(); MEL: now loads after semesters have been loaded in init_search */
  init_panes();
  init_searchpane();
  init_search();
  init_globals();
  init_favorites();
  init_feedback();
  init_display();
  init_evals();
  init_logout();
  init_suggest();
  init_updates();
})

// loads course from url
var init_load = function () {
  // Parse and display search parameters, if any exist
  parseSearchParameters()

  // Parse course from the URL to determine which course (if any) to display on pageload
  var pathnameMatch = /^\/course\/(\d+)$/.exec(window.location.pathname)
  if (pathnameMatch !== null && pathnameMatch.length === 2) {
    // Load the course
    courseId = parseInt(pathnameMatch[1])
    if (!isNaN(courseId)) displayCourseDetails(courseId)
  }
}

// Handle displaying a course after pushing the back/forward button in the browser
window.onpopstate = function (event) {
  if (event.state && event.state.courseID) {
    displayCourseDetails(event.state.courseID)
  }
  parseSearchParameters()
}

// Parse the URL to check for whether the app should be showing a course and displaying any search terms
var parseSearchParameters = function () {
  // Parse search terms
  var unparsedParameters = window.location.search.replace('?', '').split('&')
  var parameters = {}
  for (var parametersIndex in unparsedParameters) {
    var keyValue = unparsedParameters[parametersIndex].split('=')
    if (keyValue.length === 2) {
      parameters[keyValue[0]] = decodeURIComponent(keyValue[1])
    }
  }
  if (parameters.hasOwnProperty('search')) {
    $('#searchbox').val(parameters.search)
  }
  if (parameters.hasOwnProperty('semester')) {
    $('#semester').data('query', parameters.semester).val(parameters.semester)
  }
  if (parameters.hasOwnProperty('sort')) {
    $('#sort').val(parameters.sort)
  }
  if (parameters !== {}) {
    searchForCourses()
  }
}

// to initialize draggability
var init_panes = function() {
  var searchPaneWidth = localStorage.getItem('#search-resizer');
  if(searchPaneWidth !== undefined) {
    $('#search-pane').css('width', searchPaneWidth);
  }

  var infoPaneWidth = localStorage.getItem('#info-resizer');
  if(searchPaneWidth !== undefined) {
    $('#info-pane').css('width', infoPaneWidth);
  }

  $('#search-pane').css('display', "");
  $('#display-pane').css('display', "");

  $('#search-pane').resizable({
    handleSelector: "#search-resizer",
    resizeHeight: false
  })

  $('#info-pane').resizable({
    handleSelector: "#info-resizer",
    resizeHeight: false,
    resizeWidthFrom: 'left'
  })
}

// to initalize search pane section collapsing
var init_searchpane = function() {
  $('#favorite-courses').css('max-height', '30vh')
    // toggle display of favorite things
  var toggleFavDisplay = function() {
    var isVisible = $('#favorite-courses').css('display') !== 'none'

    var icon = $('#fav-display-toggle')
    icon.removeClass(isVisible ? 'fa-minus' : 'fa-plus')
    icon.addClass(isVisible ? 'fa-plus' : 'fa-minus')
    $('#favorite-courses').slideToggle()
  }
  $('#fav-display-toggle').click(toggleFavDisplay)

  // toggle display of search result things
  var toggleSearchDisplay = function() {
    var isVisible = $('#search-results').css('display') !== 'none'

    var icon = $('#search-display-toggle')
    icon.removeClass(isVisible ? 'fa-minus' : 'fa-plus')
    icon.addClass(isVisible ? 'fa-plus' : 'fa-minus')
    $('#favorite-courses').animate({'max-height': (isVisible ? '100vh' : '30vh')})

    $('#search-results').slideToggle()
  }
  $('#search-display-toggle').click(toggleSearchDisplay)
}

// to initialize searching function
var init_search = function() {
  // Every time a key is pressed inside the #searchbox, call the searchForCourses function
  $('#searchbox').on('input', searchForCourses)
  $('#semester, #sort').change(searchForCourses)

  // load the semesters for the dropdown
  $('#semester').children(":not([disabled])").remove()
  $.get('/api/semesters', function (semesters) {
    for (var semesterIndex in semesters) {
      var thisSemester = semesters[semesterIndex]
      var option = $(document.createElement('option')).attr('value', thisSemester._id).text(thisSemester.name)
      $('#semester').append(option)
    }
    if ($('#semester').data('query')) {
      $('#semester').children('[value=' + $('#semester').data('query') +']').attr('selected', true)
    } else {
      $('#semester').children().eq(1).attr('selected', true)
    }
  }).then(init_load)
}

// to initialize global data
var init_globals = function() {
  // Saving the user's netid so it is globally available
  document.netid = $("#netid").text()
}

// to initialize favorites list
var init_favorites = function() {
  // call api to get favorites and display
  document.favorites = []
  $.get('/api/user/favorites', function(courses) {

    $('#favorite-header').css('display', (courses === undefined || courses.length === 0) ? 'none' : '')

    $('#favs').html('');
    $('#favorite-title').html('');

    $('#favorite-title').append(courses.length + ' Favorite Course' + (courses.length !== 1 ? 's' : ''))
    for (var courseIndex in courses) {
      var thisCourse = courses[courseIndex];

      // Saving this user's favorite courses to the global scope
      document.favorites.push(thisCourse._id)

      // append favorite into favs pane
      $('#favs').append(newDOMResult(thisCourse, {"semester": 1, "tags": 1}));
    }
  }).done(updateFavIcons).done(displayActive)
}

// to initialize feedback mechanism
var init_feedback = function() {
  // submission
  $('#feedback-form').one('submit', function() {
    var submitURL = ''
    submitURL += 'https://docs.google.com/a/princeton.edu/forms/d/e/1FAIpQLSdX3VTSbVfwOOtwMxhWiryQFrlBNuJDUTlp-lUmsV-S0xFM_g/formResponse?'
    submitURL += 'entry.1257302391=' + document.netid
    submitURL += '&entry.680057223=' + encodeURIComponent($('#feedback-text').val())

    $(this)[0].action = submitURL
    $('#feedback-submit').text('Thank You!')
    $('#feedback-submit').addClass('disabled')
    $('#feedback-text').attr('disabled', true)
    setTimeout(toggleFeedback, 1000)
  })

  $('#feedback-toggle').click(function() {return toggleNavbar('feedback')})
}

// to initialize display toggling
var init_display = function() {
  $('#disp-instructors-toggle'  ).click(function() {section_toggle('disp', 'instructors')})
  $('#disp-description-toggle'  ).click(function() {section_toggle('disp', 'description')})
  $('#disp-readings-toggle'     ).click(function() {section_toggle('disp', 'readings')})
  $('#disp-assignments-toggle'  ).click(function() {section_toggle('disp', 'assignments')})
  $('#disp-grading-toggle'      ).click(function() {section_toggle('disp', 'grading')})
  $('#disp-prerequisites-toggle').click(function() {section_toggle('disp', 'prerequisites')})
  $('#disp-equivalent-toggle'   ).click(function() {section_toggle('disp', 'equivalent')})
  $('#disp-other-toggle'        ).click(function() {section_toggle('disp', 'other')})
  $('#disp-classes-toggle'      ).click(function() {section_toggle('disp', 'classes')})
}

// to initialize evals toggling
var init_evals = function() {
  $('#evals-semesters-toggle').click(function() {section_toggle('evals', 'semesters')})
  $('#evals-numeric-toggle').click(function() {section_toggle('evals', 'numeric')})
  $('#evals-comments-toggle').click(function() {section_toggle('evals', 'comments')})
}

// to intialize logout button
var init_logout = function() {
  $('#menu-bar').mouseleave(function() {
    var isNetidInvisible = $('#netid').css('display') === 'none'
    if (isNetidInvisible) $('#netid, #logout').animate({width: 'toggle'})
  })

  $('#netid').click(function() {
    var isLogoutVisible = $('#logout').css('display') !== 'none'
    if (!isLogoutVisible) $('#netid, #logout').animate({width: 'toggle'})
    return false;
  })
}

// to initialize suggest display
var init_suggest = function() {
  suggest_load()
  $('#suggest-toggle').click(toggleSuggest)
  $('#suggest-allcourses-toggle'   ).click(function() {section_toggle('suggest', 'allcourses')})
  $('#suggest-distributions-toggle').click(function() {section_toggle('suggest', 'distributions')})
  $('#suggest-pdfoptions-toggle'   ).click(function() {section_toggle('suggest', 'pdfoptions')})
  $('#suggest-departments-toggle'  ).click(function() {section_toggle('suggest', 'departments')})
}

// to initialize updates popup
var init_updates = function() {
  var updateMessage = 'You can now search for instructors. Also, take a look at Search Suggestions!'
  var updateNo = 0 //  BENSU: increment this number for new updates
  var updateNoStored = localStorage.getItem('updateNo'); //last update seen by user
  $("#updates-bottom-popup").append(updateMessage);
  if (updateNo != updateNoStored) // new update
  {
    localStorage.setItem('updateRead', 'False');
    setTimeout(function() {
      $('#updates-bottom-popup').show();
    }, 1000); // milliseconds
    localStorage.setItem('updateNo', updateNo);
  }
  else {
    var updateRead = localStorage.getItem('updateRead');
    if (updateRead !== 'True') {
      setTimeout(function() {
        $('#updates-bottom-popup').show();
      }, 1000); // milliseconds
    }
  }
}

// toggles display / eval sections
var section_toggle = function(pane, section) {
  var body = $('#' + pane + '-' + section + '-body')
  var icon = $('#' + pane + '-' + section + '-toggle')
  var isVisible = (body.css('display') !== 'none')

  icon.removeClass(isVisible ? 'fa-minus' : 'fa-plus')
  icon.addClass(isVisible ? 'fa-plus' : 'fa-minus')
  body.slideToggle();
}

// update is read by the user
var saveUpdatePopupState = function() {
  localStorage.setItem('updateRead', 'True');
}
<commit_msg>block empty feedback, and 'enter' key to submit<commit_after>// dependencies: module.js, search.js, display.js, resizable.js, navbar.js, suggest.js

// initialization
$(document).ready(function() {

  /* init_load(); MEL: now loads after semesters have been loaded in init_search */
  init_panes();
  init_searchpane();
  init_search();
  init_globals();
  init_favorites();
  init_feedback();
  init_display();
  init_evals();
  init_logout();
  init_suggest();
  init_updates();
})

// loads course from url
var init_load = function () {
  // Parse and display search parameters, if any exist
  parseSearchParameters()

  // Parse course from the URL to determine which course (if any) to display on pageload
  var pathnameMatch = /^\/course\/(\d+)$/.exec(window.location.pathname)
  if (pathnameMatch !== null && pathnameMatch.length === 2) {
    // Load the course
    courseId = parseInt(pathnameMatch[1])
    if (!isNaN(courseId)) displayCourseDetails(courseId)
  }
}

// Handle displaying a course after pushing the back/forward button in the browser
window.onpopstate = function (event) {
  if (event.state && event.state.courseID) {
    displayCourseDetails(event.state.courseID)
  }
  parseSearchParameters()
}

// Parse the URL to check for whether the app should be showing a course and displaying any search terms
var parseSearchParameters = function () {
  // Parse search terms
  var unparsedParameters = window.location.search.replace('?', '').split('&')
  var parameters = {}
  for (var parametersIndex in unparsedParameters) {
    var keyValue = unparsedParameters[parametersIndex].split('=')
    if (keyValue.length === 2) {
      parameters[keyValue[0]] = decodeURIComponent(keyValue[1])
    }
  }
  if (parameters.hasOwnProperty('search')) {
    $('#searchbox').val(parameters.search)
  }
  if (parameters.hasOwnProperty('semester')) {
    $('#semester').data('query', parameters.semester).val(parameters.semester)
  }
  if (parameters.hasOwnProperty('sort')) {
    $('#sort').val(parameters.sort)
  }
  if (parameters !== {}) {
    searchForCourses()
  }
}

// to initialize draggability
var init_panes = function() {
  var searchPaneWidth = localStorage.getItem('#search-resizer');
  if(searchPaneWidth !== undefined) {
    $('#search-pane').css('width', searchPaneWidth);
  }

  var infoPaneWidth = localStorage.getItem('#info-resizer');
  if(searchPaneWidth !== undefined) {
    $('#info-pane').css('width', infoPaneWidth);
  }

  $('#search-pane').css('display', "");
  $('#display-pane').css('display', "");

  $('#search-pane').resizable({
    handleSelector: "#search-resizer",
    resizeHeight: false
  })

  $('#info-pane').resizable({
    handleSelector: "#info-resizer",
    resizeHeight: false,
    resizeWidthFrom: 'left'
  })
}

// to initalize search pane section collapsing
var init_searchpane = function() {
  $('#favorite-courses').css('max-height', '30vh')
    // toggle display of favorite things
  var toggleFavDisplay = function() {
    var isVisible = $('#favorite-courses').css('display') !== 'none'

    var icon = $('#fav-display-toggle')
    icon.removeClass(isVisible ? 'fa-minus' : 'fa-plus')
    icon.addClass(isVisible ? 'fa-plus' : 'fa-minus')
    $('#favorite-courses').slideToggle()
  }
  $('#fav-display-toggle').click(toggleFavDisplay)

  // toggle display of search result things
  var toggleSearchDisplay = function() {
    var isVisible = $('#search-results').css('display') !== 'none'

    var icon = $('#search-display-toggle')
    icon.removeClass(isVisible ? 'fa-minus' : 'fa-plus')
    icon.addClass(isVisible ? 'fa-plus' : 'fa-minus')
    $('#favorite-courses').animate({'max-height': (isVisible ? '100vh' : '30vh')})

    $('#search-results').slideToggle()
  }
  $('#search-display-toggle').click(toggleSearchDisplay)
}

// to initialize searching function
var init_search = function() {
  // Every time a key is pressed inside the #searchbox, call the searchForCourses function
  $('#searchbox').on('input', searchForCourses)
  $('#semester, #sort').change(searchForCourses)

  // load the semesters for the dropdown
  $('#semester').children(":not([disabled])").remove()
  $.get('/api/semesters', function (semesters) {
    for (var semesterIndex in semesters) {
      var thisSemester = semesters[semesterIndex]
      var option = $(document.createElement('option')).attr('value', thisSemester._id).text(thisSemester.name)
      $('#semester').append(option)
    }
    if ($('#semester').data('query')) {
      $('#semester').children('[value=' + $('#semester').data('query') +']').attr('selected', true)
    } else {
      $('#semester').children().eq(1).attr('selected', true)
    }
  }).then(init_load)
}

// to initialize global data
var init_globals = function() {
  // Saving the user's netid so it is globally available
  document.netid = $("#netid").text()
}

// to initialize favorites list
var init_favorites = function() {
  // call api to get favorites and display
  document.favorites = []
  $.get('/api/user/favorites', function(courses) {

    $('#favorite-header').css('display', (courses === undefined || courses.length === 0) ? 'none' : '')

    $('#favs').html('');
    $('#favorite-title').html('');

    $('#favorite-title').append(courses.length + ' Favorite Course' + (courses.length !== 1 ? 's' : ''))
    for (var courseIndex in courses) {
      var thisCourse = courses[courseIndex];

      // Saving this user's favorite courses to the global scope
      document.favorites.push(thisCourse._id)

      // append favorite into favs pane
      $('#favs').append(newDOMResult(thisCourse, {"semester": 1, "tags": 1}));
    }
  }).done(updateFavIcons).done(displayActive)
}

// to initialize feedback mechanism
var init_feedback = function() {
  // submission
  $('#feedback-form').submit(function() {
    if ($('#feedback-text').val().length > 0)
    {
      var submitURL = ''
      submitURL += 'https://docs.google.com/a/princeton.edu/forms/d/e/1FAIpQLSdX3VTSbVfwOOtwMxhWiryQFrlBNuJDUTlp-lUmsV-S0xFM_g/formResponse?'
      submitURL += 'entry.1257302391=' + document.netid
      submitURL += '&entry.680057223=' + encodeURIComponent($('#feedback-text').val())

      $(this)[0].action = submitURL
      $('#feedback-submit').text('Thank You!')
      $('#feedback-submit').addClass('disabled')
      $('#feedback-text').attr('disabled', true)
      setTimeout(toggleFeedback, 1000)
    }
    else {
      $('#feedback-text').attr("placeholder", "Please enter feedback.");
    }
  })
  $('#feedback-toggle').click(function() {return toggleNavbar('feedback')})
}

// to initialize display toggling
var init_display = function() {
  $('#disp-instructors-toggle'  ).click(function() {section_toggle('disp', 'instructors')})
  $('#disp-description-toggle'  ).click(function() {section_toggle('disp', 'description')})
  $('#disp-readings-toggle'     ).click(function() {section_toggle('disp', 'readings')})
  $('#disp-assignments-toggle'  ).click(function() {section_toggle('disp', 'assignments')})
  $('#disp-grading-toggle'      ).click(function() {section_toggle('disp', 'grading')})
  $('#disp-prerequisites-toggle').click(function() {section_toggle('disp', 'prerequisites')})
  $('#disp-equivalent-toggle'   ).click(function() {section_toggle('disp', 'equivalent')})
  $('#disp-other-toggle'        ).click(function() {section_toggle('disp', 'other')})
  $('#disp-classes-toggle'      ).click(function() {section_toggle('disp', 'classes')})
}

// to initialize evals toggling
var init_evals = function() {
  $('#evals-semesters-toggle').click(function() {section_toggle('evals', 'semesters')})
  $('#evals-numeric-toggle').click(function() {section_toggle('evals', 'numeric')})
  $('#evals-comments-toggle').click(function() {section_toggle('evals', 'comments')})
}

// to intialize logout button
var init_logout = function() {
  $('#menu-bar').mouseleave(function() {
    var isNetidInvisible = $('#netid').css('display') === 'none'
    if (isNetidInvisible) $('#netid, #logout').animate({width: 'toggle'})
  })

  $('#netid').click(function() {
    var isLogoutVisible = $('#logout').css('display') !== 'none'
    if (!isLogoutVisible) $('#netid, #logout').animate({width: 'toggle'})
    return false;
  })
}

// to initialize suggest display
var init_suggest = function() {
  suggest_load()
  $('#suggest-toggle').click(toggleSuggest)
  $('#suggest-allcourses-toggle'   ).click(function() {section_toggle('suggest', 'allcourses')})
  $('#suggest-distributions-toggle').click(function() {section_toggle('suggest', 'distributions')})
  $('#suggest-pdfoptions-toggle'   ).click(function() {section_toggle('suggest', 'pdfoptions')})
  $('#suggest-departments-toggle'  ).click(function() {section_toggle('suggest', 'departments')})
}

// to initialize updates popup
var init_updates = function() {
  var updateMessage = 'You can now search for instructors. Also, take a look at Search Suggestions!'
  var updateNo = 0 //  BENSU: increment this number for new updates
  var updateNoStored = localStorage.getItem('updateNo'); //last update seen by user
  $("#updates-bottom-popup").append(updateMessage);
  if (updateNo != updateNoStored) // new update
  {
    localStorage.setItem('updateRead', 'False');
    setTimeout(function() {
      $('#updates-bottom-popup').show();
    }, 1000); // milliseconds
    localStorage.setItem('updateNo', updateNo);
  }
  else {
    var updateRead = localStorage.getItem('updateRead');
    if (updateRead !== 'True') {
      setTimeout(function() {
        $('#updates-bottom-popup').show();
      }, 1000); // milliseconds
    }
  }
}

// toggles display / eval sections
var section_toggle = function(pane, section) {
  var body = $('#' + pane + '-' + section + '-body')
  var icon = $('#' + pane + '-' + section + '-toggle')
  var isVisible = (body.css('display') !== 'none')

  icon.removeClass(isVisible ? 'fa-minus' : 'fa-plus')
  icon.addClass(isVisible ? 'fa-plus' : 'fa-minus')
  body.slideToggle();
}

// update is read by the user
var saveUpdatePopupState = function() {
  localStorage.setItem('updateRead', 'True');
}
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React from 'react'
import styles from 'part:@sanity/components/previews/media-style'
import MediaRender from './common/MediaRender'
import SvgPlaceholder from './common/SvgPlaceholder'

export default class MediaPreview extends React.Component {
  static propTypes = {
    item: PropTypes.shape({
      title: PropTypes.string,
      subtitle: PropTypes.string,
      description: PropTypes.string,
      media: PropTypes.node,
      imageUrl: PropTypes.string,
      sanityImage: PropTypes.object,
    }),
    assetSize: PropTypes.shape({
      width: PropTypes.number,
      height: PropTypes.number,
      fit: PropTypes.oneOf(['clip', 'crop', 'clamp'])
    }),
    aspect: PropTypes.number,
    emptyText: PropTypes.string,
    children: PropTypes.node,
    isPlaceholder: PropTypes.bool
  }

  static defaultProps = {
    assetSize: {width: 120, height: 120},
    aspect: 1,
    emptyText: 'Untitled…'
  }

  render() {
    const {item, emptyText, assetSize, children, aspect, isPlaceholder} = this.props

    if (!item || isPlaceholder) {
      return (

          <div className={styles.padder} style={{paddingTop: `${100 / aspect}%`}} />

            <SvgPlaceholder styles={styles} />

      )
    }

    return (

        <div className={styles.padder} style={{paddingTop: `${100 / aspect}%`}} />

          <MediaRender size={assetSize} item={item} aspect={aspect} fallbackText={item.title || 'No media'} />

        <div className={`${styles.meta}`}>
          <div className={`${styles.metaInner}`}>
            {
              item.title && (

                  {item.title}

              )
            }
            {
              item.subtitle &&

                {item.subtitle}

            }

{item.description}

        {children}

    )
  }
}
<commit_msg>[components] Bump default media preview to 160px (#233)<commit_after>import PropTypes from 'prop-types'
import React from 'react'
import styles from 'part:@sanity/components/previews/media-style'
import MediaRender from './common/MediaRender'
import SvgPlaceholder from './common/SvgPlaceholder'

export default class MediaPreview extends React.Component {
  static propTypes = {
    item: PropTypes.shape({
      title: PropTypes.string,
      subtitle: PropTypes.string,
      description: PropTypes.string,
      media: PropTypes.node,
      imageUrl: PropTypes.string,
      sanityImage: PropTypes.object,
    }),
    assetSize: PropTypes.shape({
      width: PropTypes.number,
      height: PropTypes.number,
      fit: PropTypes.oneOf(['clip', 'crop', 'clamp'])
    }),
    aspect: PropTypes.number,
    emptyText: PropTypes.string,
    children: PropTypes.node,
    isPlaceholder: PropTypes.bool
  }

  static defaultProps = {
    assetSize: {width: 160, height: 160},
    aspect: 1,
    emptyText: 'Untitled…'
  }

  render() {
    const {item, emptyText, assetSize, children, aspect, isPlaceholder} = this.props

    if (!item || isPlaceholder) {
      return (

          <div className={styles.padder} style={{paddingTop: `${100 / aspect}%`}} />

            <SvgPlaceholder styles={styles} />

      )
    }

    return (

        <div className={styles.padder} style={{paddingTop: `${100 / aspect}%`}} />

          <MediaRender size={assetSize} item={item} aspect={aspect} fallbackText={item.title || 'No media'} />

        <div className={`${styles.meta}`}>
          <div className={`${styles.metaInner}`}>
            {
              item.title && (

                  {item.title}

              )
            }
            {
              item.subtitle &&

                {item.subtitle}

            }

{item.description}

        {children}

    )
  }
}
<|endoftext|>


<commit_before>/* call using the following enclosure:
(function(){
  var url = 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.js';
  document.head.appendChild(document.createElement('script')).src=url;
})();
*/

function Dashboard() {
	var self = this;
	this.createElement = function(parent, tag, attributes) {
		var element = parent.appendChild(document.createElement(tag));
		for (var attribute in attributes) {
			if (attributes.hasOwnProperty(attribute)) {
				element[attribute] = attributes[attribute];
			}
		}
		return element;
	};

	this.openClient = function(client) {
		ko.dataFor(app).showManageCustomer(client);
	};

	this.closeClient = function() {
		var buttons = document.getElementsByClassName('close'),
			i = buttons.length - 1;
		if (i >= 1) buttons[i - 1].click();
	};

	this.calendar = function(month, year, data) {
		this.current_date = new Date();
		this.day_labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
		this.month_labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
		this.month = (isNaN(month) || month === null) ? this.current_date.getMonth() : month;
		this.year = (isNaN(year) || year === null) ? this.current_date.getFullYear() : year;
		this.draw = function(ele) {
			if (this.month > 11) {
				this.month -= 12;
				this.year += 1;
			} else if (month < 0) {
				this.month += 12;
				this.year -= 1;
			}
			// get dates
			var startingDay = new Date(this.year, this.month, 1).getDay(),
				endingDate = new Date(this.year, this.month + 1, 0),
				monthLength = endingDate.getDate(),
				inLastRow = 6 - endingDate.getDay();
			// generate header
			this.table = document.createElement('table');
			this.head = document.createElement('thead');
			this.prev = document.createElement('th');
			this.next = document.createElement('th');
			this.title = document.createElement('th');
			this.days = document.createElement('tr');
			this.body = document.createElement('tbody');
			this.cells = '';
			this.table.setAttribute('class', 'calendar');
			this.table.appendChild(this.head);
			this.head.appendChild(this.prev);
			this.prev.innerHTML = "«";
			this.prev.id = 'prev';
			this.head.appendChild(this.title);
			this.head.appendChild(this.next);
			this.next.innerHTML = "»";
			this.next.id = 'next';
			this.table.appendChild(this.days);
			this.title.innerHTML = this.month_labels[this.month] + " " + this.year;
			this.title.setAttribute('colspan', '5');
			this.days.setAttribute('class', 'header');
			for (var i = 0; i <= 6; i++) this.cells += '' + this.day_labels[i] + '	';
			this.days.innerHTML = this.cells;
			//generate calendar
			var html = '
';
			if (startingDay) html += '	';
			for (var day = 1; day <= monthLength; day++) {
				html += '
' + day + '
';
				//if data argument present, append key value for current day
				if (data) {
					var today = (this.month + 1) + '/' + day + '/' + this.year;
					if (data[today]) html += '
' + Object.keys(data[today]).length + ' Clients
';
				}
				html += '	';
				if ((day + startingDay) % 7 === 0 && day != monthLength) html += '

';
			}
			if (inLastRow) html += '	';
			html += '
';
			this.table.innerHTML += html;
			ele.innerHTML = this.table.outerHTML;
			// save reference to dom node in object
			this.node = ele;
			// save reference to calendar object for enclosure scope
			var cal = this;
			(function() {
				// save calendar object reference for listeners
				var self = this;
				self.prev.addEventListener('click', function() {
					cal.month--;
					cal.draw(cal.node);
				});
				self.next.addEventListener('click', function() {
					cal.month++;
					cal.draw(cal.node);
				});
				document.onkeydown = function(e) {
					e = e || window.event;
					if (e.keyCode == '37') {
						// left arrow
						cal.month--;
						cal.draw(cal.node);
					} else if (e.keyCode == '39') {
						// right arrow
						cal.month++;
						cal.draw(cal.node);
					}
				};
			})();
		};
	};
	this.HTML = {};
	this.HTML.dashboard = this.createElement(document.body, 'div', {
		className: 'navbar navbar-inverse navbar-fixed-bottom',
		id: 'dashboard',
	});
	this.HTML.style = this.createElement(this.HTML.dashboard, 'link', {
		rel: 'stylesheet',
		type: 'text/css',
		href: 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.css',
	});
	this.HTML.nav = this.createElement(this.HTML.dashboard, 'ul', {
		className: 'nav navbar-nav',
	});
	this.HTML.tools = this.createElement(this.HTML.nav, 'li', {
		innerHTML: 'Tools',
		className: 'dropup',
	});
	this.HTML.toolsMenu = this.createElement(this.HTML.tools, 'ul', {
		className: 'dropdown-menu',
	});
	this.HTML.tickets = this.createElement(this.HTML.nav, 'li', {
		innerHTML: 'Tickets',
		className: 'dropup',
	});
	this.HTML.ticketsMenu = this.createElement(this.HTML.tickets, 'ul', {
		className: 'dropdown-menu',
	});
	this.HTML.ticketCalendar = this.createElement(this.HTML.ticketsMenu, 'li', {
		innerHTML: 'Calendar',
	});
	this.HTML.critical = this.createElement(this.HTML.nav, 'li', {
		innerHTML: 'Click to get Critical',
		id: 'critical',
		onclick: function() {
			this.innerHTML = 'Critical Tickets: ' + self.Tickets.getCritical().length + '';
		},
	});

	this.Tickets = {
		getTickets: function() {
			self.Tickets.ticketArray = ko.dataFor(app).contentViewModel().myTickets();
			return self.Tickets.ticketArray;
		},
		getCritical: function() {
			var tickets = this.getTickets(),
			    critical = [];
			for (var i = 0; i < tickets.length; i++) {
				if (tickets[i].ScheduledEndDate < new Date()) {
					critical.push(tickets[i]);
				}
			}
			return critical;
		},
		sortTickets: function(){
			for (var i=0;i<db.Tickets.ticketArray.length;i++){
				if (! self.Tickets.ticketArray) this.getTickets();
				var ticket = self.Tickets.ticketArray[i],
				date = new Date(ticket.ScheduledEndDate),
				day = date.getDate()+'/'+(date.getMonth()+1)+'/'+date.getFullYear();
				if (! data[day]){ data[day] = []};
				data[day].push(ticket);
			}
		}
	}
}
<commit_msg>Update dashboard.js<commit_after>/* call using the following enclosure:
(function(){
  var url = 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.js';
  document.head.appendChild(document.createElement('script')).src=url;
})();
*/

function Dashboard() {
	var self = this;
	this.createElement = function(parent, tag, attributes) {
		var element = parent.appendChild(document.createElement(tag));
		for (var attribute in attributes) {
			if (attributes.hasOwnProperty(attribute)) {
				element[attribute] = attributes[attribute];
			}
		}
		return element;
	};

	this.openClient = function(client) {
		ko.dataFor(app).showManageCustomer(client);
	};

	this.closeClient = function() {
		var buttons = document.getElementsByClassName('close'),
			i = buttons.length - 1;
		if (i >= 1) buttons[i - 1].click();
	};

	this.calendar = function(month, year, data) {
		this.current_date = new Date();
		this.day_labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
		this.month_labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
		this.month = (isNaN(month) || month === null) ? this.current_date.getMonth() : month;
		this.year = (isNaN(year) || year === null) ? this.current_date.getFullYear() : year;
		this.draw = function(ele) {
			if (this.month > 11) {
				this.month -= 12;
				this.year += 1;
			} else if (month < 0) {
				this.month += 12;
				this.year -= 1;
			}
			// get dates
			var startingDay = new Date(this.year, this.month, 1).getDay(),
				endingDate = new Date(this.year, this.month + 1, 0),
				monthLength = endingDate.getDate(),
				inLastRow = 6 - endingDate.getDay();
			// generate header
			this.table = document.createElement('table');
			this.head = document.createElement('thead');
			this.prev = document.createElement('th');
			this.next = document.createElement('th');
			this.title = document.createElement('th');
			this.days = document.createElement('tr');
			this.body = document.createElement('tbody');
			this.cells = '';
			this.table.setAttribute('class', 'calendar');
			this.table.appendChild(this.head);
			this.head.appendChild(this.prev);
			this.prev.innerHTML = "«";
			this.prev.id = 'prev';
			this.head.appendChild(this.title);
			this.head.appendChild(this.next);
			this.next.innerHTML = "»";
			this.next.id = 'next';
			this.table.appendChild(this.days);
			this.title.innerHTML = this.month_labels[this.month] + " " + this.year;
			this.title.setAttribute('colspan', '5');
			this.days.setAttribute('class', 'header');
			for (var i = 0; i <= 6; i++) this.cells += '' + this.day_labels[i] + '	';
			this.days.innerHTML = this.cells;
			//generate calendar
			var html = '
';
			if (startingDay) html += '	';
			for (var day = 1; day <= monthLength; day++) {
				html += '
' + day + '
';
				//if data argument present, append key value for current day
				if (data) {
					var today = (this.month + 1) + '/' + day + '/' + this.year;
					if (data[today]) html += '
' + Object.keys(data[today]).length + ' Clients
';
				}
				html += '	';
				if ((day + startingDay) % 7 === 0 && day != monthLength) html += '

';
			}
			if (inLastRow) html += '	';
			html += '
';
			this.table.innerHTML += html;
			ele.innerHTML = this.table.outerHTML;
			// save reference to dom node in object
			this.node = ele;
			// save reference to calendar object for enclosure scope
			var cal = this;
			(function() {
				// save calendar object reference for listeners
				var self = this;
				self.prev.addEventListener('click', function() {
					cal.month--;
					cal.draw(cal.node);
				});
				self.next.addEventListener('click', function() {
					cal.month++;
					cal.draw(cal.node);
				});
				document.onkeydown = function(e) {
					e = e || window.event;
					if (e.keyCode == '37') {
						// left arrow
						cal.month--;
						cal.draw(cal.node);
					} else if (e.keyCode == '39') {
						// right arrow
						cal.month++;
						cal.draw(cal.node);
					}
				};
			})();
		};
	};
	this.HTML = {};
	this.HTML.dashboard = this.createElement(document.body, 'div', {
		className: 'navbar navbar-inverse navbar-fixed-bottom',
		id: 'dashboard',
	});
	this.HTML.style = this.createElement(this.HTML.dashboard, 'link', {
		rel: 'stylesheet',
		type: 'text/css',
		href: 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.css',
	});
	this.HTML.nav = this.createElement(this.HTML.dashboard, 'ul', {
		className: 'nav navbar-nav',
	});
	this.HTML.tools = this.createElement(this.HTML.nav, 'li', {
		innerHTML: 'Tools',
		className: 'dropup',
	});
	this.HTML.toolsMenu = this.createElement(this.HTML.tools, 'ul', {
		className: 'dropdown-menu',
	});
	this.HTML.tickets = this.createElement(this.HTML.nav, 'li', {
		innerHTML: 'Tickets',
		className: 'dropup',
	});
	this.HTML.ticketsMenu = this.createElement(this.HTML.tickets, 'ul', {
		className: 'dropdown-menu',
	});
	this.HTML.ticketCalendar = this.createElement(this.HTML.ticketsMenu, 'li', {
		innerHTML: 'Calendar',
	});
	this.HTML.critical = this.createElement(this.HTML.nav, 'li', {
		innerHTML: 'Click to get Critical',
		id: 'critical',
		onclick: function() {
			this.innerHTML = 'Critical Tickets: ' + self.Tickets.getCritical().length + '';
		},
	});

	this.Tickets = {
		getTickets: function() {
			self.Tickets.ticketArray = ko.dataFor(app).contentViewModel().myTickets();
			return self.Tickets.ticketArray;
		},
		getCritical: function() {
			var tickets = this.getTickets(),
			    critical = [];
			for (var i = 0; i < tickets.length; i++) {
				if (tickets[i].ScheduledEndDate < new Date()) {
					critical.push(tickets[i]);
				}
			}
			return critical;
		},
		sortTickets: function(){
			var data = [];
			for (var i=0;i<db.Tickets.ticketArray.length;i++){
				if (! self.Tickets.ticketArray) this.getTickets();
				var ticket = self.Tickets.ticketArray[i],
				date = new Date(ticket.ScheduledEndDate),
				day = date.getDate()+'/'+(date.getMonth()+1)+'/'+date.getFullYear();
				if (! data[day]){ data[day] = []};
				data[day].push(ticket);
			}
			return data;
		}
	}
}
<|endoftext|>


<commit_before>/* load and initialize using this closure (add var before "db" on line 6, to privatize scope)
  (function(){
    var url = 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.js';
    document.head.appendChild(document.createElement('script')).src=url;
    function initialize(){
      if (
          typeof(Dashboard) !== 'undefined' &&
          typeof(bootbox) !== 'undefined' &&
          typeof(ko) !== 'undefined' &&
          ko.dataFor(app) !== undefined
          ) {
          db = new Dashboard(ko.dataFor(app), ko, bootbox);
      } else {
          setTimeout(function(){initialize()}, 100);
      }
    }
    initialize();
  })();
*/

function Dashboard(application, ko, bootbox) {
  var self = this;
  this.app = application;
  console.log(this.app);
  this.Tools = {
    bobParse: function(raw){
      var clients = [], data = {};
      // exit on null entry
      if ( raw === null ) return;
      for (var cells = raw.replace(/Basic[\r\n\s\ta-z]*Partner ID[\t\s]+/i, '').split(/\t/),
        client = {}, cols = ['Account ID',	'Account Start Date',	'Account Bucket',	'Account Spend',
        'Date of Next Ticket',	'Engaged Status',	'Timezone',	'Welcome Call',	'Keyword Research',
        'Local Profile Tab',	'Obtain or Create Google Logins',	'Create and Verify Google Profile',
        'Obtain Site Access',	'Implement Onsite Edits',	'Create Yahoo Account',	'Create and Verify Yahoo Profile',
        'Create and Verify Bing Profile',	'Install Analytics',	'Company Name',	'Contact Name',	'Website URL',
        'Email Address',	'Phone Number',	'Partner ID',];
        cells.length>0;){
        var keys = Object.keys(client).length;
        if (keys<cols.length-1){
          var param = cols[keys];
          client[param] = cells[0];
          cells.shift();
        } else {
          client.count = keys;
          clients.push(client);
          client = {};
        }
      }
      for (var i=0;i<clients.length;i++){
        var date = clients[i]['Date of Next Ticket'];
        if (data[date] === undefined) data[date] = [];
        data[date].push(clients[i]);
      }
      return data;
    },
    bobCal: function(){},
    todoistExport: function (){
      var view, data,
      taskDate = function(day){
        var days = [new Date(),new Date(),new Date()];
        if (days[0].getDay() == 5) {
          days[1].setDate(days[0].getDate()+3);
          days[2].setDate(days[0].getDate()+4);
        } else if (days[0].getDay() == 4) {
          days[1].setDate(days[0].getDate()+1);
          days[2].setDate(days[0].getDate()+4);
        } else {
          days[1].setDate(days[0].getDate()+1);
          days[2].setDate(days[0].getDate()+2);
        }
        return 'date '+days[day].toDateString().substring(4);
      },
      textarea = document.createElement('textarea'), text = '',
      modal = bootbox.alert({
          size: 'large',
          message: 'placeholder',
          callback: function(){},
      })[0].children[0].children[0].children[0].children[1];
      if (ko.dataFor(window.app) !== undefined){
        view = ko.dataFor(window.app).contentViewModel();
      } else if (ko.dataFor(self.app) !== undefined){
        view = ko.dataFor(self.app).contentViewModel();
      }
      if (! view.hasOwnProperty('customersDataTable')){
      	modal.remove();
        bootbox.alert('No client data available in active view.\nTry running this tool while viewing a client.');
        return 1;
      } else {
        if (typeof(view.customersDataTable) === undefined) {
          console.log('No customersDataTable');
          return;
        } else {
          data = view.customersDataTable.dataSource()[0];
        }
        text += data.CustomerId+' - '+data.Name;
        text += '[[NOTE]]: https://launchpad.boostability.com/#customerservice/customersearch/'+data.CustomerId;
        text += '\n...'+data.CustomerId+' Welcome Call [['+taskDate(2)+']]';
        text += '\n......'+data.CustomerId+' 1st Welcome Call [['+taskDate(0)+']]';
        text += '\n......'+data.CustomerId+' 1st Welcome Email [['+taskDate(0)+']]';
        text += '\n......'+data.CustomerId+' 2nd Welcome Call [['+taskDate(1)+']]';
        text += '\n......'+data.CustomerId+' 2nd Welcome Email [['+taskDate(1)+']]';
        text += '\n......'+data.CustomerId+' 3rd Welcome Call [['+taskDate(2)+']]';
        text += '\n......'+data.CustomerId+' 3rd Welcome Email [['+taskDate(2)+']]';
        text += '\n...'+data.CustomerId+' Keyword Research';
        text += '\n...'+data.CustomerId+' Local Profile';
        textarea.value = text;
        modal.parentNode.parentNode.parentNode.style.width = "65em";
        modal.innerHTML = '
'+text+'
';
      }
    },
    openClient: function(client) {
      self.app.showManageCustomer(client);
    },
    closeClient: function() {
      var buttons = document.getElementsByClassName('close'),
      i = buttons.length - 1;
      if (i >= 1) buttons[i - 1].click();
    },
    createElement: function(parent, tag, attributes) {
      var element = parent.appendChild(document.createElement(tag));
      for (var attribute in attributes) {
        if (attributes.hasOwnProperty(attribute)) {
          element[attribute] = attributes[attribute];
        }
      }
      return element;
    },
  };
  this.Tickets = {
    calendar: function(month, year, data) {
      if ( typeof(month) === Object ) {
				data = month;
        month = null;
      }
      console.log(data);
      this.current_date = new Date();
      this.day_labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
      this.month_labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
      this.month = (isNaN(month) || month === null) ? this.current_date.getMonth() : month;
      this.year = (isNaN(year) || year === null) ? this.current_date.getFullYear() : year;
      this.draw = function(ele){
          if (this.month > 11) {
            this.month -= 12;
            this.year += 1;
          } else if (month < 0) {
            this.month += 12;
            this.year -= 1;
          }
          // get dates
          var startingDay = new Date(this.year, this.month, 1).getDay(),
          endingDate = new Date(this.year, this.month + 1, 0),
          monthLength = endingDate.getDate(),
          inLastRow = 6 - endingDate.getDay();

          // generate header
          this.table = document.createElement('table');
          this.head = document.createElement('thead');
          this.prev = document.createElement('th');
          this.next = document.createElement('th');
          this.title = document.createElement('th');
          this.days = document.createElement('tr');
          this.body = document.createElement('tbody');
          this.cells = '';
          this.table.setAttribute('class', 'calendar');
          this.table.appendChild(this.head);
          this.head.appendChild(this.prev);
          this.prev.innerHTML = "«";
          this.prev.id = 'prev';
          this.head.appendChild(this.title);
          this.head.appendChild(this.next);
          this.next.innerHTML = "»";
          this.next.id = 'next';
          this.table.appendChild(this.days);
          this.title.innerHTML = this.month_labels[this.month] + " " + this.year;
          this.title.setAttribute('colspan', '5');
          this.days.setAttribute('class', 'header');
          for (var i = 0; i <= 6; i++ ) this.cells += '' + this.day_labels[i] + '	';
          this.days.innerHTML = this.cells;

          //generate calendar
          var html = '
';
          if ( startingDay ) html += '	';
          for (var day = 1; day <= monthLength; day++) {
          html += '
' + day + '
';
          //if data argument present, append key value for current day
          if (data) {
            var today = (this.month+1)+'/'+day+'/'+this.year;
            if (data[today]) html += '
'+Object.keys(data[today]).length+' Clients
';
          }
          html += '	';
          if ( (day + startingDay) % 7 === 0 && day != monthLength ) html += '

';
          }
          if ( inLastRow ) html += '	';
          html += '
';
          this.table.innerHTML += html;
          if (ele) {
            ele.innerHTML = this.table.outerHTML;
          } else {
            return this.table.outerHTML;
          }
          // save reference to dom node in object
          this.node = ele;
          // save reference to calendar object for enclosure scope
          var cal = this;
              (function(){
            // save calendar object reference for listeners
            var self = this;
                self.prev.addEventListener('click', function(){
              cal.month--;
                    cal.draw(cal.node);
                });
            self.next.addEventListener('click', function(){
                    cal.month++;
              cal.draw(cal.node);
                });
                document.onkeydown = function(e) {
                  e = e || window.event;
                    if (e.keyCode == '37') {
                    // left arrow
                    cal.month--;
                    cal.draw(cal.node);
                    } else if (e.keyCode == '39') {
                        // right arrow
                        cal.month++;
                    cal.draw(cal.node);
                    }
                };
              })();
        };
    },
    getTickets: function() {
      //get tickets
      if (self.app.contentViewModel() !== undefined){
        if (typeof(self.app.contentViewModel().myTickets) === "function"){
          self.Tickets.ticketArray = self.app.contentViewModel().myTickets();
        }
      } else if (localStorage.getItem('ticketCache') !== null){
        self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
      }
      //return results
      if (self.Tickets.ticketArray) {
        localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
        return self.Tickets.ticketArray;
      } else {
        alert('Unable to access tickets at this time!');
        return [];
      }
    },
    getCritical: function() {
      var tickets = this.getTickets(),
      critical = [];
      for (var i = 0; i < tickets.length; i++) {
        if (tickets[i].ScheduledEndDate < new Date()) {
          critical.push(tickets[i]);
        }
      }
      if (tickets.length > 0){
        return critical;
      } else {
        return false;
      }
    },
    countCritical: function() {
      var criticals = self.Tickets.getCritical();
      if (criticals) {
        return 'Critical Tickets: ' + criticals.length + '';
      } else {
        return 'Error loading tickets!';
      }
    },
    sortTickets: function(tickets){
      if (! tickets){
        tickets = this.getTickets();
      }
      var data = {};
      for (var i=0;i<tickets.length;i++){
        var ticket = tickets[i],
        date = new Date(ticket.ScheduledEndDate),
        day = date.getDate()+'/'+(date.getMonth()+1)+'/'+date.getFullYear();
        if (! data[day]){ data[day] = [];}
        data[day].push(ticket);
      }
      return data;
    },
    listTickets: function(tickets){
      var list = document.createElement('ul');
      for (var i=0;i<tickets.length;i++){
        var ticket = tickets[i],
        listItem = document.createElement('li'),
        text = ticket.CompanyName+': '+ticket.TicketTypeName;
        text += ' (Due: '+(ticket.ScheduledEndDate.getMonth()+1);
        text += '/'+ticket.ScheduledEndDate.getDate()+'/';
        text += ticket.ScheduledEndDate.getFullYear()+')';
        listItem.innerHTML = text;
        list.appendChild(listItem);
      }
      return list;
    },
    tryCache: function(){
      try {
        if (self.Tickets.ticketArray) {
          localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
        }
      } catch(err) {
        setTimeout(function(){self.Tickets.tryCache();}, 1000);
      }
    },
  };
  this.HTML = {};
  this.HTML.dashboard = this.Tools.createElement(document.body, 'div', {
        className: 'navbar navbar-inverse navbar-fixed-bottom',
        id: 'dashboard',
  });
  this.HTML.style = this.Tools.createElement(this.HTML.dashboard, 'link', {
    rel: 'stylesheet',
    type: 'text/css',
    href: 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.css',
  }),
  this.HTML.nav = this.Tools.createElement(this.HTML.dashboard, 'ul', {
    className: 'nav navbar-nav',
  }),
  this.HTML.tools = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: 'Tools',
    className: 'dropup',
  }),
  this.HTML.toolsMenu = this.Tools.createElement(this.HTML.tools, 'ul', {
    className: 'dropdown-menu',
  }),
  this.HTML.todoistExport = this.Tools.createElement(this.HTML.toolsMenu, 'li', {
    innerHTML: 'Todoist Export',
    onclick: function(){
      self.Tools.todoistExport();
    },
  }),
  this.HTML.tickets = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: 'Tickets',
    className: 'dropup',
  }),
  this.HTML.ticketsMenu = this.Tools.createElement(this.HTML.tickets, 'ul', {
    className: 'dropdown-menu',
  }),
  this.HTML.ticketCalendar = this.Tools.createElement(this.HTML.ticketsMenu, 'li', {
    innerHTML: 'Calendar',
    onclick: function(){
      var node = bootbox.alert('none')[0].children[0].children[0].children[0],
      data = self.Tickets.sortTickets(),
      calendar = new self.Tickets.calendar(data);
      console.log(data);
      calendar.draw(node);
    }
  }),
  this.HTML.critical = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: self.Tickets.countCritical(),
    id: 'critical',
    onclick: function(){
      self.HTML.critical.innerHTML = self.Tickets.countCritical();
    },
  });

  window.beforeunload = function(){
    self.Tickets.tryCache();
  };
  window.onhashchange = function(){
    if (window.location.href == 'https://launchpad.boostability.com/#/customerservice/activetickets'){
      self.Tickets.tryCache();
    }
  };
  if (localStorage.getItem('ticketCache') !== null) self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
}
<commit_msg>Update dashboard.js<commit_after>/* load and initialize using this closure (add var before "db" on line 6, to privatize scope)
  (function(){
    var url = 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.js';
    document.head.appendChild(document.createElement('script')).src=url;
    function initialize(){
      if (
          typeof(Dashboard) !== 'undefined' &&
          typeof(bootbox) !== 'undefined' &&
          typeof(ko) !== 'undefined' &&
          ko.dataFor(app) !== undefined
          ) {
          db = new Dashboard(ko.dataFor(app), ko, bootbox);
      } else {
          setTimeout(function(){initialize()}, 100);
      }
    }
    initialize();
  })();
*/

function Dashboard(application, ko, bootbox) {
  var self = this;
  this.app = application;
  console.log(this.app);
  this.Tools = {
    bobParse: function(raw){
      var clients = [], data = {};
      // exit on null entry
      if ( raw === null ) return;
      for (var cells = raw.replace(/Basic[\r\n\s\ta-z]*Partner ID[\t\s]+/i, '').split(/\t/),
        client = {}, cols = ['Account ID',	'Account Start Date',	'Account Bucket',	'Account Spend',
        'Date of Next Ticket',	'Engaged Status',	'Timezone',	'Welcome Call',	'Keyword Research',
        'Local Profile Tab',	'Obtain or Create Google Logins',	'Create and Verify Google Profile',
        'Obtain Site Access',	'Implement Onsite Edits',	'Create Yahoo Account',	'Create and Verify Yahoo Profile',
        'Create and Verify Bing Profile',	'Install Analytics',	'Company Name',	'Contact Name',	'Website URL',
        'Email Address',	'Phone Number',	'Partner ID',];
        cells.length>0;){
        var keys = Object.keys(client).length;
        if (keys<cols.length-1){
          var param = cols[keys];
          client[param] = cells[0];
          cells.shift();
        } else {
          client.count = keys;
          clients.push(client);
          client = {};
        }
      }
      for (var i=0;i<clients.length;i++){
        var date = clients[i]['Date of Next Ticket'];
        if (data[date] === undefined) data[date] = [];
        data[date].push(clients[i]);
      }
      return data;
    },
    bobCal: function(){},
    todoistExport: function (){
      var view, data,
      taskDate = function(day){
        var days = [new Date(),new Date(),new Date()];
        if (days[0].getDay() == 5) {
          days[1].setDate(days[0].getDate()+3);
          days[2].setDate(days[0].getDate()+4);
        } else if (days[0].getDay() == 4) {
          days[1].setDate(days[0].getDate()+1);
          days[2].setDate(days[0].getDate()+4);
        } else {
          days[1].setDate(days[0].getDate()+1);
          days[2].setDate(days[0].getDate()+2);
        }
        return 'date '+days[day].toDateString().substring(4);
      },
      textarea = document.createElement('textarea'), text = '',
      modal = bootbox.alert({
          size: 'large',
          message: 'placeholder',
          callback: function(){},
      })[0].children[0].children[0].children[0].children[1];
      if (ko.dataFor(window.app) !== undefined){
        view = ko.dataFor(window.app).contentViewModel();
      } else if (ko.dataFor(self.app) !== undefined){
        view = ko.dataFor(self.app).contentViewModel();
      }
      if (! view.hasOwnProperty('customersDataTable')){
      	modal.remove();
        bootbox.alert('No client data available in active view.
Try running this tool while viewing a client.<');
        return 1;
      } else {
        if (typeof(view.customersDataTable) === undefined) {
          console.log('No customersDataTable');
          return;
        } else {
          data = view.customersDataTable.dataSource()[0];
        }
        text += data.CustomerId+' - '+data.Name;
        text += '[[NOTE]]: https://launchpad.boostability.com/#customerservice/customersearch/'+data.CustomerId;
        text += '\n...'+data.CustomerId+' Welcome Call [['+taskDate(2)+']]';
        text += '\n......'+data.CustomerId+' 1st Welcome Call [['+taskDate(0)+']]';
        text += '\n......'+data.CustomerId+' 1st Welcome Email [['+taskDate(0)+']]';
        text += '\n......'+data.CustomerId+' 2nd Welcome Call [['+taskDate(1)+']]';
        text += '\n......'+data.CustomerId+' 2nd Welcome Email [['+taskDate(1)+']]';
        text += '\n......'+data.CustomerId+' 3rd Welcome Call [['+taskDate(2)+']]';
        text += '\n......'+data.CustomerId+' 3rd Welcome Email [['+taskDate(2)+']]';
        text += '\n...'+data.CustomerId+' Keyword Research';
        text += '\n...'+data.CustomerId+' Local Profile';
        textarea.value = text;
        modal.parentNode.parentNode.parentNode.style.width = "65em";
        modal.innerHTML = '
'+text+'
';
      }
    },
    openClient: function(client) {
      self.app.showManageCustomer(client);
    },
    closeClient: function() {
      var buttons = document.getElementsByClassName('close'),
      i = buttons.length - 1;
      if (i >= 1) buttons[i - 1].click();
    },
    createElement: function(parent, tag, attributes) {
      var element = parent.appendChild(document.createElement(tag));
      for (var attribute in attributes) {
        if (attributes.hasOwnProperty(attribute)) {
          element[attribute] = attributes[attribute];
        }
      }
      return element;
    },
  };
  this.Tickets = {
    calendar: function(month, year, data) {
      if ( typeof(month) === Object ) {
				data = month;
        month = null;
      }
      console.log(data);
      this.current_date = new Date();
      this.day_labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
      this.month_labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
      this.month = (isNaN(month) || month === null) ? this.current_date.getMonth() : month;
      this.year = (isNaN(year) || year === null) ? this.current_date.getFullYear() : year;
      this.draw = function(ele){
          if (this.month > 11) {
            this.month -= 12;
            this.year += 1;
          } else if (month < 0) {
            this.month += 12;
            this.year -= 1;
          }
          // get dates
          var startingDay = new Date(this.year, this.month, 1).getDay(),
          endingDate = new Date(this.year, this.month + 1, 0),
          monthLength = endingDate.getDate(),
          inLastRow = 6 - endingDate.getDay();

          // generate header
          this.table = document.createElement('table');
          this.head = document.createElement('thead');
          this.prev = document.createElement('th');
          this.next = document.createElement('th');
          this.title = document.createElement('th');
          this.days = document.createElement('tr');
          this.body = document.createElement('tbody');
          this.cells = '';
          this.table.setAttribute('class', 'calendar');
          this.table.appendChild(this.head);
          this.head.appendChild(this.prev);
          this.prev.innerHTML = "«";
          this.prev.id = 'prev';
          this.head.appendChild(this.title);
          this.head.appendChild(this.next);
          this.next.innerHTML = "»";
          this.next.id = 'next';
          this.table.appendChild(this.days);
          this.title.innerHTML = this.month_labels[this.month] + " " + this.year;
          this.title.setAttribute('colspan', '5');
          this.days.setAttribute('class', 'header');
          for (var i = 0; i <= 6; i++ ) this.cells += '' + this.day_labels[i] + '	';
          this.days.innerHTML = this.cells;

          //generate calendar
          var html = '
';
          if ( startingDay ) html += '	';
          for (var day = 1; day <= monthLength; day++) {
          html += '
' + day + '
';
          //if data argument present, append key value for current day
          if (data) {
            var today = (this.month+1)+'/'+day+'/'+this.year;
            if (data[today]) html += '
'+Object.keys(data[today]).length+' Clients
';
          }
          html += '	';
          if ( (day + startingDay) % 7 === 0 && day != monthLength ) html += '

';
          }
          if ( inLastRow ) html += '	';
          html += '
';
          this.table.innerHTML += html;
          if (ele) {
            ele.innerHTML = this.table.outerHTML;
          } else {
            return this.table.outerHTML;
          }
          // save reference to dom node in object
          this.node = ele;
          // save reference to calendar object for enclosure scope
          var cal = this;
              (function(){
            // save calendar object reference for listeners
            var self = this;
                self.prev.addEventListener('click', function(){
              cal.month--;
                    cal.draw(cal.node);
                });
            self.next.addEventListener('click', function(){
                    cal.month++;
              cal.draw(cal.node);
                });
                document.onkeydown = function(e) {
                  e = e || window.event;
                    if (e.keyCode == '37') {
                    // left arrow
                    cal.month--;
                    cal.draw(cal.node);
                    } else if (e.keyCode == '39') {
                        // right arrow
                        cal.month++;
                    cal.draw(cal.node);
                    }
                };
              })();
        };
    },
    getTickets: function() {
      //get tickets
      if (self.app.contentViewModel() !== undefined){
        if (typeof(self.app.contentViewModel().myTickets) === "function"){
          self.Tickets.ticketArray = self.app.contentViewModel().myTickets();
        }
      } else if (localStorage.getItem('ticketCache') !== null){
        self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
      }
      //return results
      if (self.Tickets.ticketArray) {
        localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
        return self.Tickets.ticketArray;
      } else {
        alert('Unable to access tickets at this time!');
        return [];
      }
    },
    getCritical: function() {
      var tickets = this.getTickets(),
      critical = [];
      for (var i = 0; i < tickets.length; i++) {
        if (tickets[i].ScheduledEndDate < new Date()) {
          critical.push(tickets[i]);
        }
      }
      if (tickets.length > 0){
        return critical;
      } else {
        return false;
      }
    },
    countCritical: function() {
      var criticals = self.Tickets.getCritical();
      if (criticals) {
        return 'Critical Tickets: ' + criticals.length + '';
      } else {
        return 'Error loading tickets!';
      }
    },
    sortTickets: function(tickets){
      if (! tickets){
        tickets = this.getTickets();
      }
      var data = {};
      for (var i=0;i<tickets.length;i++){
        var ticket = tickets[i],
        date = new Date(ticket.ScheduledEndDate),
        day = date.getDate()+'/'+(date.getMonth()+1)+'/'+date.getFullYear();
        if (! data[day]){ data[day] = [];}
        data[day].push(ticket);
      }
      return data;
    },
    listTickets: function(tickets){
      var list = document.createElement('ul');
      for (var i=0;i<tickets.length;i++){
        var ticket = tickets[i],
        listItem = document.createElement('li'),
        text = ticket.CompanyName+': '+ticket.TicketTypeName;
        text += ' (Due: '+(ticket.ScheduledEndDate.getMonth()+1);
        text += '/'+ticket.ScheduledEndDate.getDate()+'/';
        text += ticket.ScheduledEndDate.getFullYear()+')';
        listItem.innerHTML = text;
        list.appendChild(listItem);
      }
      return list;
    },
    tryCache: function(){
      try {
        if (self.Tickets.ticketArray) {
          localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
        }
      } catch(err) {
        setTimeout(function(){self.Tickets.tryCache();}, 1000);
      }
    },
  };
  this.HTML = {};
  this.HTML.dashboard = this.Tools.createElement(document.body, 'div', {
        className: 'navbar navbar-inverse navbar-fixed-bottom',
        id: 'dashboard',
  });
  this.HTML.style = this.Tools.createElement(this.HTML.dashboard, 'link', {
    rel: 'stylesheet',
    type: 'text/css',
    href: 'https://rawgit.com/jamesona/SEO-Tools/master/am-dashboard/dashboard.css',
  }),
  this.HTML.nav = this.Tools.createElement(this.HTML.dashboard, 'ul', {
    className: 'nav navbar-nav',
  }),
  this.HTML.tools = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: 'Tools',
    className: 'dropup',
  }),
  this.HTML.toolsMenu = this.Tools.createElement(this.HTML.tools, 'ul', {
    className: 'dropdown-menu',
  }),
  this.HTML.todoistExport = this.Tools.createElement(this.HTML.toolsMenu, 'li', {
    innerHTML: 'Todoist Export',
    onclick: function(){
      self.Tools.todoistExport();
    },
  }),
  this.HTML.tickets = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: 'Tickets',
    className: 'dropup',
  }),
  this.HTML.ticketsMenu = this.Tools.createElement(this.HTML.tickets, 'ul', {
    className: 'dropdown-menu',
  }),
  this.HTML.ticketCalendar = this.Tools.createElement(this.HTML.ticketsMenu, 'li', {
    innerHTML: 'Calendar',
    onclick: function(){
      var node = bootbox.alert('none')[0].children[0].children[0].children[0],
      data = self.Tickets.sortTickets(),
      calendar = new self.Tickets.calendar(data);
      console.log(data);
      calendar.draw(node);
    }
  }),
  this.HTML.critical = this.Tools.createElement(this.HTML.nav, 'li', {
    innerHTML: self.Tickets.countCritical(),
    id: 'critical',
    onclick: function(){
      self.HTML.critical.innerHTML = self.Tickets.countCritical();
    },
  });

  window.beforeunload = function(){
    self.Tickets.tryCache();
  };
  window.onhashchange = function(){
    if (window.location.href == 'https://launchpad.boostability.com/#/customerservice/activetickets'){
      self.Tickets.tryCache();
    }
  };
  if (localStorage.getItem('ticketCache') !== null) self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
}
<|endoftext|>