<commit_before>/*
hud.js
------
    This file contains the code for controlling the player
    health HUD. The technique used is "injection", which is
    an extension of the original code. The way it works is
    by creating a new instance of original code and supply it
    with a new name. Simply put, injection is a copy of the
    original but different in the sense of the extra code we
    add. While injecting, we modify the original code. In
    the case of this plugin, we overwrite the draw() function
    of our game. The this.parent() function will point to our
    old draw() function, so everything there is kept. All we
    check for in the new isntance is the presence of a player
    entity, and if true then a HUD is drawn.

    The health HUD consists of two parts: A number and Health bar.

    Number: A function which handles drawing a black, slightly transparent
    rectangle where the health will be visible. Uses the following
    canvas properties to draw the HUD to screen:
        | fillstyle: This property sets the color
        | font: This property sets the font
        | setAlpha(): This property sets the transparency.
            | setalpha = 1: Fully Solid
            | setAlpha = 0: Fully transparent
        | fillRect(): This property draws a rectangle to the screen
          given a given position with a given width + height
        | fillText(): This property draws text on screen at a given positon.

    Bar: A function which draws two rectangles on top of each other. Uses
    the same canvas properties above to draw.

*/

ig.module(
    'plugins.hud.hud'
)
.defines(function() {
    ig.hud = ig.Class.extend({
        // Get the canvas
        canvas  : document.getElementById('canvas'),
        // Check if the canvas is being viewed
        context : canvas.getContext('2d'),

        init: function() {
            ig.Game.inject({
                draw: function() {
                    this.parent();
                    // If there is a player. draw the HUD
                    if(ig.game.getEntitiesByType('EntityPlayer').length  != 0) {
                        if(this.hud) {
                            this.hud.number_health();
                            this.hud.bar_health();
                            this.hud.number_mana();
                            this.hud.bar_mana();
                            // this.hud.number_stamina();
                            // this.hud.bar_stamina();
                            // this.hud.number_level();
                            // this.hud.bar_exp();
                        }
                    }
                }
            })
        },

        // ----- Health Meter -----
        number_health: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7; //set transparency
            context.fillRect (10, 10, 75, 13);
            //draw text on top of the rectangle
            context.fillStyle = "rgb(255, 255, 255)";
            context.font = "13px Arial";
            context.fillText ('HP: ' + player.health + '/' + player.stats.maxHP, 11, 21); //font used is the default canvas font
            context.setAlpha = 1;
            return null;
        },

        bar_health: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var h = 100 * Math.min(player.health / player.stats.maxHP, 100);
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7;
            context.fillRect (90, 10, 100, 13);
            // Determine what color of health to draw, Bright red for full, dim red otherwise
            var color = h < 100 ? "rgb(175, 0, 0)" : "rgb(225, 0, 0)";
            //var color = "rgb(200, 0, 0)";
            context.fillStyle = color;
            context.setAlpha = 0.9;
            context.fillRect (91, 11, h-2, 11);
            context.setAlpha = 1;
            return null;
        },

        // ----- Mana Meter -----
        number_mana: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7; //set transparency
            context.fillRect (10, 25, 75, 13);
            //draw text on top of the rectangle
            context.fillStyle = "rgb(255, 255, 255)";
            context.font = "13px Arial";
            context.fillText ('MP: ' + player.tp + '/' + player.stats.maxTP, 11, 36); //font used is the default canvas font
            context.setAlpha = 1;
            return null;
        },

        bar_mana: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var h = 100 * Math.min(player.tp / player.stats.maxTP, 100);
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7;
            context.fillRect (90, 25, 100, 13);
            // Determine what color of mana to draw, Bright blue for full, dim blue otherwise
            var color = h < 100 ? "rgb(0, 0, 175)" : "rgb(0, 0, 225)";
            //var color = "rgb(0, 0, 200)";
            context.fillStyle = color;
            context.setAlpha = 0.9;
            context.fillRect (91, 26, h-2, 11);
            context.setAlpha = 1;
            return null;
        },

        // ----- Stamina Meter -----
        number_stamina: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7; //set transparency
            context.fillRect (10, 40, 75, 13);
            //draw text on top of the rectangle
            context.fillStyle = "rgb(255, 255, 255)";
            context.font = "13px Arial";
            context.fillText ('SP: ' + player.stamina + '/' + player.max_stamina, 11, 51); //font used is the default canvas font
            context.setAlpha = 1;
            return null;
        },

        bar_stamina: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var h = 100 * Math.min(player.stamina / player.max_stamina, 100);
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7;
            context.fillRect (90, 40, 100, 13);
            // Determine what color of stamina to draw, Bright green for full, dim green otherwise
            var color = h < 100 ? "rgb(0, 175, 0)" : "rgb(0, 225, 0)";
            //var color = "rgb(0, 200, 0)";
            context.fillStyle = color;
            context.setAlpha = 0.9;
            context.fillRect (91, 41, h-2, 11);
            context.setAlpha = 1;
            return null;
        },

        // ----- Level/Experience Meter -----
        number_level: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7; //set transparency
            context.fillRect (10, 55, 75, 13);
            //draw text on top of the rectangle
            context.fillStyle = "rgb(255, 255, 255)";
            context.font = "13px Arial";
            context.fillText ('Level: ' + ig.game.LEVEL, 11, 66); //font used is the default canvas font
            context.setAlpha = 1;
            return null;
        },

        bar_exp: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var h = 100 * Math.min(ig.game.EXP.curr / ig.game.EXP.next, 100);
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7;
            context.fillRect (90, 55, 100, 13);
            var color = "rgb(200, 200, 0)";
            context.fillStyle = color;
            context.setAlpha = 0.9;
            context.fillRect (91, 56, h-2, 11);
            context.setAlpha = 1;
            return null;
        },
    });
})
<commit_msg>Fixing hud to properly display player technical points<commit_after>/*
hud.js
------
    This file contains the code for controlling the player
    health HUD. The technique used is "injection", which is
    an extension of the original code. The way it works is
    by creating a new instance of original code and supply it
    with a new name. Simply put, injection is a copy of the
    original but different in the sense of the extra code we
    add. While injecting, we modify the original code. In
    the case of this plugin, we overwrite the draw() function
    of our game. The this.parent() function will point to our
    old draw() function, so everything there is kept. All we
    check for in the new isntance is the presence of a player
    entity, and if true then a HUD is drawn.

    The health HUD consists of two parts: A number and Health bar.

    Number: A function which handles drawing a black, slightly transparent
    rectangle where the health will be visible. Uses the following
    canvas properties to draw the HUD to screen:
        | fillstyle: This property sets the color
        | font: This property sets the font
        | setAlpha(): This property sets the transparency.
            | setalpha = 1: Fully Solid
            | setAlpha = 0: Fully transparent
        | fillRect(): This property draws a rectangle to the screen
          given a given position with a given width + height
        | fillText(): This property draws text on screen at a given positon.

    Bar: A function which draws two rectangles on top of each other. Uses
    the same canvas properties above to draw.

*/

ig.module(
    'plugins.hud.hud'
)
.defines(function() {
    ig.hud = ig.Class.extend({
        // Get the canvas
        canvas  : document.getElementById('canvas'),
        // Check if the canvas is being viewed
        context : canvas.getContext('2d'),

        init: function() {
            ig.Game.inject({
                draw: function() {
                    this.parent();
                    // If there is a player. draw the HUD
                    if(ig.game.getEntitiesByType('EntityPlayer').length  != 0) {
                        if(this.hud) {
                            this.hud.number_health();
                            this.hud.bar_health();
                            this.hud.number_mana();
                            this.hud.bar_mana();
                            // this.hud.number_stamina();
                            // this.hud.bar_stamina();
                            // this.hud.number_level();
                            // this.hud.bar_exp();
                        }
                    }
                }
            })
        },

        // ----- Health Meter -----
        number_health: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7; //set transparency
            context.fillRect (10, 10, 75, 13);
            //draw text on top of the rectangle
            context.fillStyle = "rgb(255, 255, 255)";
            context.font = "13px Arial";
            context.fillText ('HP: ' + player.health + '/' + player.stats.maxHP, 11, 21); //font used is the default canvas font
            context.setAlpha = 1;
            return null;
        },

        bar_health: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var h = 100 * Math.min(player.health / player.stats.maxHP, 100);
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7;
            context.fillRect (90, 10, 100, 13);
            // Determine what color of health to draw, Bright red for full, dim red otherwise
            var color = h < 100 ? "rgb(175, 0, 0)" : "rgb(225, 0, 0)";
            //var color = "rgb(200, 0, 0)";
            context.fillStyle = color;
            context.setAlpha = 0.9;
            context.fillRect (91, 11, h-2, 11);
            context.setAlpha = 1;
            return null;
        },

        // ----- Mana Meter -----
        number_mana: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7; //set transparency
            context.fillRect (10, 25, 75, 13);
            //draw text on top of the rectangle
            context.fillStyle = "rgb(255, 255, 255)";
            context.font = "13px Arial";
            context.fillText ('MP: ' + player.stats.tp + '/' + player.stats.maxTP, 11, 36); //font used is the default canvas font
            context.setAlpha = 1;
            return null;
        },

        bar_mana: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var h = 100 * Math.min(player.stats.tp / player.stats.maxTP, 100);
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7;
            context.fillRect (90, 25, 100, 13);
            // Determine what color of mana to draw, Bright blue for full, dim blue otherwise
            var color = h < 100 ? "rgb(0, 0, 175)" : "rgb(0, 0, 225)";
            //var color = "rgb(0, 0, 200)";
            context.fillStyle = color;
            context.setAlpha = 0.9;
            context.fillRect (91, 26, h-2, 11);
            context.setAlpha = 1;
            return null;
        },

        // ----- Stamina Meter -----
        number_stamina: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7; //set transparency
            context.fillRect (10, 40, 75, 13);
            //draw text on top of the rectangle
            context.fillStyle = "rgb(255, 255, 255)";
            context.font = "13px Arial";
            context.fillText ('SP: ' + player.stamina + '/' + player.max_stamina, 11, 51); //font used is the default canvas font
            context.setAlpha = 1;
            return null;
        },

        bar_stamina: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var h = 100 * Math.min(player.stamina / player.max_stamina, 100);
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7;
            context.fillRect (90, 40, 100, 13);
            // Determine what color of stamina to draw, Bright green for full, dim green otherwise
            var color = h < 100 ? "rgb(0, 175, 0)" : "rgb(0, 225, 0)";
            //var color = "rgb(0, 200, 0)";
            context.fillStyle = color;
            context.setAlpha = 0.9;
            context.fillRect (91, 41, h-2, 11);
            context.setAlpha = 1;
            return null;
        },

        // ----- Level/Experience Meter -----
        number_level: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7; //set transparency
            context.fillRect (10, 55, 75, 13);
            //draw text on top of the rectangle
            context.fillStyle = "rgb(255, 255, 255)";
            context.font = "13px Arial";
            context.fillText ('Level: ' + ig.game.LEVEL, 11, 66); //font used is the default canvas font
            context.setAlpha = 1;
            return null;
        },

        bar_exp: function() {
            if(!this.context) return null;
            // Get the player instance
            var player  = ig.game.getEntitiesByType('EntityPlayer')[0];
            // Draw a transparent Black Rectangle
            var h = 100 * Math.min(ig.game.EXP.curr / ig.game.EXP.next, 100);
            var context  = this.canvas.getContext('2d');
            // Set visual properties of the HUD
            context.fillStyle = "rgb(0, 0, 0)";
            context.setAlpha = 0.7;
            context.fillRect (90, 55, 100, 13);
            var color = "rgb(200, 200, 0)";
            context.fillStyle = color;
            context.setAlpha = 0.9;
            context.fillRect (91, 56, h-2, 11);
            context.setAlpha = 1;
            return null;
        },
    });
})
<|endoftext|>


