<commit_before>

describe('Deployment/CI Search View Tests', function () {

    context('/search/?type=Item', function () {

        before(function(){ // beforeAll
            cy.visit('/search/');
        });

        it('Has at least 100 results for /search/?type=Item', function () {
            cy.location('search').should('include', 'type=Item').end()
                .get('.search-results-container .search-result-row').then(($searchResultElems)=>{
                    expect($searchResultElems.length).to.equal(25);
                }).end()
                .searchPageTotalResultCount().should('be.greaterThan', 100);
        });

    });

    context('/search/?type=Page', function(){

        before(function(){ // beforeAll
            cy.visit('/pages'); // We should get redirected to ?type=Page
        });

        beforeEach(function(){
            // Ensure we preserve search session cookie for proper ordering.
            Cypress.Cookies.preserveOnce("searchSessionID");
        });

        it('Should redirect to /search/?type=Page correctly', function(){
            cy.location('search').should('include', 'type=Page').end()
                .location('pathname').should('include', '/search/');
        });

        it('Should have at least 20 results.', function(){
            cy.get('.search-results-container .search-result-row').then(($searchResultElems)=>{
                expect($searchResultElems.length).to.be.greaterThan(20);
            });
        });

    });

    context('Search Box in Navigation', function(){

        before(function(){ // beforeAll
            cy.visit('/'); // Start at home page
        });

        beforeEach(function(){
            // Ensure we preserve search session cookie for proper ordering.
            Cypress.Cookies.preserveOnce("searchSessionID");
        });

        it('SearchBox input works, goes to /browse/ on submit', function(){
            cy.get('input[name="q"]').focus().type('mouse').wait(10).end()
                .get('form.navbar-search-form-container').submit().end()
                .wait(300).get('#slow-load-container').should('not.have.class', 'visible').end()
                .get('#page-title-container span.title').should('have.text', 'Data Browser').end() // Make sure we got redirected to /browse/. We may or may not have results here depending on if on local and logged out or not.
                .location('search')
                .should('include', 'ExperimentSetReplicate')
                .should('include', 'q=mouse');
        });

        it('"All Items" option works, takes us to search page', function(){
            cy.get('form.navbar-search-form-container button#search-item-type-selector').click().wait(100).end()
                .get('form.navbar-search-form-container div.dropdown-menu a:not(.active)').click().end()
                .get('form.navbar-search-form-container').submit().end()
                .get('#page-title-container span.title').should('have.text', 'Search').end()
                .location('search').should('not.include', 'award.project=4DN')
                .should('include', 'q=mouse').end()
                .searchPageTotalResultCount().should('be.greaterThan', 0);
        });

        it('Clear search button works ==> more results', function(){
            cy.searchPageTotalResultCount().then((origTotalResults)=>{
                cy.get('form.navbar-search-form-container .reset-button').click().end()
                    .wait(1200).get('#slow-load-container').should('not.have.class', 'visible').end()
                    .searchPageTotalResultCount().should('be.greaterThan', origTotalResults);
            });
        });

        it('Wildcard query string returns all results.', function(){
            cy.window().screenshot('Before text search "*"').end().searchPageTotalResultCount().then((origTotalResults)=>{
                cy.get('input[name="q"]').focus().clear().type('*').wait(10).end()
                    .get('form.navbar-search-form-container').submit().end()
                    .get('form.navbar-search-form-container button#search-item-type-selector').click().wait(100).end()
                    .get('form.navbar-search-form-container div.dropdown-menu a:not(.active)').click().end()
                    .get('form.navbar-search-form-container').submit().end()
                    // handle url encoding
                    .location('search').should('include', '%2A').wait(300).end()
                    .get('#slow-load-container').should('not.have.class', 'visible').end()
                    .searchPageTotalResultCount().should('be.greaterThan', 1).should('equal', origTotalResults).end().window().screenshot('After text search "*"').end();
            });
        });

    });

});
<commit_msg>fix of 4a test<commit_after>

describe('Deployment/CI Search View Tests', function () {

    context('/search/?type=Item', function () {

        before(function(){ // beforeAll
            cy.visit('/search/');
        });

        it('Has at least 100 results for /search/?type=Item', function () {
            cy.location('search').should('include', 'type=Item').end()
                .get('.search-results-container .search-result-row').then(($searchResultElems)=>{
                    expect($searchResultElems.length).to.equal(25);
                }).end()
                .searchPageTotalResultCount().should('be.greaterThan', 100);
        });

    });

    context('/search/?type=Page', function(){

        before(function(){ // beforeAll
            cy.visit('/pages'); // We should get redirected to ?type=Page
        });

        beforeEach(function(){
            // Ensure we preserve search session cookie for proper ordering.
            Cypress.Cookies.preserveOnce("searchSessionID");
        });

        it('Should redirect to /search/?type=Page correctly', function(){
            cy.location('search').should('include', 'type=Page').end()
                .location('pathname').should('include', '/search/');
        });

        it('Should have at least 20 results.', function(){
            cy.get('.search-results-container .search-result-row').then(($searchResultElems)=>{
                expect($searchResultElems.length).to.be.greaterThan(20);
            });
        });

    });

    context('Search Box in Navigation', function(){

        before(function(){ // beforeAll
            cy.visit('/'); // Start at home page
        });

        beforeEach(function(){
            // Ensure we preserve search session cookie for proper ordering.
            Cypress.Cookies.preserveOnce("searchSessionID");
        });

        it('SearchBox input works, goes to /browse/ on submit', function(){
            cy.get('input[name="q"]').focus().type('mouse').wait(10).end()
                .get('form.navbar-search-form-container').submit().end()
                .wait(300).get('#slow-load-container').should('not.have.class', 'visible').end()
                .get('#page-title-container span.title').should('have.text', 'Data Browser').end() // Make sure we got redirected to /browse/. We may or may not have results here depending on if on local and logged out or not.
                .location('search')
                .should('include', 'ExperimentSetReplicate')
                .should('include', 'q=mouse');
        });

        it('"All Items" option works, takes us to search page', function(){
            cy.get('form.navbar-search-form-container button#search-item-type-selector').click().wait(100).end()
                .get('form.navbar-search-form-container div.dropdown-menu a[data-key="all"]').click().end()
                .get('form.navbar-search-form-container').submit().end()
                .get('#page-title-container span.title').should('have.text', 'Search').end()
                .location('search').should('not.include', 'award.project=4DN')
                .should('include', 'q=mouse').end()
                .searchPageTotalResultCount().should('be.greaterThan', 0);
        });

        it('Clear search button works ==> more results', function(){
            cy.searchPageTotalResultCount().then((origTotalResults)=>{
                cy.get('form.navbar-search-form-container .reset-button').click().end()
                    .wait(1200).get('#slow-load-container').should('not.have.class', 'visible').end()
                    .searchPageTotalResultCount().should('be.greaterThan', origTotalResults);
            });
        });

        it('Wildcard query string returns all results.', function(){
            cy.window().screenshot('Before text search "*"').end().searchPageTotalResultCount().then((origTotalResults)=>{
                cy.get('input[name="q"]').focus().clear().type('*').wait(10).end()
                    .get('form.navbar-search-form-container').submit().end()
                    .get('form.navbar-search-form-container button#search-item-type-selector').click().wait(100).end()
                    .get('form.navbar-search-form-container div.dropdown-menu a[data-key="all"]').click().end()
                    .get('form.navbar-search-form-container').submit().end()
                    // handle url encoding
                    .location('search').should('include', '%2A').wait(300).end()
                    .get('#slow-load-container').should('not.have.class', 'visible').end()
                    .searchPageTotalResultCount().should('be.greaterThan', 1).should('equal', origTotalResults).end().window().screenshot('After text search "*"').end();
            });
        });

    });

});
<|endoftext|>


<commit_before>var FromMeshCustomShader = E2.plugins["from_mesh_custom_shader"] = function(core, node) {
	this.desc = 'Auto-generate a shader embedding user-defined main bodies tailored to correctly and optimally render the supplied mesh.'

	this.input_slots = [
		 { name: 'mesh', dt: core.datatypes.MESH, desc: 'Mesh to adapt the shader to.', def: null },
		 { name: 'material', dt: core.datatypes.MATERIAL, desc: 'The surface material.', def: null }
	]

	this.output_slots = [
		{ name: 'shader', dt: core.datatypes.SHADER, desc: 'The resulting shader.' }
	]

	this.state = {
		vs_src: '',
		ps_src: '',
		changed: false,
		slot_ids: {}
	}

	this.core = core
	this.node = node
	this.gl = core.renderer.context
	this.shader = null
	this.slot_data = []
}

FromMeshCustomShader.prototype.create_ui = function() {
	var that = this
	var layout = make('div')
	var vertexButton = makeButton('Vertex', 'Click to edit the vertex shader source.')
	var pixelButton = makeButton('Pixel', 'Click to edit the pixel shader source.')

	this._editors = {}

	function removeSlot(slot) {
		that.node.remove_slot(E2.slot_type.input, slot.id)
		delete that.state.slot_ids[slot.name]
	}

	function addSlot(name, dt) {
		var slotId = that.node.add_slot(E2.slot_type.input, { name: name, dt: dt })
		that.state.slot_ids[name] = { id: slotId, dt: dt, uniform: null }
		that.slot_data[slotId] = that.core.get_default_value(E2.slot_type.input, dt)
	}

	vertexButton.css('width', '55px')
	pixelButton.css({ 'width': '55px', 'margin-top': '5px' })

	function createEditor(which, srcId) {
		if (that._editors[which]) {
			that._editors[which].show()
			return
		}

		var title = that.node.parent_graph.getTitle() + '/' + which+' shader'

		that._editors[which] = E2.ShaderEditor
			.open(title, that.state[srcId], that.state.slot_ids)
			.on('closed', function() {
				that._editors[which] = null
			})
			.on('inputRemoved', function(slot) {
				removeSlot(slot)
				that.updated = that.dirty = true
				that.node.queued_update = 1
				that.state.changed = true
			})
			.on('inputAdded', function(inputName, dt) {
				addSlot(inputName, dt)
				that.updated = that.dirty = true
				that.node.queued_update = 1
				that.state.changed = true
			})
			.on('build', function() {
				that.updated = that.dirty = true
			})
			.on('changed', function(v) {
				that.updated = true
				that.node.queued_update = 1
				that.state[srcId] = v
				that.state.changed = true
			})

		that._editors[which]._ace
	}

	vertexButton.click(function() {
		createEditor('vertex', 'vs_src')
	})

	pixelButton.click(function() {
		createEditor('pixel', 'ps_src')
	})

	layout.append(vertexButton)
	layout.append(make('br'))
	layout.append(pixelButton)

	return layout
}

FromMeshCustomShader.prototype.connection_changed = function(on, conn, slot) {
	if (!on && slot.type === E2.slot_type.input) {
		if(slot.index === 0)
			this.shader = null
	}
}

