<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

/**
 * Project Schema
 */
var ProjectSchema = new Schema({
  code        : {type: String, default: ''},
  name: {
    type: String,
    default: '',
    required: 'Please fill the project name',
    trim: true
  },
  short: {
    type: String,
    default: '',
    required: 'Please complete the project short description',
    trim: true
  },
  description: {
    type: String,
    default: '',
    required: 'Please complete the project description',
    trim: true
  },
  short       : {type: String, default: ''},
  github: {
    type: String,
    default: '',
    trim: true
  },
  isPublished : {type: Boolean, default: false},
  created: {
    type: Date,
    default: Date.now
  },
  createdBy: {
    type: 'ObjectId',
    ref: 'User',
    default: null
  },
  updated: {
    type: Date,
    default: Date.now
  },
  updatedBy: {
    type: 'ObjectId',
    ref: 'User',
    default: null
  },
  program: {
    type: Schema.ObjectId,
    ref: 'Program',
    required: 'Please select a program'
  },
  user: {
    type: Schema.ObjectId,
    ref: 'User'
  },
  tags: [String]
});

ProjectSchema.statics.findUniqueCode = function (title, suffix, callback) {
  var _this = this;
  var possible = 'prj-' + (title.toLowerCase().replace(/\W/g,'-').replace(/-+/,'-')) + (suffix || '');

  _this.findOne({
    code: possible
  }, function (err, user) {
    if (!err) {
      if (!user) {
        callback(possible);
      } else {
        return _this.findUniqueCode(title, (suffix || 0) + 1, callback);
      }
    } else {
      callback(null);
    }
  });
};

mongoose.model('Project', ProjectSchema);
<commit_msg>fix warning<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  Schema = mongoose.Schema;

/**
 * Project Schema
 */
var ProjectSchema = new Schema({
  code        : {type: String, default: ''},
  name: {
    type: String,
    default: '',
    required: 'Please fill the project name',
    trim: true
  },
  short: {
    type: String,
    default: '',
    required: 'Please complete the project short description',
    trim: true
  },
  description: {
    type: String,
    default: '',
    required: 'Please complete the project description',
    trim: true
  },
  github: {
    type: String,
    default: '',
    trim: true
  },
  isPublished : {type: Boolean, default: false},
  created: {
    type: Date,
    default: Date.now
  },
  createdBy: {
    type: 'ObjectId',
    ref: 'User',
    default: null
  },
  updated: {
    type: Date,
    default: Date.now
  },
  updatedBy: {
    type: 'ObjectId',
    ref: 'User',
    default: null
  },
  program: {
    type: Schema.ObjectId,
    ref: 'Program',
    required: 'Please select a program'
  },
  user: {
    type: Schema.ObjectId,
    ref: 'User'
  },
  tags: [String]
});

ProjectSchema.statics.findUniqueCode = function (title, suffix, callback) {
  var _this = this;
  var possible = 'prj-' + (title.toLowerCase().replace(/\W/g,'-').replace(/-+/,'-')) + (suffix || '');

  _this.findOne({
    code: possible
  }, function (err, user) {
    if (!err) {
      if (!user) {
        callback(possible);
      } else {
        return _this.findUniqueCode(title, (suffix || 0) + 1, callback);
      }
    } else {
      callback(null);
    }
  });
};

mongoose.model('Project', ProjectSchema);
<|endoftext|>


<commit_before>/* Copyright 2018 Dinar Gabbasov <https://it-projects.info/team/GabbasovDinar>
 * Copyright 2018 Artem Losev
 * Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
 * License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). */
odoo.define('pos_orders_history_reprint.screens', function (require) {
    "use strict";

    var gui = require('point_of_sale.gui');
    var screens = require('pos_orders_history.screens');
    var core = require('web.core');
    var Model = require('web.Model');
    var utils = require('web.utils');

    var round_pr = utils.round_precision;
    var QWeb = core.qweb;
    var _t = core._t;

    screens.ReceiptScreenWidget.include({
        print_xml: function() {
            this._super();
            var order = this.pos.get_order();
            var env = {
                widget:  this,
                pos: this.pos,
                order: order,
                receipt: order.export_for_printing(),
                paymentlines: order.get_paymentlines()
            };
            var receipt = QWeb.render('XmlReceipt',env);
            this.save_order_receipt(order, receipt, 'xml');
        },
        save_order_receipt: function (order, receipt, receipt_type) {
            var name = order.name;
            new Model('pos.xml_receipt').call('save_xml_receipt', [[], name, receipt, receipt_type]).then(function (result) {
                console.log(receipt_type, ' receipt has been saved.');
            });
        },
        render_receipt: function() {
            this._super();
            var order = this.pos.get_order();
            var env = {
                widget:  this,
                order: order,
                receipt: order.export_for_printing(),
                orderlines: order.get_orderlines(),
                paymentlines: order.get_paymentlines()
            };
            var ticket = QWeb.render('PosTicket',env);
            this.save_order_receipt(order, ticket, 'ticket');
        },
    });

    screens.OrdersHistoryScreenWidget.include({
        show: function () {
            var self = this;
            this._super();
            if (this.pos.config.reprint_orders) {
                this.$('.actions.oe_hidden').removeClass('oe_hidden');
                this.$('.button.reprint').unbind('click');
                this.$('.button.reprint').click(function (e) {
                    var parent = $(this).parents('.order-line');
                    var id = parseInt(parent.data('id'));
                    self.click_reprint_order(id);
                });
            }
        },
        click_reprint_order: function (id) {
            this.gui.show_screen('reprint_receipt', {order_id: id});
        },
    });

    screens.ReprintReceiptScreenWidget = screens.ReceiptScreenWidget.extend({
        template: 'ReprintReceiptScreenWidget',
        show: function () {
            var self = this;
            this.reprint_receipt = false;
            this._super();
            this.$('.back').click(function () {
                self.gui.show_screen('orders_history_screen');
            });
        },
        get_order: function () {
            var order_id = this.gui.get_current_screen_param('order_id');
            return this.pos.db.orders_history_by_id[order_id];
        },
        handle_auto_print: function() {
            var self = this;
            var order = this.get_order();
            this.$('.pos-sale-ticket').hide();
            new Model('pos.xml_receipt').call('search_read', [[['pos_reference', '=', order.pos_reference],['receipt_type', '=', 'xml']]]).then(function(r) {
                self.$('.pos-sale-ticket').show();
                self.reprint_receipt = r;
                self.check_handle_auto_print();
            });
        },
        check_handle_auto_print: function() {
            if (this.should_auto_print() && this.reprint_receipt && this.reprint_receipt.length) {
                this.print();
                if (this.should_close_immediately()){
                    this.click_next();
                }
            } else {
                this.lock_screen(false);
            }
        },
        print_xml: function (receipt) {
            var self = this;
            this.show_popup = false;
            var order = this.get_order();
            if (receipt) {
                receipt = receipt.receipt;
                if (this.pos.config.show_barcode_in_receipt) {
                    var barcode = this.$el.find('#barcode').parent().html();
                    if (!barcode) {
                        var receipt_reference = order.pos_reference &&
                            order.pos_reference.match(/\d{1,}-\d{1,}-\d{1,}/g) &&
                            order.pos_reference.match(/\d{1,}-\d{1,}-\d{1,}/g)[0];
                        var el = document.createElement('div');
                        $(el).append("");
                        $(el).find('#barcode').JsBarcode(receipt_reference, {format: "code128"});
                        $(el).find('#barcode').css({
                            "width": "100%"
                        });
                        barcode = $(el).find('#barcode').parent().html();
                    }
                    if (receipt.indexOf('') !== -1) {
                        receipt = receipt.split('');
                        receipt[0] = receipt[0] + barcode + '';
                        receipt = receipt.join('');
                    }
                }
                this.pos.proxy.print_receipt(receipt);
            } else if (self.pos.config.show_posted_orders && order.state === "done") {
                if (self.reprint_receipt && self.reprint_receipt.length) {
                    self.print_xml(self.reprint_receipt[0]);
                } else {
                    self.show_popup = true;
                    self.click_next();
                }
            } else {
                receipt = this.pos.get_receipt_by_order_reference_and_type(order.pos_reference, 'xml');
                if (receipt) {
                    this.print_xml(receipt);
                } else {
                    this.show_popup = true;
                    self.click_next();
                }
            }
        },
        click_next: function() {
            this.gui.show_screen('orders_history_screen');
            if (this.show_popup) {
                this.gui.show_popup('error',{
                    'title': _t('No XML Receipt.'),
                    'body': _t('There is no XML receipt for the order.'),
                });
            }
        },
        print_web: function() {
            window.print();
        },
        render_receipt: function (ticket) {
            var self = this;
            var order = this.get_order();
            // remove old html
            this.$('.pos-receipt-container').html("");
            if (ticket) {
                // add new html
                this.$('.pos-receipt-container').html(ticket.receipt);
                if (this.pos.config.show_barcode_in_receipt) {
                    // reference without 'Order'
                    var receipt_reference = order.pos_reference &&
                        order.pos_reference.match(/\d{1,}-\d{1,}-\d{1,}/g) &&
                        order.pos_reference.match(/\d{1,}-\d{1,}-\d{1,}/g)[0];
                    this.$el.find('#barcode').JsBarcode(receipt_reference, {format: "code128"});
                    this.$el.find('#barcode').css({
                        "width": "100%"
                    });
                }
            } else if (self.pos.config.show_posted_orders && order.state === "done") {
                new Model('pos.xml_receipt').call('search_read', [[['pos_reference', '=', order.pos_reference],['receipt_type', '=', 'ticket']]]).then(function(t) {
                    if (t && t.length) {
                        self.render_receipt(t[0]);
                    } else {
                        self.gui.show_popup('error',{
                            'title': _t('No Ticket.'),
                            'body': _t('There is no Ticket for the order.'),
                        });
                    }
                });
            } else {
                ticket = this.pos.get_receipt_by_order_reference_and_type(order.pos_reference, 'ticket');
                if (ticket) {
                    self.render_receipt(ticket);
                } else {
                    this.gui.show_popup('error',{
                        'title': _t('No Ticket.'),
                        'body': _t('There is no Ticket for the order.'),
                    });
                }
            }
        }
    });

    gui.define_screen({name:'reprint_receipt', widget: screens.ReprintReceiptScreenWidget});

    return screens;
});
<commit_msg>:heart_eyes: refactoring code<commit_after>/* Copyright 2018 Dinar Gabbasov <https://it-projects.info/team/GabbasovDinar>
 * Copyright 2018 Artem Losev
 * Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
 * License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). */