<commit_before>define([
'jquery',
'underscore',
'backbone',
'libs/marked/marked',
'text!templates/style/page.html',
'config',
'jscssp',
'pagedown',
'libs/prism/prism',
'libs/parseuri/parseuri',
'libs/less/less-1.3.3.min'
],
function($, _, Backbone, marked, stylePageTemplate, config, jscssp, Pagedown, hljs, parseuri){
	var that = null;
	var StylePage = Backbone.View.extend({
		el: '.kalei-page',
		render: function () {
			that = this;

			//add more space at the bottom of the page to avoid scrolling to last node from menu
			//but we can think for something more smarter
			var pageHeight = document.body.offsetHeight;
			var lastEl = $('.kalei-page__item:last').height();
			console.log(lastEl);
			// $(that.el).css({ 'padding-bottom' : pageHeight });

			$('head').append('<link rel="stylesheet" href="' + config.css_path + '"" type="text/css" />');
			$('a.kalei-styleguide-menu-link').removeClass('active');
			if(window.location.hash === '') {
				$('.js-kalei-home').addClass('active');
			} else {
				$('[href="' + window.location.hash + '"]').addClass('active');
			}

			// $("head").find("link").attr("href", function (i, value) {
			//     if (value != config.css_path){
			//         $('head').append('<link rel="stylesheet" href="' + config.css_path + '"" type="text/css" />');
			//     }
			// });

			var styleUrl;
			var configDir;

			if(this.options.style === null) {
				this.options.style = config.css_path.substr(config.css_path.lastIndexOf('/')+1);
			}

			if(this.options.style.substr(0,1) === '/') {
				// non relative
				configDir = config.css_path.substr(0, config.css_path.lastIndexOf('/'));
				var pUrl = parseuri(configDir);
				styleUrl = pUrl.protocol + '://' + pUrl.host + (pUrl.port === '' ? '' : ':'+ pUrl) + this.options.style;
			} else {
				configDir = config.css_path.substr(0, config.css_path.lastIndexOf('/'));
				styleUrl = configDir + '/' + this.options.style;
			}

			console.log('try', configDir);
			console.log('try', styleUrl);
			require(['text!'+ styleUrl], function (stylesheet) {
				var parser = null;
				var regex = /(?:.*\/)(.*)\.(css|less|sass)$/gi;
				var result = regex.exec(styleUrl);
				//result[0] Original Input
				//result[1] Filename
				//result[2] Extension

				var page = {blocks:[]};

				switch (result[2]) {
					case 'css':
							parser = new jscssp();
							stylesheet = parser.parse(stylesheet, false, true);
							page = that.compute_css(stylesheet);
						break;
					case 'less':
							parser = new(less.Parser)({
								paths: [configDir + '/'], // Specify search paths for @import directives
							});
							parser.parse(stylesheet, function (err, tree) {
								stylesheet = tree;
							});
							page = that.compute_less(stylesheet);
						break;
					case 'sass':
						console.log("Error", "Unsupported style type.");
						/*require(['sass'], function (sass){
							//parse
						});*/
						break;
				}

				console.log((new Date()).getTime() + " bottom", page)

				$('.kalei-sheet-submenu').slideUp(200);
				var submenu = $('
');

				////////////NEEDS TO BE EXPORTED TO Menu.js
				_.each(page.blocks, function (block) {
					if (block.heading != "") {
						var li = $('
');
						li.append($('').text(block.heading));
						submenu.append(li);
					}

				});
				$('li:first-child', submenu).addClass('active');
				$('.kalei-sheet-submenu', $('[data-sheet="' + that.options.style + '"]')).html(submenu).slideDown(200);
				////////////NEEDS TO BE EXPORTED TO Menu.js

				$(that.el).html(_.template(stylePageTemplate, {_:_, page: page, config: config}));

				//Colour Coding in code Block
				Prism.highlightAll();

				//Fixed by pivanov
				//that.compute_css
				$(".kalei-sheet-submenu li").on('click', function(ev) {
					$('html, body').animate({
						scrollTop: $(".kalei-page__item h1:contains('"+$(ev.currentTarget).text()+"')," +
									   ".kalei-page__item h2:contains('"+$(ev.currentTarget).text()+"')").offset().top - 60
					}, 'slow');
					console.log($(ev.currentTarget).text());
				});

				$(window).scroll(function () {
					$(".kalei-page__item").each(function(){
						if ( that.is_on_screen($(this), 60) ) {
							$(".kalei-sheet-submenu li").removeClass('active');
							$(".kalei-sheet-submenu li:contains('" + $(this).find('h1').text() +"')," +
							   ".kalei-sheet-submenu li:contains('" + $(this).find('h2').text() +"')").addClass('active');
						}
					});
				});

				fixie.init();
			});
		},

		is_on_screen: function(el, offset) {

			var win = $(window);

			var viewport = {
				top : win.scrollTop()
			};

			viewport.bottom = viewport.top + win.height();

			var bounds = el.offset();

			return (!(viewport.top + offset < bounds.top || viewport.top > bounds.bottom));

		},

		compute_css: function(stylesheet) {
			console.log("compute_css()")
			var page = {
				blocks:[],
				css:"",
				stylesheets: []
			};
			console.log(stylesheet)
			_.each(stylesheet.cssRules, function(rule) {
				switch (rule.type) {
					case 1: //Standard rule?
						break;
					case 3: //Import Rule (@import)
						//we need to import jsscp doesnt compile imports
						stylesheet.deleteRule(rule);
						break;
					case 101: //Comment Block
						page.blocks = page.blocks.concat(that.parse_commentblock(rule.parsedCssText))
						break;
				}
			});

			page.css = stylesheet.cssText()

			var parser = new(less.Parser);
			var stylesheet
			page.css = ".kalei-page{" + page.css + "}"
			parser.parse(page.css, function (err, tree) {
				stylesheet = tree;
			});

			page.css = stylesheet.toCSS({ compress: true });
			return page;
		},

		compute_less: function(stylesheet) {
			console.log("compute_less()", stylesheet)
			var page = {
				blocks:[],
				css:"",
				stylesheets: []
			};

			_.each(stylesheet.rules, function(rule) {
				if (rule.silent != null){ //Comment block
					page.blocks = page.blocks.concat(that.parse_commentblock(rule.value))
					//page.blocks.push();
				} else if (rule.rules != null) { //Standard Rule

				} else if (rule.path != null) { //Import Rule
					// var previous_heading = page.blocks.length - 1;
					// if (typeof page.blocks[previous_heading].import_rule == "undefined") {
					//     page.blocks[previous_heading].import_rule = []
					// }
					// page.blocks[previous_heading].import_rule.push(rule.path)

				}
			});

			page.css = stylesheet.toCSS({ compress: true });
			page.css = ".kalei-page{" + page.css + "}";
			page.css = stylesheet.toCSS({ compress: true });
			return page;
		},

		parse_commentblock: function (comment_block_text) {
			//Remove /* & */
			comment_block_text = comment_block_text.replace(/(?:\/\*)|(?:\*\/)/gi, '');

			marked.setOptions(_.extend({ sanitize: false, gfm: true }, config.marked_options || {}));
			var lexedCommentblock = marked.lexer(comment_block_text);
			var lexerLinks = lexedCommentblock.links || {}; // lexer appends definition links to returned token object

			var return_val = [];
			var block_def = {
				content: [],
				heading: "",
			};
			var block = _.clone(block_def);

			_.each(lexedCommentblock, function (comment) {
				switch (comment.type) {
					case "code":
						//Push the code for an example
						block.content.push({
						  type: 'html',
						  text: '
' + comment.text + '

'
						});
						//Push the code section so marked can parse it as a
 block
						comment.text = comment.text.replace(/class=([""'])fixie\1|(?![""' ])fixie(?=[""' ])/g, "")
						block.content.push(comment);
						break;
					case "heading":
						if (block.heading != "") {  //Multiple headings in one comment block
													//We want to break them up
							//Parse the content blocks and return the HTML to display
							block.content.links = lexerLinks
							block.content = marked.parser(block.content)
							return_val.push(block);
							block = _.clone(block_def);
						}
						if (comment.depth <= 2) {
							block.heading = comment.text;
							block.content.push(comment);
						} else if (comment.depth == 3) { //Import statement title
							block.stylesheet = comment.text;
							//block.heading = "Stylesheets"
							//this is an import statement
							//if ($.inArray("Stylesheets", ))
							//console.log("else", comment)
						}
						break;
					default:
						//Push everything else
						block.content.push(comment);
						break;
				} //Switch
			});

			//Parse the content blocks and return the HTML to display
			block.content.links = lexerLinks
			block.content = marked.parser(block.content)

			return_val.push(block);
			return return_val;
		},

	});
	return StylePage;
});
<commit_msg>Removed 'clear: both' from <commit_after>define([
'jquery',
'underscore',
'backbone',
'libs/marked/marked',
'text!templates/style/page.html',
'config',
'jscssp',
'pagedown',
'libs/prism/prism',
'libs/parseuri/parseuri',
'libs/less/less-1.3.3.min'
],
function($, _, Backbone, marked, stylePageTemplate, config, jscssp, Pagedown, hljs, parseuri){
	var that = null;
	var StylePage = Backbone.View.extend({
		el: '.kalei-page',
		render: function () {
			that = this;

			//add more space at the bottom of the page to avoid scrolling to last node from menu
			//but we can think for something more smarter
			var pageHeight = document.body.offsetHeight;
			var lastEl = $('.kalei-page__item:last').height();
			console.log(lastEl);
			// $(that.el).css({ 'padding-bottom' : pageHeight });

			$('head').append('<link rel="stylesheet" href="' + config.css_path + '"" type="text/css" />');
			$('a.kalei-styleguide-menu-link').removeClass('active');
			if(window.location.hash === '') {
				$('.js-kalei-home').addClass('active');
			} else {
				$('[href="' + window.location.hash + '"]').addClass('active');
			}

			// $("head").find("link").attr("href", function (i, value) {
			//     if (value != config.css_path){
			//         $('head').append('<link rel="stylesheet" href="' + config.css_path + '"" type="text/css" />');
			//     }
			// });

			var styleUrl;
			var configDir;

			if(this.options.style === null) {
				this.options.style = config.css_path.substr(config.css_path.lastIndexOf('/')+1);
			}

			if(this.options.style.substr(0,1) === '/') {
				// non relative
				configDir = config.css_path.substr(0, config.css_path.lastIndexOf('/'));
				var pUrl = parseuri(configDir);
				styleUrl = pUrl.protocol + '://' + pUrl.host + (pUrl.port === '' ? '' : ':'+ pUrl) + this.options.style;
			} else {
				configDir = config.css_path.substr(0, config.css_path.lastIndexOf('/'));
				styleUrl = configDir + '/' + this.options.style;
			}

			console.log('try', configDir);
			console.log('try', styleUrl);
			require(['text!'+ styleUrl], function (stylesheet) {
				var parser = null;
				var regex = /(?:.*\/)(.*)\.(css|less|sass)$/gi;
				var result = regex.exec(styleUrl);
				//result[0] Original Input
				//result[1] Filename
				//result[2] Extension

				var page = {blocks:[]};

				switch (result[2]) {
					case 'css':
							parser = new jscssp();
							stylesheet = parser.parse(stylesheet, false, true);
							page = that.compute_css(stylesheet);
						break;
					case 'less':
							parser = new(less.Parser)({
								paths: [configDir + '/'], // Specify search paths for @import directives
							});
							parser.parse(stylesheet, function (err, tree) {
								stylesheet = tree;
							});
							page = that.compute_less(stylesheet);
						break;
					case 'sass':
						console.log("Error", "Unsupported style type.");
						/*require(['sass'], function (sass){
							//parse
						});*/
						break;
				}

				console.log((new Date()).getTime() + " bottom", page)

				$('.kalei-sheet-submenu').slideUp(200);
				var submenu = $('
');

				////////////NEEDS TO BE EXPORTED TO Menu.js
				_.each(page.blocks, function (block) {
					if (block.heading != "") {
						var li = $('
');
						li.append($('').text(block.heading));
						submenu.append(li);
					}

				});
				$('li:first-child', submenu).addClass('active');
				$('.kalei-sheet-submenu', $('[data-sheet="' + that.options.style + '"]')).html(submenu).slideDown(200);
				////////////NEEDS TO BE EXPORTED TO Menu.js

				$(that.el).html(_.template(stylePageTemplate, {_:_, page: page, config: config}));

				//Colour Coding in code Block
				Prism.highlightAll();

				//Fixed by pivanov
				//that.compute_css
				$(".kalei-sheet-submenu li").on('click', function(ev) {
					$('html, body').animate({
						scrollTop: $(".kalei-page__item h1:contains('"+$(ev.currentTarget).text()+"')," +
										 ".kalei-page__item h2:contains('"+$(ev.currentTarget).text()+"')").offset().top - 60
					}, 'slow');
					console.log($(ev.currentTarget).text());
				});

				$(window).scroll(function () {
					$(".kalei-page__item").each(function(){
						if ( that.is_on_screen($(this), 60) ) {
							$(".kalei-sheet-submenu li").removeClass('active');
							$(".kalei-sheet-submenu li:contains('" + $(this).find('h1').text() +"')," +
								 ".kalei-sheet-submenu li:contains('" + $(this).find('h2').text() +"')").addClass('active');
						}
					});
				});

				fixie.init();
			});
		},

		is_on_screen: function(el, offset) {

			var win = $(window);

			var viewport = {
				top : win.scrollTop()
			};

			viewport.bottom = viewport.top + win.height();

			var bounds = el.offset();

			return (!(viewport.top + offset < bounds.top || viewport.top > bounds.bottom));

		},

		compute_css: function(stylesheet) {
			console.log("compute_css()")
			var page = {
				blocks:[],
				css:"",
				stylesheets: []
			};
			console.log(stylesheet)
			_.each(stylesheet.cssRules, function(rule) {
				switch (rule.type) {
					case 1: //Standard rule?
						break;
					case 3: //Import Rule (@import)
						//we need to import jsscp doesnt compile imports
						stylesheet.deleteRule(rule);
						break;
					case 101: //Comment Block
						page.blocks = page.blocks.concat(that.parse_commentblock(rule.parsedCssText))
						break;
				}
			});

			page.css = stylesheet.cssText()

			var parser = new(less.Parser);
			var stylesheet
			page.css = ".kalei-page{" + page.css + "}"
			parser.parse(page.css, function (err, tree) {
				stylesheet = tree;
			});

			page.css = stylesheet.toCSS({ compress: true });
			return page;
		},

		compute_less: function(stylesheet) {
			console.log("compute_less()", stylesheet)
			var page = {
				blocks:[],
				css:"",
				stylesheets: []
			};

			_.each(stylesheet.rules, function(rule) {
				if (rule.silent != null){ //Comment block
					page.blocks = page.blocks.concat(that.parse_commentblock(rule.value))
					//page.blocks.push();
				} else if (rule.rules != null) { //Standard Rule

				} else if (rule.path != null) { //Import Rule
					// var previous_heading = page.blocks.length - 1;
					// if (typeof page.blocks[previous_heading].import_rule == "undefined") {
					//     page.blocks[previous_heading].import_rule = []
					// }
					// page.blocks[previous_heading].import_rule.push(rule.path)

				}
			});

			page.css = stylesheet.toCSS({ compress: true });
			page.css = ".kalei-page{" + page.css + "}";
			page.css = stylesheet.toCSS({ compress: true });
			return page;
		},

		parse_commentblock: function (comment_block_text) {
			//Remove /* & */
			comment_block_text = comment_block_text.replace(/(?:\/\*)|(?:\*\/)/gi, '');

			marked.setOptions(_.extend({ sanitize: false, gfm: true }, config.marked_options || {}));
			var lexedCommentblock = marked.lexer(comment_block_text);
			var lexerLinks = lexedCommentblock.links || {}; // lexer appends definition links to returned token object

			var return_val = [];
			var block_def = {
				content: [],
				heading: "",
			};
			var block = _.clone(block_def);

			_.each(lexedCommentblock, function (comment) {
				switch (comment.type) {
					case "code":
						//Push the code for an example
						block.content.push({
							type: 'html',
							text: '
' + comment.text + '
'
						});
						//Push the code section so marked can parse it as a
 block
						comment.text = comment.text.replace(/class=([""'])fixie\1|(?![""' ])fixie(?=[""' ])/g, "")
						block.content.push(comment);
						break;
					case "heading":
						if (block.heading != "") {  //Multiple headings in one comment block
													//We want to break them up
							//Parse the content blocks and return the HTML to display
							block.content.links = lexerLinks
							block.content = marked.parser(block.content)
							return_val.push(block);
							block = _.clone(block_def);
						}
						if (comment.depth <= 2) {
							block.heading = comment.text;
							block.content.push(comment);
						} else if (comment.depth == 3) { //Import statement title
							block.stylesheet = comment.text;
							//block.heading = "Stylesheets"
							//this is an import statement
							//if ($.inArray("Stylesheets", ))
							//console.log("else", comment)
						}
						break;
					default:
						//Push everything else
						block.content.push(comment);
						break;
				} //Switch
			});

			//Parse the content blocks and return the HTML to display
			block.content.links = lexerLinks
			block.content = marked.parser(block.content)

			return_val.push(block);
			return return_val;
		},

	});
	return StylePage;
});
<|endoftext|>


<commit_before>import React from "react";

/*
    This is a very basic graph that displays a text message
*/
class SimpleTextGraph extends React.Component {
    render() {
        const { text } = this.props;

        return (

                { text }

        );
    }
}

SimpleTextGraph.propTypes = {
  text: React.PropTypes.string
};

export default SimpleTextGraph;
<commit_msg>Updated SimpleTextGraph to wait for its data in the response property<commit_after>import React from "react";

import CircularProgress from "material-ui/CircularProgress";

/*
    This is a very basic graph that displays a text message
*/
class SimpleTextGraph extends React.Component {
    render() {
        const { response, queryConfiguration } = this.props;
        let body;

        if (response && !response.isFetching) {
            body = (

                    {response.results.length}

                    {queryConfiguration.title}

            );
        }
        else {

            body = (

                    <CircularProgress color="#eeeeee" /> Loading graph

            );
        }

        return (

                { body }

        );
    }
}

SimpleTextGraph.propTypes = {
  title: React.PropTypes.string,
  response: React.PropTypes.object
};

export default SimpleTextGraph;
<|endoftext|>


<commit_before>/* eslint-env mocha, jest */

import {
  parse,
  dayStart,
  dayEnd,
  addDays,
} from '../date';

const sampleUnixDate = 1511100000000;

it('should parse date correctly', () => {
  const expected = sampleUnixDate;
  const actual = parse(new Date(sampleUnixDate));
  expect(actual).toBe(expected);
});
it('should return day start correctly', () => {
  const expected = 1511037000000;
  const actual = dayStart(sampleUnixDate);
  expect(actual).toBe(expected);
});
it('should return day end correctly', () => {
  const expected = 1511123399999;
  const actual = dayEnd(sampleUnixDate);
  expect(actual).toBe(expected);
});
it('should add days to a date correctly', () => {
  const expected = 1511359200000;
  const actual = addDays(3, sampleUnixDate);
  expect(actual).toBe(expected);
});
<commit_msg>Fix a tiny issue in date module unit test<commit_after>/* eslint-env mocha, jest */

import {
  parse,
  dayStart,
  dayEnd,
  addDays,
} from '../date';

const sampleUnixDate = 1511100000000;

it('should parse date correctly', () => {
  const expected = sampleUnixDate;
  const actual = parse(new Date(sampleUnixDate));
  expect(actual).toBe(expected);
});
it('should return day start correctly', () => {
  const expected = (new Date(sampleUnixDate)).setHours(0, 0, 0, 0);
  const actual = dayStart(sampleUnixDate);
  expect(actual).toBe(expected);
});
it('should return day end correctly', () => {
  const expected = (new Date(sampleUnixDate)).setHours(23, 59, 59, 999);
  const actual = dayEnd(sampleUnixDate);
  expect(actual).toBe(expected);
});
it('should add days to a date correctly', () => {
  const expected = 1511359200000;
  const actual = addDays(3, sampleUnixDate);
  expect(actual).toBe(expected);
});
<|endoftext|>


<commit_before>/*
These are routes as defined in https://docs.google.com/document/d/1337m6i7Y0GPULKLsKpyHR4NRzRwhoxJnAZNnDFCigkc/edit#
Each route implementes a basic parameter/payload validation and a swagger API documentation description
*/
'use strict';

const Joi = require('joi'),
  handlers = require('./controllers/handler'),
  followHandlers = require('./controllers/followHandler'),
  slideCurrentlyEdited = require('./controllers/slideCurrentlyEditedHandler');

Joi.objectId = require('joi-objectid')(Joi);

const fanout = require('./controllers/fanout');

module.exports = function(server) {

  //Count activities of certain type, group by deck/slide ids and return max
  server.route({
    method: 'GET',
    path: '/activities/maxCount',
    handler: handlers.getActivitiesMaxCount,
    config: {
      validate: {
        query: {
          activity_type: [Joi.array().items(Joi.string()), Joi.string()],//an array or a single string
          all_revisions: Joi.string().description('Set to true to search for activities regardles of the content revision'),
          limit: Joi.string().description('If defined, return only this number of results'),
          content_kind: [Joi.array().items(Joi.string()), Joi.string()],//an array or a single string
        }
      },
      tags: ['api'],
      description: 'Count activities of certain type, grouped by deck/slide ids and return max results'
    }
  });

  //Get activities with content id id from database and return the entire list (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activities/{content_kind}/{id}',
    handler: handlers.getActivities,
    config: {
      validate: {
        params: {
          content_kind: Joi.string().valid('deck', 'slide', 'user'),
          id: Joi.string().description('The id of the deck/slide/user')
        },
        query: {
          metaonly: Joi.string().description('Set to true to return only metadata without the list of activities'),
          activity_type: [Joi.array().items(Joi.string()), Joi.string()],//an array or a single string
          include_subdecks_and_slides: Joi.string().description('Set to true to include activities of subdecks and slides'),
          all_revisions: Joi.string().description('Set to true to search for activities regardles of the content revision'),
          start: Joi.string().description('If defined, return activities starting from this index'),
          limit: Joi.string().description('If defined, return only this number of activities')
        }
      },
      tags: ['api'],
      description: 'Get a list of activities'
    }
  });

  //Create new activity (by payload) and return it (...). Validate payload
  server.route({
    method: 'POST',
    path: '/activity/new',
    handler: handlers.newActivity,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      pre: [
        { method: fanout.processActivity },
      ],
      validate: {
        payload: Joi.object().keys({
          activity_type: Joi.string(),
          user_id: Joi.string(),
          content_id: Joi.string(),
          content_kind: Joi.string().valid('deck', 'slide', 'group'),
          content_root_id: Joi.string(),
          content_name: Joi.string().allow(''),
          content_owner_id: Joi.string(),
          translation_info: Joi.object().keys({
            content_id: Joi.string(),
            language: Joi.string()
          }),
          share_info: Joi.object().keys({
            // postURI: Joi.string(),
            platform: Joi.string()
          }),
          comment_info: Joi.object().keys({
            comment_id: Joi.string(),
            text: Joi.string(),
            parent_comment_owner_id: Joi.string()
          }),
          use_info: Joi.object().keys({
            target_id: Joi.string(),
            target_name: Joi.string().allow('')
          }),
          exam_info: Joi.object().keys({
            score: Joi.number()
          }),
          fork_info: Joi.object().keys({
            content_id: Joi.string()
          }),
          delete_info: Joi.object().keys({
            content_id: Joi.string(),
            content_kind: Joi.string().valid('deck', 'slide', 'group'),
            content_name: Joi.string().allow('')
          }),
          move_info: Joi.object().keys({
            source_id: Joi.string(),
            target_id: Joi.string()
          }),
          prediction_info: Joi.object().keys({
            prediction_activity_type: Joi.string(),
            related_prediction_activity_id: Joi.string(),
            result: Joi.string(),
            accuracy: Joi.string(),
            no_of_users: Joi.string(),
            no_of_decks: Joi.string()
          }),
          react_type: Joi.string(),
          rate_type: Joi.string()
        }).requiredKeys('content_id', 'user_id', 'activity_type'),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown(),
      },
      tags: ['api'],
      description: 'Create a new activity'
    }
  });

  //Create new activities (by payload) and return them (...). Validate payload
  server.route({
    method: 'POST',
    path: '/activities/new',
    handler: handlers.newActivities,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      pre: [
        { method: fanout.processActivity },
      ],
      validate: {
        payload: Joi.array().items(
          Joi.object().keys({
            activity_type: Joi.string(),
            user_id: Joi.string(),
            content_id: Joi.string(),
            content_kind: Joi.string().valid('deck', 'slide', 'group'),
            content_root_id: Joi.string(),
            content_name: Joi.string().allow(''),
            content_owner_id: Joi.string(),
            translation_info: Joi.object().keys({
              content_id: Joi.string(),
              language: Joi.string()
            }),
            share_info: Joi.object().keys({
              // postURI: Joi.string(),
              platform: Joi.string()
            }),
            comment_info: Joi.object().keys({
              comment_id: Joi.string(),
              text: Joi.string(),
              parent_comment_owner_id: Joi.string()
            }),
            use_info: Joi.object().keys({
              target_id: Joi.string(),
              target_name: Joi.string()
            }),
            exam_info: Joi.object().keys({
              score: Joi.number()
            }),
            fork_info: Joi.object().keys({
              content_id: Joi.string()
            }),
            delete_info: Joi.object().keys({
              content_id: Joi.string(),
              content_kind: Joi.string().valid('deck', 'slide', 'group'),
              content_name: Joi.string().allow('')
            }),
            move_info: Joi.object().keys({
              source_id: Joi.string(),
              target_id: Joi.string()
            }),
            prediction_info: Joi.object().keys({
              prediction_activity_type: Joi.string(),
              related_prediction_activity_id: Joi.string(),
              result: Joi.string(),
              accuracy: Joi.string(),
              no_of_users: Joi.string(),
              no_of_decks: Joi.string()
            }),
            react_type: Joi.string(),
            rate_type: Joi.string()
          }).requiredKeys('content_id', 'user_id', 'activity_type')
        ),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown(),
      },
      tags: ['api'],
      description: 'Create new activities'
    }
  });

  //Delete activity with id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/activity/delete',
    handler: handlers.deleteActivity,
    config: {
      validate: {
        payload: {
          id: Joi.string()
        },
      },
      tags: ['api'],
      description: 'Delete an activity'
    }
  });

  //Delete activities with content id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/activities/delete',
    handler: handlers.deleteActivities,
    config: {
      validate: {
        payload: {
          content_kind: Joi.string().valid('deck', 'slide', 'group'),
          content_id: Joi.string(),
          activity_type: Joi.string(),
          user_id: Joi.string(),
          all_revisions:  Joi.boolean()
        },
      },
      tags: ['api'],
      description: 'Delete all activities for the specified content, type, user'
    }
  });

  //Get followings for a type (deck, playlist, user) and id
  server.route({
    method: 'GET',
    path: '/followings/{followed_type}/{followed_id}',
    handler: followHandlers.getFollowings,
    config: {
      validate: {
        params: {
          followed_type: Joi.string().valid('deck', 'slide', 'playlist', 'user'),
          followed_id: Joi.string().description('The id of the deck/slide/playlist/user')
        }
      },
      tags: ['api'],
      description: 'Get a list of followings'
    }
  });

  //Get followings for a user
  server.route({
    method: 'GET',
    path: '/followings/follower/{user_id}',
    handler: followHandlers.getFollowingsForFollower,
    config: {
      validate: {
        params: {
          user_id: Joi.string().description('The id of the follower - user')
        },
        query: {
          followed_type: Joi.string().description('Type of the following - "deck", "playlist", ...'),
          followed_id: Joi.string().description('Id of the following - deck_id, playlist_id, ...')
        }
      },
      tags: ['api'],
      description: 'Get a list of followings for a user (follower)'
    }
  });

  //Create new following (by payload) and return it (...). Validate payload
  server.route({
    method: 'POST',
    path: '/followings/new',
    handler: followHandlers.newFollowing,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      validate: {
        payload: Joi.object().keys({
          user_id: Joi.string(),
          followed_type: Joi.string(),
          followed_id: Joi.string(),
        }).requiredKeys('user_id', 'followed_type', 'followed_id'),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown(),
      },
      tags: ['api'],
      description: 'Create a new slide edition being performed.'
    }
  });

  //Delete following with id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/followings/delete',
    handler: followHandlers.deleteFollowing,
    config: {
      validate: {
        payload: {
          id: Joi.string()
        },
      },
      tags: ['api'],
      description: 'Delete a following'
    }
  });

  /*
        Slide Edition-related routes.
   */

  server.route({
    method: 'POST',
    path: '/slideCurrentlyEdited/new',
    handler: slideCurrentlyEdited.newSlideEdition,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      validate: {
        payload: Joi.object().keys({
          userId: Joi.string(),
          slideCurrentlyEdited: Joi.string(),
          timestamp: Joi.string(),
        }).requiredKeys('userId', 'slideCurrentlyEdited', 'timestamp'),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown()
      },
      tags: ['api'],
      description: 'Create a new "slide currently edited" instance.'
    }
  });

  server.route({
    method: 'DELETE',
    path: '/slideCurrentlyEdited/delete',
    handler: slideCurrentlyEdited.deleteSlideEdition,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      validate: {
        payload: Joi.object().keys({
          id: Joi.objectId(),
        }).requiredKeys('id'),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown()
      },
      tags: ['api'],
      description: 'Delete a slide currently edited instance'
    }

  });

  server.route({
    method: 'GET',
    path: '/slideCurrentlyEdited/slide/{slideId}',
    handler: slideCurrentlyEdited.getSlideEditionsBySlideId,
    config: {
      validate: {
        params: {
          slideId: Joi.string().description('The id of the slide to check if it is being edited.')
        }
      },
      tags: ['api'],
      description: 'Get a list of editions being performed to a slide.'
    }
  });
};
<commit_msg>Mistake fixed.<commit_after>/*
These are routes as defined in https://docs.google.com/document/d/1337m6i7Y0GPULKLsKpyHR4NRzRwhoxJnAZNnDFCigkc/edit#
Each route implementes a basic parameter/payload validation and a swagger API documentation description
*/
'use strict';