FromMeshCustomShader.prototype.rebuild_shader = function() {
	var u_vs = [];
	var u_ps = [];
	var st = this.state;
	var gl = this.gl;
	var dts = this.core.datatypes;
	var that = this;

	for(var ident in st.slot_ids) {
		var dt = '';
		var slot = st.slot_ids[ident];
		var dtid = slot.dt.id;

		if(dtid === dts.FLOAT.id)
			dt = 'float';
		else if(dtid === dts.TEXTURE.id)
			dt = 'sampler2D';
		else if(dtid === dts.COLOR.id)
			dt = 'vec4';
		else if(dtid === dts.MATRIX.id)
			dt = 'mat4';
		else if(dtid === dts.VECTOR.id)
			dt = 'vec3';

		u_vs.push('uniform ' + dt + ' ' + ident + ';');
		u_ps.push('uniform ' + dt + ' ' + ident + ';');
	}

	function onCompiled(which) {
		return function(err) {
			that.updated = that.dirty = false;

			if (!that._editors || !that._editors[which])
				return;

			var ace = that._editors[which].getAce()
			ace.getSession().clearAnnotations()

			if (!err)
				return;

			console.warn('shader', which, 'errors', err)

			ace.getSession().setAnnotations(err)
		}
	}

	this.shader = ComposeShader(null, this.mesh, this.material,
		u_vs, u_ps,
		st.vs_src && st.changed ? st.vs_src : null,
		st.ps_src && st.changed ? st.ps_src : null,
		onCompiled('vertex'),
		onCompiled('pixel'));

	if (this.shader.linked) {
		for(var ident in st.slot_ids) {
			var slot = st.slot_ids[ident]
			slot.uniform = gl.getUniformLocation(this.shader.program, ident)
		}

		this.shader.apply_uniforms_custom = function(self) { return function()
		{
			var tex_slot = 1;
			var sd = self.slot_data;
			var dts = self.core.datatypes;

			for(var ident in st.slot_ids)
			{
				var slot = st.slot_ids[ident];

				if(slot.uniform === null || sd[slot.id] === undefined || sd[slot.id] === null)
					continue;

				var dtid = slot.dt.id;

				if(dtid === dts.FLOAT.id)
					gl.uniform1f(slot.uniform, sd[slot.id]);
				else if(dtid === dts.TEXTURE.id)
				{
					gl.uniform1i(slot.uniform, tex_slot);
					sd[slot.id].enable(gl.TEXTURE0 + tex_slot);
					tex_slot++;
				}
				else if(dtid === dts.COLOR.id)
					gl.uniform4fv(slot.uniform, sd[slot.id]);
				else if(dtid === dts.MATRIX.id)
					gl.uniformMatrix4fv(slot.uniform, false, sd[slot.id]);
				else if(dtid === dts.VECTOR.id)
					gl.uniform3fv(slot.uniform, sd[slot.id]);
			}
		}}(this);
	}

	if(st.vs_src === '')
		st.vs_src = this.shader.vs_c_src;

	if(st.ps_src === '')
		st.ps_src = this.shader.ps_c_src;
};

FromMeshCustomShader.prototype.update_input = function(slot, data)
{
	if(slot.uid === undefined)
	{
		if(slot.index === 0)
		{
			if(this.mesh !== data)
			{
				this.mesh = data;
				this.dirty = true;
			}
		}
		else if(slot.index === 1)
		{
			this.material = data;
		}
	}
	else
	{
		this.slot_data[slot.uid] = data;
	}
};

FromMeshCustomShader.prototype.update_state = function()
{
	if(!this.mesh)
		return;

	var caps = Material.get_caps_hash(this.mesh, this.material);

	if(!this.dirty && this.caps_hash === caps)
	{
		if (this.shader)
			this.shader.material = this.material;
		return;
	}

	if(this.dirty || this.caps_hash !== caps)
		this.rebuild_shader();

	this.caps_hash = caps;
	this.updated = true;
	this.dirty = false;
};

FromMeshCustomShader.prototype.update_output = function(slot)
{
	return this.shader;
};

FromMeshCustomShader.prototype.state_changed = function(ui)
{
	if(!ui)
	{
		this.mesh = null;
		this.material = null;
		this.caps_mask = '';
		this.dirty = false;
	}
	else
	{
		this.core.add_aux_script('ace/src-noconflict/ace.js');
	}
};
<commit_msg>more unique title for shader tab; update canvas after removing input<commit_after>var FromMeshCustomShader = E2.plugins["from_mesh_custom_shader"] = function(core, node) {
	this.desc = 'Auto-generate a shader embedding user-defined main bodies tailored to correctly and optimally render the supplied mesh.'

	this.input_slots = [
		 { name: 'mesh', dt: core.datatypes.MESH, desc: 'Mesh to adapt the shader to.', def: null },
		 { name: 'material', dt: core.datatypes.MATERIAL, desc: 'The surface material.', def: null }
	]

	this.output_slots = [
		{ name: 'shader', dt: core.datatypes.SHADER, desc: 'The resulting shader.' }
	]

	this.state = {
		vs_src: '',
		ps_src: '',
		changed: false,
		slot_ids: {}
	}

	this.core = core
	this.node = node
	this.gl = core.renderer.context
	this.shader = null
	this.slot_data = []
}

FromMeshCustomShader.prototype.create_ui = function() {
	var that = this
	var layout = make('div')
	var vertexButton = makeButton('Vertex', 'Click to edit the vertex shader source.')
	var pixelButton = makeButton('Pixel', 'Click to edit the pixel shader source.')

	this._editors = {}

	function removeSlot(slot) {
		that.node.remove_slot(E2.slot_type.input, slot.id)
		delete that.state.slot_ids[slot.name]
		E2.app.updateCanvas()
	}

	function addSlot(name, dt) {
		var slotId = that.node.add_slot(E2.slot_type.input, { name: name, dt: dt })
		that.state.slot_ids[name] = { id: slotId, dt: dt, uniform: null }
		that.slot_data[slotId] = that.core.get_default_value(E2.slot_type.input, dt)
	}

	vertexButton.css('width', '55px')
	pixelButton.css({ 'width': '55px', 'margin-top': '5px' })

	function createEditor(which, srcId) {
		if (that._editors[which]) {
			that._editors[which].show()
			return
		}

		var id = ['', that.node.parent_graph.uid, that.node.uid].join('/')
		var title = [which, 'shader', id].join(' ')

		that._editors[which] = E2.ShaderEditor
			.open(title, that.state[srcId], that.state.slot_ids)
			.on('closed', function() {
				that._editors[which] = null
			})
			.on('inputRemoved', function(slot) {
				removeSlot(slot)
				that.updated = that.dirty = true
				that.node.queued_update = 1
				that.state.changed = true
			})
			.on('inputAdded', function(inputName, dt) {
				addSlot(inputName, dt)
				that.updated = that.dirty = true
				that.node.queued_update = 1
				that.state.changed = true
			})
			.on('build', function() {
				that.updated = that.dirty = true
			})
			.on('changed', function(v) {
				that.updated = true
				that.node.queued_update = 1
				that.state[srcId] = v
				that.state.changed = true
			})

		that._editors[which]._ace
	}

	vertexButton.click(function() {
		createEditor('vertex', 'vs_src')
	})

	pixelButton.click(function() {
		createEditor('pixel', 'ps_src')
	})

	layout.append(vertexButton)
	layout.append(make('br'))
	layout.append(pixelButton)

	return layout
}

FromMeshCustomShader.prototype.connection_changed = function(on, conn, slot) {
	if (!on && slot.type === E2.slot_type.input) {
		if(slot.index === 0)
			this.shader = null
	}
}

FromMeshCustomShader.prototype.rebuild_shader = function() {
	var u_vs = [];
	var u_ps = [];
	var st = this.state;
	var gl = this.gl;
	var dts = this.core.datatypes;
	var that = this;

	for(var ident in st.slot_ids) {
		var dt = '';
		var slot = st.slot_ids[ident];
		var dtid = slot.dt.id;

		if(dtid === dts.FLOAT.id)
			dt = 'float';
		else if(dtid === dts.TEXTURE.id)
			dt = 'sampler2D';
		else if(dtid === dts.COLOR.id)
			dt = 'vec4';
		else if(dtid === dts.MATRIX.id)
			dt = 'mat4';
		else if(dtid === dts.VECTOR.id)
			dt = 'vec3';

		u_vs.push('uniform ' + dt + ' ' + ident + ';');
		u_ps.push('uniform ' + dt + ' ' + ident + ';');
	}

	function onCompiled(which) {
		return function(err) {
			that.updated = that.dirty = false;

			if (!that._editors || !that._editors[which])
				return;

			var ace = that._editors[which].getAce()
			ace.getSession().clearAnnotations()

			if (!err)
				return;

			console.warn('shader', which, 'errors', err)

			ace.getSession().setAnnotations(err)
		}
	}

	this.shader = ComposeShader(null, this.mesh, this.material,
		u_vs, u_ps,
		st.vs_src && st.changed ? st.vs_src : null,
		st.ps_src && st.changed ? st.ps_src : null,
		onCompiled('vertex'),
		onCompiled('pixel'));

	if (this.shader.linked) {
		for(var ident in st.slot_ids) {
			var slot = st.slot_ids[ident]
			slot.uniform = gl.getUniformLocation(this.shader.program, ident)
		}

		this.shader.apply_uniforms_custom = function(self) { return function()
		{
			var tex_slot = 1;
			var sd = self.slot_data;
			var dts = self.core.datatypes;

			for(var ident in st.slot_ids)
			{
				var slot = st.slot_ids[ident];

				if(slot.uniform === null || sd[slot.id] === undefined || sd[slot.id] === null)
					continue;

				var dtid = slot.dt.id;

				if(dtid === dts.FLOAT.id)
					gl.uniform1f(slot.uniform, sd[slot.id]);
				else if(dtid === dts.TEXTURE.id)
				{
					gl.uniform1i(slot.uniform, tex_slot);
					sd[slot.id].enable(gl.TEXTURE0 + tex_slot);
					tex_slot++;
				}
				else if(dtid === dts.COLOR.id)
					gl.uniform4fv(slot.uniform, sd[slot.id]);
				else if(dtid === dts.MATRIX.id)
					gl.uniformMatrix4fv(slot.uniform, false, sd[slot.id]);
				else if(dtid === dts.VECTOR.id)
					gl.uniform3fv(slot.uniform, sd[slot.id]);
			}
		}}(this);
	}

	if(st.vs_src === '')
		st.vs_src = this.shader.vs_c_src;

	if(st.ps_src === '')
		st.ps_src = this.shader.ps_c_src;
};

FromMeshCustomShader.prototype.update_input = function(slot, data)
{
	if(slot.uid === undefined)
	{
		if(slot.index === 0)
		{
			if(this.mesh !== data)
			{
				this.mesh = data;
				this.dirty = true;
			}
		}
		else if(slot.index === 1)
		{
			this.material = data;
		}
	}
	else
	{
		this.slot_data[slot.uid] = data;
	}
};

FromMeshCustomShader.prototype.update_state = function()
{
	if(!this.mesh)
		return;

	var caps = Material.get_caps_hash(this.mesh, this.material);

	if(!this.dirty && this.caps_hash === caps)
	{
		if (this.shader)
			this.shader.material = this.material;
		return;
	}

	if(this.dirty || this.caps_hash !== caps)
		this.rebuild_shader();

	this.caps_hash = caps;
	this.updated = true;
	this.dirty = false;
};

FromMeshCustomShader.prototype.update_output = function(slot)
{
	return this.shader;
};

FromMeshCustomShader.prototype.state_changed = function(ui)
{
	if(!ui)
	{
		this.mesh = null;
		this.material = null;
		this.caps_mask = '';
		this.dirty = false;
	}
	else
	{
		this.core.add_aux_script('ace/src-noconflict/ace.js');
	}
};
<|endoftext|>


<commit_before>// Collection of all users (registered accounts with 'user' role)

'use strict';

module.exports = require('mano').db.User.find('roles', 'user');
<commit_msg>#915 cleanup<commit_after><|endoftext|>