odoo.define('pos_orders_history_reprint.screens', function (require) {
    "use strict";

    var gui = require('point_of_sale.gui');
    var screens = require('pos_orders_history.screens');
    var core = require('web.core');
    var Model = require('web.Model');
    var utils = require('web.utils');

    var round_pr = utils.round_precision;
    var QWeb = core.qweb;
    var _t = core._t;

    screens.ReceiptScreenWidget.include({
        print_xml: function() {
            this._super();
            var order = this.pos.get_order();
            var env = {
                widget:  this,
                pos: this.pos,
                order: order,
                receipt: order.export_for_printing(),
                paymentlines: order.get_paymentlines()
            };
            var receipt = QWeb.render('XmlReceipt',env);
            this.save_order_receipt(order, receipt, 'xml');
        },
        save_order_receipt: function (order, receipt, receipt_type) {
            var name = order.name;
            new Model('pos.xml_receipt').call('save_xml_receipt', [[], name, receipt, receipt_type]).then(function (result) {
                console.log(receipt_type, ' receipt has been saved.');
            });
        },
        render_receipt: function() {
            this._super();
            var order = this.pos.get_order();
            var env = {
                widget:  this,
                order: order,
                receipt: order.export_for_printing(),
                orderlines: order.get_orderlines(),
                paymentlines: order.get_paymentlines()
            };
            var ticket = QWeb.render('PosTicket',env);
            this.save_order_receipt(order, ticket, 'ticket');
        },
    });

    screens.OrdersHistoryScreenWidget.include({
        show: function () {
            var self = this;
            this._super();
            if (this.pos.config.reprint_orders) {
                this.set_reprint_action();
            }
        },
        set_reprint_action: function() {
            var self = this;
            this.$('.actions.oe_hidden').removeClass('oe_hidden');
            this.$('.button.reprint').unbind('click');
            this.$('.button.reprint').click(function (e) {
                var parent = $(this).parents('.order-line');
                var id = parseInt(parent.data('id'));
                self.click_reprint_order(id);
            });
        },
        click_reprint_order: function (id) {
            this.gui.show_screen('reprint_receipt', {order_id: id});
        },
        render_list: function(orders) {
            this._super(orders);
            if (this.pos.config.reprint_orders) {
                this.set_reprint_action();
            }
        }
    });

    screens.ReprintReceiptScreenWidget = screens.ReceiptScreenWidget.extend({
        template: 'ReprintReceiptScreenWidget',
        show: function () {
            var self = this;
            this.reprint_receipt = false;
            this._super();
            this.$('.back').click(function () {
                self.gui.show_screen('orders_history_screen');
            });
        },
        get_order: function () {
            var order_id = this.gui.get_current_screen_param('order_id');
            return this.pos.db.orders_history_by_id[order_id];
        },
        handle_auto_print: function() {
            var self = this;
            var order = this.get_order();
            this.$('.pos-sale-ticket').hide();
            new Model('pos.xml_receipt').call('search_read', [[['pos_reference', '=', order.pos_reference],['receipt_type', '=', 'xml']]]).then(function(r) {
                self.$('.pos-sale-ticket').show();
                self.reprint_receipt = r;
                self.check_handle_auto_print();
            });
        },
        check_handle_auto_print: function() {
            if (this.should_auto_print() && this.reprint_receipt && this.reprint_receipt.length) {
                this.print();
                if (this.should_close_immediately()){
                    this.click_next();
                }
            } else {
                this.lock_screen(false);
            }
        },
        print_xml: function (receipt) {
            var self = this;
            this.show_popup = false;
            var order = this.get_order();
            if (receipt) {
                receipt = receipt.receipt;
                if (this.pos.config.show_barcode_in_receipt) {
                    var barcode = this.$el.find('#barcode').parent().html();
                    if (!barcode) {
                        var receipt_reference = order.pos_reference &&
                            order.pos_reference.match(/\d{1,}-\d{1,}-\d{1,}/g) &&
                            order.pos_reference.match(/\d{1,}-\d{1,}-\d{1,}/g)[0];
                        var el = document.createElement('div');
                        $(el).append("");
                        $(el).find('#barcode').JsBarcode(receipt_reference, {format: "code128"});
                        $(el).find('#barcode').css({
                            "width": "100%"
                        });
                        barcode = $(el).find('#barcode').parent().html();
                    }
                    if (receipt.indexOf('') !== -1) {
                        receipt = receipt.split('');
                        receipt[0] = receipt[0] + barcode + '';
                        receipt = receipt.join('');
                    }
                }
                this.pos.proxy.print_receipt(receipt);
            } else if (self.pos.config.show_posted_orders && order.state === "done") {
                if (self.reprint_receipt && self.reprint_receipt.length) {
                    self.print_xml(self.reprint_receipt[0]);
                } else {
                    self.show_popup = true;
                    self.click_next();
                }
            } else {
                receipt = this.pos.get_receipt_by_order_reference_and_type(order.pos_reference, 'xml');
                if (receipt) {
                    this.print_xml(receipt);
                } else {
                    this.show_popup = true;
                    self.click_next();
                }
            }
        },
        click_next: function() {
            this.gui.show_screen('orders_history_screen');
            if (this.show_popup) {
                this.gui.show_popup('error',{
                    'title': _t('No XML Receipt.'),
                    'body': _t('There is no XML receipt for the order.'),
                });
            }
        },
        print_web: function() {
            window.print();
        },
        render_receipt: function (ticket) {
            var self = this;
            var order = this.get_order();
            // remove old html
            this.$('.pos-receipt-container').html("");
            if (ticket) {
                // add new html
                this.$('.pos-receipt-container').html(ticket.receipt);
                if (this.pos.config.show_barcode_in_receipt) {
                    // reference without 'Order'
                    var receipt_reference = order.pos_reference &&
                        order.pos_reference.match(/\d{1,}-\d{1,}-\d{1,}/g) &&
                        order.pos_reference.match(/\d{1,}-\d{1,}-\d{1,}/g)[0];
                    this.$el.find('#barcode').JsBarcode(receipt_reference, {format: "code128"});
                    this.$el.find('#barcode').css({
                        "width": "100%"
                    });
                }
            } else if (self.pos.config.show_posted_orders && order.state === "done") {
                new Model('pos.xml_receipt').call('search_read', [[['pos_reference', '=', order.pos_reference],['receipt_type', '=', 'ticket']]]).then(function(t) {
                    if (t && t.length) {
                        self.render_receipt(t[0]);
                    } else {
                        self.gui.show_popup('error',{
                            'title': _t('No Ticket.'),
                            'body': _t('There is no Ticket for the order.'),
                        });
                    }
                });
            } else {
                ticket = this.pos.get_receipt_by_order_reference_and_type(order.pos_reference, 'ticket');
                if (ticket) {
                    self.render_receipt(ticket);
                } else {
                    this.gui.show_popup('error',{
                        'title': _t('No Ticket.'),
                        'body': _t('There is no Ticket for the order.'),
                    });
                }
            }
        }
    });

    gui.define_screen({name:'reprint_receipt', widget: screens.ReprintReceiptScreenWidget});

    return screens;
});
<|endoftext|>