const Joi = require('joi'),
  handlers = require('./controllers/handler'),
  followHandlers = require('./controllers/followHandler'),
  slideCurrentlyEdited = require('./controllers/slideCurrentlyEditedHandler');

Joi.objectId = require('joi-objectid')(Joi);

const fanout = require('./controllers/fanout');

module.exports = function(server) {

  //Count activities of certain type, group by deck/slide ids and return max
  server.route({
    method: 'GET',
    path: '/activities/maxCount',
    handler: handlers.getActivitiesMaxCount,
    config: {
      validate: {
        query: {
          activity_type: [Joi.array().items(Joi.string()), Joi.string()],//an array or a single string
          all_revisions: Joi.string().description('Set to true to search for activities regardles of the content revision'),
          limit: Joi.string().description('If defined, return only this number of results'),
          content_kind: [Joi.array().items(Joi.string()), Joi.string()],//an array or a single string
        }
      },
      tags: ['api'],
      description: 'Count activities of certain type, grouped by deck/slide ids and return max results'
    }
  });

  //Get activities with content id id from database and return the entire list (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activities/{content_kind}/{id}',
    handler: handlers.getActivities,
    config: {
      validate: {
        params: {
          content_kind: Joi.string().valid('deck', 'slide', 'user'),
          id: Joi.string().description('The id of the deck/slide/user')
        },
        query: {
          metaonly: Joi.string().description('Set to true to return only metadata without the list of activities'),
          activity_type: [Joi.array().items(Joi.string()), Joi.string()],//an array or a single string
          include_subdecks_and_slides: Joi.string().description('Set to true to include activities of subdecks and slides'),
          all_revisions: Joi.string().description('Set to true to search for activities regardles of the content revision'),
          start: Joi.string().description('If defined, return activities starting from this index'),
          limit: Joi.string().description('If defined, return only this number of activities')
        }
      },
      tags: ['api'],
      description: 'Get a list of activities'
    }
  });

  //Create new activity (by payload) and return it (...). Validate payload
  server.route({
    method: 'POST',
    path: '/activity/new',
    handler: handlers.newActivity,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      pre: [
        { method: fanout.processActivity },
      ],
      validate: {
        payload: Joi.object().keys({
          activity_type: Joi.string(),
          user_id: Joi.string(),
          content_id: Joi.string(),
          content_kind: Joi.string().valid('deck', 'slide', 'group'),
          content_root_id: Joi.string(),
          content_name: Joi.string().allow(''),
          content_owner_id: Joi.string(),
          translation_info: Joi.object().keys({
            content_id: Joi.string(),
            language: Joi.string()
          }),
          share_info: Joi.object().keys({
            // postURI: Joi.string(),
            platform: Joi.string()
          }),
          comment_info: Joi.object().keys({
            comment_id: Joi.string(),
            text: Joi.string(),
            parent_comment_owner_id: Joi.string()
          }),
          use_info: Joi.object().keys({
            target_id: Joi.string(),
            target_name: Joi.string().allow('')
          }),
          exam_info: Joi.object().keys({
            score: Joi.number()
          }),
          fork_info: Joi.object().keys({
            content_id: Joi.string()
          }),
          delete_info: Joi.object().keys({
            content_id: Joi.string(),
            content_kind: Joi.string().valid('deck', 'slide', 'group'),
            content_name: Joi.string().allow('')
          }),
          move_info: Joi.object().keys({
            source_id: Joi.string(),
            target_id: Joi.string()
          }),
          prediction_info: Joi.object().keys({
            prediction_activity_type: Joi.string(),
            related_prediction_activity_id: Joi.string(),
            result: Joi.string(),
            accuracy: Joi.string(),
            no_of_users: Joi.string(),
            no_of_decks: Joi.string()
          }),
          react_type: Joi.string(),
          rate_type: Joi.string()
        }).requiredKeys('content_id', 'user_id', 'activity_type'),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown(),
      },
      tags: ['api'],
      description: 'Create a new activity'
    }
  });

  //Create new activities (by payload) and return them (...). Validate payload
  server.route({
    method: 'POST',
    path: '/activities/new',
    handler: handlers.newActivities,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      pre: [
        { method: fanout.processActivity },
      ],
      validate: {
        payload: Joi.array().items(
          Joi.object().keys({
            activity_type: Joi.string(),
            user_id: Joi.string(),
            content_id: Joi.string(),
            content_kind: Joi.string().valid('deck', 'slide', 'group'),
            content_root_id: Joi.string(),
            content_name: Joi.string().allow(''),
            content_owner_id: Joi.string(),
            translation_info: Joi.object().keys({
              content_id: Joi.string(),
              language: Joi.string()
            }),
            share_info: Joi.object().keys({
              // postURI: Joi.string(),
              platform: Joi.string()
            }),
            comment_info: Joi.object().keys({
              comment_id: Joi.string(),
              text: Joi.string(),
              parent_comment_owner_id: Joi.string()
            }),
            use_info: Joi.object().keys({
              target_id: Joi.string(),
              target_name: Joi.string()
            }),
            exam_info: Joi.object().keys({
              score: Joi.number()
            }),
            fork_info: Joi.object().keys({
              content_id: Joi.string()
            }),
            delete_info: Joi.object().keys({
              content_id: Joi.string(),
              content_kind: Joi.string().valid('deck', 'slide', 'group'),
              content_name: Joi.string().allow('')
            }),
            move_info: Joi.object().keys({
              source_id: Joi.string(),
              target_id: Joi.string()
            }),
            prediction_info: Joi.object().keys({
              prediction_activity_type: Joi.string(),
              related_prediction_activity_id: Joi.string(),
              result: Joi.string(),
              accuracy: Joi.string(),
              no_of_users: Joi.string(),
              no_of_decks: Joi.string()
            }),
            react_type: Joi.string(),
            rate_type: Joi.string()
          }).requiredKeys('content_id', 'user_id', 'activity_type')
        ),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown(),
      },
      tags: ['api'],
      description: 'Create new activities'
    }
  });

  //Delete activity with id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/activity/delete',
    handler: handlers.deleteActivity,
    config: {
      validate: {
        payload: {
          id: Joi.string()
        },
      },
      tags: ['api'],
      description: 'Delete an activity'
    }
  });

  //Delete activities with content id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/activities/delete',
    handler: handlers.deleteActivities,
    config: {
      validate: {
        payload: {
          content_kind: Joi.string().valid('deck', 'slide', 'group'),
          content_id: Joi.string(),
          activity_type: Joi.string(),
          user_id: Joi.string(),
          all_revisions:  Joi.boolean()
        },
      },
      tags: ['api'],
      description: 'Delete all activities for the specified content, type, user'
    }
  });

  //Get followings for a type (deck, playlist, user) and id
  server.route({
    method: 'GET',
    path: '/followings/{followed_type}/{followed_id}',
    handler: followHandlers.getFollowings,
    config: {
      validate: {
        params: {
          followed_type: Joi.string().valid('deck', 'slide', 'playlist', 'user'),
          followed_id: Joi.string().description('The id of the deck/slide/playlist/user')
        }
      },
      tags: ['api'],
      description: 'Get a list of followings'
    }
  });

  //Get followings for a user
  server.route({
    method: 'GET',
    path: '/followings/follower/{user_id}',
    handler: followHandlers.getFollowingsForFollower,
    config: {
      validate: {
        params: {
          user_id: Joi.string().description('The id of the follower - user')
        },
        query: {
          followed_type: Joi.string().description('Type of the following - "deck", "playlist", ...'),
          followed_id: Joi.string().description('Id of the following - deck_id, playlist_id, ...')
        }
      },
      tags: ['api'],
      description: 'Get a list of followings for a user (follower)'
    }
  });

  //Create new following (by payload) and return it (...). Validate payload
  server.route({
    method: 'POST',
    path: '/followings/new',
    handler: followHandlers.newFollowing,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      validate: {
        payload: Joi.object().keys({
          user_id: Joi.string(),
          followed_type: Joi.string(),
          followed_id: Joi.string(),
        }).requiredKeys('user_id', 'followed_type', 'followed_id'),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown(),
      },
      tags: ['api'],
      description: 'Create a new slide following.'
    }
  });

  //Delete following with id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/followings/delete',
    handler: followHandlers.deleteFollowing,
    config: {
      validate: {
        payload: {
          id: Joi.string()
        },
      },
      tags: ['api'],
      description: 'Delete a following'
    }
  });

  /*
        Slide Edition-related routes.
   */

  server.route({
    method: 'POST',
    path: '/slideCurrentlyEdited/new',
    handler: slideCurrentlyEdited.newSlideEdition,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      validate: {
        payload: Joi.object().keys({
          userId: Joi.string(),
          slideCurrentlyEdited: Joi.string(),
          timestamp: Joi.string(),
        }).requiredKeys('userId', 'slideCurrentlyEdited', 'timestamp'),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown()
      },
      tags: ['api'],
      description: 'Create a new "slide currently edited" instance.'
    }
  });

  server.route({
    method: 'DELETE',
    path: '/slideCurrentlyEdited/delete',
    handler: slideCurrentlyEdited.deleteSlideEdition,
    config: {
      auth: {
        mode: 'optional',
        strategy: 'jwt'
      },
      validate: {
        payload: Joi.object().keys({
          id: Joi.objectId(),
        }).requiredKeys('id'),
        headers: Joi.object({
          '----jwt----': Joi.string().description('JWT header provided by /login')
        }).unknown()
      },
      tags: ['api'],
      description: 'Delete a slide currently edited instance'
    }

  });

  server.route({
    method: 'GET',
    path: '/slideCurrentlyEdited/slide/{slideId}',
    handler: slideCurrentlyEdited.getSlideEditionsBySlideId,
    config: {
      validate: {
        params: {
          slideId: Joi.string().description('The id of the slide to check if it is being edited.')
        }
      },
      tags: ['api'],
      description: 'Get a list of editions being performed to a slide.'
    }
  });
};
<|endoftext|>


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