<commit_before>module.exports = function() {
  'use strict';

  DependencyInjection.model('PhotoModel', function($AbstractModel, $RealTimeService) {

    var REALTIME_EVENTS = {
          photos: {
            permissions: ['photos-access'],
            call: 'callPhotos'
          }
        },
        PERMISSIONS = {
          'photos-access': {
            title: 'Access to the Photos app',
            description: 'Access to the Photos app.',
            isPublic: true
          },
          'photos-moments': {
            title: 'Moments administration',
            description: 'Moments administration of the Photos app.',
            isPublic: true
          },
          'photos-people': {
            title: 'People administration',
            description: 'People administration of the Photos app.',
            isPublic: true
          }
        };

    return $AbstractModel('PhotoModel', function() {

      var extend = require('extend'),
          async = require('async'),
          fs = require('fs-extra'),
          path = require('path'),
          _mediaFolder = path.resolve('media');

      return {
        identity: 'photos',
        entities: true,
        entityType: 'photo',
        isSearchable: true,
        isSearchableAdvanced: true,
        attributes: {
          shotDate: {
            type: 'date',
            index: true
          },
          shotTime: {
            type: 'integer',
            index: true
          },
          sourceModifiedAt: 'integer',
          name: {
            type: 'string',
            index: true
          },
          source: {
            type: 'string',
            index: true
          },
          url: {
            type: 'string',
            index: true
          },
          cover: 'string',
          isVideo: 'boolean',
          moments: {
            type: 'array',
            index: true
          },
          people: {
            type: 'array',
            index: true
          },

          publicData: function(moreData, remove) {
            var photo = this.toJSON();

            delete photo.isSearchable;
            delete photo.isSearchableAdvanced;
            delete photo.entityType;

            if (moreData) {
              extend(true, photo, moreData);
            }

            if (remove) {
              remove.forEach(function(removeKey) {
                delete photo[removeKey];
              });
            }

            return photo;
          }
        },

        init: function() {
          var _this = this,
              GroupModel = DependencyInjection.injector.model.get('GroupModel'),
              $RealTimeService = DependencyInjection.injector.model.get('$RealTimeService');

          GroupModel.registerPermissions(PERMISSIONS);

          Object.keys(REALTIME_EVENTS).forEach(function(eventName) {
            if (REALTIME_EVENTS[eventName].call) {
              var call = REALTIME_EVENTS[eventName].call;

              REALTIME_EVENTS[eventName].call = function() {
                _this[call].apply(_this, arguments);
              };
            }
          });

          $RealTimeService.registerEvents(REALTIME_EVENTS);
        },

        callPhotos: function($socket, eventName, args, callback, addOnly, socketOrigin) {
          eventName = eventName || 'photos';

          var sockets = $socket ? [$socket] : $RealTimeService.socketsFromOrigin(eventName);

          this
            .find()
            .sort({
              shotTime: 'desc'
            })
            .exec(function(err, photos) {
              if (err || !photos) {
                return callback();
              }

              var photosLength = 0,
                  videosLength = 0;

              photos = photos.map(function(photo) {
                if (photo.isVideo) {
                  videosLength++;
                }
                else {
                  photosLength++;
                }

                return {
                  cover: photo.cover,
                  shotTime: photo.shotTime,
                  isVideo: photo.isVideo,
                  thumbnail: photo.thumbnail,
                  url: photo.url,
                  moments: photo.moments,
                  people: photo.people
                };
              });

              var eventResult = {
                photosLength: photosLength,
                videosLength: videosLength,
                photos: photos
              };

              if (addOnly) {
                eventResult.addOnly = true;
              }

              sockets.forEach(function(socket) {
                eventResult.isOrigin = socket == $socket || socket == socketOrigin || false;

                $RealTimeService.fire(eventName, eventResult, socket);
              });
            });
        },

        updateMoment: function($socket, name, photos) {
          var _this = this;

          this
            .find({
              url: photos
            })
            .exec(function(err, photos) {
              if (err || !photos || !photos.length) {
                return;
              }

              async.eachSeries(photos, function(photo, nextPhoto) {
                photo.moments = photo.moments || [];

                if (photo.moments.indexOf(name) > -1) {
                  return nextPhoto();
                }

                photo.moments.push(name);

                _this
                  .update({
                    id: photo.id
                  }, {
                    moments: photo.moments
                  })
                  .exec(function() {
                    nextPhoto();
                  });
              }, function() {
                setTimeout(function() {
                  _this.callPhotos(null, null, null, null, true, $socket);
                });
              });
            });
        },

        deleteMoment: function($socket, names, photos) {
          var _this = this;

          this
            .find({
              url: photos
            })
            .exec(function(err, photos) {
              if (err || !photos || !photos.length) {
                return;
              }

              async.eachSeries(photos, function(photo, nextPhoto) {
                photo.moments = photo.moments || [];

                var hasRemoved = false;

                names.forEach(function(name) {
                  var index = photo.moments.indexOf(name);

                  if (index > -1) {
                    photo.moments.splice(index, 1);

                    hasRemoved = true;
                  }
                })

                if (!hasRemoved) {
                  return nextPhoto();
                }

                _this
                  .update({
                    id: photo.id
                  }, {
                    moments: photo.moments
                  })
                  .exec(function() {
                    nextPhoto();
                  });
              }, function() {
                setTimeout(function() {
                  _this.callPhotos();
                });
              });

            });
        },

        updatePeople: function($socket, name, photos) {
          var _this = this;

          this
            .find({
              url: photos
            })
            .exec(function(err, photos) {
              if (err || !photos || !photos.length) {
                return;
              }

              async.eachSeries(photos, function(photo, nextPhoto) {
                photo.people = photo.people || [];

                if (photo.people.indexOf(name) > -1) {
                  return nextPhoto();
                }

                photo.people.push(name);

                _this
                  .update({
                    id: photo.id
                  }, {
                    people: photo.people
                  })
                  .exec(function() {
                    nextPhoto();
                  });
              }, function() {
                var identityFile = path.join(_mediaFolder, 'photos/people/' + name + '.jpg');

                if (!fs.existsSync(identityFile)) {
                  fs.copySync(path.resolve(__dirname, '../views/resources/identity.jpg'), identityFile);
                }

                setTimeout(function() {
                  _this.callPhotos(null, null, null, null, true, $socket);
                });
              });

            });
        },

        deletePeople: function($socket, photos) {
          var _this = this;

          this
            .find({
              url: photos
            })
            .exec(function(err, photos) {
              if (err || !photos || !photos.length) {
                return;
              }

              async.eachSeries(photos, function(photo, nextPhoto) {
                if (!photo.people || !photo.people.length) {
                  return nextPhoto();
                }

                photo.people = [];

                _this
                  .update({
                    id: photo.id
                  }, {
                    people: photo.people
                  })
                  .exec(function() {
                    nextPhoto();
                  });
              }, function() {
                setTimeout(function() {
                  _this.callPhotos();
                });
              });

            });
        },

        updateAvatar: function($socket, name, photos) {
          this
            .findOne({
              url: photos[0]
            })
            .exec(function(err, photo) {
              if (err || !photo) {
                return;
              }

              var identityFile = path.join(_mediaFolder, 'photos/people/' + name + '.jpg'),
                  sourceFile = path.join(_mediaFolder, photo.cover.replace('/media/', ''));

              fs.copySync(sourceFile, identityFile);

              $socket.emit('read(photos/avatar)', {
                name: name
              });
            });
        }
      };

    });

  });

  return 'PhotoModel';
};
<commit_msg>fix(photos photo model): people and moments names don't differt on different case formating<commit_after>module.exports = function() {
  'use strict';

  DependencyInjection.model('PhotoModel', function($AbstractModel, $RealTimeService) {

    var REALTIME_EVENTS = {
          photos: {
            permissions: ['photos-access'],
            call: 'callPhotos'
          }
        },
        PERMISSIONS = {
          'photos-access': {
            title: 'Access to the Photos app',
            description: 'Access to the Photos app.',
            isPublic: true
          },
          'photos-moments': {
            title: 'Moments administration',
            description: 'Moments administration of the Photos app.',
            isPublic: true
          },
          'photos-people': {
            title: 'People administration',
            description: 'People administration of the Photos app.',
            isPublic: true
          }
        };

    return $AbstractModel('PhotoModel', function() {

      var extend = require('extend'),
          async = require('async'),
          fs = require('fs-extra'),
          path = require('path'),
          _mediaFolder = path.resolve('media');

      return {
        identity: 'photos',
        entities: true,
        entityType: 'photo',
        isSearchable: true,
        isSearchableAdvanced: true,
        attributes: {
          shotDate: {
            type: 'date',
            index: true
          },
          shotTime: {
            type: 'integer',
            index: true
          },
          sourceModifiedAt: 'integer',
          name: {
            type: 'string',
            index: true
          },
          source: {
            type: 'string',
            index: true
          },
          url: {
            type: 'string',
            index: true
          },
          cover: 'string',
          isVideo: 'boolean',
          moments: {
            type: 'array',
            index: true
          },
          people: {
            type: 'array',
            index: true
          },

          publicData: function(moreData, remove) {
            var photo = this.toJSON();

            delete photo.isSearchable;
            delete photo.isSearchableAdvanced;
            delete photo.entityType;

            if (moreData) {
              extend(true, photo, moreData);
            }

            if (remove) {
              remove.forEach(function(removeKey) {
                delete photo[removeKey];
              });
            }

            return photo;
          }
        },

        init: function() {
          var _this = this,
              GroupModel = DependencyInjection.injector.model.get('GroupModel'),
              $RealTimeService = DependencyInjection.injector.model.get('$RealTimeService');

          GroupModel.registerPermissions(PERMISSIONS);

          Object.keys(REALTIME_EVENTS).forEach(function(eventName) {
            if (REALTIME_EVENTS[eventName].call) {
              var call = REALTIME_EVENTS[eventName].call;

              REALTIME_EVENTS[eventName].call = function() {
                _this[call].apply(_this, arguments);
              };
            }
          });

          $RealTimeService.registerEvents(REALTIME_EVENTS);
        },

        callPhotos: function($socket, eventName, args, callback, addOnly, socketOrigin) {
          eventName = eventName || 'photos';

          var sockets = $socket ? [$socket] : $RealTimeService.socketsFromOrigin(eventName);

          this
            .find()
            .sort({
              shotTime: 'desc'
            })
            .exec(function(err, photos) {
              if (err || !photos) {
                return callback();
              }

              var photosLength = 0,
                  videosLength = 0;

              photos = photos.map(function(photo) {
                if (photo.isVideo) {
                  videosLength++;
                }
                else {
                  photosLength++;
                }

                return {
                  cover: photo.cover,
                  shotTime: photo.shotTime,
                  isVideo: photo.isVideo,
                  thumbnail: photo.thumbnail,
                  url: photo.url,
                  moments: photo.moments,
                  people: photo.people
                };
              });

              var eventResult = {
                photosLength: photosLength,
                videosLength: videosLength,
                photos: photos
              };

              if (addOnly) {
                eventResult.addOnly = true;
              }

              sockets.forEach(function(socket) {
                eventResult.isOrigin = socket == $socket || socket == socketOrigin || false;

                $RealTimeService.fire(eventName, eventResult, socket);
              });
            });
        },

        updateMoment: function($socket, name, photos) {
          var _this = this,
              nameFormatted = name.toLowerCase();

          this
            .find({
              url: photos
            })
            .exec(function(err, photos) {
              if (err || !photos || !photos.length) {
                return;
              }

              async.eachSeries(photos, function(photo, nextPhoto) {
                photo.moments = photo.moments || [];

                for (var i = 0; i < photo.moments.length; i++) {
                  if (photo.moments[i].toLowerCase() == nameFormatted) {
                    return nextPhoto();
                  }
                }

                photo.moments.push(name);

                _this
                  .update({
                    id: photo.id
                  }, {
                    moments: photo.moments
                  })
                  .exec(function() {
                    nextPhoto();
                  });
              }, function() {
                setTimeout(function() {
                  _this.callPhotos(null, null, null, null, true, $socket);
                });
              });
            });
        },

        deleteMoment: function($socket, names, photos) {
          var _this = this;

          this
            .find({
              url: photos
            })
            .exec(function(err, photos) {
              if (err || !photos || !photos.length) {
                return;
              }

              async.eachSeries(photos, function(photo, nextPhoto) {
                photo.moments = photo.moments || [];

                var hasRemoved = false;

                names.forEach(function(name) {
                  var nameFormatted = name.toLowerCase(),
                      index = -1;

                  for (var i = 0; i < photo.moments.length; i++) {
                    if (photo.moments[i].toLowerCase() == nameFormatted) {
                      index = i;

                      break;
                    }
                  }

                  if (index > -1) {
                    photo.moments.splice(index, 1);

                    hasRemoved = true;
                  }
                });

                if (!hasRemoved) {
                  return nextPhoto();
                }

                _this
                  .update({
                    id: photo.id
                  }, {
                    moments: photo.moments
                  })
                  .exec(function() {
                    nextPhoto();
                  });
              }, function() {
                setTimeout(function() {
                  _this.callPhotos();
                });
              });

            });
        },

        updatePeople: function($socket, name, photos) {
          var _this = this,
              nameFormatted = name.toLowerCase();

          this
            .find({
              url: photos
            })
            .exec(function(err, photos) {
              if (err || !photos || !photos.length) {
                return;
              }

              async.eachSeries(photos, function(photo, nextPhoto) {
                photo.people = photo.people || [];

                for (var i = 0; i < photo.people.length; i++) {
                  if (photo.people[i].toLowerCase() == nameFormatted) {
                    return nextPhoto();
                  }
                }

                if (photo.people.indexOf(name) > -1) {
                  return nextPhoto();
                }

                photo.people.push(name);

                _this
                  .update({
                    id: photo.id
                  }, {
                    people: photo.people
                  })
                  .exec(function() {
                    nextPhoto();
                  });
              }, function() {
                var identityFile = path.join(_mediaFolder, 'photos/people/' + name + '.jpg');

                if (!fs.existsSync(identityFile)) {
                  fs.copySync(path.resolve(__dirname, '../views/resources/identity.jpg'), identityFile);
                }

                setTimeout(function() {
                  _this.callPhotos(null, null, null, null, true, $socket);
                });
              });

            });
        },

        deletePeople: function($socket, photos) {
          var _this = this;

          this
            .find({
              url: photos
            })
            .exec(function(err, photos) {
              if (err || !photos || !photos.length) {
                return;
              }

              async.eachSeries(photos, function(photo, nextPhoto) {
                if (!photo.people || !photo.people.length) {
                  return nextPhoto();
                }

                photo.people = [];

                _this
                  .update({
                    id: photo.id
                  }, {
                    people: photo.people
                  })
                  .exec(function() {
                    nextPhoto();
                  });
              }, function() {
                setTimeout(function() {
                  _this.callPhotos();
                });
              });

            });
        },

        updateAvatar: function($socket, name, photos) {
          this
            .findOne({
              url: photos[0]
            })
            .exec(function(err, photo) {
              if (err || !photo) {
                return;
              }

              var identityFile = path.join(_mediaFolder, 'photos/people/' + name + '.jpg'),
                  sourceFile = path.join(_mediaFolder, photo.cover.replace('/media/', ''));

              fs.copySync(sourceFile, identityFile);

              $socket.emit('read(photos/avatar)', {
                name: name
              });
            });
        }
      };

    });

  });

  return 'PhotoModel';
};
<|endoftext|>