<commit_before>/* renderer.js */
define ([
	'three',
	'1401/objects/viewport',
	'1401/settings'
], function (
	THREE,
	VIEWPORT,
	SETTINGS
) {

	var DBGOUT = true;

/**	RENDERER *****************************************************************\

	ThreeJS-based rendering system

/** MODULE PRIVATE VARIABLES *************************************************/

	var _timer_resizing;

	var RP_BG 		= new THREE.Scene();	// drawn with camBG
	var RP_WORLD 	= new THREE.Scene();	// drawn with camWORLD
	var RP_WORLD2 	= new THREE.Scene();	// drawn with camWORLD
	var RP_UI 		= new THREE.Scene();	// drawn with camSCREEN
	var RP_OVER 	= new THREE.Scene();	// drawn with camSCREEN

	var BG_SPRITE 	= null;

	var PICK_SUBSCRIBERS = null;			// API.SubscribeToMousePicks()

/** PUBLIC API ***************************************************************/

	var API = {};
	API.name = "renderer";

///	RENDER INIT & CONTROL ////////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	Initialize Rendersystem
/*/	API.Initialize = function ( parm ) {

		// order of initialization is important
		VIEWPORT.InitializeRenderer(
			parm.renderWidth,
			parm.renderHeight,
			parm.attachTo
		);
		VIEWPORT.InitializeWorld(
			parm.worldUnits
		);
		VIEWPORT.InitializeCameras();

		// assign default cameras to renderpasses
		RP_BG.camera = VIEWPORT.BackgroundCam();
		RP_WORLD.camera = VIEWPORT.WorldCam();
		RP_WORLD2.camera = VIEWPORT.WorldCam();
		RP_UI.camera = VIEWPORT.ScreenCam();
		RP_OVER.camera = VIEWPORT.ScreenCam();

	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ for manually rendering on every update with explicit call
/*/	API.Render = function () {

		VIEWPORT.Clear();
		VIEWPORT.Render ( RP_BG );

		VIEWPORT.ClearDepth();
		VIEWPORT.Render ( RP_WORLD );

		VIEWPORT.ClearDepth();
		VIEWPORT.Render ( RP_WORLD2 );

		VIEWPORT.ClearDepth();
		VIEWPORT.Render ( RP_UI );

		VIEWPORT.ClearDepth();
		VIEWPORT.Render ( RP_OVER );

	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ call once to start auto drawing with no need to call on update
/*/	API.AutoRender = function () {
		requestAnimationFrame( API.AutoRender );
		API.Render();
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ called by Master.Step() prior to Game.MasterStep()
/*/	API.HeartBeat = function ( interval_ms ) {
		// do system-related cleanup and processing
	};

///	RENDERPASSES /////////////////////////////////////////////////////////////
/*/	These routines are useful for adding/removing a single visual (which is
	a THREE object3d) at a time.
/*/
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddWorldVisual = function ( visual ) {
		RP_WORLD.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_WORLD");
	};
///	---
	API.SetWorldVisualFog = function ( fog ) {
		RP_WORLD.fog = fog;
		if (DBGOUT) console.log("added fog"+fog.name,">>> RP_WORLD");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddWorldOverlayVisual = function ( visual ) {
		RP_WORLD2.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_WORLD2");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddBackgroundVisual = function ( visual ) {
		RP_BG.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_BG");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddUIVisual = function ( visual ) {
		RP_UI.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_UI");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddScreenOverlayVisual = function ( visual ) {
		RP_OVER.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_OVER");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveWorldVisual = function ( visual ) {
		RP_WORLD.remove(visual);
		if (DBGOUT) console.log("RP_WORLD >>>",visual.id.toString(),"removed");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveWorldVisual = function ( visual ) {
		RP_WORLD2.remove(visual);
		if (DBGOUT) console.log("RP_WORLD2 >>>",visual.id.toString(),"removed");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveBackgroundVisual = function ( visual ) {
		RP_BG.remove(visual);
		if (DBGOUT) console.log("RP_BG >>>",visual.id.toString(),"removed");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveUIVisual = function ( visual ) {
		RP_UI.remove(visual);
		if (DBGOUT) console.log("RP_UI >>>",visual.id.toString(),"removed");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveScreenOverlayVisual = function ( visual ) {
		RP_OVER.remove(visual);
		if (DBGOUT) console.log("RP_OVER >>>",visual.id.toString(),"removed");
	};

///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.SelectWorld2D = function ( index ) {
		VIEWPORT.SelectWorld2D();
		RP_WORLD.camera = VIEWPORT.WorldCam();
		RP_WORLD2.camera = VIEWPORT.WorldCam();
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.SelectWorld3D = function ( index ) {
		VIEWPORT.SelectWorld3D();
		RP_WORLD.camera = VIEWPORT.WorldCam();
		RP_WORLD2.camera = VIEWPORT.WorldCam();
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.Viewport = function ( index ) {
		return VIEWPORT;
	};

///	BACKGROUND IMAGE /////////////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.SetBackgroundImage = function ( textureName, callback, callee ) {

		var bgMap = THREE.ImageUtils.loadTexture(textureName,THREE.UVMAPPING, mi_SaveHeight);
		var bgMat = new THREE.SpriteMaterial( {map:bgMap} );
		if (BG_SPRITE) this.RemoveBackgroundVisual(BG_SPRITE);
		BG_SPRITE = new THREE.Sprite(bgMat);
		BG_SPRITE.position.set(0,0,-1000); // clip for 2D is 1000
		this.AddBackgroundVisual(BG_SPRITE);

		function mi_SaveHeight(texture) {
			BG_SPRITE.scale.set(texture.image.width,texture.image.height,1);
			if (callback) callback.call(callee, texture);
		}

	};

/// RAYCASTING CLICK SUPPORT///////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

	API.EnableMousePicks = function () {
		if (!PICK_SUBSCRIBERS) {
			PICK_SUBSCRIBERS = [];
			$(VIEWPORT.WebGL().domElement).click(m_CastRay);
		} else {
			console.error("MousePicking already enabled");
		}
	};

	API.SubscribeToMousePicks = function ( func ) {

		// make sure a function is provided
		if (!(func instanceof Function)) return;
		// fail if EnableMousePicks() wasn't called first
		if (!PICK_SUBSCRIBERS) {
			console.error("Renderer.EnableMousePicks() must be called before subscribing");
			return;
		}

		// add function to subscribers if it's not already one
		if (PICK_SUBSCRIBERS.indexOf(func) < 0) {
			PICK_SUBSCRIBERS.push(func);
		} else {
			console.log("SubscribeToMousePicks:","duplicate subscription ignored",func.toString());
			return;
		}
	};

/**	SUPPORT FUNCTIONS *******************************************************/

///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	m_CastRay ( event ) handles clicks on objects in the world
/*/	function m_CastRay ( event ) {
		event.preventDefault();

		// requires ThreeJS R69 or greater

		// mouse->world position
		var offset = $(event.currentTarget).offset();
		// normalize to -1 to 1
		// this appears to be threejs convention, though our coordinates in the world
		var dim = VIEWPORT.Dimensions();
		var x = ( (event.pageX-offset.left) / dim.width ) * 2 - 1;
		var y = -(( (event.pageY-offset.top) / dim.height ) * 2 - 1);
		var vector = new THREE.Vector3(x, y, -1);

		// current camera, objects
		var camera = VIEWPORT.WorldCam();

		/*/	NOTE:
			we are using an orthographic camera setup that differs from most
			orthographic example setups (not using screen coordinates),
			so the typical raycasting algorithms aren't working out of the box. Plus
			our version of threeJS is R67, and raycasting changed in R69.
			So I'm doing a 2D-only walk of our pieces
		/*/

		var raycaster, dir;

		if (camera instanceof THREE.OrthographicCamera) {

			dir = new THREE.Vector3();
			raycaster = new THREE.Raycaster();

			vector.unproject(camera);
			dir.set(0,0,-1).transformDirection(camera.matrixWorld);
			raycaster.set(vector,dir);

		} else {
			console.error("perspective camera raypicking is not yet implemented");
		}

		var objects = RP.pieces.children;
		var intersections = raycaster.intersectObjects(objects);

		var type = (camera instanceof THREE.PerspectiveCamera) ? 'PerspectiveCam' : 'OrthoCam';
		if (intersections.length) {
			// console.log(type,'('+x.toFixed(2)+', '+y.toFixed(2)+')',intersections);
			for (var i=0;i<PICK_SUBSCRIBERS.length;i++) {
				var func = PICK_SUBSCRIBERS[i];
				func.call(null,intersections);
			}
		}

	}
/** RETURN MODULE DEFINITION FOR REQUIREJS ***********************************/

	return API;

});<commit_msg>bugfix: AddWorldVisual using wrong renderpass<commit_after>/* renderer.js */
define ([
	'three',
	'1401/objects/viewport',
	'1401/settings'
], function (
	THREE,
	VIEWPORT,
	SETTINGS
) {

	var DBGOUT = true;

/**	RENDERER *****************************************************************\

	ThreeJS-based rendering system

/** MODULE PRIVATE VARIABLES *************************************************/

	var _timer_resizing;

	var RP_BG 		= new THREE.Scene();	// drawn with camBG
	var RP_WORLD 	= new THREE.Scene();	// drawn with camWORLD
	var RP_WORLD2 	= new THREE.Scene();	// drawn with camWORLD
	var RP_UI 		= new THREE.Scene();	// drawn with camSCREEN
	var RP_OVER 	= new THREE.Scene();	// drawn with camSCREEN

	var BG_SPRITE 	= null;

	var PICK_SUBSCRIBERS = null;			// API.SubscribeToMousePicks()

/** PUBLIC API ***************************************************************/

	var API = {};
	API.name = "renderer";

///	RENDER INIT & CONTROL ////////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	Initialize Rendersystem
/*/	API.Initialize = function ( parm ) {

		// order of initialization is important
		VIEWPORT.InitializeRenderer(
			parm.renderWidth,
			parm.renderHeight,
			parm.attachTo
		);
		VIEWPORT.InitializeWorld(
			parm.worldUnits
		);
		VIEWPORT.InitializeCameras();

		// assign default cameras to renderpasses
		RP_BG.camera = VIEWPORT.BackgroundCam();
		RP_WORLD.camera = VIEWPORT.WorldCam();
		RP_WORLD2.camera = VIEWPORT.WorldCam();
		RP_UI.camera = VIEWPORT.ScreenCam();
		RP_OVER.camera = VIEWPORT.ScreenCam();

	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ for manually rendering on every update with explicit call
/*/	API.Render = function () {

		VIEWPORT.Clear();
		VIEWPORT.Render ( RP_BG );

		VIEWPORT.ClearDepth();
		VIEWPORT.Render ( RP_WORLD );

		VIEWPORT.ClearDepth();
		VIEWPORT.Render ( RP_WORLD2 );

		VIEWPORT.ClearDepth();
		VIEWPORT.Render ( RP_UI );

		VIEWPORT.ClearDepth();
		VIEWPORT.Render ( RP_OVER );

	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ call once to start auto drawing with no need to call on update
/*/	API.AutoRender = function () {
		requestAnimationFrame( API.AutoRender );
		API.Render();
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ called by Master.Step() prior to Game.MasterStep()
/*/	API.HeartBeat = function ( interval_ms ) {
		// do system-related cleanup and processing
	};

///	RENDERPASSES /////////////////////////////////////////////////////////////
/*/	These routines are useful for adding/removing a single visual (which is
	a THREE object3d) at a time.
/*/
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddWorldVisual = function ( visual ) {
		RP_WORLD.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_WORLD");
	};
///	---
	API.SetWorldVisualFog = function ( fog ) {
		RP_WORLD.fog = fog;
		if (DBGOUT) console.log("added fog"+fog.name,">>> RP_WORLD");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddWorldOverlayVisual = function ( visual ) {
		RP_WORLD2.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_WORLD2");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddBackgroundVisual = function ( visual ) {
		RP_BG.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_BG");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddUIVisual = function ( visual ) {
		RP_UI.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_UI");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.AddScreenOverlayVisual = function ( visual ) {
		RP_OVER.add(visual);
		if (DBGOUT) console.log("added "+visual.id,">>> RP_OVER");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveWorldVisual = function ( visual ) {
		RP_WORLD.remove(visual);
		if (DBGOUT) console.log("RP_WORLD >>>",visual.id.toString(),"removed");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveWorldOverlayVisual = function ( visual ) {
		RP_WORLD2.remove(visual);
		if (DBGOUT) console.log("RP_WORLD2 >>>",visual.id.toString(),"removed");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveBackgroundVisual = function ( visual ) {
		RP_BG.remove(visual);
		if (DBGOUT) console.log("RP_BG >>>",visual.id.toString(),"removed");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveUIVisual = function ( visual ) {
		RP_UI.remove(visual);
		if (DBGOUT) console.log("RP_UI >>>",visual.id.toString(),"removed");
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.RemoveScreenOverlayVisual = function ( visual ) {
		RP_OVER.remove(visual);
		if (DBGOUT) console.log("RP_OVER >>>",visual.id.toString(),"removed");
	};

///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.SelectWorld2D = function ( index ) {
		VIEWPORT.SelectWorld2D();
		RP_WORLD.camera = VIEWPORT.WorldCam();
		RP_WORLD2.camera = VIEWPORT.WorldCam();
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.SelectWorld3D = function ( index ) {
		VIEWPORT.SelectWorld3D();
		RP_WORLD.camera = VIEWPORT.WorldCam();
		RP_WORLD2.camera = VIEWPORT.WorldCam();
	};
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.Viewport = function ( index ) {
		return VIEWPORT;
	};

///	BACKGROUND IMAGE /////////////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	API.SetBackgroundImage = function ( textureName, callback, callee ) {

		var bgMap = THREE.ImageUtils.loadTexture(textureName,THREE.UVMAPPING, mi_SaveHeight);
		var bgMat = new THREE.SpriteMaterial( {map:bgMap} );
		if (BG_SPRITE) this.RemoveBackgroundVisual(BG_SPRITE);
		BG_SPRITE = new THREE.Sprite(bgMat);
		BG_SPRITE.position.set(0,0,-1000); // clip for 2D is 1000
		this.AddBackgroundVisual(BG_SPRITE);

		function mi_SaveHeight(texture) {
			BG_SPRITE.scale.set(texture.image.width,texture.image.height,1);
			if (callback) callback.call(callee, texture);
		}

	};

/// RAYCASTING CLICK SUPPORT///////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

	API.EnableMousePicks = function () {
		if (!PICK_SUBSCRIBERS) {
			PICK_SUBSCRIBERS = [];
			$(VIEWPORT.WebGL().domElement).click(m_CastRay);
		} else {
			console.error("MousePicking already enabled");
		}
	};

	API.SubscribeToMousePicks = function ( func ) {

		// make sure a function is provided
		if (!(func instanceof Function)) return;
		// fail if EnableMousePicks() wasn't called first
		if (!PICK_SUBSCRIBERS) {
			console.error("Renderer.EnableMousePicks() must be called before subscribing");
			return;
		}

		// add function to subscribers if it's not already one
		if (PICK_SUBSCRIBERS.indexOf(func) < 0) {
			PICK_SUBSCRIBERS.push(func);
		} else {
			console.log("SubscribeToMousePicks:","duplicate subscription ignored",func.toString());
			return;
		}
	};

/**	SUPPORT FUNCTIONS *******************************************************/

///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	m_CastRay ( event ) handles clicks on objects in the world
/*/	function m_CastRay ( event ) {
		event.preventDefault();

		// requires ThreeJS R69 or greater

		// mouse->world position
		var offset = $(event.currentTarget).offset();
		// normalize to -1 to 1
		// this appears to be threejs convention, though our coordinates in the world
		var dim = VIEWPORT.Dimensions();
		var x = ( (event.pageX-offset.left) / dim.width ) * 2 - 1;
		var y = -(( (event.pageY-offset.top) / dim.height ) * 2 - 1);
		var vector = new THREE.Vector3(x, y, -1);

		// current camera, objects
		var camera = VIEWPORT.WorldCam();

		/*/	NOTE:
			we are using an orthographic camera setup that differs from most
			orthographic example setups (not using screen coordinates),
			so the typical raycasting algorithms aren't working out of the box. Plus
			our version of threeJS is R67, and raycasting changed in R69.
			So I'm doing a 2D-only walk of our pieces
		/*/

		var raycaster, dir;

		if (camera instanceof THREE.OrthographicCamera) {

			dir = new THREE.Vector3();
			raycaster = new THREE.Raycaster();

			vector.unproject(camera);
			dir.set(0,0,-1).transformDirection(camera.matrixWorld);
			raycaster.set(vector,dir);

		} else {
			console.error("perspective camera raypicking is not yet implemented");
		}

		var objects = RP.pieces.children;
		var intersections = raycaster.intersectObjects(objects);

		var type = (camera instanceof THREE.PerspectiveCamera) ? 'PerspectiveCam' : 'OrthoCam';
		if (intersections.length) {
			// console.log(type,'('+x.toFixed(2)+', '+y.toFixed(2)+')',intersections);
			for (var i=0;i<PICK_SUBSCRIBERS.length;i++) {
				var func = PICK_SUBSCRIBERS[i];
				func.call(null,intersections);
			}
		}

	}
/** RETURN MODULE DEFINITION FOR REQUIREJS ***********************************/

	return API;

});<|endoftext|>


<commit_before>angular.module('trackship.controllers', [])
.controller('MainCtrl', function($scope, $rootScope, $ionicUser, $ionicPush, $log, $ionicLoading, $http, $ionicModal, $ionicPopup) {
  // $ionicLoading.show({
  //   template: 'Loading...'
  // });
  // Handles incoming device tokens
  $rootScope.$on('$cordovaPush:tokenReceived', function(event, data) {
    $log.info('Ionic Push: Got token ', data.token, data.platform);
    $scope.token = data.token;

    $http({
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
    }).
    success(function(data, status, headers, config) {
      $scope.projects = data;
    }).
    error(function(data, status, headers, config) {
      alert(data);
    });

    $http({
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/notifications',
    }).
    success(function(data, status, headers, config) {
      $scope.notifications = data;
    }).
    error(function(data, status, headers, config) {
      alert(data);
    });
  });

  $rootScope.$on('project-added', function() {
      $http({
        url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
      }).
      success(function(data, status, headers, config) {
        $scope.projects = data;
      }).
      error(function(data, status, headers, config) {
        alert(data);
      });
  });

  $log.info('Ionic User: Identifying with Ionic User service');

  var user = $ionicUser.get();
  if(!user.user_id) {
    // Set your user_id here, or generate a random one.
    user.user_id = $ionicUser.generateGUID();
  };

  // Identify your user with the Ionic User Service
  $ionicUser.identify(user).then(function(){
    $scope.identified = true;

    $log.info('Ionic Push: Registering user');
    // Register with the Ionic Push service.  All parameters are optional.
    $ionicPush.register({
      canShowAlert: true, //Can pushes show an alert on your screen?
      canSetBadge: true, //Can pushes update app icon badges?
      canPlaySound: true, //Can notifications play a sound?
      canRunActionsOnWake: true, //Can run actions outside the app,
      onNotification: function(notification) {
        // Handle new push notifications here
        // $log.info(notification);
        return true;
      }
    });
  });

  $scope.removeProject = function(id) {
    $http({
      method: 'DELETE',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
      data: {project_id:id},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $ionicLoading.show({
        template: 'Project has been removed.',
        duration: 1000
      });
      $rootScope.$emit('project-added');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }

  $scope.showModal = function(id) {
    $scope.project_id = id;

    $ionicModal.fromTemplateUrl('templates/subscriptions.html', {
      scope: $scope
    }).then(function(modal) {
      $scope.modal = modal;
      modal.show();
    });
  }

  $scope.projects = [{name:'asdasds', id:'0c28f3b4-26df-400c-bcc3-0c936190d564'}];
  $scope.project_id;
  $scope.data = {};
})
.controller('NewProjectCtrl', function($scope, $ionicHistory, $http, $location, $rootScope) {
  $scope.project = {};
  $scope.submit = {disabled:true};
  $scope.myGoBack = function() {
    $ionicHistory.goBack();
  };
  $scope.toggleSubmit = function() {
    if ($scope.project.name.length > 0) {
      $scope.submit.disabled = false;
    } else {
      $scope.submit.disabled = true;
    };
  }
  $scope.createProject = function() {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/projects',
      data: {name:$scope.project.name},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $http({
        method: 'POST',
        url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
        data: {project_id:data.project_id},
        headers: {
          'Content-Type': 'application/json'
        }
      }).
      success(function(data, status, headers, config) {
        $scope.project = {};
        $location.path("/landing");
        $rootScope.$emit('project-added');
      }).
      error(function(data, status, headers, config) {
        alert(JSON.stringify(data));
      });
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  };
})
.controller('JoinProjectCtrl', function($scope, $ionicHistory, $http, $location, $rootScope) {
  $scope.project = {};
  $scope.submit = {disabled:true};
  $scope.myGoBack = function() {
    $ionicHistory.goBack();
  };
  $scope.toggleSubmit = function() {
    if ($scope.project.id.length > 0) {
      $scope.submit.disabled = false;
    } else {
      $scope.submit.disabled = true;
    };
  }
  $scope.joinProject = function() {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
      data: {project_id:$scope.project.id},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.project = {};
      $location.path("/landing");
      $rootScope.$emit('project-added');
    }).
    error(function(data, status, headers, config) {
      alert('This project does not exist');
    });
  };
})
.controller('SubscriptionsCtrl', function($scope, $http, $ionicPopup) {
  $scope.materials = [];

  $scope.$on('materials-update', function() {
    $http({
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/project/' + $scope.project_id + '/materials/user/' + $scope.token,
    }).
    success(function(data, status, headers, config) {
      $scope.materials = data;
    }).
    error(function(data, status, headers, config) {
      alert(data);
    });
  });

  $scope.$emit('materials-update');

  $scope.addMaterial = function() {
    $ionicPopup.show({
      template: '<input type="text" ng-model="data.material">',
      title: 'Enter Material Name',
      scope: $scope,
      buttons: [
        { text: 'Cancel' },
        {
          text: 'Save',
          type: 'button-positive',
          onTap: function(e) {
            if (!$scope.data.material) {
              //don't allow the user to close unless he enters wifi password
              e.preventDefault();
            } else {
              $http({
                method: 'POST',
                url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/project/' + $scope.project_id + '/materials',
                data: {name:$scope.data.material},
                headers: {
                  'Content-Type': 'application/json'
                }
              }).
              success(function(data, status, headers, config) {
                $scope.data.material = "";
                $scope.$emit('materials-update');
              }).
              error(function(data, status, headers, config) {
                alert('This project does not exist');
              });
              return $scope.data.wifi;
            }
          }
        }
      ]
    });
  }

  $scope.subscribeMaterial = function(id) {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/subscribe',
      data: {user_id:$scope.token, material_id:id},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.$emit('materials-update');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }

  $scope.unsubscribeMaterial = function(id) {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/subscribe',
      data: {user_id:$scope.token, material_id:id},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.$emit('materials-update');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }

  $scope.notifyMaterial = function(id, name) {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/notify',
      data: {
        project_id:$scope.project_id,
        material_id:id,
        message:name + " has arrived."
      },
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.$emit('materials-update');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }

  $scope.removeMaterial = function(id) {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/project/' + $scope.project_id + '/materials',
      data: {name:$scope.data.material},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.$emit('materials-update');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }
});
<commit_msg>add unsubscribe endpoint<commit_after>angular.module('trackship.controllers', [])
.controller('MainCtrl', function($scope, $rootScope, $ionicUser, $ionicPush, $log, $ionicLoading, $http, $ionicModal, $ionicPopup) {
  // $ionicLoading.show({
  //   template: 'Loading...'
  // });
  // Handles incoming device tokens
  $rootScope.$on('$cordovaPush:tokenReceived', function(event, data) {
    $log.info('Ionic Push: Got token ', data.token, data.platform);
    $scope.token = data.token;

    $http({
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
    }).
    success(function(data, status, headers, config) {
      $scope.projects = data;
    }).
    error(function(data, status, headers, config) {
      alert(data);
    });

    $http({
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/notifications',
    }).
    success(function(data, status, headers, config) {
      $scope.notifications = data;
    }).
    error(function(data, status, headers, config) {
      alert(data);
    });
  });

  $rootScope.$on('project-added', function() {
      $http({
        url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
      }).
      success(function(data, status, headers, config) {
        $scope.projects = data;
      }).
      error(function(data, status, headers, config) {
        alert(data);
      });
  });

  $log.info('Ionic User: Identifying with Ionic User service');

  var user = $ionicUser.get();
  if(!user.user_id) {
    // Set your user_id here, or generate a random one.
    user.user_id = $ionicUser.generateGUID();
  };

  // Identify your user with the Ionic User Service
  $ionicUser.identify(user).then(function(){
    $scope.identified = true;

    $log.info('Ionic Push: Registering user');
    // Register with the Ionic Push service.  All parameters are optional.
    $ionicPush.register({
      canShowAlert: true, //Can pushes show an alert on your screen?
      canSetBadge: true, //Can pushes update app icon badges?
      canPlaySound: true, //Can notifications play a sound?
      canRunActionsOnWake: true, //Can run actions outside the app,
      onNotification: function(notification) {
        // Handle new push notifications here
        // $log.info(notification);
        return true;
      }
    });
  });

  $scope.removeProject = function(id) {
    $http({
      method: 'DELETE',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
      data: {project_id:id},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $ionicLoading.show({
        template: 'Project has been removed.',
        duration: 1000
      });
      $rootScope.$emit('project-added');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }

  $scope.showModal = function(id) {
    $scope.project_id = id;

    $ionicModal.fromTemplateUrl('templates/subscriptions.html', {
      scope: $scope
    }).then(function(modal) {
      $scope.modal = modal;
      modal.show();
    });
  }

  $scope.projects = [{name:'asdasds', id:'0c28f3b4-26df-400c-bcc3-0c936190d564'}];
  $scope.project_id;
  $scope.data = {};
})
.controller('NewProjectCtrl', function($scope, $ionicHistory, $http, $location, $rootScope) {
  $scope.project = {};
  $scope.submit = {disabled:true};
  $scope.myGoBack = function() {
    $ionicHistory.goBack();
  };
  $scope.toggleSubmit = function() {
    if ($scope.project.name.length > 0) {
      $scope.submit.disabled = false;
    } else {
      $scope.submit.disabled = true;
    };
  }
  $scope.createProject = function() {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/projects',
      data: {name:$scope.project.name},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $http({
        method: 'POST',
        url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
        data: {project_id:data.project_id},
        headers: {
          'Content-Type': 'application/json'
        }
      }).
      success(function(data, status, headers, config) {
        $scope.project = {};
        $location.path("/landing");
        $rootScope.$emit('project-added');
      }).
      error(function(data, status, headers, config) {
        alert(JSON.stringify(data));
      });
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  };
})
.controller('JoinProjectCtrl', function($scope, $ionicHistory, $http, $location, $rootScope) {
  $scope.project = {};
  $scope.submit = {disabled:true};
  $scope.myGoBack = function() {
    $ionicHistory.goBack();
  };
  $scope.toggleSubmit = function() {
    if ($scope.project.id.length > 0) {
      $scope.submit.disabled = false;
    } else {
      $scope.submit.disabled = true;
    };
  }
  $scope.joinProject = function() {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/user/' + $scope.token + '/projects',
      data: {project_id:$scope.project.id},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.project = {};
      $location.path("/landing");
      $rootScope.$emit('project-added');
    }).
    error(function(data, status, headers, config) {
      alert('This project does not exist');
    });
  };
})
.controller('SubscriptionsCtrl', function($scope, $http, $ionicPopup) {
  $scope.materials = [];

  $scope.$on('materials-update', function() {
    $http({
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/project/' + $scope.project_id + '/materials/user/' + $scope.token,
    }).
    success(function(data, status, headers, config) {
      $scope.materials = data;
    }).
    error(function(data, status, headers, config) {
      alert(data);
    });
  });

  $scope.$emit('materials-update');

  $scope.addMaterial = function() {
    $ionicPopup.show({
      template: '<input type="text" ng-model="data.material">',
      title: 'Enter Material Name',
      scope: $scope,
      buttons: [
        { text: 'Cancel' },
        {
          text: 'Save',
          type: 'button-positive',
          onTap: function(e) {
            if (!$scope.data.material) {
              //don't allow the user to close unless he enters wifi password
              e.preventDefault();
            } else {
              $http({
                method: 'POST',
                url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/project/' + $scope.project_id + '/materials',
                data: {name:$scope.data.material},
                headers: {
                  'Content-Type': 'application/json'
                }
              }).
              success(function(data, status, headers, config) {
                $scope.data.material = "";
                $scope.$emit('materials-update');
              }).
              error(function(data, status, headers, config) {
                alert('This project does not exist');
              });
              return $scope.data.wifi;
            }
          }
        }
      ]
    });
  }

  $scope.subscribeMaterial = function(id) {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/subscribe',
      data: {user_id:$scope.token, material_id:id},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.$emit('materials-update');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }

  $scope.unsubscribeMaterial = function(id) {
    $http({
      method: 'DELETE',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/unsubscribe',
      data: {user_id:$scope.token, material_id:id},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.$emit('materials-update');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }

  $scope.notifyMaterial = function(id, name) {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/notify',
      data: {
        project_id:$scope.project_id,
        material_id:id,
        message:name + " has arrived."
      },
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.$emit('materials-update');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }

  $scope.removeMaterial = function(id) {
    $http({
      method: 'POST',
      url: 'http://ec2-54-237-22-83.compute-1.amazonaws.com/project/' + $scope.project_id + '/materials',
      data: {name:$scope.data.material},
      headers: {
        'Content-Type': 'application/json'
      }
    }).
    success(function(data, status, headers, config) {
      $scope.$emit('materials-update');
    }).
    error(function(data, status, headers, config) {
      alert(JSON.stringify(data));
    });
  }
});
<|endoftext|>


<commit_before>/**
 * Defines custom events for touch related gusters.
 * Following events are defined:
 * tap, dbltap, taphold, swipe, swipeleft, swiperight
 * @author aniketn3@gmail.com
 */

/**
 * Tap event definition
 */
(function($, undefined) {
   var state = {/* id, x, y, target */};

   function clearState() {
      state.id = state.x = state.y = state.moved = state.target = undefined;
   }

   function hasMoved(x1, y1, x2, y2) {
      var dx = x1 - x2, dy = y1 - y2;
      return Math.abs(dx) > 15 || Math.abs(dy) > 15;
   }

   function handler(te) {
      var type = te.type, touch, touches = te.touches, cTouches = te.changedTouches, target = te.target;
      switch(type) {
         case "touchstart":
            if(touches.length !== 1) {
               return;
            }
            touch = touches[0];
            state.id = touch.identifier;
            state.x = touch.pageX;
            state.y = touch.pageY;
            state.target = target;
            break;
         case "touchmove":
            touch = cTouches[0];
            if(!state.moved && touch.identifier === state.id) {
               state.moved = hasMoved(state.x, state.y, touch.pageX, touch.pageY);
            }
            break;
         case "touchend":
            if(cTouches.length === 0 || state.moved) {
               clearState();
               return;
            }
            touch = cTouches[0];
            if(touch.identifier === state.id && !state.moved &&
                  // !hasMoved(state.x, state.y, touch.pageX, touch.pageY) &&
                  state.target === target) {
               $(target).dispatch("tap");
            }
            break;
         case "touchcancel":
            clearState();
            break;
      }
   }

   $.defineEvent({
      type: "tap",
      setup: function() {
         $(document).on("touchstart", handler).on("touchmove", handler)
            .on("touchend", handler).on("touchcancel", handler);
      },
      destroy: function() {
         $(document).un("touchstart", handler).un("touchmove", handler)
            .un("touchend", handler).un("touchcancel", handler);
      }
   });
})(h5);

/**
 * Double Tap event definition
 */
(function($, undefined) {
   var state = {/* last, target */};

   function handler(te) {
      var now = Date.now(), elapsed = now - (state.last || now), target = te.target;
      if(elapsed > 0 && elapsed < 300 && state.target === target) {
         $(target).dispatch("dbltap");
         state.last = state.target = null;
      }else {
         state.last = now;
         state.target = te.target;
      }
   }

   $.defineEvent({
      type: "dbltap",
      setup: function() {
         $(document).on("tap", handler);
      },
      destroy: function() {
         $(document).un("tap", handler);
      }
   });
})(h5);

/**
 * Tap hold event
 */
(function($, undefined) {
      var state = {/* moved, x, y */}, timer;

   function hasMoved(x1, y1, x2, y2) {
      var dx = x1 - x2, dy = y1 - y2;
      return Math.abs(dx) > 20 || Math.abs(dy) > 20;
   }

   function clearState() {
      state.moved = state.x = state.y = undefined;
   }

   function handler(te) {
      var type = te.type, target = te.target;
      switch(type) {
         case "touchstart":
            if(te.touches.length !== 1) {
               return;
            }
            state.x = te.pageX;
            state.y = te.pageY;
            timer = setTimeout(function() {
               if(!state.moved) {
                  $(target).dispatch("taphold");
               }
            }, 700);
            break;
         case "touchmove":
            if(!state.moved) {
               if(state.moved = hasMoved(state.x, state.y, te.pageX, te.pageY)) { // jshint ignore:line
                  clearTimeout(timer);
               }
            }
            break;
         case "touchend":
         case "touchcancel":
            /* falls through */
         default:
            clearTimeout(timer);
            clearState();
            break;
      }
   }

   $.defineEvent({
      type: "taphold",
      setup: function() {
         $(document).on("touchstart", handler).on("touchmove", handler).on("touchend", handler)
            .on("touchcancel", handler);
      },
      destroy: function() {
         $(document).un("touchstart", handler).un("touchmove", handler).un("touchend", handler)
            .un("touchcancel", handler);
      }
   });
})(h5);

/**
 * Swipe event
 */
(function($, undefined) {
   var state = {};

   /**
    * Calculate the delta difference between two points (x1,y1) and (x2,y2)
    * @return A delta object {x: xdelta, y: ydelta} if the difference is more
    * than 30 pixels or null if its less. The values x and y can be -ve
    */
   function getMovement(x1, y1, x2, y2) {
      var dx = x1 - x2, dy = y1 - y2, xa, ya;
      if((xa = Math.abs(dx)) < 30 & (ya = Math.abs(dy)) < 30) {
         return null;
      }
      return {
         startX: x2,
         startY: y2,
         endX: x1,
         endY: y1,
         dir: xa >= ya ? (dx < 0 ? "left" : "right") : (dy < 0 ? "up" : "down")
      };
   }

   function clearState() {
      state.id = state.x = state.y = state.movement = undefined;
   }

   function handler(te) {
      var type = te.type, touches = te.touches, touch, target, m, evtData;

      switch(type) {
         case "touchstart":
            touches = te.touches;
            if(touches.length > 1) {
               return;
            }
            touch = touches[0];
            state.id = touch.identifier;
            state.x = touch.pageX;
            state.y = touch.pageY;
            break;
         case "touchmove":
            touches = te.changedTouches;
            touch = touches[0];
            if(touch.identifier === state.id && te.touches.length === 1) {
               state.movement = getMovement(touch.pageX, touch.pageY, state.x, state.y);
            }
            break;
         case "touchend":
            touches = te.changedTouches;
            touch = touches[0];
            if(state.id === touch.identifier && (m = state.movement)) {
               evtData = {movement: m};
               $(te.target).dispatch("swipe", evtData); // available as event.movement
               clearState();
            }
            break;
         default:
            clearState();
            break;
      }
   }

   $.defineEvent({
      type: "swipe",
      setup: function() {
         $(document).on("touchstart", handler).on("touchmove", handler).on("touchend", handler)
            .on("touchcancel", handler);
      },
      destroy: function() {
         $(document).un("touchstart", handler).un("touchmove", handler).un("touchend", handler)
            .un("touchcancel", handler);
      }
   });
})(h5);

<commit_msg>Minor fix in swipe event<commit_after>/**
 * Defines custom events for touch related gusters.
 * Following events are defined:
 * tap, dbltap, taphold, swipe, swipeleft, swiperight
 * @author aniketn3@gmail.com
 */

/**
 * Tap event definition
 */
(function($, undefined) {
   var state = {/* id, x, y, target */};

   function clearState() {
      state.id = state.x = state.y = state.moved = state.target = undefined;
   }

   function hasMoved(x1, y1, x2, y2) {
      var dx = x1 - x2, dy = y1 - y2;
      return Math.abs(dx) > 15 || Math.abs(dy) > 15;
   }

   function handler(te) {
      var type = te.type, touch, touches = te.touches, cTouches = te.changedTouches, target = te.target;
      switch(type) {
         case "touchstart":
            if(touches.length !== 1) {
               return;
            }
            touch = touches[0];
            state.id = touch.identifier;
            state.x = touch.pageX;
            state.y = touch.pageY;
            state.target = target;
            break;
         case "touchmove":
            touch = cTouches[0];
            if(!state.moved && touch.identifier === state.id) {
               state.moved = hasMoved(state.x, state.y, touch.pageX, touch.pageY);
            }
            break;
         case "touchend":
            if(cTouches.length === 0 || state.moved) {
               clearState();
               return;
            }
            touch = cTouches[0];
            if(touch.identifier === state.id && !state.moved &&
                  // !hasMoved(state.x, state.y, touch.pageX, touch.pageY) &&
                  state.target === target) {
               $(target).dispatch("tap");
            }
            break;
         case "touchcancel":
            clearState();
            break;
      }
   }

   $.defineEvent({
      type: "tap",
      setup: function() {
         $(document).on("touchstart", handler).on("touchmove", handler)
            .on("touchend", handler).on("touchcancel", handler);
      },
      destroy: function() {
         $(document).un("touchstart", handler).un("touchmove", handler)
            .un("touchend", handler).un("touchcancel", handler);
      }
   });
})(h5);

/**
 * Double Tap event definition
 */
(function($, undefined) {
   var state = {/* last, target */};

   function handler(te) {
      var now = Date.now(), elapsed = now - (state.last || now), target = te.target;
      if(elapsed > 0 && elapsed < 300 && state.target === target) {
         $(target).dispatch("dbltap");
         state.last = state.target = null;
      }else {
         state.last = now;
         state.target = te.target;
      }
   }

   $.defineEvent({
      type: "dbltap",
      setup: function() {
         $(document).on("tap", handler);
      },
      destroy: function() {
         $(document).un("tap", handler);
      }
   });
})(h5);

/**
 * Tap hold event
 */
(function($, undefined) {
      var state = {/* moved, x, y */}, timer;

   function hasMoved(x1, y1, x2, y2) {
      var dx = x1 - x2, dy = y1 - y2;
      return Math.abs(dx) > 20 || Math.abs(dy) > 20;
   }

   function clearState() {
      state.moved = state.x = state.y = undefined;
   }

   function handler(te) {
      var type = te.type, target = te.target;
      switch(type) {
         case "touchstart":
            if(te.touches.length !== 1) {
               return;
            }
            state.x = te.pageX;
            state.y = te.pageY;
            timer = setTimeout(function() {
               if(!state.moved) {
                  $(target).dispatch("taphold");
               }
            }, 700);
            break;
         case "touchmove":
            if(!state.moved) {
               if(state.moved = hasMoved(state.x, state.y, te.pageX, te.pageY)) { // jshint ignore:line
                  clearTimeout(timer);
               }
            }
            break;
         case "touchend":
         case "touchcancel":
            /* falls through */
         default:
            clearTimeout(timer);
            clearState();
            break;
      }
   }

   $.defineEvent({
      type: "taphold",
      setup: function() {
         $(document).on("touchstart", handler).on("touchmove", handler).on("touchend", handler)
            .on("touchcancel", handler);
      },
      destroy: function() {
         $(document).un("touchstart", handler).un("touchmove", handler).un("touchend", handler)
            .un("touchcancel", handler);
      }
   });
})(h5);

/**
 * Swipe event
 */
(function($, undefined) {
   var state = {};

   /**
    * Calculate the delta difference between two points (x1,y1) and (x2,y2)
    * @return A delta object {x: xdelta, y: ydelta} if the difference is more
    * than 30 pixels or null if its less. The values x and y can be -ve
    */
   function getMovement(x1, y1, x2, y2) {
      var dx = x1 - x2, dy = y1 - y2, xa, ya;
      if((xa = Math.abs(dx)) < 30 & (ya = Math.abs(dy)) < 30) {
         return null;
      }
      return {
         startX: x2,
         startY: y2,
         endX: x1,
         endY: y1,
         dir: xa >= ya ? (dx < 0 ? "left" : "right") : (dy < 0 ? "up" : "down")
      };
   }

   function clearState() {
      state.id = state.x = state.y = state.movement = undefined;
   }

   function handler(te) {
      var type = te.type, touches = te.touches, touch, target, m, evtData;

      switch(type) {
         case "touchstart":
            touches = te.touches;
            if(touches.length > 1) {
               return;
            }
            touch = touches[0];
            state.id = touch.identifier;
            state.x = touch.pageX;
            state.y = touch.pageY;
            break;
         case "touchmove":
            touches = te.changedTouches;
            touch = touches[0];
            if(touch.identifier === state.id && te.touches.length === 1) {
               state.movement = getMovement(touch.pageX, touch.pageY, state.x, state.y);
            }
            break;
         case "touchend":
            touches = te.changedTouches;
            touch = touches[0];
            if(state.id === touch.identifier && (m = state.movement)) {
               evtData = m;
               $(te.target).dispatch("swipe", evtData); // available as event.data
               clearState();
            }
            break;
         default:
            clearState();
            break;
      }
   }

   $.defineEvent({
      type: "swipe",
      setup: function() {
         $(document).on("touchstart", handler).on("touchmove", handler).on("touchend", handler)
            .on("touchcancel", handler);
      },
      destroy: function() {
         $(document).un("touchstart", handler).un("touchmove", handler).un("touchend", handler)
            .un("touchcancel", handler);
      }
   });
})(h5);

<|endoftext|>


<commit_before>/*
  This file is part of the "FnordMetric" project
    Copyright (c) 2014 Laura Schlimmer
    Copyright (c) 2014 Paul Asmuth, Google Inc.
  FnordMetric is free software: you can redistribute it and/or modify it under
  the terms of the GNU General Public License v3.0. You should have received a
  copy of the GNU General Public License along with this program. If not, see
  <http://www.gnu.org/licenses/>
*/

var TabbableComponent = function() {
  this.createdCallback = function() {
    this.init();
  };
  this.attributeChangedCallback = function(attr, old_val, new_val) {
    if (attr == 'data-content-attached') {
      this.init();
    }
  }
  this.init = function() {
    var active_tab = this.querySelector("z-tab[data-active]");
    if (active_tab == null) {
      var tabs = this.querySelectorAll("z-tab");
      if (tabs && tabs[0]) {
        tabs[0].setAttribute('data-active', 'active');
        active_tab = tabs[0];
      }
    }
    if (this.hasAttribute('data-content-attached')) {
      var index = active_tab.getAttribute('data-index');
      this.setContent(index);
    }
    if (this.hasAttribute('data-evenly-sized')) {
      this.setTabWidth();
    }
    this.observeTabs();
  }
  this.setContent = function(index) {
    var active_content = this.querySelector("z-tab-content[data-active]");
    if (active_content) {
      active_content.removeAttribute('data-active');
    }
    var tab_content =
      this.querySelector("z-tab-content[data-index='" + index + "']");
    if (tab_content) {
      tab_content.setAttribute('data-active', 'active');
    }
  };
  this.setTabWidth = function() {
    var tabs = this.querySelectorAll("z-tab");
    if (tabs.length == 0) {
      return;
    }
    var width = 100 / tabs.length;
    for (var i = 0; i < tabs.length; i++) {
      tabs[i].style.width = width + "%";
    }
  }
  this.observeTabs = function() {
    var base = this;
    var tabs = this.querySelectorAll("z-tab");
    for (var i = 0; i < tabs.length; i++) {
      tabs[i].addEventListener('click', function() {
        var current_tab = base.querySelector("z-tab[data-active]");
        current_tab.removeAttribute("data-active");
        this.setAttribute("data-active", "active");
        if (base.hasAttribute('data-content-attached')) {
          var index = this.getAttribute('data-index');
          if (index) {
            base.setContent(index);
          }
        }
        base.fireClickTabEvent(this);
      }, false);
    }
  }
  this.fireClickTabEvent = function(elem) {
    var ev = new CustomEvent('z-tabbable-click', {
      bubbles: true,
      cancelable: true});
    elem.dispatchEvent(ev);
  };
};

var proto = Object.create(HTMLElement.prototype);
TabbableComponent.apply(proto);
document.registerElement("z-tabbable", { prototype: proto });
<commit_msg>z-tabbable refactoring<commit_after>/*
  This file is part of the "FnordMetric" project
    Copyright (c) 2014 Laura Schlimmer
    Copyright (c) 2014 Paul Asmuth, Google Inc.
  FnordMetric is free software: you can redistribute it and/or modify it under
  the terms of the GNU General Public License v3.0. You should have received a
  copy of the GNU General Public License along with this program. If not, see
  <http://www.gnu.org/licenses/>
*/

var TabbableComponent = function() {
  this.setContent = function() {
    var active_content = this.querySelector("z-tab-content[data-active]");
    if (active_content) {
      active_content.removeAttribute('data-active');
    }

    var tab = getActiveTab.call(this);
    var index = tab.getAttribute("data-index");
    var tab_content =
      this.querySelector("z-tab-content[data-index='" + index + "']");
    if (tab_content) {
      tab_content.setAttribute('data-active', 'active');
    }
  };

  var setTabWidth = function() {
    var tabs = this.querySelectorAll("z-tab");
    if (tabs.length == 0) {
      return;
    }
    var width = 100 / tabs.length;
    for (var i = 0; i < tabs.length; i++) {
      tabs[i].style.width = width + "%";
    }
  };

  var onTabClick = function(tab) {
    var current_active_tab = this.querySelector("z-tab[data-active]");
    current_active_tab.removeAttribute("data-active");
    tab.setAttribute("data-active", "active");

    if (this.hasAttribute("data-content-attached")) {
      this.setContent(tab.getAttribute('data-index'));
    }

    var click_event = new CustomEvent("tab-click", {
      bubbles: true,
      cancelable: true});
    tab.dispatchEvent(click_event);
  };

  var getActiveTab = function() {
    var active_tab = this.querySelector("z-tab[data-active]");
    if (active_tab != null) {
      return active_tab;
    }

    // set first tab active
    active_tab = this.querySelector("z-tab");
    if (active_tab) {
      active_tab.setAttribute('data-active', 'active');
    }

    return active_tab;
  };

  var init = function() {
    if (this.hasAttribute('data-content-attached')) {
      this.setContent();
    }

    if (this.hasAttribute('data-evenly-sized')) {
      setTabWidth.call(this);
    }

    var tabs = this.querySelectorAll("z-tab");
    for (var i = 0; i < tabs.length; i++) {
      tabs[i].addEventListener('click', (function(_this) {
        return function(e) {
          onTabClick.call(_this, this);
        }
      })(this));
    }
  };

  this.createdCallback = function() {
    init.call(this);
  };

  this.attributeChangedCallback = function(attr, old_val, new_val) {
    if (attr == 'data-content-attached') {
      this.setContent();
    }
  };

};

var proto = Object.create(HTMLElement.prototype);
TabbableComponent.apply(proto);
document.registerElement("z-tabbable", { prototype: proto });
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc function
 * @name groongaAdminApp.service:schemaLoader
 * @description
 * # schemaLoader
 * Groonga database schema loader.
 */
angular.module('groongaAdminApp')
  .factory('schemaLoader', [
    '$q', '$http', '$timeout',
    function ($q, $http, $timeout) {
      var fetching = false;
      var waitingDeferes = [];
      var fetched = false;
      var schema;
      var client = new GroongaClient($http);

      function createSchema() {
        var newSchema = {};
        fillTypes(newSchema);
        return newSchema;
      }

      function fillTypes(schema) {
        var builtinTypes = [
          {
            name: 'Bool'
          },
          {
            name: 'Int8'
          },
          {
            name: 'UInt8'
          },
          {
            name: 'Int16'
          },
          {
            name: 'UInt16'
          },
          {
            name: 'Int32'
          },
          {
            name: 'UInt32'
          },
          {
            name: 'Int64'
          },
          {
            name: 'UInt64'
          },
          {
            name: 'Float'
          },
          {
            name: 'Time'
          },
          {
            name: 'ShortText'
          },
          {
            name: 'Text'
          },
          {
            name: 'LongText'
          },
          {
            name: 'TokyoGeoPoint'
          },
          {
            name: 'WGS84GeoPoint'
          }
        ];
        schema.types = {};
        angular.forEach(builtinTypes, function(type) {
          schema.types[type.name] = type;
        });
      }

      function isTextType(typeName) {
        switch (typeName) {
        case 'ShortText':
        case 'Text':
        case 'LongText':
          return true;
        default:
          return false;
        }
      }

      function isReferenceType(schema, typeName) {
        return typeName in schema.tables;
      }

      function buildTable(rawTable) {
        var table = {};
        table.id           = 0; // XXX it exists in a table_list response but missing in a schema response.
        table.name         = rawTable.name;
        table.path         = ''; // XXX it exists in a table_list response but missing in a schema response.
        table.valueType    = rawTable.value_type && rawTable.value_type.name
        table.tokenizer    = rawTable.tokenizer && rawTable.tokenizer.name;
        table.normalizer   = rawTable.normalizer && rawTable.normalizer.name;
        table.type         = rawTable.type;

        table.flags = [];
        if (rawTable.command &&
            rawTable.command.arguments &&
            rawTable.command.arguments.flags)
          table.flags = rawTable.command.arguments.flags.split('|');

        table.tokenFilters = '';
        if (rawTable.token_filters)
          table.tokenFilters = rawTable.token_filters.join('|'); // XXX what is the correct delimiter?

        table.keyType = null;
        if (rawTable.key_type) {
          table.keyType = {
            name: rawTable.key_type.name,
            isTextType: isTextType(rawTable.key_type.name)
          };
        }

        table.isArray           = table.type == 'array';
        table.isHashTable       = table.type == 'hash table';
        table.isPatriciaTrie    = table.type == 'patricia trie';
        table.isDoubleArrayTrie = table.type == 'double attay trie';
        table.hasKey            = !table.isArray;

        table.range  = table.valueType; // for backward compatibility
        table.domain = table.keyType && table.keyType.name; // for backward compatibility

        return table;
      }

      function buildTables(response) {
        var rawTables = response.tables();
        var tables = {};
        angular.forEach(rawTables, function(table, name) {
          tables[name] = buildTable(table);
        });
        return tables;
      }

      function resolveColumn(schema, column) {
        column.valueType = {
          name: column.range,
          isTextType: isTextType(column.range),
          isReferenceType: isReferenceType(schema, column.range)
        };
      }

      function resolveColumns(schema) {
        angular.forEach(schema.tables, function(table) {
          angular.forEach(table.columns, function(column) {
            resolveColumn(schema, column);
          });
        });
      }

      function resolveIndex(schema, column) {
        var table = schema.tables[column.range];
        column.sources.forEach(function(source) {
          var columnName;
          if (source.indexOf('.') === -1) {
            columnName = '_key';
          } else {
            columnName = source.split('.')[1];
          }
          var targetColumn = table.columns[columnName];
          targetColumn.indexes.push(column);
        });
      }

      function resolveIndexes(schema) {
        angular.forEach(schema.tables, function(table) {
          angular.forEach(table.columns, function(column) {
            if (column.isIndex) {
              resolveIndex(schema, column);
            }
          });
        });
      }

      function buildColumn(rawTable, rawColumn) {
        var column = {};
        column.id       = 0; // XXX it exists in a table_list response but missing in a schema response.
        column.name     = rawColumn.name;
        column.path     = ''; // XXX it exists in a table_list response but missing in a schema response.
        column.type     = rawColumn.type;
        column.sizeType = rawColumn.type;
        column.table    = rawTable;

        column.flags = [];
        if (rawColumn.command &&
            rawColumn.command.arguments &&
            rawColumn.command.arguments.flags)
          column.flags = rawColumn.command.arguments.flags.split('|');

        column.sources = [];
        if (rawColumn.sources)
          column.sources = rawColumn.sources.map(function(source) {
            return source.full_name;
          });

        column.valueType = null;
        if (rawColumn.value_type)
          column.valueType = {
            name: rawColumn.value_type.name,
            isTextType: isTextType(rawColumn.value_type.name),
            isReferenceType: rawColumn.value_type.type == 'reference'
          };

        column.isScalar = column.type == 'scalar';
        column.isVector = column.type == 'vector';
        column.isIndex  = column.type == 'index';

        column.range  = column.valueType && column.valueType.name; // for backward compatibility
        column.domain = rawTable.name; // for backward compatibility
        column.source = column.sources; // for backward compatibility

        column.indexes = [];
        return column;
      }

      function buildColumns(rawTable) {
        var columns = {};

        columns._id = {
          name:   '_id',
          id:     rawTable.id || 0,
          path:   rawTable.path || '',
          type:   'fix',
          flags:  ['COLUMN_SCALAR', 'PERSISTENT'],
          domain: rawTable.name,
          range:  'UInt32',
          source: null
        };

        if (rawTable.type != 'array') {
          columns._key = {
            name:    '_key',
            id:      rawTable.id || 0,
            path:    '',
            type:    'fix',
            flags:   ['COLUMN_SCALAR'],
            domain:  rawTable.name,
            range:   rawTable.key_type.name,
            source:  null,
            indexes: []
          };
        }

        angular.forEach(rawTable.columns, function(rawColumn, name) {
          columns[name] = buildColumn(rawTable, rawColumn);
        });

        return columns;
      }

      function fetchColumns(table) {
        return client.execute('schema')
          .success(function(response) {
            table.columns = buildColumns(response.tables()[table.name]);
          });
      }

      function fetchTables(schema) {
        schema.tables = {};
        return client.execute('schema')
          .success(function(response) {
            schema.tables = buildTables(response);

            var fetchColumnsTasks = [];
            angular.forEach(schema.tables, function(table) {
              fetchColumnsTasks.push(fetchColumns(table));
            });

            return $q.all(fetchColumnsTasks)
              .then(function() {
                resolveColumns(schema);
                resolveIndexes(schema);
                fetched = true;
                fetching = false;
                waitingDeferes.forEach(function(defer) {
                  defer.resolve(schema);
                });
                waitingDeferes = [];
                return schema;
              });
          });
      }

      schema = createSchema();

      return function() {
        var defer;
        var loader;
        if (fetching) {
          defer = $q.defer();
          waitingDeferes.push(defer);
          loader = defer.promise;
        } else if (fetched) {
          defer = $q.defer();
          $timeout(function() {
            defer.resolve(schema);
          });
          loader = defer.promise;
        } else {
          fetching = true;
          loader = fetchTables(schema);
        }
        loader.reload = function() {
          fetching = false;
          fetched = false;
          schema = createSchema();
        };
        return loader;
      };
    }]);
<commit_msg>Remove needless (obsolete) operations to resolve columns<commit_after>'use strict';

/**
 * @ngdoc function
 * @name groongaAdminApp.service:schemaLoader
 * @description
 * # schemaLoader
 * Groonga database schema loader.
 */
angular.module('groongaAdminApp')
  .factory('schemaLoader', [
    '$q', '$http', '$timeout',
    function ($q, $http, $timeout) {
      var fetching = false;
      var waitingDeferes = [];
      var fetched = false;
      var schema;
      var client = new GroongaClient($http);

      function createSchema() {
        var newSchema = {};
        fillTypes(newSchema);
        return newSchema;
      }

      function fillTypes(schema) {
        var builtinTypes = [
          {
            name: 'Bool'
          },
          {
            name: 'Int8'
          },
          {
            name: 'UInt8'
          },
          {
            name: 'Int16'
          },
          {
            name: 'UInt16'
          },
          {
            name: 'Int32'
          },
          {
            name: 'UInt32'
          },
          {
            name: 'Int64'
          },
          {
            name: 'UInt64'
          },
          {
            name: 'Float'
          },
          {
            name: 'Time'
          },
          {
            name: 'ShortText'
          },
          {
            name: 'Text'
          },
          {
            name: 'LongText'
          },
          {
            name: 'TokyoGeoPoint'
          },
          {
            name: 'WGS84GeoPoint'
          }
        ];
        schema.types = {};
        angular.forEach(builtinTypes, function(type) {
          schema.types[type.name] = type;
        });
      }

      function isTextType(typeName) {
        switch (typeName) {
        case 'ShortText':
        case 'Text':
        case 'LongText':
          return true;
        default:
          return false;
        }
      }

      function buildTable(rawTable) {
        var table = {};
        table.id           = 0; // XXX it exists in a table_list response but missing in a schema response.
        table.name         = rawTable.name;
        table.path         = ''; // XXX it exists in a table_list response but missing in a schema response.
        table.valueType    = rawTable.value_type && rawTable.value_type.name
        table.tokenizer    = rawTable.tokenizer && rawTable.tokenizer.name;
        table.normalizer   = rawTable.normalizer && rawTable.normalizer.name;
        table.type         = rawTable.type;

        table.flags = [];
        if (rawTable.command &&
            rawTable.command.arguments &&
            rawTable.command.arguments.flags)
          table.flags = rawTable.command.arguments.flags.split('|');

        table.tokenFilters = '';
        if (rawTable.token_filters)
          table.tokenFilters = rawTable.token_filters.join('|'); // XXX what is the correct delimiter?

        table.keyType = null;
        if (rawTable.key_type) {
          table.keyType = {
            name: rawTable.key_type.name,
            isTextType: isTextType(rawTable.key_type.name)
          };
        }

        table.isArray           = table.type == 'array';
        table.isHashTable       = table.type == 'hash table';
        table.isPatriciaTrie    = table.type == 'patricia trie';
        table.isDoubleArrayTrie = table.type == 'double attay trie';
        table.hasKey            = !table.isArray;

        table.range  = table.valueType; // for backward compatibility
        table.domain = table.keyType && table.keyType.name; // for backward compatibility

        return table;
      }

      function buildTables(response) {
        var rawTables = response.tables();
        var tables = {};
        angular.forEach(rawTables, function(table, name) {
          tables[name] = buildTable(table);
        });
        return tables;
      }

      function resolveIndex(schema, column) {
        var table = schema.tables[column.range];
        column.sources.forEach(function(source) {
          var columnName;
          if (source.indexOf('.') === -1) {
            columnName = '_key';
          } else {
            columnName = source.split('.')[1];
          }
          var targetColumn = table.columns[columnName];
          targetColumn.indexes.push(column);
        });
      }

      function resolveIndexes(schema) {
        angular.forEach(schema.tables, function(table) {
          angular.forEach(table.columns, function(column) {
            if (column.isIndex) {
              resolveIndex(schema, column);
            }
          });
        });
      }

      function buildColumn(rawTable, rawColumn) {
        var column = {};
        column.id       = 0; // XXX it exists in a table_list response but missing in a schema response.
        column.name     = rawColumn.name;
        column.path     = ''; // XXX it exists in a table_list response but missing in a schema response.
        column.type     = rawColumn.type;
        column.sizeType = rawColumn.type;
        column.table    = rawTable;

        column.flags = [];
        if (rawColumn.command &&
            rawColumn.command.arguments &&
            rawColumn.command.arguments.flags)
          column.flags = rawColumn.command.arguments.flags.split('|');

        column.sources = [];
        if (rawColumn.sources)
          column.sources = rawColumn.sources.map(function(source) {
            return source.full_name;
          });

        column.valueType = null;
        if (rawColumn.value_type)
          column.valueType = {
            name: rawColumn.value_type.name,
            isTextType: isTextType(rawColumn.value_type.name),
            isReferenceType: rawColumn.value_type.type == 'reference'
          };

        column.isScalar = column.type == 'scalar';
        column.isVector = column.type == 'vector';
        column.isIndex  = column.type == 'index';

        column.range  = column.valueType && column.valueType.name; // for backward compatibility
        column.domain = rawTable.name; // for backward compatibility
        column.source = column.sources; // for backward compatibility

        column.indexes = [];
        return column;
      }

      function buildColumns(rawTable) {
        var columns = {};

        columns._id = {
          name:   '_id',
          id:     rawTable.id || 0,
          path:   rawTable.path || '',
          type:   'fix',
          flags:  ['COLUMN_SCALAR', 'PERSISTENT'],
          domain: rawTable.name,
          range:  'UInt32',
          source: null
        };

        if (rawTable.type != 'array') {
          columns._key = {
            name:    '_key',
            id:      rawTable.id || 0,
            path:    '',
            type:    'fix',
            flags:   ['COLUMN_SCALAR'],
            domain:  rawTable.name,
            range:   rawTable.key_type.name,
            source:  null,
            indexes: []
          };
        }

        angular.forEach(rawTable.columns, function(rawColumn, name) {
          columns[name] = buildColumn(rawTable, rawColumn);
        });

        return columns;
      }

      function fetchColumns(table) {
        return client.execute('schema')
          .success(function(response) {
            table.columns = buildColumns(response.tables()[table.name]);
          });
      }

      function fetchTables(schema) {
        schema.tables = {};
        return client.execute('schema')
          .success(function(response) {
            schema.tables = buildTables(response);

            var fetchColumnsTasks = [];
            angular.forEach(schema.tables, function(table) {
              fetchColumnsTasks.push(fetchColumns(table));
            });

            return $q.all(fetchColumnsTasks)
              .then(function() {
                resolveIndexes(schema);
                fetched = true;
                fetching = false;
                waitingDeferes.forEach(function(defer) {
                  defer.resolve(schema);
                });
                waitingDeferes = [];
                return schema;
              });
          });
      }

      schema = createSchema();

      return function() {
        var defer;
        var loader;
        if (fetching) {
          defer = $q.defer();
          waitingDeferes.push(defer);
          loader = defer.promise;
        } else if (fetched) {
          defer = $q.defer();
          $timeout(function() {
            defer.resolve(schema);
          });
          loader = defer.promise;
        } else {
          fetching = true;
          loader = fetchTables(schema);
        }
        loader.reload = function() {
          fetching = false;
          fetched = false;
          schema = createSchema();
        };
        return loader;
      };
    }]);
<|endoftext|>


<commit_before>import { computed } from '@ember/object';
import { htmlSafe } from '@ember/template';

// An Ember.Computed property for transforming an object into an
// html compatible style attribute
//
// ex. styleProps: { color: '#FF0', border-width: '1px' }
//     styleStr: styleStringProperty('styleProps') // color:#FF0;border-width:1px
export default function styleStringProperty(prop) {
  return computed(prop, function() {
    const styles = this.get(prop);
    let str = '';

    if (styles) {
      str = Object.keys(styles)
        .reduce(function(arr, key) {
          const val = styles[key];
          arr.push(key + ':' + (typeof val === 'number' ? val.toFixed(2) + 'px' : val));
          return arr;
        }, [])
        .join(';');
    }

    return htmlSafe(str);
  });
}
<commit_msg>Make the style-string property glimmer safe<commit_after>import { computed, get } from '@ember/object';
import { htmlSafe } from '@ember/template';

// An Ember.Computed property for transforming an object into an
// html compatible style attribute
//
// ex. styleProps: { color: '#FF0', border-width: '1px' }
//     styleStr: styleStringProperty('styleProps') // color:#FF0;border-width:1px
export default function styleStringProperty(prop) {
  return computed(prop, function() {
    const styles = get(this, prop);
    let str = '';

    if (styles) {
      str = Object.keys(styles)
        .reduce(function(arr, key) {
          const val = styles[key];
          arr.push(key + ':' + (typeof val === 'number' ? val.toFixed(2) + 'px' : val));
          return arr;
        }, [])
        .join(';');
    }

    return htmlSafe(str);
  });
}
<|endoftext|>