import '../Login.scss';

class Login extends React.Component {
  constructor () {
    super();

    this.handleUserLinkClick = this.handleUserLinkClick.bind(this);
  }

  componentWillMount () {
    this.props.retrieveUserFromSession();
  }

  handleUserLinkClick (e) {
    e.preventDefault();
    const { user } = this.props;
    const linkMethod = user.id ? this.props.logout : this.props.login;
    linkMethod();
  }

  getUserLink () {
    const { user } = this.props;
    const linkText = user.id ? 'Kirjaudu ulos' : 'Kirjaudu sisään';

    return (
      {linkText}
    );
  }

  render () {
    return (

        {this.getUserLink()}

    );
  }
}

Login.propTypes = {
  login: PropTypes.func.isRequired,
  logout: PropTypes.func.isRequired,
  retrieveUserFromSession: PropTypes.func.isRequired,
  user: PropTypes.object.isRequired
};

export default Login;
<commit_msg>Display users firstName on login-component<commit_after>import React, { PropTypes } from 'react';

import '../Login.scss';

class Login extends React.Component {
  constructor () {
    super();

    this.handleUserLinkClick = this.handleUserLinkClick.bind(this);
  }

  componentWillMount () {
    this.props.retrieveUserFromSession();
  }

  handleUserLinkClick (e) {
    e.preventDefault();
    const { user } = this.props;
    const linkMethod = user.id ? this.props.logout : this.props.login;
    linkMethod();
  }