<commit_before>import d1 from "pkg";
import d2 from "#internal";

it("imports field to resolve to the same", () => {
	expect(d1).toBe(d2);
});
<commit_msg>even simpler example<commit_after>import d1 from "./pkg.mjs";
import d2 from "#internal";

it("imports field to resolve to the same", () => {
	expect(d1).toBe(d2);
});
<|endoftext|>


<commit_before>var ClientSecureChannelLayer = require("../../lib/client/client_secure_channel_layer").ClientSecureChannelLayer;
var should  = require("should");
var assert = require("assert");

var debugLog  = require("../../lib/utils").make_debugLog(__filename);

var MockTransport           = require("../mocks/mock_transport").MockTransport;
var fake_AcknowledgeMessage = require("../mocks/mock_transport").fake_AcknowledgeMessage;
var assert = require("assert");

describe("testing ClientSecureChannelLayer ",function(){

    it("should create a ClientSecureChannelLayer",function(done){

        var mock = new MockTransport([

            //
            opcua.packTcpMessage("ACK", fake_AcknowledgeMessage),

            require("../fixtures/fixture_full_tcp_packets").packet_sc_2 // OpenChannelResponse

        ],done);

        require("../../lib/transport/tcp_transport").setFakeTransport(mock.fake_socket.client);

        var secureChannel = new ClientSecureChannelLayer();

        secureChannel.create("fake://localhost:2033/SomeAddress",function(err){
            done(err);
        });
    });

    it("should close a ClientSecureChannelLayer",function(done){

        var mock = new MockTransport([

            // ---------------------------------------------------- Transaction 1
            // Client will send a HEl_message
            // Server will reply with this :
            opcua.packTcpMessage("ACK", fake_AcknowledgeMessage),

            // ---------------------------------------------------- Transaction 2
            // client will send a "OPN" OpenSecureChannelRequest
            // Server will reply with this:
            require("../fixtures/fixture_full_tcp_packets").packet_sc_2, // OpenChannelResponse

            // ---------------------------------------------------- Transaction 3
            // client will send a "CLO" CloseSecureChannelRequest
            // Server will close the socket, without sending a response
            function() { this.fake_socket.server.end(); },

            function() { done(new Error("no more packet to mock")); }

        ],done);

        require("../../lib/transport/tcp_transport").setFakeTransport(mock.fake_socket.client);

        var secureChannel = new ClientSecureChannelLayer();

        secureChannel.create("fake://localhost:2033/SomeAddress",function(err){
            secureChannel.close(function(err){
                done(err);
            });
        });
    });

    it("should use token provided by server in messages",function(done){

        var mock = new MockTransport([
            // ---------------------------------------------------- Transaction 1
            // Client will send a HEl_message
            // Server will reply with this :
            opcua.packTcpMessage("ACK", fake_AcknowledgeMessage),

            // ---------------------------------------------------- Transaction 2
            // client will send a "OPN" OpenSecureChannelRequest
            // Server will reply with this:
            require("../fixtures/fixture_full_tcp_packets").packet_sc_2,

            // ---------------------------------------------------- Transaction 3
            // client will send a "CLO" CloseSecureChannelRequest
            // Server will close the socket, without sending a response
            function() { this.fake_socket.server.end(); }

        ],done);

        require("../../lib/transport/tcp_transport").setFakeTransport(mock.fake_socket.client);

        var secureChannel = new ClientSecureChannelLayer();

        (!!secureChannel.tokenId).should.equal(false);

        secureChannel.create("fake://localhost:2033/SomeAddress",function(err){

            secureChannel.tokenId.should.equal(1);
            secureChannel.close(function(err){
                done(err);
            });
        });
    });

});
<commit_msg>Add test in client secure channel to make sure error is raised if performMessageTransaction is called before connection<commit_after>var ClientSecureChannelLayer = require("../../lib/client/client_secure_channel_layer").ClientSecureChannelLayer;
var should  = require("should");
var assert = require("assert");

var debugLog  = require("../../lib/utils").make_debugLog(__filename);

var MockTransport           = require("../mocks/mock_transport").MockTransport;
var fake_AcknowledgeMessage = require("../mocks/mock_transport").fake_AcknowledgeMessage;
var assert = require("assert");

describe("testing ClientSecureChannelLayer ",function(){

    it("should create a ClientSecureChannelLayer",function(done){

        var mock = new MockTransport([

            //
            opcua.packTcpMessage("ACK", fake_AcknowledgeMessage),

            require("../fixtures/fixture_full_tcp_packets").packet_sc_2 // OpenChannelResponse

        ],done);

        require("../../lib/transport/tcp_transport").setFakeTransport(mock.fake_socket.client);

        var secureChannel = new ClientSecureChannelLayer();

        secureChannel.create("fake://localhost:2033/SomeAddress",function(err){
            done(err);
        });
    });

    it("should close a ClientSecureChannelLayer",function(done){

        var mock = new MockTransport([

            // ---------------------------------------------------- Transaction 1
            // Client will send a HEl_message
            // Server will reply with this :
            opcua.packTcpMessage("ACK", fake_AcknowledgeMessage),

            // ---------------------------------------------------- Transaction 2
            // client will send a "OPN" OpenSecureChannelRequest
            // Server will reply with this:
            require("../fixtures/fixture_full_tcp_packets").packet_sc_2, // OpenChannelResponse

            // ---------------------------------------------------- Transaction 3
            // client will send a "CLO" CloseSecureChannelRequest
            // Server will close the socket, without sending a response
            function() { this.fake_socket.server.end(); },

            function() { done(new Error("no more packet to mock")); }

        ],done);

        require("../../lib/transport/tcp_transport").setFakeTransport(mock.fake_socket.client);

        var secureChannel = new ClientSecureChannelLayer();

        secureChannel.create("fake://localhost:2033/SomeAddress",function(err){
            secureChannel.close(function(err){
                done(err);
            });
        });
    });

    it("should use token provided by server in messages",function(done){

        var mock = new MockTransport([
            // ---------------------------------------------------- Transaction 1
            // Client will send a HEl_message
            // Server will reply with this :
            opcua.packTcpMessage("ACK", fake_AcknowledgeMessage),

            // ---------------------------------------------------- Transaction 2
            // client will send a "OPN" OpenSecureChannelRequest
            // Server will reply with this:
            require("../fixtures/fixture_full_tcp_packets").packet_sc_2,

            // ---------------------------------------------------- Transaction 3
            // client will send a "CLO" CloseSecureChannelRequest
            // Server will close the socket, without sending a response
            function() { this.fake_socket.server.end(); }

        ],done);

        require("../../lib/transport/tcp_transport").setFakeTransport(mock.fake_socket.client);

        var secureChannel = new ClientSecureChannelLayer();

        (!!secureChannel.tokenId).should.equal(false);

        secureChannel.create("fake://localhost:2033/SomeAddress",function(err){

            secureChannel.tokenId.should.equal(1);
            secureChannel.close(function(err){
                done(err);
            });
        });
    });

    it("should callback with an error if performMessageTransaction is called before connection",function(done){

        var secureChannel = new ClientSecureChannelLayer();
        var s = require("../../lib/structures");
        var message = new s.GetEndpointsRequest();
        secureChannel.performMessageTransaction(message, s.GetEndpointsResponse,function(err){
            err.message.should.equal("Client not connected");
            done();
        });
    });

});
<|endoftext|>