  getUserLink () {
    const { user } = this.props;
    const linkText = user.id ? `${user.firstName}, Kirjaudu ulos` : 'Kirjaudu sisään';

    return (
      {linkText}
    );
  }

  render () {
    return (

        {this.getUserLink()}

    );
  }
}

Login.propTypes = {
  login: PropTypes.func.isRequired,
  logout: PropTypes.func.isRequired,
  retrieveUserFromSession: PropTypes.func.isRequired,
  user: PropTypes.object.isRequired
};

export default Login;
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.SceneExporter2 = function () {};

THREE.SceneExporter2.prototype = {

	constructor: THREE.SceneExporter2,

	parse: function ( scene ) {

		var output = {
			metadata: {
				version: 4.0,
				type: 'scene',
				generator: 'SceneExporter'
			}
		};

		console.log( scene );

		//

		var geometries = {};
		var geometryExporter = new THREE.GeometryExporter();

		var parseGeometry = function ( geometry ) {

			if ( geometries[ geometry.id ] === undefined ) {

				if ( output.geometries === undefined ) {

					output.geometries = [];

				}

				geometries[ geometry.id ] = output.geometries.length;

				output.geometries.push( geometryExporter.parse( geometry ) );

			}

			return geometries[ geometry.id ];

		};

		/*
		var materials = {};
		var materialExporter = new THREE.MaterialExporter();

		var parseMaterial = function ( material ) {

		};
		*/

		var parseObject = function ( object ) {

			var data = { name: object.name };

			if ( object instanceof THREE.PerspectiveCamera ) {

				data.type = 'PerspectiveCamera';
				data.fov = object.fov;
				data.aspect = object.aspect;
				data.near = object.near;
				data.far = object.far;
				data.position = object.position.toArray();
				data.rotation = object.rotation.toArray();

			} else if ( object instanceof THREE.OrthographicCamera ) {

				data.type = 'OrthographicCamera';
				data.left = object.left;
				data.right = object.right;
				data.top = object.top;
				data.bottom = object.bottom;
				data.near = object.near;
				data.far = object.far;
				data.position = object.position.toArray();
				data.rotation = object.rotation.toArray();

			} else if ( object instanceof THREE.AmbientLight ) {

				data.type = 'AmbientLight';
				data.color = object.color.getHex();
				data.intensity = object.intensity;

			} else if ( object instanceof THREE.DirectionalLight ) {

				data.type = 'DirectionalLight';
				data.color = object.color.getHex();
				data.intensity = object.intensity;
				data.position = object.position.toArray();

			} else if ( object instanceof THREE.PointLight ) {

				data.type = 'PointLight';
				data.color = object.color.getHex();
				data.intensity = object.intensity;
				data.position = object.position.toArray();

			} else if ( object instanceof THREE.SpotLight ) {

				data.type = 'SpotLight';
				data.color = object.color.getHex();
				data.intensity = object.intensity;
				data.position = object.position.toArray();

			} else if ( object instanceof THREE.HemisphereLight ) {

				data.type = 'HemisphereLight';
				data.color = object.color.getHex();

			} else if ( object instanceof THREE.Mesh ) {

				data.type = 'Mesh';
				data.position = object.position.toArray();
				data.rotation = object.rotation.toArray();
				data.scale = object.scale.toArray();
				data.geometry = parseGeometry( object.geometry );

			} else {

				data.type = 'Object3D';
				data.position = object.position.toArray();
				data.rotation = object.rotation.toArray();
				data.scale = object.scale.toArray();

			}

			// parse children

			if ( object.children.length > 0 ) {

				data.children = [];

				for ( var i = 0; i < object.children.length; i ++ ) {

					data.children.push( parseObject( object.children[ i ] ) );

				}

			}

			return data;

		}

		output.scene = parseObject( scene ).children;

		return output;

	}

}
<commit_msg>SceneExporter2 exporting userData.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 */