<commit_before>var uTest = {
   testGroups: {
      "_default": {
         name: "_default",
         tests: [ ]
      }
   },

   TEST_GROUP: function (group) {
      group.tests = [ ];
      this.testGroups[group.name] = group;
   },

   TEST: function (test) {
      test.group = test.group || "_default";
      this.testGroups[test.group].tests.push(test);
   },

   CHECK: function (condition) {
      var errorString = this.getErrorString() + "\tCHECK failed";

      if (condition !== true) {
         throw new Error(errorString);
      }
   },

   CHECK_TEXT: function (condition, text) {
      var errorString = this.getErrorString() + "\tMessage: " + text + "\n\tCHECK failed";
      if (condition !== true) {
         throw new Error(errorString);
      }
   },

   CHECK_EQUAL: function (expected, actual) {
      var errorString = this.getErrorString() + "\texpected <" + expected  + ">\n" +
                                                "\tbut was  <" + actual    + ">";
      if (expected !== actual) {
         throw new Error(errorString);
      }
   },

   STRCMP_EQUAL: function (expected, actual) {
      var errorString = this.getErrorString() + "\texpected <" + expected.toString()   + ">\n" +
                                                "\tbut was  <" + actual.toString()     + ">";
      if (expected.toString() !== actual.toString()) {
         throw new Error(errorString);
      }
   },

   LONGS_EQUAL: function (expected, actual) {
      var errorString = this.getErrorString() + "\texpected <" + Math.floor(expected)  + ">\n" +
                                                "\tbut was  <" + Math.floor(actual)    + ">";
      if (Math.floor(expected) !== Math.floor(actual)) {
         throw new Error(errorString);
      }
   },

   DOUBLES_EQUAL: function (expected, actual, tolerance) {
      var errorString = this.getErrorString() + "\texpected <" + expected  + ">\n"  +
                                                "\tbut was  <" + actual    + ">"    +
                                                " threshold was <" + tolerance + ">";
      if (Math.abs(expected - actual) > tolerance) {
         throw new Error(errorString);
      }
   },

   FAIL: function (text) {
      var errorString = this.getErrorString() + "\t" + text;
      throw new Error(errorString);
   },

   getErrorString: function () {
      var errorString = "error: Failiure in TEST(" +
                        this.currentGroup + ", "   +
                        this.currentTest + ")\n";

      return errorString;
   },

   runAllTests: function () {
      try {
         for (var groupName in this.testGroups)
         {
            this.runTestGroup(groupName);
         }
      } catch (ex) {
         console.log(ex.message);
      }
   },

   runTestGroup: function (groupName) {
      var group = this.testGroups[groupName];

      this.currentGroup = group.name;

      for (var i = 0; i < group.tests.length; i++)
      {
         this.currentTest = group.tests[i].name;

         if (typeof group.setup === "function") {
            group.setup();
         }

         if (typeof group.tests[i].run  === "function") {
            group.tests[i].run();
         }

         if (typeof group.teardown === "function") {
            group.teardown();
         }
      }
   }
};
<commit_msg>Add BYTES_EQUAL<commit_after>var uTest = {
   testGroups: {
      "_default": {
         name: "_default",
         tests: [ ]
      }
   },

   TEST_GROUP: function (group) {
      group.tests = [ ];
      this.testGroups[group.name] = group;
   },

   TEST: function (test) {
      test.group = test.group || "_default";
      this.testGroups[test.group].tests.push(test);
   },

   CHECK: function (condition) {
      var errorString = this.getErrorString() + "\tCHECK failed";

      if (condition !== true) {
         throw new Error(errorString);
      }
   },

   CHECK_TEXT: function (condition, text) {
      var errorString = this.getErrorString() + "\tMessage: " + text + "\n\tCHECK failed";
      if (condition !== true) {
         throw new Error(errorString);
      }
   },

   CHECK_EQUAL: function (expected, actual) {
      var errorString = this.getErrorString() + "\texpected <" + expected  + ">\n" +
                                                "\tbut was  <" + actual    + ">";
      if (expected !== actual) {
         throw new Error(errorString);
      }
   },

   STRCMP_EQUAL: function (expected, actual) {
      var errorString = this.getErrorString() + "\texpected <" + expected.toString()   + ">\n" +
                                                "\tbut was  <" + actual.toString()     + ">";
      if (expected.toString() !== actual.toString()) {
         throw new Error(errorString);
      }
   },

   LONGS_EQUAL: function (expected, actual) {
      var errorString = this.getErrorString() + "\texpected <" + Math.floor(expected)  + ">\n" +
                                                "\tbut was  <" + Math.floor(actual)    + ">";
      if (Math.floor(expected) !== Math.floor(actual)) {
         throw new Error(errorString);
      }
   },

   BYTES_EQUAL: function (expected, actual) {
      this.LONGS_EQUAL(expected & 0xFF, actual & 0xFF);
   },

   DOUBLES_EQUAL: function (expected, actual, tolerance) {
      var errorString = this.getErrorString() + "\texpected <" + expected  + ">\n"  +
                                                "\tbut was  <" + actual    + ">"    +
                                                " threshold was <" + tolerance + ">";
      if (Math.abs(expected - actual) > tolerance) {
         throw new Error(errorString);
      }
   },

   FAIL: function (text) {
      var errorString = this.getErrorString() + "\t" + text;
      throw new Error(errorString);
   },

   getErrorString: function () {
      var errorString = "error: Failiure in TEST(" +
                        this.currentGroup + ", "   +
                        this.currentTest + ")\n";

      return errorString;
   },

   runAllTests: function () {
      try {
         for (var groupName in this.testGroups)
         {
            this.runTestGroup(groupName);
         }
      } catch (ex) {
         console.log(ex.message);
      }
   },

   runTestGroup: function (groupName) {
      var group = this.testGroups[groupName];

      this.currentGroup = group.name;

      for (var i = 0; i < group.tests.length; i++)
      {
         this.currentTest = group.tests[i].name;

         if (typeof group.setup === "function") {
            group.setup();
         }

         if (typeof group.tests[i].run  === "function") {
            group.tests[i].run();
         }

         if (typeof group.teardown === "function") {
            group.teardown();
         }
      }
   }
};
<|endoftext|>


<commit_before>"use strict";

var createResource = require("../../util/create-resource");
var path = require("path");
var sh = require("shelljs");

describe("createResource", function () {
  afterEach(function () { teardown() });
  beforeEach(function () { standup() });

  describe("no file already exists at dstPath", function () {
    var dstPath = path.join(tmpRoot, ".titorrc.yml");

    it("create file at dstPath", function () {
      createResource(".titorrc.yml");

      expect(sh.test("-e", dstPath)).to.be.true;
    });

    it("return true", function () {
      expect(createResource(".titorrc.yml")).to.be.true;
    });
  });

  describe("a file already exists at dstPath", function () {
    var dstPath = path.join(tmpRoot, ".titorrc.yml");

    beforeEach(function () { sh.ShellString("testing").to(dstPath) });

    it("don't replace existing file at dstPath", function () {
      createResource(".titorrc.yml");

      expect(sh.cat(dstPath).stdout).to.equal("testing");
    });

    it("return false", function () {
      expect(createResource(".titorrc.yml")).to.be.false;
    });
  });

  describe("pkgExport is undefined", function () {
    it("don't replace PACKAGE_EXPORT with pkgExport in dst file", function () {
      var dstPath = path.join(tmpRoot, ".titorrc.yml");

      createResource(".titorrc.yml");

      expect(sh.grep("export", dstPath).stdout.trim())
        .to.equal("export: PACKAGE_EXPORT");
    });
  });

  describe("pkgExport is defined", function () {
    it("replace PACKAGE_EXPORT with pkgExport in dst file", function () {
      var dstPath = path.join(tmpRoot, ".titorrc.yml");

      createResource(".titorrc.yml", "testPackage");

      expect(sh.grep("export", dstPath).stdout.trim())
        .to.equal("export: testPackage");
    });
  });

  describe("srcPath is undefined", function () {
    it("copy src file from default path to dstPath", function () {
      var dstPath = path.join(tmpRoot, ".titorrc.yml");
      var srcPath = path.join(__dirname, "../../resource/_.titorrc.yml");

      createResource(".titorrc.yml");

      expect(sh.cat(dstPath).stdout).to.equal(sh.cat(srcPath).stdout);
    });
  });

  describe("srcPath is defined", function () {
    it("copy src file from srcPath to dstPath", function () {
      var dstPath = path.join(tmpRoot, "src/testPackage.js");
      var srcPath = path.join(
                      __dirname,
                      "../../resource/src/_package-export.js"
                    );

      createResource("src/testPackage.js", undefined, srcPath);

      expect(sh.cat(dstPath).stdout).to.equal(sh.cat(srcPath).stdout);
    });
  });
});
<commit_msg>Fix small style issue<commit_after>"use strict";

var createResource = require("../../util/create-resource");
var path = require("path");
var sh = require("shelljs");

describe("createResource", function () {
  afterEach(function () { teardown() });
  beforeEach(function () { standup() });

  describe("no file already exists at dstPath", function () {
    var dstPath = path.join(tmpRoot, ".titorrc.yml");

    it("create file at dstPath", function () {
      createResource(".titorrc.yml");

      expect(sh.test("-e", dstPath)).to.be.true;
    });

    it("return true", function () {
      expect(createResource(".titorrc.yml")).to.be.true;
    });
  });

  describe("a file already exists at dstPath", function () {
    var dstPath = path.join(tmpRoot, ".titorrc.yml");

    beforeEach(function () { sh.ShellString("testing").to(dstPath) });

    it("don't replace existing file at dstPath", function () {
      createResource(".titorrc.yml");

      expect(sh.cat(dstPath).stdout).to.equal("testing");
    });

    it("return false", function () {
      expect(createResource(".titorrc.yml")).to.be.false;
    });
  });

  describe("pkgExport is undefined", function () {
    it("don't replace PACKAGE_EXPORT with pkgExport in dst file", function () {
      var dstPath = path.join(tmpRoot, ".titorrc.yml");

      createResource(".titorrc.yml");

      expect(sh.grep("export", dstPath).stdout.trim())
        .to.equal("export: PACKAGE_EXPORT");
    });
  });

  describe("pkgExport is defined", function () {
    it("replace PACKAGE_EXPORT with pkgExport in dst file", function () {
      var dstPath = path.join(tmpRoot, ".titorrc.yml");

      createResource(".titorrc.yml", "testPackage");

      expect(sh.grep("export", dstPath).stdout.trim())
        .to.equal("export: testPackage");
    });
  });

  describe("srcPath is undefined", function () {
    it("copy src file from default path to dstPath", function () {
      var dstPath = path.join(tmpRoot, ".titorrc.yml");
      var srcPath = path.join(__dirname, "../../resource/_.titorrc.yml");

      createResource(".titorrc.yml");

      expect(sh.cat(dstPath).stdout).to.equal(sh.cat(srcPath).stdout);
    });
  });

  describe("srcPath is defined", function () {
    it("copy src file from srcPath to dstPath", function () {
      var dstPath = path.join(tmpRoot, "src/testPackage.js");
      var srcPath = path.join(
        __dirname,
        "../../resource/src/_package-export.js"
      );

      createResource("src/testPackage.js", undefined, srcPath);

      expect(sh.cat(dstPath).stdout).to.equal(sh.cat(srcPath).stdout);
    });
  });
});
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////
//// Hello Translation Widget
//// by Aurelio Jargas 2012-02-17
//
// A simple sample widget, using translated strings.
//
// Copy/paste all this code to the end of your config.js file.

// Create a new widget instance (id, name, instance name)
var HelloTranslation = new Widget('hello-translation', 'Hello Translation', 'HelloTranslation');

// Save widget translation to the main database
// header
i18nDatabase.en.HelloTranslationHeaderLabel = 'Hello Translation';
i18nDatabase.es.HelloTranslationHeaderLabel = 'Hola Traducción';
i18nDatabase.pt.HelloTranslationHeaderLabel = 'Oi Tradução';
// checkbox label
i18nDatabase.en.HelloTranslationOptionLabel = 'Say hello!';
i18nDatabase.es.HelloTranslationOptionLabel = '¡Decir hola!';
i18nDatabase.pt.HelloTranslationOptionLabel = 'Diga oi!';
// Note: always use {InstanceName}HeaderLabel for automatic header translation

// Debug: change the app language to test the translations
// lang = 'es';   // en:English, es:Spanish, pt:Portuguese

// Set widget contents
HelloTranslation.populate = function () {
	// Here we use the translated label.
	// Note that the prefix is just i18n.
	this.addCheckbox('foo', i18n.HelloTranslationOptionLabel);
};

// Handle checkbox click
HelloTranslation.checkboxClicked = function (checkbox) {  // eslint-disable-line no-unused-vars
	return;  // do nothing
};
<commit_msg>Improve sample widget to avoid lint issues<commit_after>///////////////////////////////////////////////////////////////////////
//// Hello Translation Widget
//// by Aurelio Jargas 2012-02-17
//
// A simple sample widget, using translated strings.
//
// Copy/paste all this code to the end of your config.js file.

// Create a new widget instance (id, name, instance name)
var HelloTranslation = new Widget('hello-translation', 'Hello Translation', 'HelloTranslation');

// Save widget translation to the main database
// header
i18nDatabase.en.HelloTranslationHeaderLabel = 'Hello Translation';
i18nDatabase.es.HelloTranslationHeaderLabel = 'Hola Traducción';
i18nDatabase.pt.HelloTranslationHeaderLabel = 'Oi Tradução';
// checkbox label
i18nDatabase.en.HelloTranslationOptionLabel = 'Say hello!';
i18nDatabase.es.HelloTranslationOptionLabel = '¡Decir hola!';
i18nDatabase.pt.HelloTranslationOptionLabel = 'Diga oi!';
// Note: always use {InstanceName}HeaderLabel for automatic header translation

// Debug: change the app language to test the translations
// lang = 'es';   // en:English, es:Spanish, pt:Portuguese

// Set widget contents
HelloTranslation.populate = function () {
	// Here we use the translated label.
	// Note that the prefix is just i18n.
	this.addCheckbox('foo', i18n.HelloTranslationOptionLabel);
};

// Handle checkbox click
HelloTranslation.checkboxClicked = function (checkbox) {
	console.log('clicked ' + checkbox.id);
};
<|endoftext|>


<commit_before>/**
 * @class  	Notifications
 * @author  Flavio De Stefano <flavio.destefano@caffeinalab.com>
 */

/**
 * @property config
 * @property {Boolean} 	[config.autoReset=true] 	Check if auto-reset the badge when app is open.
 * @property {String} 	[config.driver="http"] 		The driver to use.
 * @property {Boolean} 	[config.useRouter=true]		When a notification with a `{url:""}` parameter is received, auto-route using the Router class.
 * @type {Object}
 */
exports.config = _.extend({
	autoReset: true,
	useRouter: true,
	driver: 'http',
}, Alloy.CFG.T ? Alloy.CFG.T.notifications : {});

var Event = require('T/event');
var Util = require('T/util');
var Router = require('T/router');
var Q = require('T/ext/q');

var interactiveCategories = [];
var interactiveCategoriesCallbacks = {};

var INTERACTIVE_NOTIFICATIONS_CAPABLE = (OS_IOS && Util.getIOSVersion() >= 8);

function validateToken(token) {
	return token != null && token != "undefined" && token != "null" && token.length >= 32;
}

function onNotificationReceived(e) {
	if (OS_ANDROID) {
		if (_.isString(e.data)) {
			try {
				e.data = JSON.parse(e.data);
			} catch (ex) {
				e.data = {};
			}
		}
	}

	Ti.API.debug("Notifications: Received", e);

	// Auto-reset the badge
	if (exports.config.autoReset === true) {
		exports.resetBadge();
	}

	// Router
	if (exports.config.useRouter === true) {
		if (e.inBackground == true) {
			if (e.data.url != null) {
				Router.go(e.data.url);
			}
		}
	}

	Event.trigger('notifications.received', e);
}

/**
 * @method loadDriver
 */
exports.loadDriver = function(name) {
	return Alloy.Globals.Trimethyl.loadDriver('notifications', name, {
		subscribe: function(opt) {},
		unsubscribe: function(opt) {}
	});
};

/**
 * @method event
 */
exports.event = function(name, cb) {
	Event.on('notifications.' + name, cb);
};

/**
 * @method activate
 * @param  {Function} callback Callback invoked when success occur
 */
exports.activate = function(callback) {
	var defer = Q.defer();

	if (INTERACTIVE_NOTIFICATIONS_CAPABLE) {

		var userNotificationsCallback = function(settings) {
			Ti.App.iOS.removeEventListener('usernotificationsettings', userNotificationsCallback);

			if (_.isEmpty(settings.types)) {
				return defer.reject({
					disabled: true
				});
			}

			Ti.Network.registerForPushNotifications({

				callback: onNotificationReceived,

				success: function(e) {
					if ( ! validateToken(e.deviceToken)) {
						Ti.API.error('Notifications: Retrieve device token failed');
						return defer.reject({
							invalidToken: true
						});
					}

					defer.resolve(e.deviceToken);
					Event.trigger('notifications.activation.success');
				},
				error: function(err) {
					Ti.API.error('Notifications: Retrieve device token failed', err);

					defer.reject(err);
					Event.trigger('notifications.activation.error', err);
				}
			});
		};

		Ti.App.iOS.addEventListener('usernotificationsettings', userNotificationsCallback);
		Ti.App.iOS.registerUserNotificationSettings({
			types: [
				Ti.Network.NOTIFICATION_TYPE_BADGE,
				Ti.Network.NOTIFICATION_TYPE_ALERT,
				Ti.Network.NOTIFICATION_TYPE_SOUND
			],
			categories: interactiveCategories
		});

	} else {

		var Module = null;
		var moduleOpt = {};

		if (OS_IOS) {

			Module = Ti.Network;
			moduleOpt.types = [
				Ti.Network.NOTIFICATION_TYPE_BADGE,
				Ti.Network.NOTIFICATION_TYPE_ALERT,
				Ti.Network.NOTIFICATION_TYPE_SOUND
			];

		} else if (OS_ANDROID) {

			Module = require('it.caffeina.gcm');
			moduleOpt.senderId = Ti.App.Properties.getString('gcm.senderid');

		} else return;

		Module.registerForPushNotifications(_.extend(moduleOpt, {

			callback: onNotificationReceived,

			success: function(e) {
				if ( ! validateToken(e.deviceToken)) {
					Ti.API.error('Notifications: Retrieve device token failed');
					return defer.reject({
						invalidToken: true
					});
				}

				defer.resolve(e.deviceToken);
				Event.trigger('notifications.activation.success');
			},
			error: function(err) {
				Ti.API.error('Notifications: Retrieve device token failed', err);

				defer.reject(err);
				Event.trigger('notifications.activation.error', err);
			},
		}));
	}

	return defer.promise;
};

/**
 * @method deactivate
 * Deactivate completely the notifications
 */
exports.deactivate = function() {
	if (OS_IOS) {
		Module = Ti.Network;
	} else if (OS_ANDROID) {
		Module = require("it.caffeina.gcm");
	} else return;

	Module.unregisterForPushNotifications();
};

/**
 * @method subscribe
 * Subscribe for that channel
 * @param {String} channel 	Channel name
 * @param {Object} data 		Additional data
 */
exports.subscribe = function(channel, data) {
	var defer = Q.defer();

	if (!Ti.Network.online) {
		defer.reject({
			offline: true
		});
		return defer.promise;
	}

	exports.activate()
	.then(function(deviceToken) {

		exports.loadDriver(exports.config.driver).subscribe({
			deviceToken: deviceToken,
			channel: channel,
			data: data,
			success: function(response) {
				Event.trigger('notifications.subscription.success', { channel: channel });
				Ti.API.debug('Notifications: Subscription to channel <' + (channel || 'default') + '> succeded', response);

				defer.resolve(response);
			},
			error: function(err) {
				Event.trigger('notifications.subscription.error', err);
				Ti.API.error('Notifications: Subscription failed to channel <' + (channel || 'default') + '>', err);

				defer.reject(err);
			}
		});

	})
	.fail(defer.reject);

	return defer.promise;
};

/**
 * @method unsubscribe
 * Unsubscribe for that channel
 * @param {String} channel 	Channel name
 * @param {Object} data 		Additional data
 */
exports.unsubscribe = function(channel, data) {
	var defer = Q.defer();

	if (!Ti.Network.online) {
		defer.reject({
			offline: true
		});
		return defer.promise;
	}

	var deviceToken = exports.getStoredDeviceToken();
	if (_.isEmpty(deviceToken)) {
		Ti.API.error('Notifications: Error while getting deviceToken');
		defer.reject({
			missingToken: true
		});

		return defer.promise;
	}

	exports.loadDriver(exports.config.driver).unsubscribe({
		deviceToken: deviceToken,
		channel: channel,
		data: data,
		success: function(response) {
			Event.trigger('notifications.unsubscription.error', { channel: channel });
			Ti.API.debug('Notifications: Unsubscription to channel <' + (channel || 'default') + '> succeded', response);

			defer.resolve(response);
		},
		error: function(err) {
			Event.trigger('notifications.unsubscription.error', err);
			Ti.API.error('Notifications: Unsubscription failed to channel <' + (channel || 'default') + '>', err);

			defer.reject(err);
		}
	});

	return defer.promise;
};

/**
 * @method setBadge
 * Set the App badge value
 * @param {Number} x
 */
exports.setBadge = function(x) {
	var Module = OS_IOS ? Ti.UI.iPhone : require('it.caffeina.gcm');
	Module.setAppBadge(Math.max(x,0));
};

/**
 * @method getBadge
 * Get the App badge value
 * @return {Number}
 */
exports.getBadge = function() {
	var Module = OS_IOS ? Ti.UI.iPhone : require('it.caffeina.gcm');
	return Module.getAppBadge();
};

/**
 * @method resetBadge
 * Reset to 0 the badge
 */
exports.resetBadge = function() {
	exports.setBadge(0);
};

/**
 * @method incBadge
 * Increment the badge app
 * @param  {Number} i The value to increment
 */
exports.incBadge = function(i) {
	exports.setBadge(exports.getBadge() + i);
};

/**
 * @method getRemoteDeviceUUID
 * Get the stored device token.
 * Don't rely on this method to check if notifications are active, use `isRemoteNotificationsEnabled()` instead
 * @return {String}
 */
exports.getStoredDeviceToken = exports.getDeviceToken = exports.getRemoteDeviceUUID = function() {
	var Module = OS_IOS ? Ti.Network : require('it.caffeina.gcm');
	return Module.remoteDeviceUUID;
};

/**
 * @method isRemoteNotificationsEnabled
 * Check if the remote notifications has been registered once
 * Use this method at startup in conjunction with `activate()`
 * @return {Boolean} [description]
 */
exports.isRemoteNotificationsEnabled = function() {
	var Module = OS_IOS ? Ti.Network : require('it.caffeina.gcm');
	return Module.remoteNotificationsEnabled;
};

///////////////////////////////
// Interactive notifications //
///////////////////////////////

function createIntNotifAction(opt) {
	if (opt.id == null) throw new Error('Notifications: interactive notifications must have and ID');
	if (opt.title == null) throw new Error('Notifications: interactive notifications must have a title');

	return Ti.App.iOS.createUserNotificationAction({
		identifier: opt.id,
		title: opt.title,
		activationMode: Ti.App.iOS["USER_NOTIFICATION_ACTIVATION_MODE_" + (opt.openApplication == true ? "FOREGROUND" : "BACKGROUND")],
		destructive: !!opt.destructive,
		authenticationRequired: !!opt.authenticationRequired
	});
}