THREE.SceneExporter2 = function () {};

THREE.SceneExporter2.prototype = {

	constructor: THREE.SceneExporter2,

	parse: function ( scene ) {

		var output = {
			metadata: {
				version: 4.0,
				type: 'scene',
				generator: 'SceneExporter'
			}
		};

		console.log( scene );

		//

		var geometries = {};
		var geometryExporter = new THREE.GeometryExporter();

		var parseGeometry = function ( geometry ) {

			if ( geometries[ geometry.id ] === undefined ) {

				if ( output.geometries === undefined ) {

					output.geometries = [];

				}

				geometries[ geometry.id ] = output.geometries.length;

				output.geometries.push( geometryExporter.parse( geometry ) );

			}

			return geometries[ geometry.id ];

		};

		/*
		var materials = {};
		var materialExporter = new THREE.MaterialExporter();

		var parseMaterial = function ( material ) {

		};
		*/

		var parseObject = function ( object ) {

			var data = { name: object.name };

			if ( object instanceof THREE.PerspectiveCamera ) {

				data.type = 'PerspectiveCamera';
				data.fov = object.fov;
				data.aspect = object.aspect;
				data.near = object.near;
				data.far = object.far;
				data.position = object.position.toArray();
				data.rotation = object.rotation.toArray();

			} else if ( object instanceof THREE.OrthographicCamera ) {

				data.type = 'OrthographicCamera';
				data.left = object.left;
				data.right = object.right;
				data.top = object.top;
				data.bottom = object.bottom;
				data.near = object.near;
				data.far = object.far;
				data.position = object.position.toArray();
				data.rotation = object.rotation.toArray();

			} else if ( object instanceof THREE.AmbientLight ) {

				data.type = 'AmbientLight';
				data.color = object.color.getHex();
				data.intensity = object.intensity;

			} else if ( object instanceof THREE.DirectionalLight ) {

				data.type = 'DirectionalLight';
				data.color = object.color.getHex();
				data.intensity = object.intensity;
				data.position = object.position.toArray();

			} else if ( object instanceof THREE.PointLight ) {

				data.type = 'PointLight';
				data.color = object.color.getHex();
				data.intensity = object.intensity;
				data.position = object.position.toArray();

			} else if ( object instanceof THREE.SpotLight ) {

				data.type = 'SpotLight';
				data.color = object.color.getHex();
				data.intensity = object.intensity;
				data.position = object.position.toArray();

			} else if ( object instanceof THREE.HemisphereLight ) {

				data.type = 'HemisphereLight';
				data.color = object.color.getHex();

			} else if ( object instanceof THREE.Mesh ) {

				data.type = 'Mesh';
				data.position = object.position.toArray();
				data.rotation = object.rotation.toArray();
				data.scale = object.scale.toArray();
				data.geometry = parseGeometry( object.geometry );

			} else {

				data.type = 'Object3D';
				data.position = object.position.toArray();
				data.rotation = object.rotation.toArray();
				data.scale = object.scale.toArray();

			}

			data.userData = object.userData;

			// parse children

			if ( object.children.length > 0 ) {

				data.children = [];

				for ( var i = 0; i < object.children.length; i ++ ) {

					data.children.push( parseObject( object.children[ i ] ) );

				}

			}

			return data;

		}

		output.scene = parseObject( scene ).children;

		return output;

	}

}
<|endoftext|>


<commit_before>var DbEditor = require('./DbManipulator');
var Schema = require('./Schema');

var getArticle = function(id, callback){
  var q = 'SELECT ' + Schema.Article.column.id + ', ' + Schema.User.column.username + ' as author ,' + Schema.Article.column.content + ', ' + Schema.Article.column.time + ', ' + Schema.Article.column.title + ', ' + Schema.ArticleImage.column.url + ' ' +
          'FROM ' + Schema.Article.table + ', ' + Schema.User.table + ' ' +
          'WHERE ' + Schema.Article.column.id + '=' + id + ' AND ' + Schema.Article.column.authorId + '=' + Schema.User.column.commentId + ';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
  // DbEditor.query(Schema.Article.table, ['*'], [Schema.Article.column.id+'='], [id], callback);
};

var getLatestArticles = function(callback){
  var q = 'SELECT articleId, username as author, content, createTime, title, authorId' + ' ' +
          'FROM ' + Schema.Article.table + ', ' + Schema.User.table + ' ' +
          'WHERE ' + Schema.Article.table + '.' + Schema.Article.column.authorId + '=' + Schema.User.table + '.' + Schema.User.column.id + ' ' +
          'ORDER BY ' + Schema.Article.column.time + ' DESC;';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getLove = function(articleId, callback){
  var q = 'SELECT ' + Schema.Love.table + '.' + Schema.Love.column.uid + ', '+ Schema.User.column.fname + ', ' + Schema.User.column.lname + ' ' +
          'FROM ' + Schema.User.table + ', ' + Schema.Love.table + ' ' +
          'WHERE ' + Schema.Love.table + '.' + Schema.Love.column.aid + '=' + articleId + ' AND ' + Schema.Love.table + '.' + Schema.Love.column.uid + '=' + Schema.User.table +'.' + Schema.User.column.id +';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
  // DbEditor.query(Schema.Love.table, [Schema.Love.column.uid, 'count(' + Schema.Love.column.aid +') as number'], [Schema.Love.column.aid+'='], [articleId], callback);
};

var postLove = function(userId, articleId, callback){
  var q = 'INSERT INTO ' + Schema.Love.table + ' VALUES (' + articleId + ', ' + userId + ');';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var deleteLove = function(userId, articleId, callback){
  var q = 'DELETE FROM ' + Schema.Love.table +
          ' WHERE ' + Schema.Love.column.uid + '=' + userId + ' AND ' + Schema.Love.column.aid + '=' + articleId + ';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var postArticle = function(newArticleId ,userId, title, content, callback){
  var q = 'INSERT INTO ' + Schema.Article.table +
          ' VALUES ('+ newArticleId + ', ' + userId + ', ' + title + ', ' + content + ', NOW() );';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getComments = function(articleId, callback){
  var q = 'SELECT ' + Schema.Comment.column.commentId + ', ' + Schema.User.column.fname + ', ' + Schema.User.column.lname + ', ' + Schema.Comment.column.comment + ', ' + Schema.Comment.column.time + ' ' +
          'FROM ' + Schema.Comment.table + ', ' + Schema.User.table + ' ' +
          'WHERE ' + Schema.Comment.column.aid + '=' + articleId + ' AND ' + Schema.Comment.column.commentorId + '=' + Schema.User.column.id + ';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
  // DbEditor.query(Schema.Comment.table, [Schema.Comment.column.commentId, Schema.Comment.column.commentorId, Schema.Comment.column.comment, 'date_format(' + Schema.Comment.column.time + ', \'%e-%c-%Y %T\') as createTime'], [Schema.Comment.column.aid+'='], [articleId], callback);
};

var postComment = function(newCommentId, articleId, commentorId, comment, callback){
  var q = 'INSERT INTO ' + Schema.Comment.table + ' ' +
          'VALUES (' + newCommentId + ', ' + articleId + ', ' + commentorId + ', ' + toString(comment) + ', NOW());';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getUserInfo = function(username, callback){
  var q = 'SELECT ' + Schema.User.column.id + ', ' + Schema.User.column.username + ', ' + Schema.User.column.fname + ', ' + Schema.User.column.lname + ' ' +
          'FROM ' + Schema.User.table + ' '+
          'WHERE ' + Schema.User.column.username + '=' + toString(username) + ';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var postArticleImage = function(articleId, imageURL, callback){
  var q = 'INSERT INTO ' + Schema.ArticleImage.table + ' ' +
          'VAULES (' + articleId + ', ' + toString(imageURL) + ');';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var postTagFromArticle = function(articleId, tags, callback){
  var q = 'INSERT INTO ' + Schema.Tag.table + ' ' +
          'VALUES ';
  for(var i = 0; i < tags.length; i++) {
    q += '( ' + toString(tags[i]) + ', ' + articleId + ')';
    if(i < tags.length - 1) q += ',';
    else q += ';';
  }
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getFollowingsArticle = function(userId, callback){
  var q = 'SELECT tbl_articles.articleId, tbl_users.username, tbl_users.firstName, tbl_users.lastName, tbl_articles.content, tbl_articles.title, tbl_articles.createTime ' +
          'FROM tbl_articles, tbl_users, tbl_follows ' +
          'WHERE tbl_follows.uid=' + userId + ' AND tbl_follows.following=tbl_articles.authorId AND tbl_follows.following=tbl_users.uid';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getFollowings = function(userId, callback){
  var q = 'SELECT tbl_users.uid, tbl_users.username, tbl_users.firstName, tbl_users.lastName ' +
          'FROM tbl_users, tbl_follows ' +
          'WHERE tbl_follows.uid=' + userId + ' AND tbl_follows.following=tbl_users.uid;';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var postFollowing = function(userId, followingId, callback){
  var q = 'INSERT INTO tbl_follows ' +
          'VALUES(' + userId + ', ' + followingId + ');';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

function toString(s){
  return '\''+s+'\'';
}

module.exports = {
  getArticle: getArticle,
  getLatestArticle: getLatestArticles,
  getLovesInArticle: getLove,
  postLoveToArticle: postLove,
  removeLoveFromArticle: deleteLove,
  postArticle: postArticle,
  getCommentsOfArticle: getComments,
  postCommentsToArticle: postComment,
  getUserInfo: getUserInfo,
  getFollowingsArticle: getFollowingsArticle,
  getFollowings: getFollowings,
  postFollowing: postFollowing
};
<commit_msg>modify getFollowingsArticle to have same keys as getLatestArticle<commit_after>var DbEditor = require('./DbManipulator');
var Schema = require('./Schema');

var getArticle = function(id, callback){
  var q = 'SELECT ' + Schema.Article.column.id + ', ' + Schema.User.column.username + ' as author ,' + Schema.Article.column.content + ', ' + Schema.Article.column.time + ', ' + Schema.Article.column.title + ', ' + Schema.ArticleImage.column.url + ' ' +
          'FROM ' + Schema.Article.table + ', ' + Schema.User.table + ' ' +
          'WHERE ' + Schema.Article.column.id + '=' + id + ' AND ' + Schema.Article.column.authorId + '=' + Schema.User.column.commentId + ';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
  // DbEditor.query(Schema.Article.table, ['*'], [Schema.Article.column.id+'='], [id], callback);
};

var getLatestArticles = function(callback){
  var q = 'SELECT articleId, username as author, content, createTime, title, authorId' + ' ' +
          'FROM ' + Schema.Article.table + ', ' + Schema.User.table + ' ' +
          'WHERE ' + Schema.Article.table + '.' + Schema.Article.column.authorId + '=' + Schema.User.table + '.' + Schema.User.column.id + ' ' +
          'ORDER BY ' + Schema.Article.column.time + ' DESC;';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getLove = function(articleId, callback){
  var q = 'SELECT ' + Schema.Love.table + '.' + Schema.Love.column.uid + ', '+ Schema.User.column.fname + ', ' + Schema.User.column.lname + ' ' +
          'FROM ' + Schema.User.table + ', ' + Schema.Love.table + ' ' +
          'WHERE ' + Schema.Love.table + '.' + Schema.Love.column.aid + '=' + articleId + ' AND ' + Schema.Love.table + '.' + Schema.Love.column.uid + '=' + Schema.User.table +'.' + Schema.User.column.id +';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
  // DbEditor.query(Schema.Love.table, [Schema.Love.column.uid, 'count(' + Schema.Love.column.aid +') as number'], [Schema.Love.column.aid+'='], [articleId], callback);
};

var postLove = function(userId, articleId, callback){
  var q = 'INSERT INTO ' + Schema.Love.table + ' VALUES (' + articleId + ', ' + userId + ');';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var deleteLove = function(userId, articleId, callback){
  var q = 'DELETE FROM ' + Schema.Love.table +
          ' WHERE ' + Schema.Love.column.uid + '=' + userId + ' AND ' + Schema.Love.column.aid + '=' + articleId + ';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var postArticle = function(newArticleId ,userId, title, content, callback){
  var q = 'INSERT INTO ' + Schema.Article.table +
          ' VALUES ('+ newArticleId + ', ' + userId + ', ' + title + ', ' + content + ', NOW() );';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getComments = function(articleId, callback){
  var q = 'SELECT ' + Schema.Comment.column.commentId + ', ' + Schema.User.column.fname + ', ' + Schema.User.column.lname + ', ' + Schema.Comment.column.comment + ', ' + Schema.Comment.column.time + ' ' +
          'FROM ' + Schema.Comment.table + ', ' + Schema.User.table + ' ' +
          'WHERE ' + Schema.Comment.column.aid + '=' + articleId + ' AND ' + Schema.Comment.column.commentorId + '=' + Schema.User.column.id + ';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
  // DbEditor.query(Schema.Comment.table, [Schema.Comment.column.commentId, Schema.Comment.column.commentorId, Schema.Comment.column.comment, 'date_format(' + Schema.Comment.column.time + ', \'%e-%c-%Y %T\') as createTime'], [Schema.Comment.column.aid+'='], [articleId], callback);
};

var postComment = function(newCommentId, articleId, commentorId, comment, callback){
  var q = 'INSERT INTO ' + Schema.Comment.table + ' ' +
          'VALUES (' + newCommentId + ', ' + articleId + ', ' + commentorId + ', ' + toString(comment) + ', NOW());';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getUserInfo = function(username, callback){
  var q = 'SELECT ' + Schema.User.column.id + ', ' + Schema.User.column.username + ', ' + Schema.User.column.fname + ', ' + Schema.User.column.lname + ' ' +
          'FROM ' + Schema.User.table + ' '+
          'WHERE ' + Schema.User.column.username + '=' + toString(username) + ';';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var postArticleImage = function(articleId, imageURL, callback){
  var q = 'INSERT INTO ' + Schema.ArticleImage.table + ' ' +
          'VAULES (' + articleId + ', ' + toString(imageURL) + ');';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var postTagFromArticle = function(articleId, tags, callback){
  var q = 'INSERT INTO ' + Schema.Tag.table + ' ' +
          'VALUES ';
  for(var i = 0; i < tags.length; i++) {
    q += '( ' + toString(tags[i]) + ', ' + articleId + ')';
    if(i < tags.length - 1) q += ',';
    else q += ';';
  }
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getFollowingsArticle = function(userId, callback){
  var q = 'SELECT tbl_articles.articleId, tbl_users.username as author, tbl_users.firstName, tbl_users.lastName, tbl_articles.content, tbl_articles.title, tbl_articles.createTime, tbl_articles.authorId ' +
          'FROM tbl_articles, tbl_users, tbl_follows ' +
          'WHERE tbl_follows.uid=' + userId + ' AND tbl_follows.following=tbl_articles.authorId AND tbl_follows.following=tbl_users.uid';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var getFollowings = function(userId, callback){
  var q = 'SELECT tbl_users.uid, tbl_users.username, tbl_users.firstName, tbl_users.lastName ' +
          'FROM tbl_users, tbl_follows ' +
          'WHERE tbl_follows.uid=' + userId + ' AND tbl_follows.following=tbl_users.uid;';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

var postFollowing = function(userId, followingId, callback){
  var q = 'INSERT INTO tbl_follows ' +
          'VALUES(' + userId + ', ' + followingId + ');';
  console.log(q);
  DbEditor.rawQuery(q, callback);
};

function toString(s){
  return '\''+s+'\'';
}

module.exports = {
  getArticle: getArticle,
  getLatestArticle: getLatestArticles,
  getLovesInArticle: getLove,
  postLoveToArticle: postLove,
  removeLoveFromArticle: deleteLove,
  postArticle: postArticle,
  getCommentsOfArticle: getComments,
  postCommentsToArticle: postComment,
  getUserInfo: getUserInfo,
  getFollowingsArticle: getFollowingsArticle,
  getFollowings: getFollowings,
  postFollowing: postFollowing
};
<|endoftext|>


<commit_before>import React from 'react';
import pluralize from 'pluralize';
import { IndexLink } from 'react-router';
import { Menu, MenuItem, Button } from 'react-toolbox';
import AppBar from 'react-toolbox/lib/app_bar';
import FindBar from '../FindBar/FindBar';
import styles from './AppHeader.css';

export default class AppHeader extends React.Component {

  // props: {
  //   // collections: React.,
  //   // commands,
  //   // defaultCommands
  // }

  state = {
    createMenuActive: false
  }

  handleCreatePostClick = collectionName => {
    const { onCreateEntryClick } = this.props;
    if (onCreateEntryClick) {
      onCreateEntryClick(collectionName);
    }
  }

  onCreateButtonClick = () => {
    this.setState({
      createMenuActive: true
    });
  }

  onCreateMenuHide = () => {
    this.setState({
      createMenuActive: false
    });
  }

  render() {
    const { collections, commands, defaultCommands, runCommand } = this.props;
    const { createMenuActive } = this.state;

    return (
      <AppBar
          fixed
          theme={styles}
      >
        <IndexLink to="/">
          Dashboard
        </IndexLink>
        <FindBar
            commands={commands}
            defaultCommands={defaultCommands}
            runCommand={runCommand}
        />
        <Button
            className={styles.createBtn}
            icon='add'
            floating
            accent
            onClick={this.onCreateButtonClick}
        >
          <Menu
              active={createMenuActive}
              position="topRight"
              onHide={this.onCreateMenuHide}
          >
            {
              collections.valueSeq().map(collection =>
                <MenuItem
                    key={collection.get('name')}
                    value={collection.get('name')}
                    onClick={this.handleCreatePostClick.bind(this, collection.get('name'))}
                    caption={pluralize(collection.get('label'), 1)}
                />
              )
            }
          </Menu>
        </Button>
      </AppBar>
    );
  }
}
<commit_msg>Better names for methods. Fixes ESLint warnings.<commit_after>import React from 'react';
import pluralize from 'pluralize';
import { IndexLink } from 'react-router';
import { Menu, MenuItem, Button, IconButton } from 'react-toolbox';
import AppBar from 'react-toolbox/lib/app_bar';
import FindBar from '../FindBar/FindBar';
import styles from './AppHeader.css';

export default class AppHeader extends React.Component {

  state = {
    createMenuActive: false
  }

  handleCreatePostClick = collectionName => {
    const { onCreateEntryClick } = this.props;
    if (onCreateEntryClick) {
      onCreateEntryClick(collectionName);
    }
  }

  handleCreateButtonClick = () => {
    this.setState({
      createMenuActive: true
    });
  }

  handleCreateMenuHide = () => {
    this.setState({
      createMenuActive: false
    });
  }

  render() {
    const {
      collections,
      commands,
      defaultCommands,
      runCommand,
      toggleNavDrawer
    } = this.props;
    const { createMenuActive } = this.state;

    return (
      <AppBar
          fixed
          theme={styles}
      >
        <IconButton
            icon="menu"
            inverse
            onClick={toggleNavDrawer}
        />
        <IndexLink to="/">
          Dashboard
        </IndexLink>
        <FindBar
            commands={commands}
            defaultCommands={defaultCommands}
            runCommand={runCommand}
        />
        <Button
            className={styles.createBtn}
            icon='add'
            floating
            accent
            onClick={this.handleCreateButtonClick}
        >
          <Menu
              active={createMenuActive}
              position="topRight"
              onHide={this.handleCreateMenuHide}
          >
            {
              collections.valueSeq().map(collection =>
                <MenuItem
                    key={collection.get('name')}
                    value={collection.get('name')}
                    onClick={this.handleCreatePostClick.bind(this, collection.get('name'))}
                    caption={pluralize(collection.get('label'), 1)}
                />
              )
            }
          </Menu>
        </Button>

      </AppBar>
    );
  }
}
<|endoftext|>