/**
 * @method addInteractiveNotificationCategory
 * @param {String}   id       	The ID of the category. It must be unique.
 * @param {Array}    dict     	An array of actions, with `id, title` (required) and `openApplication, destructive, authenticationRequired` (optional)
 * @param {Function} callback 	The callback to invoke
 */
exports.addInteractiveNotificationCategory = function(id, dict, callback) {
	if (!INTERACTIVE_NOTIFICATIONS_CAPABLE) return;

	var category = Ti.App.iOS.createUserNotificationCategory({
		identifier: id,
		actionsForDefaultContext: dict.map(createIntNotifAction)
	});

	// Add in the interactiveCategories array to register in the activate method
	interactiveCategories.push(category);
	interactiveCategoriesCallbacks[id] = callback;
};

//////////
// Init //
//////////

if (INTERACTIVE_NOTIFICATIONS_CAPABLE) {
	Ti.App.iOS.addEventListener('remotenotificationaction', function(e) {
		var func = interactiveCategoriesCallbacks[e.category];
		if (_.isFunction(func)) {
			func(e);
		} else {
			Ti.API.error('Notifications: remote notification with an unregistered category (' + e.category + ')');
		}
	});
}

if (exports.config.autoReset === true) {
	exports.resetBadge();
	Ti.App.addEventListener('resumed', exports.resetBadge);
}
<commit_msg>Deprecation of getStoredDeviceToken<commit_after>/**
 * @class  	Notifications
 * @author  Flavio De Stefano <flavio.destefano@caffeinalab.com>
 */

/**
 * @property config
 * @property {Boolean} 	[config.autoReset=true] 	Check if auto-reset the badge when app is open.
 * @property {String} 	[config.driver="http"] 		The driver to use.
 * @property {Boolean} 	[config.useRouter=true]		When a notification with a `{url:""}` parameter is received, auto-route using the Router class.
 * @type {Object}
 */
exports.config = _.extend({
	autoReset: true,
	useRouter: true,
	driver: 'http',
}, Alloy.CFG.T ? Alloy.CFG.T.notifications : {});

var Event = require('T/event');
var Util = require('T/util');
var Router = require('T/router');
var Q = require('T/ext/q');

var interactiveCategories = [];
var interactiveCategoriesCallbacks = {};

var INTERACTIVE_NOTIFICATIONS_CAPABLE = (OS_IOS && Util.getIOSVersion() >= 8);

function validateToken(token) {
	return token != null && token != "undefined" && token != "null" && token.length >= 32;
}

function onNotificationReceived(e) {
	if (OS_ANDROID) {
		if (_.isString(e.data)) {
			try {
				e.data = JSON.parse(e.data);
			} catch (ex) {
				e.data = {};
			}
		}
	}

	Ti.API.debug("Notifications: Received", e);

	// Auto-reset the badge
	if (exports.config.autoReset === true) {
		exports.resetBadge();
	}

	// Router
	if (exports.config.useRouter === true) {
		if (e.inBackground == true) {
			if (e.data.url != null) {
				Router.go(e.data.url);
			}
		}
	}

	Event.trigger('notifications.received', e);
}

/**
 * @method loadDriver
 */
exports.loadDriver = function(name) {
	return Alloy.Globals.Trimethyl.loadDriver('notifications', name, {
		subscribe: function(opt) {},
		unsubscribe: function(opt) {}
	});
};

/**
 * @method event
 */
exports.event = function(name, cb) {
	Event.on('notifications.' + name, cb);
};

/**
 * @method activate
 * @param  {Function} callback Callback invoked when success occur
 */
exports.activate = function(callback) {
	var defer = Q.defer();

	if (INTERACTIVE_NOTIFICATIONS_CAPABLE) {

		var userNotificationsCallback = function(settings) {
			Ti.App.iOS.removeEventListener('usernotificationsettings', userNotificationsCallback);

			if (_.isEmpty(settings.types)) {
				return defer.reject({
					disabled: true
				});
			}

			Ti.Network.registerForPushNotifications({

				callback: onNotificationReceived,

				success: function(e) {
					if ( ! validateToken(e.deviceToken)) {
						Ti.API.error('Notifications: Retrieve device token failed');
						return defer.reject({
							invalidToken: true
						});
					}

					defer.resolve(e.deviceToken);
					Event.trigger('notifications.activation.success');
				},
				error: function(err) {
					Ti.API.error('Notifications: Retrieve device token failed', err);

					defer.reject(err);
					Event.trigger('notifications.activation.error', err);
				}
			});
		};

		Ti.App.iOS.addEventListener('usernotificationsettings', userNotificationsCallback);
		Ti.App.iOS.registerUserNotificationSettings({
			types: [
				Ti.Network.NOTIFICATION_TYPE_BADGE,
				Ti.Network.NOTIFICATION_TYPE_ALERT,
				Ti.Network.NOTIFICATION_TYPE_SOUND
			],
			categories: interactiveCategories
		});

	} else {

		var Module = null;
		var moduleOpt = {};

		if (OS_IOS) {

			Module = Ti.Network;
			moduleOpt.types = [
				Ti.Network.NOTIFICATION_TYPE_BADGE,
				Ti.Network.NOTIFICATION_TYPE_ALERT,
				Ti.Network.NOTIFICATION_TYPE_SOUND
			];

		} else if (OS_ANDROID) {

			Module = require('it.caffeina.gcm');
			moduleOpt.senderId = Ti.App.Properties.getString('gcm.senderid');

		} else return;

		Module.registerForPushNotifications(_.extend(moduleOpt, {

			callback: onNotificationReceived,

			success: function(e) {
				if ( ! validateToken(e.deviceToken)) {
					Ti.API.error('Notifications: Retrieve device token failed');
					return defer.reject({
						invalidToken: true
					});
				}

				defer.resolve(e.deviceToken);
				Event.trigger('notifications.activation.success');
			},
			error: function(err) {
				Ti.API.error('Notifications: Retrieve device token failed', err);

				defer.reject(err);
				Event.trigger('notifications.activation.error', err);
			},
		}));
	}

	return defer.promise;
};

/**
 * @method deactivate
 * Deactivate completely the notifications
 */
exports.deactivate = function() {
	if (OS_IOS) {
		Module = Ti.Network;
	} else if (OS_ANDROID) {
		Module = require("it.caffeina.gcm");
	} else return;

	Module.unregisterForPushNotifications();
};

/**
 * @method subscribe
 * Subscribe for that channel
 * @param {String} channel 	Channel name
 * @param {Object} data 		Additional data
 */
exports.subscribe = function(channel, data) {
	var defer = Q.defer();

	if (!Ti.Network.online) {
		defer.reject({
			offline: true
		});
		return defer.promise;
	}

	exports.activate()
	.then(function(deviceToken) {

		exports.loadDriver(exports.config.driver).subscribe({
			deviceToken: deviceToken,
			channel: channel,
			data: data,
			success: function(response) {
				Event.trigger('notifications.subscription.success', { channel: channel });
				Ti.API.debug('Notifications: Subscription to channel <' + (channel || 'default') + '> succeded', response);

				defer.resolve(response);
			},
			error: function(err) {
				Event.trigger('notifications.subscription.error', err);
				Ti.API.error('Notifications: Subscription failed to channel <' + (channel || 'default') + '>', err);

				defer.reject(err);
			}
		});

	})
	.fail(defer.reject);

	return defer.promise;
};

/**
 * @method unsubscribe
 * Unsubscribe for that channel
 * @param {String} channel 	Channel name
 * @param {Object} data 		Additional data
 */
exports.unsubscribe = function(channel, data) {
	var defer = Q.defer();

	if (!Ti.Network.online) {
		defer.reject({
			offline: true
		});
		return defer.promise;
	}

	exports.loadDriver(exports.config.driver).unsubscribe({
		deviceToken: exports.getRemoteDeviceUUID(),
		channel: channel,
		data: data,
		success: function(response) {
			Event.trigger('notifications.unsubscription.error', { channel: channel });
			Ti.API.debug('Notifications: Unsubscription to channel <' + (channel || 'default') + '> succeded', response);

			defer.resolve(response);
		},
		error: function(err) {
			Event.trigger('notifications.unsubscription.error', err);
			Ti.API.error('Notifications: Unsubscription failed to channel <' + (channel || 'default') + '>', err);

			defer.reject(err);
		}
	});

	return defer.promise;
};

/**
 * @method setBadge
 * Set the App badge value
 * @param {Number} x
 */
exports.setBadge = function(x) {
	var Module = OS_IOS ? Ti.UI.iPhone : require('it.caffeina.gcm');
	Module.setAppBadge(Math.max(x,0));
};

/**
 * @method getBadge
 * Get the App badge value
 * @return {Number}
 */
exports.getBadge = function() {
	var Module = OS_IOS ? Ti.UI.iPhone : require('it.caffeina.gcm');
	return Module.getAppBadge();
};

/**
 * @method resetBadge
 * Reset to 0 the badge
 */
exports.resetBadge = function() {
	exports.setBadge(0);
};

/**
 * @method incBadge
 * Increment the badge app
 * @param  {Number} i The value to increment
 */
exports.incBadge = function(i) {
	exports.setBadge(exports.getBadge() + i);
};

/**
 * @deprecated Use getRemoteDeviceUUID instead
 * @method getStoredDeviceToken
 * @return {String}
 */
exports.getStoredDeviceToken = function() {
	Ti.API.warn('Notifications: getStoredDeviceToken is deprecated, use getRemoteDeviceUUID instead');
	return exports.getRemoteDeviceUUID();
};

/**
 * @method getRemoteDeviceUUID
 * Get the stored device token.
 * Don't rely on this method to check if notifications are active, use `isRemoteNotificationsEnabled()` instead
 * @return {String}
 */
exports.getRemoteDeviceUUID = function() {
	var Module = OS_IOS ? Ti.Network : require('it.caffeina.gcm');
	return Module.remoteDeviceUUID;
};

/**
 * @method isRemoteNotificationsEnabled
 * Check if the remote notifications has been registered once
 * Use this method at startup in conjunction with `activate()`
 * @return {Boolean} [description]
 */
exports.isRemoteNotificationsEnabled = function() {
	var Module = OS_IOS ? Ti.Network : require('it.caffeina.gcm');
	return Module.remoteNotificationsEnabled;
};

///////////////////////////////
// Interactive notifications //
///////////////////////////////

function createIntNotifAction(opt) {
	if (opt.id == null) throw new Error('Notifications: interactive notifications must have and ID');
	if (opt.title == null) throw new Error('Notifications: interactive notifications must have a title');

	return Ti.App.iOS.createUserNotificationAction({
		identifier: opt.id,
		title: opt.title,
		activationMode: Ti.App.iOS["USER_NOTIFICATION_ACTIVATION_MODE_" + (opt.openApplication == true ? "FOREGROUND" : "BACKGROUND")],
		destructive: !!opt.destructive,
		authenticationRequired: !!opt.authenticationRequired
	});
}

/**
 * @method addInteractiveNotificationCategory
 * @param {String}   id       	The ID of the category. It must be unique.
 * @param {Array}    dict     	An array of actions, with `id, title` (required) and `openApplication, destructive, authenticationRequired` (optional)
 * @param {Function} callback 	The callback to invoke
 */
exports.addInteractiveNotificationCategory = function(id, dict, callback) {
	if (!INTERACTIVE_NOTIFICATIONS_CAPABLE) return;

	var category = Ti.App.iOS.createUserNotificationCategory({
		identifier: id,
		actionsForDefaultContext: dict.map(createIntNotifAction)
	});

	// Add in the interactiveCategories array to register in the activate method
	interactiveCategories.push(category);
	interactiveCategoriesCallbacks[id] = callback;
};

//////////
// Init //
//////////

if (INTERACTIVE_NOTIFICATIONS_CAPABLE) {
	Ti.App.iOS.addEventListener('remotenotificationaction', function(e) {
		var func = interactiveCategoriesCallbacks[e.category];
		if (_.isFunction(func)) {
			func(e);
		} else {
			Ti.API.error('Notifications: remote notification with an unregistered category (' + e.category + ')');
		}
	});
}

if (exports.config.autoReset === true) {
	exports.resetBadge();
	Ti.App.addEventListener('resumed', exports.resetBadge);
}
<|endoftext|>


<commit_before>'use strict';

/* Controllers */

var ermInitController = angular.module('ermInitController', ['facetsModel', 'facetsService']);

//angular.module('ermrestApp').controller('InitListCtrl', ['$scope', '$location', 'FacetsData',
ermInitController.controller('InitListCtrl', ['$scope', '$location', '$window', 'FacetsData', 'FacetsService', 'ermrest',
                                                      function($scope, $location, $window, FacetsData, FacetsService, ermrest) {

	$('footer').hide();
	$('.panel-collapse').on('hide.bs.collapse', function () {
	      $(this).prev('.panel-heading').find('.glyphicon').removeClass('glyphicon-minus').addClass('glyphicon-plus');
	});
	$('.panel-collapse').on('show.bs.collapse', function () {
	      $(this).prev('.panel-heading').find('.glyphicon').removeClass('glyphicon-plus').addClass('glyphicon-minus');
	});

	$('#attrsort').click(function(){
		if ($('span').hasClass("glyphicon-sort-by-attributes")) {
		$("#attrsort span.glyphicon").removeClass("glyphicon-sort-by-attributes").addClass("glyphicon-sort-by-attributes-alt");
		}
		else {
		$("#attrsort span.glyphicon").removeClass("glyphicon-sort-by-attributes-alt").addClass("glyphicon-sort-by-attributes");
		}
	});

	$('.sidebar-overlay').click(function(event) {
    	if (!$('#editfilter').hasClass('open') && $('.sidebar-overlay').hasClass('active')) {
	        $('.sidebar-overlay').removeClass('active');
    		if ($('#sidebar').hasClass('open')) {
    	        $('#sidebar').toggleClass('open');
    		} else if ($('#collectionsTree').hasClass('open')) {
    	        $('#collectionsTree').toggleClass('open');
    		}
    	}
	});

	if ($location.search()['schema'] != null) {
		SCHEMA = $location.search()['schema'];
	} else if (SCHEMA == null) {
		//SCHEMA = 'legacy';
	}
	if ($location.search()['catalog'] != null) {
		CATALOG = $location.search()['catalog'];
	} else if (CATALOG == null) {
		if (chaiseConfig['catalog'] != null) {
			CATALOG = chaiseConfig['catalog'];
		} else {
			CATALOG = ermrest.catalog;
		}
	}
	authnProvider = ermrest.authnProvider;
	if (chaiseConfig['authnProvider'] != null) {
		authnProvider = chaiseConfig['authnProvider'];
	}

	if (chaiseConfig['facetPolicy'] != null) {
		facetPolicy = chaiseConfig['facetPolicy'];
	}

	$scope.FacetsData = FacetsData;

	FacetsService.initTable();

	if ($location.search()['table'] != null) {
		$scope.FacetsData.table = $location.search()['table'];
	} else {
		$scope.FacetsData.table = '';
	}

	if ($location.search()['filter'] != null) {
		$scope.FacetsData.filter = JSON.parse(decodeURIComponent($location.search()['filter']));
	} else {
		$scope.FacetsData.filter = null;
	}

	$window.addEventListener('popstate', function(event) {
    	event.stopPropagation();
		event.preventDefault();
		$scope.FacetsData.isDetail = false;
		if (!$scope.$$phase) {
			$scope.$apply();
		}
	});

	$scope.FacetsData.location = $location;
	$scope.FacetsData.view = ermrest.layout;
	if ($location.search()['layout'] != null) {
		$scope.FacetsData.view = $location.search()['layout'];
	} else if (chaiseConfig['layout'] != null) {
		$scope.FacetsData.view = chaiseConfig['layout'];
	}

	initApplication();

	this.hideSpinner = function hideSpinner() {
		//return !$scope.FacetsData.progress;
		return true;
	};
}]);
<commit_msg>Close all the sidebars when click outside the sidebar.<commit_after>'use strict';

/* Controllers */

var ermInitController = angular.module('ermInitController', ['facetsModel', 'facetsService']);

//angular.module('ermrestApp').controller('InitListCtrl', ['$scope', '$location', 'FacetsData',
ermInitController.controller('InitListCtrl', ['$scope', '$location', '$window', 'FacetsData', 'FacetsService', 'ermrest',
                                                      function($scope, $location, $window, FacetsData, FacetsService, ermrest) {

	$('footer').hide();
	$('.panel-collapse').on('hide.bs.collapse', function () {
	      $(this).prev('.panel-heading').find('.glyphicon').removeClass('glyphicon-minus').addClass('glyphicon-plus');
	});
	$('.panel-collapse').on('show.bs.collapse', function () {
	      $(this).prev('.panel-heading').find('.glyphicon').removeClass('glyphicon-plus').addClass('glyphicon-minus');
	});

	$('#attrsort').click(function(){
		if ($('span').hasClass("glyphicon-sort-by-attributes")) {
		$("#attrsort span.glyphicon").removeClass("glyphicon-sort-by-attributes").addClass("glyphicon-sort-by-attributes-alt");
		}
		else {
		$("#attrsort span.glyphicon").removeClass("glyphicon-sort-by-attributes-alt").addClass("glyphicon-sort-by-attributes");
		}
	});

	$('.sidebar-overlay').click(function(event) {
    	if ($('.sidebar-overlay').hasClass('active')) {
    		if ($('#editfilter').hasClass('open')) {
    			$('#editfilter').toggleClass('open');
    		}
	        $('.sidebar-overlay').removeClass('active');
    		if ($('#sidebar').hasClass('open')) {
    	        $('#sidebar').toggleClass('open');
    		} else if ($('#collectionsTree').hasClass('open')) {
    	        $('#collectionsTree').toggleClass('open');
    		}
    	}
	});

	if ($location.search()['schema'] != null) {
		SCHEMA = $location.search()['schema'];
	} else if (SCHEMA == null) {
		//SCHEMA = 'legacy';
	}
	if ($location.search()['catalog'] != null) {
		CATALOG = $location.search()['catalog'];
	} else if (CATALOG == null) {
		if (chaiseConfig['catalog'] != null) {
			CATALOG = chaiseConfig['catalog'];
		} else {
			CATALOG = ermrest.catalog;
		}
	}
	authnProvider = ermrest.authnProvider;
	if (chaiseConfig['authnProvider'] != null) {
		authnProvider = chaiseConfig['authnProvider'];
	}

	if (chaiseConfig['facetPolicy'] != null) {
		facetPolicy = chaiseConfig['facetPolicy'];
	}

	$scope.FacetsData = FacetsData;

	FacetsService.initTable();

	if ($location.search()['table'] != null) {
		$scope.FacetsData.table = $location.search()['table'];
	} else {
		$scope.FacetsData.table = '';
	}

	if ($location.search()['filter'] != null) {
		$scope.FacetsData.filter = JSON.parse(decodeURIComponent($location.search()['filter']));
	} else {
		$scope.FacetsData.filter = null;
	}

	$window.addEventListener('popstate', function(event) {
    	event.stopPropagation();
		event.preventDefault();
		$scope.FacetsData.isDetail = false;
		if (!$scope.$$phase) {
			$scope.$apply();
		}
	});

	$scope.FacetsData.location = $location;
	$scope.FacetsData.view = ermrest.layout;
	if ($location.search()['layout'] != null) {
		$scope.FacetsData.view = $location.search()['layout'];
	} else if (chaiseConfig['layout'] != null) {
		$scope.FacetsData.view = chaiseConfig['layout'];
	}

	initApplication();

	this.hideSpinner = function hideSpinner() {
		//return !$scope.FacetsData.progress;
		return true;
	};
}]);
<|endoftext|>


<commit_before>/**
 * @file TimeLine component
 * @author wendy(wendy.wei@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

import TimeLineItem from '../_TimelineItem';
import Theme from '../Theme';

import Util from '../_vendors/Util';

export default class TimeLine extends Component {

    static Type = TimeLineItem.Type;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    render() {

        const {data, style, className} = this.props;

        return (
            <ul className={`time-line ${className}`}
                style={style}>

                {
                    data.map((item, index) => {
                        return (
                            <TimeLineItem key={index}
                                          theme={item.theme}
                                          type={item.type}
                                          title={item.title}
                                          date={item.date}
                                          hasBorder={item.hasBorder}
                                          contentText={item.contentText}
                                          headerText={item.headerText}/>
                        );
                    })
                }

        );

    }
}

TimeLine.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The items data.
     */
    data: PropTypes.arrayOf(PropTypes.shape({

        /**
         * The TimeLine theme.Can be primary,highlight,success,warning,error.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The TimeLine type.Can be header or title.
         */
        type: PropTypes.string,

        /**
         * The text value of TimeLine header.
         */
        headerText: PropTypes.string,

        /**
         * The date value of TimeLine.
         */
        date: PropTypes.string,

        /**
         * If true,the right content will have border style.
         */
        hasBorder: PropTypes.bool,

        /**
         * The text value of right content.
         */
        contentText: PropTypes.string

    })).isRequired

};

TimeLine.defaultProps = {

    className: '',
    style: null,

    hasBorder: true,
    title: '',
    type: ''

};<commit_msg>optimize TimeLine<commit_after>/**
 * @file TimeLine component
 * @author wendy(wendy.wei@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

import TimeLineItem from '../_TimelineItem';
import Theme from '../Theme';

import Util from '../_vendors/Util';

export default class TimeLine extends Component {

    static Type = TimeLineItem.Type;
    static Theme = Theme;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    render() {

        const {data, style, className} = this.props;

        return (
            <ul className={`time-line ${className}`}
                style={style}>

                {
                    data.map((item, index) => {
                        return (
                            <TimeLineItem key={index}
                                          theme={item.theme}
                                          type={item.type}
                                          title={item.title}
                                          date={item.date}
                                          hasBorder={item.hasBorder}
                                          contentText={item.contentText}
                                          headerText={item.headerText}/>
                        );
                    })
                }

        );

    }
}

TimeLine.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The items data.
     */
    data: PropTypes.arrayOf(PropTypes.shape({

        /**
         * The TimeLine theme.Can be primary,highlight,success,warning,error.
         */
        theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

        /**
         * The TimeLine type.Can be header or title.
         */
        type: PropTypes.string,

        /**
         * The text value of TimeLine header.
         */
        headerText: PropTypes.string,

        /**
         * The date value of TimeLine.
         */
        date: PropTypes.string,

        /**
         * If true,the right content will have border style.
         */
        hasBorder: PropTypes.bool,

        /**
         * The text value of right content.
         */
        contentText: PropTypes.string

    })).isRequired

};

TimeLine.defaultProps = {

    className: '',
    style: null,

    hasBorder: true,
    title: '',
    type: ''

};<|endoftext|>